Move localId up from IndividualCall to SignalCall

Group calls don't normally have stable IDs, but we need an opaque ID
to represent a particular ring for CallKit or notifications.

The next commit will drop the localId on IndividualCall, but right now
it's still needed for presenting notifications.
This commit is contained in:
Jordan Rose 2022-08-25 18:03:43 -07:00
parent a74c7e0885
commit f0ccdd9787
9 changed files with 44 additions and 46 deletions

View File

@ -570,7 +570,7 @@ public final class CallService: LightweightCallManager {
AssertIsOnMainThread()
guard !hasCallInProgress else { return nil }
let call = SignalCall.outgoingIndividualCall(localId: UUID(), thread: thread)
let call = SignalCall.outgoingIndividualCall(thread: thread)
call.individualCall.offerMediaType = hasVideo ? .video : .audio
addCall(call)
@ -594,7 +594,6 @@ public final class CallService: LightweightCallManager {
}
let newCall = SignalCall.incomingIndividualCall(
localId: UUID(),
thread: thread,
sentAtTimestamp: sentAtTimestamp,
offerMediaType: offerMediaType

View File

@ -113,7 +113,7 @@ public class IndividualCall: NSObject, IndividualCallNotificationInfo {
var wasRemovedFromSystem = false
@objc
public let remoteAddress: SignalServiceAddress
public var remoteAddress: SignalServiceAddress { thread.contactAddress }
public var isEnded: Bool {
switch state {
@ -128,7 +128,7 @@ public class IndividualCall: NSObject, IndividualCallNotificationInfo {
// Distinguishes between calls locally, e.g. in CallKit
@objc
public let localId: UUID
public let localId: UUID = UUID()
public let thread: TSContactThread
@ -208,11 +208,9 @@ public class IndividualCall: NSObject, IndividualCallNotificationInfo {
// MARK: Initializers and Factory Methods
init(direction: CallDirection, localId: UUID, state: CallState, thread: TSContactThread, sentAtTimestamp: UInt64, callAdapterType: CallAdapterType) {
init(direction: CallDirection, state: CallState, thread: TSContactThread, sentAtTimestamp: UInt64, callAdapterType: CallAdapterType) {
self.direction = direction
self.localId = localId
self.state = state
self.remoteAddress = thread.contactAddress
self.thread = thread
self.sentAtTimestamp = sentAtTimestamp
self.callAdapterType = callAdapterType

View File

@ -61,7 +61,7 @@ final public class IndividualCallService: NSObject {
AssertIsOnMainThread()
Logger.info("call: \(call)")
BenchEventStart(title: "Outgoing Call Connection", eventId: "call-\(call.individualCall.localId)")
BenchEventStart(title: "Outgoing Call Connection", eventId: "call-\(call.localId)")
guard callService.currentCall == nil else {
owsFailDebug("call already exists: \(String(describing: callService.currentCall))")
@ -264,7 +264,7 @@ final public class IndividualCallService: NSObject {
callType: callType
)
BenchEventStart(title: "Incoming Call Connection", eventId: "call-\(newCall.individualCall.localId)")
BenchEventStart(title: "Incoming Call Connection", eventId: "call-\(newCall.localId)")
guard tsAccountManager.isOnboarded(with: transaction) else {
Logger.warn("user is not onboarded, skipping call.")
@ -1222,10 +1222,10 @@ final public class IndividualCallService: NSObject {
switch call.individualCall.state {
case .dialing:
BenchEventComplete(eventId: "call-\(call.individualCall.localId)")
BenchEventComplete(eventId: "call-\(call.localId)")
call.individualCall.state = .remoteRinging
case .answering:
BenchEventComplete(eventId: "call-\(call.individualCall.localId)")
BenchEventComplete(eventId: "call-\(call.localId)")
call.individualCall.state = isAnticipatory ? .localRinging_Anticipatory : .localRinging_ReadyToAnswer
self.callUIAdapter.reportIncomingCall(call, thread: call.individualCall.thread)
case .localRinging_Anticipatory:

View File

@ -106,6 +106,9 @@ public class SignalCall: NSObject, CallManagerCallReference {
didSet { AssertIsOnMainThread() }
}
// Distinguishes between calls locally, e.g. in CallKit
public let localId: UUID
@objc
public let thread: TSThread
@ -174,6 +177,7 @@ public class SignalCall: NSObject, CallManagerCallReference {
audioDescription: "[SignalCall] with group \(groupThread.groupModel.groupId)",
behavior: .call
)
localId = UUID()
thread = groupThread
if !RemoteConfig.groupRings {
ringRestrictions = .notApplicable
@ -213,6 +217,7 @@ public class SignalCall: NSObject, CallManagerCallReference {
behavior: .call
)
thread = individualCall.thread
localId = individualCall.localId
ringRestrictions = .notApplicable
super.init()
individualCall.delegate = self
@ -240,10 +245,9 @@ public class SignalCall: NSObject, CallManagerCallReference {
return call
}
public class func outgoingIndividualCall(localId: UUID, thread: TSContactThread) -> SignalCall {
public class func outgoingIndividualCall(thread: TSContactThread) -> SignalCall {
let individualCall = IndividualCall(
direction: .outgoing,
localId: localId,
state: .dialing,
thread: thread,
sentAtTimestamp: Date.ows_millisecondTimestamp(),
@ -253,7 +257,6 @@ public class SignalCall: NSObject, CallManagerCallReference {
}
public class func incomingIndividualCall(
localId: UUID,
thread: TSContactThread,
sentAtTimestamp: UInt64,
offerMediaType: TSRecentCallOfferType
@ -273,7 +276,6 @@ public class SignalCall: NSObject, CallManagerCallReference {
let individualCall = IndividualCall(
direction: .incoming,
localId: localId,
state: .answering,
thread: thread,
sentAtTimestamp: sentAtTimestamp,

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
//
import UIKit
@ -48,12 +48,12 @@ final class CallKitCallManager: NSObject {
}
handle = CXHandle(type: type, value: value)
} else {
let callKitId = CallKitCallManager.kAnonymousCallHandlePrefix + call.individualCall.localId.uuidString
let callKitId = CallKitCallManager.kAnonymousCallHandlePrefix + call.localId.uuidString
handle = CXHandle(type: .generic, value: callKitId)
CallKitIdStore.setAddress(call.individualCall.remoteAddress, forCallKitId: callKitId)
}
let startCallAction = CXStartCallAction(call: call.individualCall.localId, handle: handle)
let startCallAction = CXStartCallAction(call: call.localId, handle: handle)
startCallAction.isVideo = call.individualCall.hasLocalVideo
@ -64,7 +64,7 @@ final class CallKitCallManager: NSObject {
}
func localHangup(call: SignalCall) {
let endCallAction = CXEndCallAction(call: call.individualCall.localId)
let endCallAction = CXEndCallAction(call: call.localId)
let transaction = CXTransaction()
transaction.addAction(endCallAction)
@ -72,7 +72,7 @@ final class CallKitCallManager: NSObject {
}
func setHeld(call: SignalCall, onHold: Bool) {
let setHeldCallAction = CXSetHeldCallAction(call: call.individualCall.localId, onHold: onHold)
let setHeldCallAction = CXSetHeldCallAction(call: call.localId, onHold: onHold)
let transaction = CXTransaction()
transaction.addAction(setHeldCallAction)
@ -80,7 +80,7 @@ final class CallKitCallManager: NSObject {
}
func setIsMuted(call: SignalCall, isMuted: Bool) {
let muteCallAction = CXSetMutedCallAction(call: call.individualCall.localId, muted: isMuted)
let muteCallAction = CXSetMutedCallAction(call: call.localId, muted: isMuted)
let transaction = CXTransaction()
transaction.addAction(muteCallAction)
@ -88,7 +88,7 @@ final class CallKitCallManager: NSObject {
}
func answer(call: SignalCall) {
let answerCallAction = CXAnswerCallAction(call: call.individualCall.localId)
let answerCallAction = CXAnswerCallAction(call: call.localId)
let transaction = CXTransaction()
transaction.addAction(answerCallAction)
@ -110,7 +110,7 @@ final class CallKitCallManager: NSObject {
private(set) var calls = [SignalCall]()
func callWithLocalId(_ localId: UUID) -> SignalCall? {
guard let index = calls.firstIndex(where: { $0.individualCall.localId == localId }) else {
guard let index = calls.firstIndex(where: { $0.localId == localId }) else {
return nil
}
return calls[index]

View File

@ -131,9 +131,9 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
switch error {
case .timeout(description: _):
self.provider.reportCall(with: call.individualCall.localId, endedAt: Date(), reason: CXCallEndedReason.unanswered)
self.provider.reportCall(with: call.localId, endedAt: Date(), reason: CXCallEndedReason.unanswered)
default:
self.provider.reportCall(with: call.individualCall.localId, endedAt: Date(), reason: CXCallEndedReason.failed)
self.provider.reportCall(with: call.localId, endedAt: Date(), reason: CXCallEndedReason.failed)
}
self.callManager.removeCall(call)
}
@ -152,7 +152,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
update.remoteHandle = CXHandle(type: .phoneNumber, value: phoneNumber)
}
} else {
let callKitId = CallKitCallManager.kAnonymousCallHandlePrefix + call.individualCall.localId.uuidString
let callKitId = CallKitCallManager.kAnonymousCallHandlePrefix + call.localId.uuidString
update.remoteHandle = CXHandle(type: .generic, value: callKitId)
CallKitIdStore.setAddress(call.individualCall.remoteAddress, forCallKitId: callKitId)
update.localizedCallerName = NSLocalizedString("CALLKIT_ANONYMOUS_CONTACT_NAME", comment: "The generic name used for calls if CallKit privacy is enabled")
@ -164,7 +164,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
// Report the incoming call to the system
self.provider.reportNewIncomingCall(with: call.individualCall.localId, update: update) { error in
self.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.
@ -207,12 +207,12 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Logger.info("")
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
self.provider.reportOutgoingCall(with: call.individualCall.localId, connectedAt: nil)
self.provider.reportOutgoingCall(with: call.localId, connectedAt: nil)
let update = CXCallUpdate()
self.disableUnsupportedFeatures(callUpdate: update)
self.provider.reportCall(with: call.individualCall.localId, updated: update)
self.provider.reportCall(with: call.localId, updated: update)
// When we tell CallKit about the call, it tries
// to unmute the call. We can work around this
@ -245,7 +245,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Logger.info("")
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
self.provider.reportCall(with: call.individualCall.localId, endedAt: nil, reason: CXCallEndedReason.remoteEnded)
self.provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.remoteEnded)
self.callManager.removeCall(call)
}
}
@ -255,7 +255,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Logger.info("")
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
self.provider.reportCall(with: call.individualCall.localId, endedAt: nil, reason: CXCallEndedReason.unanswered)
self.provider.reportCall(with: call.localId, endedAt: nil, reason: CXCallEndedReason.unanswered)
self.callManager.removeCall(call)
}
}
@ -265,7 +265,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Logger.info("")
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
self.provider.reportCall(with: call.individualCall.localId, endedAt: nil, reason: .answeredElsewhere)
self.provider.reportCall(with: call.localId, endedAt: nil, reason: .answeredElsewhere)
self.callManager.removeCall(call)
}
}
@ -275,7 +275,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Logger.info("")
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
self.provider.reportCall(with: call.individualCall.localId, endedAt: nil, reason: .declinedElsewhere)
self.provider.reportCall(with: call.localId, endedAt: nil, reason: .declinedElsewhere)
self.callManager.removeCall(call)
}
}
@ -286,7 +286,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
// Callkit doesn't have a reason for "busy elsewhere", .declinedElsewhere is close enough.
self.provider.reportCall(with: call.individualCall.localId, endedAt: nil, reason: .declinedElsewhere)
self.provider.reportCall(with: call.localId, endedAt: nil, reason: .declinedElsewhere)
self.callManager.removeCall(call)
}
}
@ -309,7 +309,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Self.providerReadyFlag.runNowOrWhenDidBecomeReadySync {
let update = CXCallUpdate()
update.hasVideo = hasLocalVideo
self.provider.reportCall(with: call.individualCall.localId, updated: update)
self.provider.reportCall(with: call.localId, updated: update)
}
}
@ -349,7 +349,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
self.callService.individualCallService.handleOutgoingCall(call)
action.fulfill()
provider.reportOutgoingCall(with: call.individualCall.localId, startedConnectingAt: nil)
provider.reportOutgoingCall(with: call.localId, startedConnectingAt: nil)
// Update the name used in the CallKit UI for outgoing calls when the user prefers not to show names
// in their notifications
@ -357,7 +357,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
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.individualCall.localId, updated: update)
provider.reportCall(with: call.localId, updated: update)
}
}

View File

@ -208,7 +208,7 @@ public class CallUIAdapter: NSObject, CallServiceObserver {
return
}
guard call.individualCall.localId == localId else {
guard call.localId == localId else {
owsFailDebug("localId does not match current call")
return
}
@ -267,7 +267,7 @@ public class CallUIAdapter: NSObject, CallServiceObserver {
return
}
guard call.individualCall.localId == localId else {
guard call.localId == localId else {
owsFailDebug("localId does not match current call")
return
}

View File

@ -74,7 +74,7 @@ class NonCallKitCallUIAdaptee: NSObject, CallUIAdaptee {
return
}
guard call.individualCall.localId == localId else {
guard call.localId == localId else {
owsFailDebug("localId does not match current call")
return
}
@ -85,7 +85,7 @@ class NonCallKitCallUIAdaptee: NSObject, CallUIAdaptee {
func answerCall(_ call: SignalCall) {
AssertIsOnMainThread()
guard call.individualCall.localId == self.callService.currentCall?.individualCall.localId else {
guard call.localId == self.callService.currentCall?.localId else {
owsFailDebug("localId does not match current call")
return
}
@ -111,7 +111,7 @@ class NonCallKitCallUIAdaptee: NSObject, CallUIAdaptee {
return
}
guard call.individualCall.localId == localId else {
guard call.localId == localId else {
owsFailDebug("localId does not match current call")
return
}
@ -124,7 +124,7 @@ class NonCallKitCallUIAdaptee: NSObject, CallUIAdaptee {
// If both parties hang up at the same moment,
// call might already be nil.
guard self.callService.currentCall == nil || call.individualCall.localId == self.callService.currentCall?.individualCall.localId else {
guard self.callService.currentCall == nil || call.localId == self.callService.currentCall?.localId else {
owsFailDebug("localId does not match current call")
return
}
@ -171,7 +171,7 @@ class NonCallKitCallUIAdaptee: NSObject, CallUIAdaptee {
func setIsMuted(call: SignalCall, isMuted: Bool) {
AssertIsOnMainThread()
guard call.individualCall.localId == self.callService.currentCall?.individualCall.localId else {
guard call.localId == self.callService.currentCall?.localId else {
owsFailDebug("localId does not match current call")
return
}
@ -182,7 +182,7 @@ class NonCallKitCallUIAdaptee: NSObject, CallUIAdaptee {
func setHasLocalVideo(call: SignalCall, hasLocalVideo: Bool) {
AssertIsOnMainThread()
guard call.individualCall.localId == self.callService.currentCall?.individualCall.localId else {
guard call.localId == self.callService.currentCall?.localId else {
owsFailDebug("localId does not match current call")
return
}

View File

@ -92,7 +92,6 @@ class DebugUINotifications: DebugUIPage {
func delayedNotificationDispatchWithFakeCall(thread: TSContactThread, callBlock: @escaping (IndividualCall) -> Void) -> Guarantee<Void> {
let call = SignalCall.incomingIndividualCall(
localId: UUID(),
thread: thread,
sentAtTimestamp: Date.ows_millisecondTimestamp(),
offerMediaType: .audio