2017-01-18 23:29:47 +01:00
|
|
|
//
|
2019-01-18 00:24:19 +01:00
|
|
|
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
2017-01-18 23:29:47 +01:00
|
|
|
//
|
2016-11-12 18:22:29 +01:00
|
|
|
|
|
|
|
import Foundation
|
2017-01-06 15:47:50 +01:00
|
|
|
import UIKit
|
|
|
|
import CallKit
|
|
|
|
import AVFoundation
|
2017-11-28 00:17:46 +01:00
|
|
|
import SignalServiceKit
|
2017-12-01 16:48:18 +01:00
|
|
|
import SignalMessaging
|
2016-11-12 18:22:29 +01:00
|
|
|
|
2017-01-06 15:38:35 +01:00
|
|
|
/**
|
2017-01-09 17:19:50 +01:00
|
|
|
* Connects user interface to the CallService using CallKit.
|
2017-01-06 15:47:50 +01:00
|
|
|
*
|
2017-01-09 17:19:50 +01:00
|
|
|
* User interface is routed to the CallManager which requests CXCallActions, and if the CXProvider accepts them,
|
|
|
|
* their corresponding consequences are implmented in the CXProviderDelegate methods, e.g. using the CallService
|
2017-01-06 15:38:35 +01:00
|
|
|
*/
|
2016-11-12 18:22:29 +01:00
|
|
|
@available(iOS 10.0, *)
|
2017-01-06 15:47:50 +01:00
|
|
|
final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
|
2016-11-12 18:22:29 +01:00
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
private let callManager: CallKitCallManager
|
2017-01-18 21:17:55 +01:00
|
|
|
internal let callService: CallService
|
2019-01-18 18:54:09 +01:00
|
|
|
internal let notificationPresenter: NotificationPresenter
|
2017-09-07 22:25:57 +02:00
|
|
|
internal let contactsManager: OWSContactsManager
|
2018-02-23 23:08:21 +01:00
|
|
|
private let showNamesOnCallScreen: Bool
|
2017-01-06 15:47:50 +01:00
|
|
|
private let provider: CXProvider
|
2018-02-23 23:08:21 +01:00
|
|
|
private let audioActivity: AudioActivity
|
2017-01-06 15:47:50 +01:00
|
|
|
|
2017-01-18 18:31:18 +01:00
|
|
|
// CallKit handles incoming ringer stop/start for us. Yay!
|
|
|
|
let hasManualRinger = false
|
|
|
|
|
2018-03-08 22:21:34 +01:00
|
|
|
// Instantiating more than one CXProvider can cause us to miss call transactions, so
|
|
|
|
// we maintain the provider across Adaptees using a singleton pattern
|
|
|
|
private static var _sharedProvider: CXProvider?
|
|
|
|
class func sharedProvider(useSystemCallLog: Bool) -> CXProvider {
|
|
|
|
let configuration = buildProviderConfiguration(useSystemCallLog: useSystemCallLog)
|
2018-04-11 21:17:34 +02:00
|
|
|
|
2018-03-08 22:21:34 +01:00
|
|
|
if let sharedProvider = self._sharedProvider {
|
|
|
|
sharedProvider.configuration = configuration
|
|
|
|
return sharedProvider
|
|
|
|
} else {
|
|
|
|
SwiftSingletons.register(self)
|
|
|
|
let provider = CXProvider(configuration: configuration)
|
|
|
|
_sharedProvider = provider
|
|
|
|
return provider
|
|
|
|
}
|
|
|
|
}
|
2018-04-11 21:17:34 +02:00
|
|
|
|
2017-01-18 18:31:18 +01:00
|
|
|
// The app's provider configuration, representing its CallKit capabilities
|
2018-02-23 23:08:21 +01:00
|
|
|
class func buildProviderConfiguration(useSystemCallLog: Bool) -> CXProviderConfiguration {
|
2017-01-06 15:47:50 +01:00
|
|
|
let localizedName = NSLocalizedString("APPLICATION_NAME", comment: "Name of application")
|
|
|
|
let providerConfiguration = CXProviderConfiguration(localizedName: localizedName)
|
|
|
|
|
|
|
|
providerConfiguration.supportsVideo = true
|
|
|
|
|
2017-01-18 15:50:22 +01:00
|
|
|
providerConfiguration.maximumCallGroups = 1
|
2017-01-27 17:11:33 +01:00
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
providerConfiguration.maximumCallsPerCallGroup = 1
|
|
|
|
|
2017-02-22 05:17:54 +01:00
|
|
|
providerConfiguration.supportedHandleTypes = [.phoneNumber, .generic]
|
2017-01-06 15:47:50 +01:00
|
|
|
|
2017-11-20 18:45:19 +01:00
|
|
|
let iconMaskImage = #imageLiteral(resourceName: "logoSignal")
|
2019-03-30 14:22:31 +01:00
|
|
|
providerConfiguration.iconTemplateImageData = iconMaskImage.pngData()
|
2017-01-06 15:47:50 +01:00
|
|
|
|
2018-02-23 20:36:21 +01:00
|
|
|
// We don't set the ringtoneSound property, so that we use either the
|
|
|
|
// default iOS ringtone OR the custom ringtone associated with this user's
|
|
|
|
// system contact, if possible (iOS 11 or later).
|
|
|
|
|
2018-02-23 16:52:46 +01:00
|
|
|
if #available(iOS 11.0, *) {
|
2018-02-23 23:08:21 +01:00
|
|
|
providerConfiguration.includesCallsInRecents = useSystemCallLog
|
|
|
|
} else {
|
|
|
|
// not configurable for iOS10+
|
|
|
|
assert(useSystemCallLog)
|
2018-02-23 16:52:46 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
return providerConfiguration
|
|
|
|
}
|
|
|
|
|
2019-01-18 18:54:09 +01:00
|
|
|
init(callService: CallService, contactsManager: OWSContactsManager, notificationPresenter: NotificationPresenter, showNamesOnCallScreen: Bool, useSystemCallLog: Bool) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.debug("")
|
2017-02-02 03:33:30 +01:00
|
|
|
|
2018-02-23 23:08:21 +01:00
|
|
|
self.callManager = CallKitCallManager(showNamesOnCallScreen: showNamesOnCallScreen)
|
2017-01-06 15:47:50 +01:00
|
|
|
self.callService = callService
|
2017-09-07 22:25:57 +02:00
|
|
|
self.contactsManager = contactsManager
|
2019-01-18 18:54:09 +01:00
|
|
|
self.notificationPresenter = notificationPresenter
|
2018-02-23 23:08:21 +01:00
|
|
|
|
2018-03-08 22:21:34 +01:00
|
|
|
self.provider = type(of: self).sharedProvider(useSystemCallLog: useSystemCallLog)
|
2018-02-23 23:08:21 +01:00
|
|
|
|
2018-10-23 16:40:09 +02:00
|
|
|
self.audioActivity = AudioActivity(audioDescription: "[CallKitCallUIAdaptee]", behavior: .call)
|
2018-02-23 23:08:21 +01:00
|
|
|
self.showNamesOnCallScreen = showNamesOnCallScreen
|
2017-01-06 15:47:50 +01:00
|
|
|
|
|
|
|
super.init()
|
|
|
|
|
2018-02-23 23:08:21 +01:00
|
|
|
// We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings
|
2017-12-07 16:33:27 +01:00
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
self.provider.setDelegate(self, queue: nil)
|
2016-11-12 18:22:29 +01:00
|
|
|
}
|
|
|
|
|
2018-10-23 02:55:39 +02:00
|
|
|
// MARK: Dependencies
|
|
|
|
|
|
|
|
var audioSession: OWSAudioSession {
|
|
|
|
return Environment.shared.audioSession
|
|
|
|
}
|
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
// MARK: CallUIAdaptee
|
|
|
|
|
2017-01-18 21:17:55 +01:00
|
|
|
func startOutgoingCall(handle: String) -> SignalCall {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-18 21:17:55 +01:00
|
|
|
let call = SignalCall.outgoingCall(localId: UUID(), remotePhoneNumber: handle)
|
|
|
|
|
2018-02-16 22:00:11 +01:00
|
|
|
// make sure we don't terminate audio session during call
|
2018-11-12 16:54:42 +01:00
|
|
|
_ = self.audioSession.startAudioActivity(call.audioActivity)
|
2018-02-16 22:00:11 +01:00
|
|
|
|
2016-11-12 18:22:29 +01:00
|
|
|
// Add the new outgoing call to the app's list of calls.
|
|
|
|
// So we can find it in the provider delegate callbacks.
|
2017-01-06 15:47:50 +01:00
|
|
|
callManager.addCall(call)
|
|
|
|
callManager.startCall(call)
|
2017-01-18 21:17:55 +01:00
|
|
|
|
|
|
|
return call
|
2016-11-12 18:22:29 +01:00
|
|
|
}
|
|
|
|
|
2017-01-26 19:18:06 +01:00
|
|
|
// Called from CallService after call has ended to clean up any remaining CallKit call state.
|
|
|
|
func failCall(_ call: SignalCall, error: CallError) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-02-22 05:17:54 +01:00
|
|
|
switch error {
|
2017-02-08 19:39:23 +01:00
|
|
|
case .timeout(description: _):
|
|
|
|
provider.reportCall(with: call.localId, endedAt: Date(), reason: CXCallEndedReason.unanswered)
|
|
|
|
default:
|
|
|
|
provider.reportCall(with: call.localId, endedAt: Date(), reason: CXCallEndedReason.failed)
|
|
|
|
}
|
|
|
|
|
2017-01-26 19:18:06 +01:00
|
|
|
self.callManager.removeCall(call)
|
|
|
|
}
|
|
|
|
|
2017-01-09 19:36:45 +01:00
|
|
|
func reportIncomingCall(_ call: SignalCall, callerName: String) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
// Construct a CXCallUpdate describing the incoming call, including the caller.
|
|
|
|
let update = CXCallUpdate()
|
2018-02-23 23:08:21 +01:00
|
|
|
|
|
|
|
if showNamesOnCallScreen {
|
|
|
|
update.localizedCallerName = self.contactsManager.stringForConversationTitle(withPhoneIdentifier: call.remotePhoneNumber)
|
|
|
|
update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
|
|
|
|
} else {
|
2017-02-22 15:50:41 +01:00
|
|
|
let callKitId = CallKitCallManager.kAnonymousCallHandlePrefix + call.localId.uuidString
|
|
|
|
update.remoteHandle = CXHandle(type: .generic, value: callKitId)
|
2018-03-05 15:30:58 +01:00
|
|
|
OWSPrimaryStorage.shared().setPhoneNumber(call.remotePhoneNumber, forCallKitId: callKitId)
|
2017-09-07 22:25:57 +02:00
|
|
|
update.localizedCallerName = NSLocalizedString("CALLKIT_ANONYMOUS_CONTACT_NAME", comment: "The generic name used for calls if CallKit privacy is enabled")
|
2017-02-22 15:50:41 +01:00
|
|
|
}
|
|
|
|
|
2017-01-27 17:11:33 +01:00
|
|
|
update.hasVideo = call.hasLocalVideo
|
2017-09-07 22:25:57 +02:00
|
|
|
|
2017-01-30 22:11:39 +01:00
|
|
|
disableUnsupportedFeatures(callUpdate: update)
|
2017-01-27 17:11:33 +01:00
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
// Report the incoming call to the system
|
|
|
|
provider.reportNewIncomingCall(with: call.localId, update: update) { error in
|
|
|
|
/*
|
|
|
|
Only add incoming call to the app's list of calls if the call was allowed (i.e. there was no error)
|
|
|
|
since calls may be "denied" for various legitimate reasons. See CXErrorCodeIncomingCallError.
|
|
|
|
*/
|
|
|
|
guard error == nil else {
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.error("failed to report new incoming call")
|
2017-01-06 15:47:50 +01:00
|
|
|
return
|
|
|
|
}
|
2016-11-12 18:22:29 +01:00
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
self.callManager.addCall(call)
|
|
|
|
}
|
2016-11-12 18:22:29 +01:00
|
|
|
}
|
|
|
|
|
2017-01-18 21:17:55 +01:00
|
|
|
func answerCall(localId: UUID) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-27 16:27:48 +02:00
|
|
|
owsFailDebug("CallKit should answer calls via system call screen, not via notifications.")
|
2017-01-18 21:17:55 +01:00
|
|
|
}
|
|
|
|
|
2017-01-09 19:36:45 +01:00
|
|
|
func answerCall(_ call: SignalCall) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-09 17:19:50 +01:00
|
|
|
callManager.answer(call: call)
|
2016-11-12 18:22:29 +01:00
|
|
|
}
|
|
|
|
|
2017-01-18 21:17:55 +01:00
|
|
|
func declineCall(localId: UUID) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-27 16:27:48 +02:00
|
|
|
owsFailDebug("CallKit should decline calls via system call screen, not via notifications.")
|
2017-01-18 21:17:55 +01:00
|
|
|
}
|
|
|
|
|
2017-01-09 19:36:45 +01:00
|
|
|
func declineCall(_ call: SignalCall) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-26 19:18:06 +01:00
|
|
|
callManager.localHangup(call: call)
|
2016-11-12 18:22:29 +01:00
|
|
|
}
|
|
|
|
|
2017-01-10 18:36:54 +01:00
|
|
|
func recipientAcceptedCall(_ call: SignalCall) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-30 21:10:47 +01:00
|
|
|
self.provider.reportOutgoingCall(with: call.localId, connectedAt: nil)
|
2017-01-30 22:11:39 +01:00
|
|
|
|
|
|
|
let update = CXCallUpdate()
|
|
|
|
disableUnsupportedFeatures(callUpdate: update)
|
|
|
|
|
|
|
|
provider.reportCall(with: call.localId, updated: update)
|
2017-01-26 19:18:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func localHangupCall(_ call: SignalCall) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-26 19:18:06 +01:00
|
|
|
callManager.localHangup(call: call)
|
2017-01-10 18:36:54 +01:00
|
|
|
}
|
|
|
|
|
2017-01-26 19:18:06 +01:00
|
|
|
func remoteDidHangupCall(_ call: SignalCall) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-26 19:18:06 +01:00
|
|
|
provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.remoteEnded)
|
2016-11-12 18:22:29 +01:00
|
|
|
}
|
2017-01-06 15:47:50 +01:00
|
|
|
|
2017-02-02 03:33:30 +01:00
|
|
|
func remoteBusy(_ call: SignalCall) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-02-02 03:33:30 +01:00
|
|
|
|
|
|
|
provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.unanswered)
|
|
|
|
}
|
|
|
|
|
2017-01-18 23:29:47 +01:00
|
|
|
func setIsMuted(call: SignalCall, isMuted: Bool) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-18 23:29:47 +01:00
|
|
|
callManager.setIsMuted(call: call, isMuted: isMuted)
|
|
|
|
}
|
|
|
|
|
2017-01-27 17:11:33 +01:00
|
|
|
func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.debug("")
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2017-01-18 23:29:47 +01:00
|
|
|
let update = CXCallUpdate()
|
2017-01-27 17:11:33 +01:00
|
|
|
update.hasVideo = hasLocalVideo
|
2017-01-18 23:29:47 +01:00
|
|
|
|
|
|
|
// Update the CallKit UI.
|
|
|
|
provider.reportCall(with: call.localId, updated: update)
|
|
|
|
|
2017-01-31 21:28:01 +01:00
|
|
|
self.callService.setHasLocalVideo(hasLocalVideo: hasLocalVideo)
|
2017-01-09 15:28:04 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
// MARK: CXProviderDelegate
|
|
|
|
|
|
|
|
func providerDidReset(_ provider: CXProvider) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("")
|
2017-01-06 15:47:50 +01:00
|
|
|
|
2017-02-03 00:04:54 +01:00
|
|
|
// End any ongoing calls if the provider resets, and remove them from the app's list of calls,
|
|
|
|
// since they are no longer valid.
|
2017-04-18 17:50:55 +02:00
|
|
|
callService.handleFailedCurrentCall(error: .providerReset)
|
2017-01-06 15:47:50 +01:00
|
|
|
|
|
|
|
// Remove all calls from the app's list of calls.
|
|
|
|
callManager.removeAllCalls()
|
|
|
|
}
|
|
|
|
|
|
|
|
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("CXStartCallAction")
|
2017-01-06 15:47:50 +01:00
|
|
|
|
|
|
|
guard let call = callManager.callWithLocalId(action.callUUID) else {
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.error("unable to find call")
|
2017-01-06 15:47:50 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-02-08 21:49:17 +01:00
|
|
|
// We can't wait for long before fulfilling the CXAction, else CallKit will show a "Failed Call". We don't
|
|
|
|
// actually need to wait for the outcome of the handleOutgoingCall promise, because it handles any errors by
|
|
|
|
// manually failing the call.
|
2018-10-13 21:21:46 +02:00
|
|
|
self.callService.handleOutgoingCall(call).retainUntilComplete()
|
2017-05-04 19:49:44 +02:00
|
|
|
|
2017-02-08 21:49:17 +01:00
|
|
|
action.fulfill()
|
|
|
|
self.provider.reportOutgoingCall(with: call.localId, startedConnectingAt: nil)
|
2017-02-22 15:50:41 +01:00
|
|
|
|
2018-02-23 23:08:21 +01:00
|
|
|
// Update the name used in the CallKit UI for outgoing calls when the user prefers not to show names
|
|
|
|
// in ther notifications
|
|
|
|
if !showNamesOnCallScreen {
|
2017-02-23 16:18:37 +01:00
|
|
|
let update = CXCallUpdate()
|
|
|
|
update.localizedCallerName = NSLocalizedString("CALLKIT_ANONYMOUS_CONTACT_NAME",
|
|
|
|
comment: "The generic name used for calls if CallKit privacy is enabled")
|
|
|
|
provider.reportCall(with: call.localId, updated: update)
|
2017-02-22 15:23:56 +01:00
|
|
|
}
|
2017-01-06 15:47:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("Received \(#function) CXAnswerCallAction")
|
2017-02-03 00:04:54 +01:00
|
|
|
// Retrieve the instance corresponding to the action's call UUID
|
2017-01-06 15:47:50 +01:00
|
|
|
guard let call = callManager.callWithLocalId(action.callUUID) else {
|
|
|
|
action.fail()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-01-31 21:28:01 +01:00
|
|
|
self.callService.handleAnswerCall(call)
|
|
|
|
self.showCall(call)
|
|
|
|
action.fulfill()
|
2017-01-06 15:47:50 +01:00
|
|
|
}
|
|
|
|
|
2017-01-09 15:28:04 +01:00
|
|
|
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("Received \(#function) CXEndCallAction")
|
2017-01-06 15:47:50 +01:00
|
|
|
guard let call = callManager.callWithLocalId(action.callUUID) else {
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.error("trying to end unknown call with localId: \(action.callUUID)")
|
2017-01-06 15:47:50 +01:00
|
|
|
action.fail()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-01-31 21:28:01 +01:00
|
|
|
self.callService.handleLocalHungupCall(call)
|
2017-01-06 15:47:50 +01:00
|
|
|
|
2017-02-01 20:43:47 +01:00
|
|
|
// Signal to the system that the action has been successfully performed.
|
|
|
|
action.fulfill()
|
2017-01-06 15:47:50 +01:00
|
|
|
|
2017-02-01 20:43:47 +01:00
|
|
|
// Remove the ended call from the app's list of calls.
|
|
|
|
self.callManager.removeCall(call)
|
2017-01-06 15:47:50 +01:00
|
|
|
}
|
|
|
|
|
2017-01-09 15:28:04 +01:00
|
|
|
public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("Received \(#function) CXSetHeldCallAction")
|
2017-01-06 15:47:50 +01:00
|
|
|
guard let call = callManager.callWithLocalId(action.callUUID) else {
|
|
|
|
action.fail()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-01-30 21:40:40 +01:00
|
|
|
// Update the SignalCall's underlying hold state.
|
2017-10-31 18:47:12 +01:00
|
|
|
self.callService.setIsOnHold(call: call, isOnHold: action.isOnHold)
|
2017-01-30 21:40:40 +01:00
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
// Signal to the system that the action has been successfully performed.
|
|
|
|
action.fulfill()
|
|
|
|
}
|
|
|
|
|
2017-01-09 15:28:04 +01:00
|
|
|
public func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.info("Received \(#function) CXSetMutedCallAction")
|
2017-10-31 18:47:12 +01:00
|
|
|
guard let call = callManager.callWithLocalId(action.callUUID) else {
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.error("Failing CXSetMutedCallAction for unknown call: \(action.callUUID)")
|
2017-01-09 15:28:04 +01:00
|
|
|
action.fail()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-10-31 18:47:12 +01:00
|
|
|
self.callService.setIsMuted(call: call, isMuted: action.isMuted)
|
2017-01-31 21:28:01 +01:00
|
|
|
action.fulfill()
|
2017-01-09 15:28:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public func provider(_ provider: CXProvider, perform action: CXSetGroupCallAction) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.warn("unimplemented \(#function) for CXSetGroupCallAction")
|
2017-01-09 15:28:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.warn("unimplemented \(#function) for CXPlayDTMFCallAction")
|
2017-01-09 15:28:04 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 15:47:50 +01:00
|
|
|
func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-27 16:27:48 +02:00
|
|
|
owsFailDebug("Timed out while performing \(action)")
|
2017-01-06 15:47:50 +01:00
|
|
|
|
|
|
|
// React to the action timeout if necessary, such as showing an error UI.
|
|
|
|
}
|
|
|
|
|
|
|
|
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.debug("Received")
|
2018-02-16 22:11:57 +01:00
|
|
|
|
2018-11-12 16:54:42 +01:00
|
|
|
_ = self.audioSession.startAudioActivity(self.audioActivity)
|
2018-10-23 02:55:39 +02:00
|
|
|
self.audioSession.isRTCAudioEnabled = true
|
2017-01-06 15:47:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
|
2018-08-22 19:44:22 +02:00
|
|
|
AssertIsOnMainThread()
|
2017-01-30 19:46:19 +01:00
|
|
|
|
2018-08-23 16:37:34 +02:00
|
|
|
Logger.debug("Received")
|
2018-10-23 02:55:39 +02:00
|
|
|
self.audioSession.isRTCAudioEnabled = false
|
|
|
|
self.audioSession.endAudioActivity(self.audioActivity)
|
2017-01-06 15:47:50 +01:00
|
|
|
}
|
2017-01-30 22:11:39 +01:00
|
|
|
|
|
|
|
// MARK: - Util
|
|
|
|
|
|
|
|
private func disableUnsupportedFeatures(callUpdate: CXCallUpdate) {
|
|
|
|
// Call Holding is failing to restart audio when "swapping" calls on the CallKit screen
|
|
|
|
// until user returns to in-app call screen.
|
|
|
|
callUpdate.supportsHolding = false
|
|
|
|
|
|
|
|
// Not yet supported
|
|
|
|
callUpdate.supportsGrouping = false
|
|
|
|
callUpdate.supportsUngrouping = false
|
|
|
|
|
|
|
|
// Is there any reason to support this?
|
|
|
|
callUpdate.supportsDTMF = false
|
|
|
|
}
|
2016-11-12 18:22:29 +01:00
|
|
|
}
|