Require screen unlock before starting calls

This commit is contained in:
Elaine 2026-06-01 11:44:33 -04:00 committed by GitHub
parent 2259a151d9
commit 8663b50018
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 51 additions and 4 deletions

View File

@ -1768,7 +1768,15 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
return false
}
let isVideo = isVideoCall(intent)
appReadiness.runNowOrWhenAppDidBecomeReadySync {
Task { @MainActor [appReadiness, screenLockUI] in
do {
try await appReadiness.waitForAppReady()
try await screenLockUI.waitForScreenUnlockThrowingPrevious()
} catch {
return
}
let tsAccountManager = DependenciesBridge.shared.tsAccountManager
guard tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegistered else {
Logger.warn("Ignoring user activity; not registered.")
@ -1799,6 +1807,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
}
callService.initiateCall(to: callTarget, isVideo: isVideo)
}
return true
}
@ -1928,7 +1937,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
withCompletionHandler completionHandler: @escaping () -> Void,
) {
let startDate = MonotonicDate()
Task { @MainActor [appReadiness] () -> Void in
Task { @MainActor [appReadiness, screenLockUI] () -> Void in
defer { completionHandler() }
try await self.appReadiness.waitForAppReady()
@ -1942,7 +1951,11 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
let elapsedDuration = (MonotonicDate() - startDate).seconds
try await withCooperativeTimeout(seconds: 27 - elapsedDuration) {
// Do the actual thing we care about.
try await NotificationActionHandler.handleNotificationResponse(response, appReadiness: appReadiness)
try await NotificationActionHandler.handleNotificationResponse(
response,
appReadiness: appReadiness,
screenLockUI: screenLockUI,
)
// Then wait for any enqueued messages (e.g., read receipts) to be sent.
try await backgroundMessageFetcher.waitForFetchingProcessingAndSideEffects()

View File

@ -15,6 +15,7 @@ public class NotificationActionHandler {
class func handleNotificationResponse(
_ response: UNNotificationResponse,
appReadiness: AppReadinessSetter,
screenLockUI: ScreenLockUI,
) async throws {
owsAssertDebug(appReadiness.isAppReady)
@ -63,6 +64,7 @@ public class NotificationActionHandler {
}
switch responseAction {
case .callBack:
try await screenLockUI.waitForScreenUnlockThrowingPrevious()
try await self.callBack(userInfo: userInfo)
case .markAsRead:
try await markAsRead(userInfo: userInfo)

View File

@ -65,7 +65,39 @@ class ScreenLockUI {
// * The user is also locked out if they spend more than
// "timeout" seconds outside the app. When the user leaves
// the app, a "countdown" begins.
private var isScreenLockLocked: Bool = false
private var isScreenLockLocked: Bool = false {
didSet {
AssertIsOnMainThread()
guard !isScreenLockLocked else { return }
if let pending = pendingScreenUnlockContinuation {
pendingScreenUnlockContinuation = nil
pending.resume()
}
}
}
struct ScreenUnlockActionReplacedError: Error {}
private var pendingScreenUnlockContinuation: CheckedContinuation<Void, Error>?
@MainActor
func waitForScreenUnlockThrowingPrevious() async throws {
AssertIsOnMainThread()
tryToActivateScreenLockBasedOnCountdown()
ensureUI()
if !isScreenLockLocked {
return
}
if let existing = pendingScreenUnlockContinuation {
pendingScreenUnlockContinuation = nil
existing.resume(throwing: ScreenUnlockActionReplacedError())
}
try await withCheckedThrowingContinuation { continuation in
self.pendingScreenUnlockContinuation = continuation
}
}
// The "countdown" until screen lock takes effect.
private var screenLockCountdownTimestamp: UInt64?