Display the system-calling UI for your app’s VoIP services and coordinate your calling services with other apps and the system using CallKit.

Posts under CallKit tag

200 Posts

Post

Replies

Boosts

Views

Activity

CallKit and PushToTalk related changes in iOS 26
Starting in iOS 26, two notable changes have been made to CallKit, LiveCommunicationKit, and the PushToTalk framework: As a diagnostic aid, we're introducing new dialogs to warn apps of voip push related issue, for example when they fail to report a call or when when voip push delivery stops. The specific details of that behavior are still being determined and are likely to change over time, however, the critical point here is that these alerts are only intended to help developers debug and improve their app. Because of that, they're specifically tied to development and TestFlight signed builds, so the alert dialogs will not appear for customers running app store builds. The existing termination/crashes will still occur, but the new warning alerts will not appear. As PushToTalk developers have previously been warned, the last unrestricted PushKit entitlement ("com.apple.developer.pushkit.unrestricted-voip.ptt") has been disabled in the iOS 26 SDK. ALL apps that link against the iOS 26 SDK which receive a voip push through PushKit and which fail to report a call to CallKit will be now be terminated by the system, as the API contract has long specified. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
0
0
2.2k
Jun ’25
New PushKit delegate in iOS 26.4
Starting in iOS 26.4, PushKit has introduced a new "didReceiveIncomingVoIPPushWithPayload" delegate, making it explicit whether or not an app is required to report a call for any given push. The new delegate passes in a PKVoIPPushMetadata object which includes a "mustReport" property. We have not documented the exact criteria that will cause a mustReport to return false, but those criteria currently include: The app being in the foreground at the point the push is received. The app being on an active call at the point the push is received. The system determines that delivery delays have made the call old enough that it may no longer be viable. When mustReport is false, apps should call the PushKit completion handler (as they previously have) but are otherwise not required to take any other action. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
0
0
1.2k
Feb ’26
CallKit Call Directory database corruption (sqlite Code 11)
Hi everyone, I’ve filed a Feedback report (FB20986470) for a serious issue affecting the Call Directory database when add phone numbers for call blocking. When adding blocking numbers to a Call Directory extension, the system’s CallKit database (/private/var/mobile/Library/CallDirectory/CallDirectory.db) becomes corrupted. The reload call (reloadExtensionWithIdentifier) fails with error code 11 when the system tries to insert blocking entries, and the Console app on macOS shows the following errors: database corruption page 2265525 of /private/var/mobile/Library/CallDirectory/CallDirectory.db at line 81343 of [f0ca7bba1c] database corruption at line 79387 of [f0ca7bba1c] Error Domain=com.apple.callkit.database.sqlite Code=11 "sqlite3_step for query 'INSERT INTO PhoneNumberBlockingEntry (extension_id, phone_number_id) VALUES (?, (SELECT id FROM PhoneNumber WHERE (number = ?))), (?, (SELECT id FROM PhoneNumber WHERE (number = ?))),...)'" After this happens, CallKit becomes fully corrupted on the device and no further numbers can be added, even after: Disabling and re-enabling the extension Restarting the device (either force or soft restart) Reinstalling the app Waiting for a couple of minutes after this issue happens (that CallKit could possibly self-recovered) I also tested other call-blocking apps, and they all fail with the same error. The only thing that recovers the system is a full “Reset All Settings.” This issue has been reported by many users of my app, across multiple iOS versions and devices. Similar related issue reported by another developer: https://developer.apple.com/forums/thread/806129 Steps to Reproduce: Enable the Call Directory extension from a call-blocking app. Add and reload blocking numbers (a few thousand entries). Perform multiple reloads between additions. Check the Console, the corruption errors appear. From this point, all insert attempts fail system-wide. Expected Result: Entries should be inserted successfully, or the system should self-recover without persistent corruption. Actual Result: sqlite3_step fails with Code=11, and the Call Directory database remains corrupted until the user resets all settings. Additional Notes: All numbers are sorted and deduplicated before insertion. Happens intermittently after multiple reloads. The system log always shows internal database failure. Environment: Device: iPhone 16 Plus iOS 18.2 Beta (23C5027f) Xcode 16.1 (17B55) Attachments (included in Feedback FB20986470): sysdiagnose captured immediately after the failure (with Phone app General Profile) It seems like a system-level corruption affecting all Call Directory extensions once it occurs.
15
4
2.3k
1d
Mac Catalyst: outgoing CallKit call opens FaceTime and turns on the camera
We're bringing our CallKit-based VoIP app to the Mac with Mac Catalyst. Incoming calls work fine. For outgoing calls we request a CXStartCallAction (audio only, isVideo = false), the provider fulfills it and the call connects. But at the moment the call starts dialing, macOS launches FaceTime.app, which turns on the camera preview and shows its own call screen for our call ("no video"). When the call ends, FaceTime stays open and the camera stays on until FaceTime is quit manually. The system log shows callservicesd deciding to launch the in-call application for our call: callservicesd _shouldLaunchInCallApplicationForCall: 1 callservicesd Opening URL: <private> for call <private> CoreServicesUIAgent LAUNCH: ... com.apple.FaceTime starting stopped process.Reported as FB25284357 (macOS 27.0.1, Xcode 27.1). Is this expected for third-party CallKit providers on macOS? Is there a supported way to keep the call in our own app without dropping CallKit for outgoing calls?
1
0
51
2d
App "In Review" since September 24 (4 weeks), two support cases with no update
Our iOS app has been sitting in "In Review" for four weeks and we have not been able to get a status update through any channel, so I'm posting here in case someone from App Review can take a look. App: Epocra, iOS, version 1.0, build 268 Apple ID: 6813697639 Status: In Review since September 24, as Developer Support confirmed on October 1 Timeline Sept 22: build 267 rejected under 2.1(a), a launch crash on iPad Air running iPadOS 27. Fixed the same day and resubmitted as build 268. Sept 22: a reviewer signed in to the demo account that evening. No activity since. Sept 28: opened a status request through Contact Us, case 102979044954. On Oct 1 Developer Support replied that the review was "outside of our normal timeframe" and that the review team had been notified. Nothing since. Oct 5: second status request, case 102986888342. Acknowledgement only. Oct 9: replied in the App Review message thread for the submission citing both cases. No response. We have not changed anything on the submission while it is in review so we don't reset the queue. The app is a business phone app (CallKit and PushKit VoIP with server-side call recording and a consent screen on first launch). The review notes include a demo account, a walkthrough video, and a phone number the reviewer can call to test inbound calls. Is there anything else we should be doing to get this looked at, or can someone from App Review check on it? Happy to provide anything that would help.
1
1
188
2d
CallKit VoIP call on the receiver: the side (lock) button only locks the screen, no CXEndCallAction is delivered
Device and versions iPhone 15, iOS 27.0.1 App: Hush, a private messenger. Capacitor 8.5.2 iOS app; the UI is a web page in a WKWebView. Call signalling runs in the page; call audio runs in a native Swift Capacitor plugin on stasel/WebRTC 154.0.0, integrated with CallKit. Built on Codemagic with the latest Xcode, distributed through TestFlight. UIBackgroundModes: audio, voip. No PushKit yet: calls are placed and answered in the app's own screen while it is in the foreground. Setup RTCAudioSession manual audio (useManualAudio = true). isAudioEnabled is set only after ICE connects AND provider(_:didActivate:) is called (a 3-second fallback exists but never fired in these tests). We call RTCAudioSession.audioSessionDidActivate / audioSessionDidDeactivate from the provider delegate. Session: playAndRecord, mode voiceChat, options allowBluetoothHFP, no defaultToSpeaker. overrideOutputAudioPort is only called when the user picks Speaker (never in the failing tests). One CXProvider, created lazily, delegate on the main queue. Configuration: supportsVideo false (also tested true), maximumCallGroups 1, maximumCallsPerCallGroup 1, supportedHandleTypes [.generic], includesCallsInRecents false (also tested true). Outgoing: CXStartCallAction is requested via CXCallController when ICE first connects (not at dial time; the page plays its own ringback until then), handle generic, value "Hush". In perform(CXStartCallAction) we configure the audio session (no activation), reportCall(with:updated:), fulfil, then reportOutgoingCall(startedConnectingAt:) and (connectedAt:). Answering side: reportNewIncomingCall, then an immediate CXAnswerCallAction (the user already accepted in the app's screen). Mute: CXSetMutedCallAction. In-app End reported the call with reportCall(with:endedAt:reason: .remoteEnded) in all tests below (we are changing this to a CXEndCallAction request; not yet tested). Proximity: isProximityMonitoringEnabled = true from dialling while on the receiver. The screen does go dark at the ear. Also tested with our proximity monitoring off. The problem With a Hush call live, route Receiver, CallKit holding the call (the system call UI shows it), didActivate delivered exactly once, our audio running inside that activation, proximity on and the screen dark at the ear: pressing the side button only locks the screen. No CXEndCallAction arrives and the call continues. In the Phone app on the same iPhone the side button ends the call at the ear. Snapchat calls on this iPhone end on the side button while Snapchat's call screen is open. What works: End on the system lock-screen call UI delivers a CXEndCallAction and we end the call. Mute from the system UI arrives as CXSetMutedCallAction. So provider delegate delivery works. What we tried, in order (each tested on device, with a readout of the plugin's state after the call) First CallKit build: side button did nothing; lock-screen End worked. Readout: "CallKit off, its audio off (0x), fallback no, route speaker, proximity on". Cause: CXStartCallAction was refused (missing voip background mode) and the error swallowed. Fixed: voip added; on CXErrorCodeRequestTransactionError.unknownCallProvider we invalidate and recreate the provider and retry once. Next build: CallKit held the call, didActivate once, route Receiver. Side button still did nothing, no CXEndCallAction. Our route log showed two route changes caused by our own overrideOutputAudioPort(.none) on every activation and route change. Removed: no override unless Speaker is selected. Result: no change. Diagnostic switches, tested in combinations: our proximity monitoring on/off; supportsVideo false/true; includesCallsInRecents false/true; callee now reported with reportNewIncomingCall + CXAnswerCallAction (previously both sides used CXStartCallAction). Result: the side button ended the call EXACTLY ONCE: the first call after the provider was recreated (changing supportsVideo makes us invalidate() and create a new CXProvider). Every later call with the same configuration failed. Readout for the failures: "CallKit on, its audio on (1x), fallback no, route Receiver, proximity on", screen dark at the ear. Following thread 837211 (creating a provider implicitly pushes the audio session ID to callservicesd, which can keep a stale one; set the configuration before reporting each call): we now assign provider.configuration = a fresh CXProviderConfiguration at call start and again immediately before each CXStartCallAction request / reportNewIncomingCall. We also added a switch that recreates the CXProvider for every call. With the re-push alone: no end action. With a fresh provider every call: no end action either. Readout each time: "provider calls 1, config re-pushed yes, CallKit on, its audio on (1x), route Receiver, proximity on". The single success in step 3 has not been reproduced. Not tried on purpose: detecting the lock ourselves (protectedDataWillBecomeUnavailable arrives about 10 seconds late and needs a passcode; a 2017 thread says Home and Lock cannot be told apart); reporting the CallKit call at dial time instead of ICE connect; PushKit. Threads we relied on 819363 (April 2026): the lock button hangs up a CallKit call handled directly by the device (not through a headset), delivered as the provider's end action. 837211 (August 2026): stale audio session ID in callservicesd after provider creation; set the configuration before reporting a call. How we differ from apps where it works WKWebView: WebKit's GPU process holds a second AVAudioSession in our app's name. During the call the page captures no mic (the plugin owns it); before connect the page plays a Web Audio ringback (Ambient category). The CallKit call starts at ICE connect, not at dial time. In-app End reported as .remoteEnded rather than requested as a CXEndCallAction. The callee's immediate CXAnswerCallAction after reportNewIncomingCall. Questions Which conditions must hold for iOS to treat the side button as "end call" for a CallKit call, and which is our app failing? Is there a log subsystem or category (callservicesd, TelephonyUtilities) we can read in a sysdiagnose to see why the press is handled as lock? Could WebKit's GPU-process audio session in the same app confuse CallKit about which session carries the call? Would reporting the call at dial time, before any audio, change the outcome? Can ending the in-app call with reportCall(.remoteEnded) instead of a CXEndCallAction leave state in callservicesd that affects the NEXT call? That would fit "works once after a fresh provider, never again". We have no Mac. Is a sysdiagnose captured on the iPhone right after a failing press enough to diagnose this? If you need a project, we can provide the plugin's Swift source (one file) and the Capacitor app project that Codemagic builds.
0
0
41
4d
CallKit never calls didActivateAudioSession because callservicesd fails to create the audio session (SessionID 0x0) on iOS 24A446
Summary On iOS build 24A446, an incoming CallKit VoIP call is reported and answered, but the system never creates or activates the CallKit audio session, so CXProviderDelegate provider:didActivateAudioSession: is never called. Both directions of call audio stay silent. The failure is inside callservicesd / audiomxd, before the app starts its audio unit. Once it starts, later calls from the same processes keep failing until the app process is killed. App and device Bundle ID: us.zoom.videomeetings OS build: 24A446 (iPhone) Log: sysdiagnose_2026.10.16_11-15-45-0700_iPhone-OS_iPhone_24A446 Sample call: 2026-10-15 13:29:06–13:29:22 PDT Processes in that window: Zoom PID 816, callservicesd PID 2474, audiomxd PID 115 How the user hits it The app is not in the foreground. A VoIP push wakes it and we call reportNewIncomingCallWithUUID:update:completion:. The user answers from the system incoming-call UI (phone locked or unlocked). The ringtone plays. After answer there is no call audio. The same failure then happens on later calls, including a call started from inside the app, until the Zoom process is killed. Signing out or rebooting only clears it temporarily. We cannot reproduce it in our lab. It became much more frequent after devices moved to this OS. What the app does We configure one CXProvider (PlayAndRecord is applied when the system activates the session). We fulfill CXAnswerCallAction when the user answers. We start the voice audio unit only from provider:didActivateAudioSession:. We do not call AVAudioSession setActive: during this answered call. Our log line "ZMCallKitManager::didActivateAudioSession" is not present for this call. System log for the sample call 13:29:06 — incoming call reported Zoom log: Provider was asked to report a new incoming call At that moment Zoom's existing primary session is sid:0x7304f, Zoom(816), 'prim', and the app is BackgroundRunning. callservicesd then fails while creating the CallKit session: audiomxd AVAudioSessionXPCServer.mm:231 -[AVAudioSessionRemoteXPCClient createProxySession:reply:] failed due to session lookup failure for SessionID 0x0 callservicesd AVAudioSession_iOS.mm:643 Creating proxy session failed, session ID = 0x0, NSOSStatusErrorDomain -50, "Session lookup failed" audiomxd ServerSessionManager.mm:192 Sibling session creation failed. Source sessionID: 0x0. SessionID is not valid. Source PID: 2474 audiomxd AVAudioSessionXPCServer.mm:1287 Session creation failed callservicesd SessionCore_Create.mm:92 AudioSession creation failed, NSOSStatusErrorDomain 2003329396, "Session creation failed in server" callservicesd Audio session not found for call. Returning nil The ringtone still plays. That audio is callservicesd's own session sid:0x732fa, category Ringtone/Default, which activates at 13:29:06.650. It is not the call session. 13:29:15 — user answers callservicesd: Performing answer request / Perform answer call callservicesd: No provider returned for descriptor callservicesd: Audio session not found for call. Returning nil callservicesd: Answer call action fulfilled callservicesd: Error retrieving AVAudioSession provider with ID 0 Sibling session creation fails again with Source sessionID 0x0, Source PID 2474. The ringtone session is stopped. From 13:29:15 to 13:29:22 there is no "action":"activate" for a CallKit call audio session, and no provider:didActivateAudioSession: notification to Zoom. Zoom's primary session 0x7304f is still inactive. Its category is updated to PlayAndRecord / VoiceChat, but it is not activated while this call is up. 13:29:22 — call ends Provider was asked to report that call ended with reason 2 callservicesd: Setting disconnected reason to remote hangup because ended reason is 2 sid:0x732fa callservicesd going inactive The call lasted about 7 seconds with no call audio session ever created. 13:29:33 — following call, same stuck state About 11 seconds later a CXStartCallAction is fulfilled. Zoom's own session then activates: sid:0x7304f, Zoom(816), 'prim' PlayAndRecord_WithBluetooth / VoiceChat, NonMixable, going active callservicesd still cannot build its session: "No existing proxy AVAudioSession interruption provider for ID 0, creating a new one" Session creation failed in server Error retrieving AVAudioSession provider with ID 0 Audio session not found for call So an app-side setActive: after the failed call does not repair the CallKit provider. The system session id remains 0x0. How often it happens in this sysdiagnose Filtering the archive for the hard failure (not the generic "Audio session not found" line, which also appears on earlier days): "Sibling session creation failed. Source sessionID: 0x0": 93 hits, grouped into 57 bursts First burst: 2026-10-15 09:52:11 PDT Last burst: 2026-10-16 11:14:30 PDT (about a minute before this sysdiagnose was taken) "Error retrieving AVAudioSession provider with ID 0": 34 hits "Session creation failed in server": 93 hits Every one of these sibling-session failures is Source PID 2474. callservicesd stays PID 2474 and audiomxd stays PID 115 across the whole window, including overnight. The bad session id is stuck in those daemons, not in one Zoom call object. There is no log line in this archive showing callservicesd successfully activating a provider audio session for these calls. Request Please confirm this is the known CallKit failure where didActivateAudioSession is not delivered because callservicesd cannot create the audio session (Session lookup failed / Session creation failed in server, session ID 0x0). Related public reports: Feedback FB19429215, "CallKit does not activate audio session after iOS 18.4.1", and the iOS 27 thread "iOS 27 CallKit didActivateAudioSession". DTS previously advised apps not to call setActive: themselves, because the CallKit session has higher priority and an app activation can fail or disturb system state. This log matches that: the session is never created, so there is nothing for the system to activate. Please also advise which of these is safe on 24A446 when provider:didActivateAudioSession: does not arrive: Call CXProvider setConfiguration: again (same configuration) before every reportNewIncomingCallWithUUID:update:completion:. On a timeout, fail the unanswered CXAnswerCallAction so the CallKit state machine resets, without invalidating or recreating the CXProvider. Anything else that clears the stuck session ID 0x0 inside callservicesd without a device reboot. I can provide another sysdiagnose if you need a logging profile installed before the next reproduction.
3
0
997
4d
watchOS CallKit calls: no DTMF keypad, no audio-route picker, no Recents — are these system-gated for third-party providers?
Hi all, I'm building a watchOS VoIP app that places and receives calls through CallKit, with call audio staying on the watch (not routed to the paired iPhone). Calls connect and audio works. But three parts of the system in-call UI that the native Phone app shows never appear for my app, and I'd like to confirm whether this is expected or a misconfiguration on my side. Environment watchOS 26.0, Apple Watch 11 (reproduced on a physical device) Xcode 27.1 Companion watchOS app, calls driven by CXProvider / CXCallController What's missing during an active call No DTMF keypad. The user can't open a keypad from the system call screen, so in-call DTMF (e.g. navigating an IVR) is impossible. No audio-route picker. No control to switch output route (e.g. speaker vs. the default route). No entry in Recents. Completed calls don't appear in the watch's call history. The system call UI is full-screen and in front, so I also can't present my own keypad or route control on top of it. What I've already tried (all public API) // Reported call callUpdate.supportsDTMF = true // Provider configuration config.includesCallsInRecents = true config.supportedHandleTypes = [.phoneNumber] config.maximumCallGroups = 1 // Audio session: route changes programmatically, but adds no user-facing picker try session.setCategory(.playAndRecord, mode: .voiceChat) try session.overrideOutputAudioPort(.speaker) // Never invoked — no keypad exists to generate the action func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) { ... } None of these make the keypad, the route picker, or a Recents entry appear. The behavior is identical regardless of these values, which makes me suspect these controls are exposed only for the native telephony/relay call path, not for third-party CXProvider calls on the watch. Questions Are the in-call DTMF keypad, audio-route picker, and Recents entry available to third-party CXProvider calls on standalone watchOS at all, or are they reserved for the system (relayed cellular / FaceTime) call UI? If not, is there a supported way to present my own keypad or route control during an active CallKit call, given the system call UI is in front? Thanks!
1
0
640
1w
LiveCommunicationKit: Handle.displayName is never shown — the call UI and Recents show Handle.value
On iOS [27.x (build)], LiveCommunicationKit shows Handle.value on every system surface and ignores Handle.displayName. That forces a choice that CallKit doesn't: Put a stable account id in value (as WWDC26 session 226 recommends, so Recents redial can identify the person), and the raw id appears on the incoming call screen, the banner and in Recents. Put the person's name in value so the UI reads correctly, and a redial from Recents hands back only the name, which can't reliably identify anyone. Minimal reproduction let configuration = ConversationManager.Configuration( ringtoneName: nil, iconTemplateImageData: nil, maximumConversationGroups: 1, maximumConversationsPerConversationGroup: 1, includesConversationInRecents: true, supportsVideo: false, supportedHandleTypes: [.generic, .phoneNumber, .emailAddress] ) let manager = ConversationManager(configuration: configuration) let remote = Handle(type: .generic, value: "u-1234", displayName: "Jane Appleseed") try await manager.reportNewIncomingConversation( uuid: UUID(), update: Conversation.Update(members: [remote], capabilities: []) ) Expected: the incoming call UI and the Recents row show "Jane Appleseed". Session 226 says displayName is "what the system shows when it can't match the handle to a contact". Tapping the Recents row delivers an INStartCallIntent whose contact personHandle.value is u-1234. Actual: the full-screen ring, the foreground banner and the Recents row all show u-1234. Tapping the row does deliver INStartCallIntent with personHandle.value == "u-1234", so redial works, but the user never sees the name. What we tried, all with the same result (the value is shown): Handle.Kind set to .generic, .phoneNumber or .emailAddress, with every kind listed in supportedHandleTypes Conversation.Update(localMember:) set to the local user's handle activeRemoteMembers set to the remote handle, and localMember plus activeRemoteMembers together Donating an INInteraction (an INStartCallIntent whose INPerson has personHandle set to the id, displayName set to the name and customIdentifier set to the id) when the conversation ends. The donation succeeds, but the Recents row and the redial payload don't change. CallKit comparison, same device: CXCallUpdate.remoteHandle = CXHandle(type: .generic, value: "u-1234") with localizedCallerName = "Jane Appleseed" shows the name on the ring and in Recents. A redial from Recents delivers personHandle.value == "u-1234". That's the behaviour we expected from LiveCommunicationKit. Questions: Is Handle.displayName meant to be shown when the handle doesn't match a contact? If so, is there a configuration step we're missing? If this is a bug, is there a supported way with LiveCommunicationKit to show a name while keeping a stable identifier for Recents redial? Filed as FB24933340. Device: iPhone 15 pro, iOS [27.0.1].
4
0
450
2w
Issues with AVRoutePickerView channel switching
We are developing a voice call application that uses AVRoutePickerView, allowing users to switch between an iPhone, a speaker, and Bluetooth earphones. However, we have encountered an intermittent issue: when switching from the speaker to Bluetooth earphones, the earphones remain in a loading state, and the audio channel subsequently switches back to the speaker. How can we resolve this issue? Here is the sample code: let session = AVAudioSession.sharedInstance() do { try session.setCategory(.playAndRecord, mode: .default, options: [.allowBluetooth]) try session.overrideOutputAudioPort(isBluetoothConnected ? .none : .speaker) try session.setPreferredSampleRate(48000) try session.setPreferredIOBufferDuration(0.02) try session.setActive(true, options: []) INFO(" >>> start: hasBluetooth=\(isBluetoothConnected), inputs: \(session.currentRoute.inputs.map { $0.portType }) outputs: \(session.currentRoute.outputs.map { $0.portType })") } catch { ERROR("(error.localizedDescription)") }
5
0
2.0k
2w
Can CXCallObserver detect missed cellular calls while an iOS app is suspended?
Hello, I am developing an iPhone application to help users avoid missing important phone calls. The intended behavior is: A user receives a regular cellular call through the built-in iPhone Phone app. The user does not answer the call. Our application automatically detects the missed call. The application schedules repeated local notifications until the user acknowledges the missed call. The critical requirement is that detection must work while our application is in the background, without the user reopening it. Implementation We currently use CXCallObserver to observe cellular call events. When an incoming call ends without being connected, we classify it as a missed call and schedule notifications using UNUserNotificationCenter. Test environment Device: iPhone 17 iOS: 26.7.1 Distribution target: Standard App Store, Japan Testing: Physical device without an attached Xcode debugger Observed behavior Scenario A: Our application is visible immediately before the iPhone is locked. Missed calls have been detected and notifications scheduled after more than 30 to 60 minutes of device lock. Scenario B: Our application is moved to the background before the iPhone is locked, for example by returning to the Home Screen or opening Safari. Missed calls are not detected promptly, even after only a short period in the background. When the user subsequently opens our application, CXCallObserver callbacks may arrive and the earlier missed call is then detected. This defeats the purpose of the application because the user must reopen it to receive alerts. Questions Is CXCallObserver expected to deliver callbacks while its application is suspended, or only when the process is executing? Is there any supported public iOS API, extension, or background execution mechanism that allows a third-party application to detect missed calls from the built-in Phone app while the application is suspended or terminated? Can a regular cellular missed-call event wake or relaunch a third-party application? If CXCallObserver cannot support this use case, is there another Apple-supported solution available to ordinary App Store applications distributed in Japan? We are looking for an approach that does not require external hardware, carrier integration, private APIs, or unsupported background execution techniques. If this use case is not supported by the public iOS SDK, confirmation of that limitation would be very helpful. Thank you for your guidance.
1
0
235
2w
Can an AAC app start synthesized speech in an auto-answered cellular call while the iPhone is locked?
I am testing a native Swift iPhone app that adds synthesized speech to an existing cellular call using: AVAudioApplication microphone injection permission AVAudioSession.setPreferredMicrophoneInjectionMode(.spokenAudio) AVSpeechSynthesizer CXCallObserver The audio background mode Device: iPhone 16 Pro Carrier: Vodafone Romania iOS version: [enter exact version] Both the system “Add Audio in Calls” setting and the app permission are enabled. Confirmed behavior: With the app in the foreground, the iPhone’s accessibility Auto-Answer Calls feature answers the call, and the remote caller hears the synthesized greeting. Problem: With the iPhone locked, the phone answers automatically, but the greeting does not start. Logs show ringing, connected, and ended events being processed together when the app returns to the foreground. This suggests the app was suspended. The app does not record the call or play continuous audio while waiting. Questions: Is there a supported public API that lets this app wake or execute when a cellular call connects while the iPhone is locked? Can microphone injection support this use case without keeping the app in the foreground? If supported, what audio-session configuration and background execution mechanism should be used? If unsupported, can you confirm this limitation? I can provide a minimal sample project and diagnostic logs.
3
0
1.2k
3w
Live Caller ID Lookup: 1-second blocking timeout is often exceeded on real-world networks
We ship a Live Caller ID Lookup extension (PIR-based) for spam call blocking. It works, and our PIR server is fast. But in practice, whether a call gets blocked depends on the quality of the user's internet connection at the moment the call arrives. The system waits only about 1 second for the blocking response. On a fast, stable connection it arrives in time. On an average or unstable connection it often doesn't, and the spam call rings through. So under the current platform limits we cannot guarantee blocking for every call. How we measured For each call we read the device syslog (CommCenter, CallDirectory, ciphermld, callservicesd) and our server logs. The extension cache was reset before each call, so every call triggered a real network lookup. All times are in ms and measured from addNewIncomingCall. Server-side processing of the PIR query was consistently 51–61 ms. The variance is almost entirely network transfer between the device and the server (or relay): In call D, HTTP/2 metrics show the ~28 KB request was handed to the network stack immediately (outbound_duration_ms=0), but response headers arrived only after 2216 ms. In call E, the device waited ~660 ms between finishing the upload to the relay and receiving the first byte of the response. Connection setup on a new connection cost 176–271 ms (DNS + TCP + TLS, or a QUIC handshake to the relay). Before the first byte was sent, the system spent another 54–225 ms after the call arrived. In the failing cases the syslog shows: CallDirectory: not all blocking fetches returned within 1 second(s) callservicesd: shouldBlock: NO shouldSilence NO The block response (shouldBlock=1) then arrives 100–1500 ms too late, and the call keeps ringing. What works: repeat calls After the first lookup the result is cached on the device. A repeat call from the same number is silenced without contacting the server, whatever the connection speed. In our logs, follow-up calls from the same number were silenced within ~65 ms of addNewIncomingCall, with no network request. So a user may get the first spam call from a number but not the next ones. The first call, though, is exactly the one users complain about. The problem with the 1-second budget Each blocking lookup has to: Send a PIR query Receive a response of ~22–25 KB. Often open a new TLS/QUIC connection through the OHTTP relay. All of this has to fit into about 1 second, together with the system's own overhead before the request is sent. On a good connection that takes about 250–650 ms. On an average mobile or congested Wi-Fi connection it easily goes past 1 second, and nothing the developer can optimize on the server helps. Our server already responds in about 50 ms.
1
1
466
3w
Clarification on iOS restrictions for call recording access, SMS/iMessage access and background voice activation
I’m looking for clarification on what iOS currently allows third-party apps to do in these areas: Siri integration and background voice activation: Can an iOS app implement a custom voice assistant that responds to a wake phrase such as “Hey Nowa” and performs app tasks through voice commands? Could it listen while the app is terminated or the iPhone is locked, similar to Siri? Call recordings: Is there a supported way for an iOS app to access recordings of phone calls made on the user’s iPhone and make them available within the app? I couldn’t find documentation for an API that provides access to these recordings. SMS access: Is there a supported way for an iOS app to access and fetch all SMS and iMessage conversations stored in the user’s Messages app, so they can be viewed within our app? As far as I understand, iOS may not allow these capabilities for third-party apps, but I’d appreciate clarification. If any are supported, could you please point me to the relevant Apple documentation?
3
0
839
3w
Inquiry regarding issues with the CXSetTranslatingCallAction action
We are currently verifying the functionality of CXSetTranslatingCallAction. We tested its implementation in a VoIP app—using Apple's Translate app by default—and confirmed that it works correctly in some instances. However, we have encountered an issue where, under certain conditions, the real-time translation feature becomes unavailable until the device is rebooted. The issue manifests as follows: When the real-time translation feature is enabled in CallKit, a beep sounds accompanied by the announcement "Starting translation," but the translation fails to proceed and terminates immediately. This behavior persists upon repeated attempts. Restarting the app does not resolve the issue; once this occurs, the feature remains unusable until the device itself is rebooted. Since the feature works normally after a device reboot, it does not appear to be a fundamental implementation error; I would like to investigate the root cause of this behavior. What information or steps are required to investigate this? I conducted the test using an iPhone 16 Pro running OS version 26.5. It is the same for both CallKit and LCK.
4
0
559
3w
iOS 27: tel: links with call-forwarding codes now blocked as "Malicious Link Blocked" (FB24843805)
Starting in iOS 27, opening a tel: URL that contains a call-forwarding MMI code from an app shows a system alert and dials nothing: Malicious Link Blocked: This link was blocked because it contains malware that will forward all of your incoming messages and calls to 1 (XXX) XXX-XXXX. Scammers often provide malicious links that look legitimate via email, text, or chat. On iOS 26 the same call showed the normal call confirmation prompt and the carrier applied the forwarding. Repro (in response to a button tap): UIApplication.shared.open(URL(string: "tel:*21*XXXXXXXXXXX%23")!) Typing *21*XXXXXXXXXXX# into the Phone app's keypad by hand still works on iOS 27, so the capability is still there; only the in-app handoff is blocked. This breaks setup for call-screening and visual-voicemail apps whose onboarding depends on carrier forwarding (*21*, *61*, *67*, *71*, *72). It also blocks the disable codes (##21#, ##004#, *73), so users can't turn forwarding off from inside the app, which works against the user's own safety. The anti-hijack intent makes sense for links arriving from Messages, Mail or Safari. For a user tap inside an installed App Store app, a confirmation sheet ("Forward calls to ...? Allow") seems like the right balance, and disable codes should always be allowed. Filed as FB24843805. Questions: Is this block meant to apply to links opened by an installed app in response to a user tap? Is there a supported API, entitlement or URL form to hand a forwarding code to the Phone app with user confirmation? Our current workaround is to copy the code to the clipboard and ask the user to paste it into the keypad, which is a real drop-off point for our (mostly older) users. If you're affected too, please file your own feedback and reference FB24843805.
3
1
828
4w
Siri announces GenericHandle Value instead of custom caller Name
Hello fellow developers, I’ve been working with the CallKit framework in iOS, specifically handling incoming calls. One issue I’ve encountered is that Siri when "read caller name" is enabled announces the caller name/surname set via localizedCallerName and then reads the generic handle value (usually alphanumeric) too! Has anyone encountered a similar situation or if there’s a solution to prioritize the localizedCallerName over the generic handle value without using CXHandleType.emailAddress? Alternatively, any insights or workarounds you know would be greatly appreciated. TLDR: even when I correctly configure the localizedCallerName property, Siri persists in reading the CXHandleType.generic. The original Implementation with CXHandleType.generic: The issue arises when using CXHandleType.generic for alphanumeric IDs (or even URLs as stated by documentation https://developer.apple.com/documentation/callkit/cxhandle). Despite correctly setting the localizedCallerName, Siri continues to announce the generic handle value. Expected Behavior: Siri should read only the localizedCallerName when set and ignore the generic handle value when announcing incoming calls. Workaround: Currently, the only workaround is to use CXHandleType.emailAddress for alphanumeric IDs. However, this is not ideal since it repurposes an email-related handle type for a different purpose. Steps to Reproduce: Create a CallKit app that handles incoming calls (example app from documentation can be used too). On incoming call create CXCallUpdate object Create a CXHandle with CXHandleType.generic and an alphanumeric value (e.g., “ABC123”). Pass the CXHandle to the CXCallUpdate objects' remoteHandle. Set the localizedCallerName property of the CXCallUpdate object with a custom caller name/surname. Report the call with reportNewIncomingCallWithUUID Observe that Siri reads both the localizedCallerName and the generic handle value during call announcements. While we are here a Feature Request: Developers should be able to provide a user-friendly caller name without resorting to workarounds like using CXHandleType.emailAddress. I kindly request that Apple consider enhancing Siri’s behavior in the following ways: Allow developers to suppress the reading of generic handle values while still using the correct handle type. Introduce additional type options for call announcements that don't read the generic value. Both of the above. Thank you for your help! 🙌
3
0
1.4k
Sep ’26
Dual SIM call uses wrong default line
Hello, I am investigating call behaviour on a dual SIM iPhone. Observed behavior: A specific line is selected in Settings > Cellular > Default Voice Line. Our app initiates the native call flow by opening a phone-number URL scheme with the destination number. The native Phone app does not always place the call using the selected default line. Expected behaviour: The native Phone app should place the call using the line selected in Settings > Cellular > Default Voice Line Questions: In this flow, is line selection fully controlled by iOS? Is there any supported way for an app to ensure the native Phone app respects the selected default line? Is this a known limitation or known issue on dual SIM devices? Any clarification on expected iOS behaviour would be appreciated.
3
0
672
Sep ’26
CallKit does not activate audio session with higher probability after upgrading to iOS 18.4.1
Hi, We've noticed that this issue occurs more frequently after upgrading to iOS 18.4.1 and can result in one-way audio. Our app uses CallKit with WebRTC to establish VoIP connections. However, on iOS 18.4.1, CallKit no longer triggers: func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) We're currently comparing the occurrence rate across different iOS versions to better understand the impact. Could you please help analyze the root cause of this issue?
40
1
5.7k
Sep ’26
CallKit and PushToTalk related changes in iOS 26
Starting in iOS 26, two notable changes have been made to CallKit, LiveCommunicationKit, and the PushToTalk framework: As a diagnostic aid, we're introducing new dialogs to warn apps of voip push related issue, for example when they fail to report a call or when when voip push delivery stops. The specific details of that behavior are still being determined and are likely to change over time, however, the critical point here is that these alerts are only intended to help developers debug and improve their app. Because of that, they're specifically tied to development and TestFlight signed builds, so the alert dialogs will not appear for customers running app store builds. The existing termination/crashes will still occur, but the new warning alerts will not appear. As PushToTalk developers have previously been warned, the last unrestricted PushKit entitlement ("com.apple.developer.pushkit.unrestricted-voip.ptt") has been disabled in the iOS 26 SDK. ALL apps that link against the iOS 26 SDK which receive a voip push through PushKit and which fail to report a call to CallKit will be now be terminated by the system, as the API contract has long specified. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
Replies
0
Boosts
0
Views
2.2k
Activity
Jun ’25
New PushKit delegate in iOS 26.4
Starting in iOS 26.4, PushKit has introduced a new "didReceiveIncomingVoIPPushWithPayload" delegate, making it explicit whether or not an app is required to report a call for any given push. The new delegate passes in a PKVoIPPushMetadata object which includes a "mustReport" property. We have not documented the exact criteria that will cause a mustReport to return false, but those criteria currently include: The app being in the foreground at the point the push is received. The app being on an active call at the point the push is received. The system determines that delivery delays have made the call old enough that it may no longer be viable. When mustReport is false, apps should call the PushKit completion handler (as they previously have) but are otherwise not required to take any other action. __ Kevin Elliott DTS Engineer, CoreOS/Hardware
Replies
0
Boosts
0
Views
1.2k
Activity
Feb ’26
CallKit Call Directory database corruption (sqlite Code 11)
Hi everyone, I’ve filed a Feedback report (FB20986470) for a serious issue affecting the Call Directory database when add phone numbers for call blocking. When adding blocking numbers to a Call Directory extension, the system’s CallKit database (/private/var/mobile/Library/CallDirectory/CallDirectory.db) becomes corrupted. The reload call (reloadExtensionWithIdentifier) fails with error code 11 when the system tries to insert blocking entries, and the Console app on macOS shows the following errors: database corruption page 2265525 of /private/var/mobile/Library/CallDirectory/CallDirectory.db at line 81343 of [f0ca7bba1c] database corruption at line 79387 of [f0ca7bba1c] Error Domain=com.apple.callkit.database.sqlite Code=11 "sqlite3_step for query 'INSERT INTO PhoneNumberBlockingEntry (extension_id, phone_number_id) VALUES (?, (SELECT id FROM PhoneNumber WHERE (number = ?))), (?, (SELECT id FROM PhoneNumber WHERE (number = ?))),...)'" After this happens, CallKit becomes fully corrupted on the device and no further numbers can be added, even after: Disabling and re-enabling the extension Restarting the device (either force or soft restart) Reinstalling the app Waiting for a couple of minutes after this issue happens (that CallKit could possibly self-recovered) I also tested other call-blocking apps, and they all fail with the same error. The only thing that recovers the system is a full “Reset All Settings.” This issue has been reported by many users of my app, across multiple iOS versions and devices. Similar related issue reported by another developer: https://developer.apple.com/forums/thread/806129 Steps to Reproduce: Enable the Call Directory extension from a call-blocking app. Add and reload blocking numbers (a few thousand entries). Perform multiple reloads between additions. Check the Console, the corruption errors appear. From this point, all insert attempts fail system-wide. Expected Result: Entries should be inserted successfully, or the system should self-recover without persistent corruption. Actual Result: sqlite3_step fails with Code=11, and the Call Directory database remains corrupted until the user resets all settings. Additional Notes: All numbers are sorted and deduplicated before insertion. Happens intermittently after multiple reloads. The system log always shows internal database failure. Environment: Device: iPhone 16 Plus iOS 18.2 Beta (23C5027f) Xcode 16.1 (17B55) Attachments (included in Feedback FB20986470): sysdiagnose captured immediately after the failure (with Phone app General Profile) It seems like a system-level corruption affecting all Call Directory extensions once it occurs.
Replies
15
Boosts
4
Views
2.3k
Activity
1d
Mac Catalyst: outgoing CallKit call opens FaceTime and turns on the camera
We're bringing our CallKit-based VoIP app to the Mac with Mac Catalyst. Incoming calls work fine. For outgoing calls we request a CXStartCallAction (audio only, isVideo = false), the provider fulfills it and the call connects. But at the moment the call starts dialing, macOS launches FaceTime.app, which turns on the camera preview and shows its own call screen for our call ("no video"). When the call ends, FaceTime stays open and the camera stays on until FaceTime is quit manually. The system log shows callservicesd deciding to launch the in-call application for our call: callservicesd _shouldLaunchInCallApplicationForCall: 1 callservicesd Opening URL: <private> for call <private> CoreServicesUIAgent LAUNCH: ... com.apple.FaceTime starting stopped process.Reported as FB25284357 (macOS 27.0.1, Xcode 27.1). Is this expected for third-party CallKit providers on macOS? Is there a supported way to keep the call in our own app without dropping CallKit for outgoing calls?
Replies
1
Boosts
0
Views
51
Activity
2d
App "In Review" since September 24 (4 weeks), two support cases with no update
Our iOS app has been sitting in "In Review" for four weeks and we have not been able to get a status update through any channel, so I'm posting here in case someone from App Review can take a look. App: Epocra, iOS, version 1.0, build 268 Apple ID: 6813697639 Status: In Review since September 24, as Developer Support confirmed on October 1 Timeline Sept 22: build 267 rejected under 2.1(a), a launch crash on iPad Air running iPadOS 27. Fixed the same day and resubmitted as build 268. Sept 22: a reviewer signed in to the demo account that evening. No activity since. Sept 28: opened a status request through Contact Us, case 102979044954. On Oct 1 Developer Support replied that the review was "outside of our normal timeframe" and that the review team had been notified. Nothing since. Oct 5: second status request, case 102986888342. Acknowledgement only. Oct 9: replied in the App Review message thread for the submission citing both cases. No response. We have not changed anything on the submission while it is in review so we don't reset the queue. The app is a business phone app (CallKit and PushKit VoIP with server-side call recording and a consent screen on first launch). The review notes include a demo account, a walkthrough video, and a phone number the reviewer can call to test inbound calls. Is there anything else we should be doing to get this looked at, or can someone from App Review check on it? Happy to provide anything that would help.
Replies
1
Boosts
1
Views
188
Activity
2d
CallKit VoIP call on the receiver: the side (lock) button only locks the screen, no CXEndCallAction is delivered
Device and versions iPhone 15, iOS 27.0.1 App: Hush, a private messenger. Capacitor 8.5.2 iOS app; the UI is a web page in a WKWebView. Call signalling runs in the page; call audio runs in a native Swift Capacitor plugin on stasel/WebRTC 154.0.0, integrated with CallKit. Built on Codemagic with the latest Xcode, distributed through TestFlight. UIBackgroundModes: audio, voip. No PushKit yet: calls are placed and answered in the app's own screen while it is in the foreground. Setup RTCAudioSession manual audio (useManualAudio = true). isAudioEnabled is set only after ICE connects AND provider(_:didActivate:) is called (a 3-second fallback exists but never fired in these tests). We call RTCAudioSession.audioSessionDidActivate / audioSessionDidDeactivate from the provider delegate. Session: playAndRecord, mode voiceChat, options allowBluetoothHFP, no defaultToSpeaker. overrideOutputAudioPort is only called when the user picks Speaker (never in the failing tests). One CXProvider, created lazily, delegate on the main queue. Configuration: supportsVideo false (also tested true), maximumCallGroups 1, maximumCallsPerCallGroup 1, supportedHandleTypes [.generic], includesCallsInRecents false (also tested true). Outgoing: CXStartCallAction is requested via CXCallController when ICE first connects (not at dial time; the page plays its own ringback until then), handle generic, value "Hush". In perform(CXStartCallAction) we configure the audio session (no activation), reportCall(with:updated:), fulfil, then reportOutgoingCall(startedConnectingAt:) and (connectedAt:). Answering side: reportNewIncomingCall, then an immediate CXAnswerCallAction (the user already accepted in the app's screen). Mute: CXSetMutedCallAction. In-app End reported the call with reportCall(with:endedAt:reason: .remoteEnded) in all tests below (we are changing this to a CXEndCallAction request; not yet tested). Proximity: isProximityMonitoringEnabled = true from dialling while on the receiver. The screen does go dark at the ear. Also tested with our proximity monitoring off. The problem With a Hush call live, route Receiver, CallKit holding the call (the system call UI shows it), didActivate delivered exactly once, our audio running inside that activation, proximity on and the screen dark at the ear: pressing the side button only locks the screen. No CXEndCallAction arrives and the call continues. In the Phone app on the same iPhone the side button ends the call at the ear. Snapchat calls on this iPhone end on the side button while Snapchat's call screen is open. What works: End on the system lock-screen call UI delivers a CXEndCallAction and we end the call. Mute from the system UI arrives as CXSetMutedCallAction. So provider delegate delivery works. What we tried, in order (each tested on device, with a readout of the plugin's state after the call) First CallKit build: side button did nothing; lock-screen End worked. Readout: "CallKit off, its audio off (0x), fallback no, route speaker, proximity on". Cause: CXStartCallAction was refused (missing voip background mode) and the error swallowed. Fixed: voip added; on CXErrorCodeRequestTransactionError.unknownCallProvider we invalidate and recreate the provider and retry once. Next build: CallKit held the call, didActivate once, route Receiver. Side button still did nothing, no CXEndCallAction. Our route log showed two route changes caused by our own overrideOutputAudioPort(.none) on every activation and route change. Removed: no override unless Speaker is selected. Result: no change. Diagnostic switches, tested in combinations: our proximity monitoring on/off; supportsVideo false/true; includesCallsInRecents false/true; callee now reported with reportNewIncomingCall + CXAnswerCallAction (previously both sides used CXStartCallAction). Result: the side button ended the call EXACTLY ONCE: the first call after the provider was recreated (changing supportsVideo makes us invalidate() and create a new CXProvider). Every later call with the same configuration failed. Readout for the failures: "CallKit on, its audio on (1x), fallback no, route Receiver, proximity on", screen dark at the ear. Following thread 837211 (creating a provider implicitly pushes the audio session ID to callservicesd, which can keep a stale one; set the configuration before reporting each call): we now assign provider.configuration = a fresh CXProviderConfiguration at call start and again immediately before each CXStartCallAction request / reportNewIncomingCall. We also added a switch that recreates the CXProvider for every call. With the re-push alone: no end action. With a fresh provider every call: no end action either. Readout each time: "provider calls 1, config re-pushed yes, CallKit on, its audio on (1x), route Receiver, proximity on". The single success in step 3 has not been reproduced. Not tried on purpose: detecting the lock ourselves (protectedDataWillBecomeUnavailable arrives about 10 seconds late and needs a passcode; a 2017 thread says Home and Lock cannot be told apart); reporting the CallKit call at dial time instead of ICE connect; PushKit. Threads we relied on 819363 (April 2026): the lock button hangs up a CallKit call handled directly by the device (not through a headset), delivered as the provider's end action. 837211 (August 2026): stale audio session ID in callservicesd after provider creation; set the configuration before reporting a call. How we differ from apps where it works WKWebView: WebKit's GPU process holds a second AVAudioSession in our app's name. During the call the page captures no mic (the plugin owns it); before connect the page plays a Web Audio ringback (Ambient category). The CallKit call starts at ICE connect, not at dial time. In-app End reported as .remoteEnded rather than requested as a CXEndCallAction. The callee's immediate CXAnswerCallAction after reportNewIncomingCall. Questions Which conditions must hold for iOS to treat the side button as "end call" for a CallKit call, and which is our app failing? Is there a log subsystem or category (callservicesd, TelephonyUtilities) we can read in a sysdiagnose to see why the press is handled as lock? Could WebKit's GPU-process audio session in the same app confuse CallKit about which session carries the call? Would reporting the call at dial time, before any audio, change the outcome? Can ending the in-app call with reportCall(.remoteEnded) instead of a CXEndCallAction leave state in callservicesd that affects the NEXT call? That would fit "works once after a fresh provider, never again". We have no Mac. Is a sysdiagnose captured on the iPhone right after a failing press enough to diagnose this? If you need a project, we can provide the plugin's Swift source (one file) and the Capacitor app project that Codemagic builds.
Replies
0
Boosts
0
Views
41
Activity
4d
CallKit never calls didActivateAudioSession because callservicesd fails to create the audio session (SessionID 0x0) on iOS 24A446
Summary On iOS build 24A446, an incoming CallKit VoIP call is reported and answered, but the system never creates or activates the CallKit audio session, so CXProviderDelegate provider:didActivateAudioSession: is never called. Both directions of call audio stay silent. The failure is inside callservicesd / audiomxd, before the app starts its audio unit. Once it starts, later calls from the same processes keep failing until the app process is killed. App and device Bundle ID: us.zoom.videomeetings OS build: 24A446 (iPhone) Log: sysdiagnose_2026.10.16_11-15-45-0700_iPhone-OS_iPhone_24A446 Sample call: 2026-10-15 13:29:06–13:29:22 PDT Processes in that window: Zoom PID 816, callservicesd PID 2474, audiomxd PID 115 How the user hits it The app is not in the foreground. A VoIP push wakes it and we call reportNewIncomingCallWithUUID:update:completion:. The user answers from the system incoming-call UI (phone locked or unlocked). The ringtone plays. After answer there is no call audio. The same failure then happens on later calls, including a call started from inside the app, until the Zoom process is killed. Signing out or rebooting only clears it temporarily. We cannot reproduce it in our lab. It became much more frequent after devices moved to this OS. What the app does We configure one CXProvider (PlayAndRecord is applied when the system activates the session). We fulfill CXAnswerCallAction when the user answers. We start the voice audio unit only from provider:didActivateAudioSession:. We do not call AVAudioSession setActive: during this answered call. Our log line "ZMCallKitManager::didActivateAudioSession" is not present for this call. System log for the sample call 13:29:06 — incoming call reported Zoom log: Provider was asked to report a new incoming call At that moment Zoom's existing primary session is sid:0x7304f, Zoom(816), 'prim', and the app is BackgroundRunning. callservicesd then fails while creating the CallKit session: audiomxd AVAudioSessionXPCServer.mm:231 -[AVAudioSessionRemoteXPCClient createProxySession:reply:] failed due to session lookup failure for SessionID 0x0 callservicesd AVAudioSession_iOS.mm:643 Creating proxy session failed, session ID = 0x0, NSOSStatusErrorDomain -50, "Session lookup failed" audiomxd ServerSessionManager.mm:192 Sibling session creation failed. Source sessionID: 0x0. SessionID is not valid. Source PID: 2474 audiomxd AVAudioSessionXPCServer.mm:1287 Session creation failed callservicesd SessionCore_Create.mm:92 AudioSession creation failed, NSOSStatusErrorDomain 2003329396, "Session creation failed in server" callservicesd Audio session not found for call. Returning nil The ringtone still plays. That audio is callservicesd's own session sid:0x732fa, category Ringtone/Default, which activates at 13:29:06.650. It is not the call session. 13:29:15 — user answers callservicesd: Performing answer request / Perform answer call callservicesd: No provider returned for descriptor callservicesd: Audio session not found for call. Returning nil callservicesd: Answer call action fulfilled callservicesd: Error retrieving AVAudioSession provider with ID 0 Sibling session creation fails again with Source sessionID 0x0, Source PID 2474. The ringtone session is stopped. From 13:29:15 to 13:29:22 there is no "action":"activate" for a CallKit call audio session, and no provider:didActivateAudioSession: notification to Zoom. Zoom's primary session 0x7304f is still inactive. Its category is updated to PlayAndRecord / VoiceChat, but it is not activated while this call is up. 13:29:22 — call ends Provider was asked to report that call ended with reason 2 callservicesd: Setting disconnected reason to remote hangup because ended reason is 2 sid:0x732fa callservicesd going inactive The call lasted about 7 seconds with no call audio session ever created. 13:29:33 — following call, same stuck state About 11 seconds later a CXStartCallAction is fulfilled. Zoom's own session then activates: sid:0x7304f, Zoom(816), 'prim' PlayAndRecord_WithBluetooth / VoiceChat, NonMixable, going active callservicesd still cannot build its session: "No existing proxy AVAudioSession interruption provider for ID 0, creating a new one" Session creation failed in server Error retrieving AVAudioSession provider with ID 0 Audio session not found for call So an app-side setActive: after the failed call does not repair the CallKit provider. The system session id remains 0x0. How often it happens in this sysdiagnose Filtering the archive for the hard failure (not the generic "Audio session not found" line, which also appears on earlier days): "Sibling session creation failed. Source sessionID: 0x0": 93 hits, grouped into 57 bursts First burst: 2026-10-15 09:52:11 PDT Last burst: 2026-10-16 11:14:30 PDT (about a minute before this sysdiagnose was taken) "Error retrieving AVAudioSession provider with ID 0": 34 hits "Session creation failed in server": 93 hits Every one of these sibling-session failures is Source PID 2474. callservicesd stays PID 2474 and audiomxd stays PID 115 across the whole window, including overnight. The bad session id is stuck in those daemons, not in one Zoom call object. There is no log line in this archive showing callservicesd successfully activating a provider audio session for these calls. Request Please confirm this is the known CallKit failure where didActivateAudioSession is not delivered because callservicesd cannot create the audio session (Session lookup failed / Session creation failed in server, session ID 0x0). Related public reports: Feedback FB19429215, "CallKit does not activate audio session after iOS 18.4.1", and the iOS 27 thread "iOS 27 CallKit didActivateAudioSession". DTS previously advised apps not to call setActive: themselves, because the CallKit session has higher priority and an app activation can fail or disturb system state. This log matches that: the session is never created, so there is nothing for the system to activate. Please also advise which of these is safe on 24A446 when provider:didActivateAudioSession: does not arrive: Call CXProvider setConfiguration: again (same configuration) before every reportNewIncomingCallWithUUID:update:completion:. On a timeout, fail the unanswered CXAnswerCallAction so the CallKit state machine resets, without invalidating or recreating the CXProvider. Anything else that clears the stuck session ID 0x0 inside callservicesd without a device reboot. I can provide another sysdiagnose if you need a logging profile installed before the next reproduction.
Replies
3
Boosts
0
Views
997
Activity
4d
watchOS CallKit calls: no DTMF keypad, no audio-route picker, no Recents — are these system-gated for third-party providers?
Hi all, I'm building a watchOS VoIP app that places and receives calls through CallKit, with call audio staying on the watch (not routed to the paired iPhone). Calls connect and audio works. But three parts of the system in-call UI that the native Phone app shows never appear for my app, and I'd like to confirm whether this is expected or a misconfiguration on my side. Environment watchOS 26.0, Apple Watch 11 (reproduced on a physical device) Xcode 27.1 Companion watchOS app, calls driven by CXProvider / CXCallController What's missing during an active call No DTMF keypad. The user can't open a keypad from the system call screen, so in-call DTMF (e.g. navigating an IVR) is impossible. No audio-route picker. No control to switch output route (e.g. speaker vs. the default route). No entry in Recents. Completed calls don't appear in the watch's call history. The system call UI is full-screen and in front, so I also can't present my own keypad or route control on top of it. What I've already tried (all public API) // Reported call callUpdate.supportsDTMF = true // Provider configuration config.includesCallsInRecents = true config.supportedHandleTypes = [.phoneNumber] config.maximumCallGroups = 1 // Audio session: route changes programmatically, but adds no user-facing picker try session.setCategory(.playAndRecord, mode: .voiceChat) try session.overrideOutputAudioPort(.speaker) // Never invoked — no keypad exists to generate the action func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) { ... } None of these make the keypad, the route picker, or a Recents entry appear. The behavior is identical regardless of these values, which makes me suspect these controls are exposed only for the native telephony/relay call path, not for third-party CXProvider calls on the watch. Questions Are the in-call DTMF keypad, audio-route picker, and Recents entry available to third-party CXProvider calls on standalone watchOS at all, or are they reserved for the system (relayed cellular / FaceTime) call UI? If not, is there a supported way to present my own keypad or route control during an active CallKit call, given the system call UI is in front? Thanks!
Replies
1
Boosts
0
Views
640
Activity
1w
LiveCommunicationKit: Handle.displayName is never shown — the call UI and Recents show Handle.value
On iOS [27.x (build)], LiveCommunicationKit shows Handle.value on every system surface and ignores Handle.displayName. That forces a choice that CallKit doesn't: Put a stable account id in value (as WWDC26 session 226 recommends, so Recents redial can identify the person), and the raw id appears on the incoming call screen, the banner and in Recents. Put the person's name in value so the UI reads correctly, and a redial from Recents hands back only the name, which can't reliably identify anyone. Minimal reproduction let configuration = ConversationManager.Configuration( ringtoneName: nil, iconTemplateImageData: nil, maximumConversationGroups: 1, maximumConversationsPerConversationGroup: 1, includesConversationInRecents: true, supportsVideo: false, supportedHandleTypes: [.generic, .phoneNumber, .emailAddress] ) let manager = ConversationManager(configuration: configuration) let remote = Handle(type: .generic, value: "u-1234", displayName: "Jane Appleseed") try await manager.reportNewIncomingConversation( uuid: UUID(), update: Conversation.Update(members: [remote], capabilities: []) ) Expected: the incoming call UI and the Recents row show "Jane Appleseed". Session 226 says displayName is "what the system shows when it can't match the handle to a contact". Tapping the Recents row delivers an INStartCallIntent whose contact personHandle.value is u-1234. Actual: the full-screen ring, the foreground banner and the Recents row all show u-1234. Tapping the row does deliver INStartCallIntent with personHandle.value == "u-1234", so redial works, but the user never sees the name. What we tried, all with the same result (the value is shown): Handle.Kind set to .generic, .phoneNumber or .emailAddress, with every kind listed in supportedHandleTypes Conversation.Update(localMember:) set to the local user's handle activeRemoteMembers set to the remote handle, and localMember plus activeRemoteMembers together Donating an INInteraction (an INStartCallIntent whose INPerson has personHandle set to the id, displayName set to the name and customIdentifier set to the id) when the conversation ends. The donation succeeds, but the Recents row and the redial payload don't change. CallKit comparison, same device: CXCallUpdate.remoteHandle = CXHandle(type: .generic, value: "u-1234") with localizedCallerName = "Jane Appleseed" shows the name on the ring and in Recents. A redial from Recents delivers personHandle.value == "u-1234". That's the behaviour we expected from LiveCommunicationKit. Questions: Is Handle.displayName meant to be shown when the handle doesn't match a contact? If so, is there a configuration step we're missing? If this is a bug, is there a supported way with LiveCommunicationKit to show a name while keeping a stable identifier for Recents redial? Filed as FB24933340. Device: iPhone 15 pro, iOS [27.0.1].
Replies
4
Boosts
0
Views
450
Activity
2w
Issues with AVRoutePickerView channel switching
We are developing a voice call application that uses AVRoutePickerView, allowing users to switch between an iPhone, a speaker, and Bluetooth earphones. However, we have encountered an intermittent issue: when switching from the speaker to Bluetooth earphones, the earphones remain in a loading state, and the audio channel subsequently switches back to the speaker. How can we resolve this issue? Here is the sample code: let session = AVAudioSession.sharedInstance() do { try session.setCategory(.playAndRecord, mode: .default, options: [.allowBluetooth]) try session.overrideOutputAudioPort(isBluetoothConnected ? .none : .speaker) try session.setPreferredSampleRate(48000) try session.setPreferredIOBufferDuration(0.02) try session.setActive(true, options: []) INFO(" >>> start: hasBluetooth=\(isBluetoothConnected), inputs: \(session.currentRoute.inputs.map { $0.portType }) outputs: \(session.currentRoute.outputs.map { $0.portType })") } catch { ERROR("(error.localizedDescription)") }
Replies
5
Boosts
0
Views
2.0k
Activity
2w
Can CXCallObserver detect missed cellular calls while an iOS app is suspended?
Hello, I am developing an iPhone application to help users avoid missing important phone calls. The intended behavior is: A user receives a regular cellular call through the built-in iPhone Phone app. The user does not answer the call. Our application automatically detects the missed call. The application schedules repeated local notifications until the user acknowledges the missed call. The critical requirement is that detection must work while our application is in the background, without the user reopening it. Implementation We currently use CXCallObserver to observe cellular call events. When an incoming call ends without being connected, we classify it as a missed call and schedule notifications using UNUserNotificationCenter. Test environment Device: iPhone 17 iOS: 26.7.1 Distribution target: Standard App Store, Japan Testing: Physical device without an attached Xcode debugger Observed behavior Scenario A: Our application is visible immediately before the iPhone is locked. Missed calls have been detected and notifications scheduled after more than 30 to 60 minutes of device lock. Scenario B: Our application is moved to the background before the iPhone is locked, for example by returning to the Home Screen or opening Safari. Missed calls are not detected promptly, even after only a short period in the background. When the user subsequently opens our application, CXCallObserver callbacks may arrive and the earlier missed call is then detected. This defeats the purpose of the application because the user must reopen it to receive alerts. Questions Is CXCallObserver expected to deliver callbacks while its application is suspended, or only when the process is executing? Is there any supported public iOS API, extension, or background execution mechanism that allows a third-party application to detect missed calls from the built-in Phone app while the application is suspended or terminated? Can a regular cellular missed-call event wake or relaunch a third-party application? If CXCallObserver cannot support this use case, is there another Apple-supported solution available to ordinary App Store applications distributed in Japan? We are looking for an approach that does not require external hardware, carrier integration, private APIs, or unsupported background execution techniques. If this use case is not supported by the public iOS SDK, confirmation of that limitation would be very helpful. Thank you for your guidance.
Replies
1
Boosts
0
Views
235
Activity
2w
Can an AAC app start synthesized speech in an auto-answered cellular call while the iPhone is locked?
I am testing a native Swift iPhone app that adds synthesized speech to an existing cellular call using: AVAudioApplication microphone injection permission AVAudioSession.setPreferredMicrophoneInjectionMode(.spokenAudio) AVSpeechSynthesizer CXCallObserver The audio background mode Device: iPhone 16 Pro Carrier: Vodafone Romania iOS version: [enter exact version] Both the system “Add Audio in Calls” setting and the app permission are enabled. Confirmed behavior: With the app in the foreground, the iPhone’s accessibility Auto-Answer Calls feature answers the call, and the remote caller hears the synthesized greeting. Problem: With the iPhone locked, the phone answers automatically, but the greeting does not start. Logs show ringing, connected, and ended events being processed together when the app returns to the foreground. This suggests the app was suspended. The app does not record the call or play continuous audio while waiting. Questions: Is there a supported public API that lets this app wake or execute when a cellular call connects while the iPhone is locked? Can microphone injection support this use case without keeping the app in the foreground? If supported, what audio-session configuration and background execution mechanism should be used? If unsupported, can you confirm this limitation? I can provide a minimal sample project and diagnostic logs.
Replies
3
Boosts
0
Views
1.2k
Activity
3w
Live Caller ID Lookup: 1-second blocking timeout is often exceeded on real-world networks
We ship a Live Caller ID Lookup extension (PIR-based) for spam call blocking. It works, and our PIR server is fast. But in practice, whether a call gets blocked depends on the quality of the user's internet connection at the moment the call arrives. The system waits only about 1 second for the blocking response. On a fast, stable connection it arrives in time. On an average or unstable connection it often doesn't, and the spam call rings through. So under the current platform limits we cannot guarantee blocking for every call. How we measured For each call we read the device syslog (CommCenter, CallDirectory, ciphermld, callservicesd) and our server logs. The extension cache was reset before each call, so every call triggered a real network lookup. All times are in ms and measured from addNewIncomingCall. Server-side processing of the PIR query was consistently 51–61 ms. The variance is almost entirely network transfer between the device and the server (or relay): In call D, HTTP/2 metrics show the ~28 KB request was handed to the network stack immediately (outbound_duration_ms=0), but response headers arrived only after 2216 ms. In call E, the device waited ~660 ms between finishing the upload to the relay and receiving the first byte of the response. Connection setup on a new connection cost 176–271 ms (DNS + TCP + TLS, or a QUIC handshake to the relay). Before the first byte was sent, the system spent another 54–225 ms after the call arrived. In the failing cases the syslog shows: CallDirectory: not all blocking fetches returned within 1 second(s) callservicesd: shouldBlock: NO shouldSilence NO The block response (shouldBlock=1) then arrives 100–1500 ms too late, and the call keeps ringing. What works: repeat calls After the first lookup the result is cached on the device. A repeat call from the same number is silenced without contacting the server, whatever the connection speed. In our logs, follow-up calls from the same number were silenced within ~65 ms of addNewIncomingCall, with no network request. So a user may get the first spam call from a number but not the next ones. The first call, though, is exactly the one users complain about. The problem with the 1-second budget Each blocking lookup has to: Send a PIR query Receive a response of ~22–25 KB. Often open a new TLS/QUIC connection through the OHTTP relay. All of this has to fit into about 1 second, together with the system's own overhead before the request is sent. On a good connection that takes about 250–650 ms. On an average mobile or congested Wi-Fi connection it easily goes past 1 second, and nothing the developer can optimize on the server helps. Our server already responds in about 50 ms.
Replies
1
Boosts
1
Views
466
Activity
3w
Clarification on iOS restrictions for call recording access, SMS/iMessage access and background voice activation
I’m looking for clarification on what iOS currently allows third-party apps to do in these areas: Siri integration and background voice activation: Can an iOS app implement a custom voice assistant that responds to a wake phrase such as “Hey Nowa” and performs app tasks through voice commands? Could it listen while the app is terminated or the iPhone is locked, similar to Siri? Call recordings: Is there a supported way for an iOS app to access recordings of phone calls made on the user’s iPhone and make them available within the app? I couldn’t find documentation for an API that provides access to these recordings. SMS access: Is there a supported way for an iOS app to access and fetch all SMS and iMessage conversations stored in the user’s Messages app, so they can be viewed within our app? As far as I understand, iOS may not allow these capabilities for third-party apps, but I’d appreciate clarification. If any are supported, could you please point me to the relevant Apple documentation?
Replies
3
Boosts
0
Views
839
Activity
3w
Inquiry regarding issues with the CXSetTranslatingCallAction action
We are currently verifying the functionality of CXSetTranslatingCallAction. We tested its implementation in a VoIP app—using Apple's Translate app by default—and confirmed that it works correctly in some instances. However, we have encountered an issue where, under certain conditions, the real-time translation feature becomes unavailable until the device is rebooted. The issue manifests as follows: When the real-time translation feature is enabled in CallKit, a beep sounds accompanied by the announcement "Starting translation," but the translation fails to proceed and terminates immediately. This behavior persists upon repeated attempts. Restarting the app does not resolve the issue; once this occurs, the feature remains unusable until the device itself is rebooted. Since the feature works normally after a device reboot, it does not appear to be a fundamental implementation error; I would like to investigate the root cause of this behavior. What information or steps are required to investigate this? I conducted the test using an iPhone 16 Pro running OS version 26.5. It is the same for both CallKit and LCK.
Replies
4
Boosts
0
Views
559
Activity
3w
iOS 27: tel: links with call-forwarding codes now blocked as "Malicious Link Blocked" (FB24843805)
Starting in iOS 27, opening a tel: URL that contains a call-forwarding MMI code from an app shows a system alert and dials nothing: Malicious Link Blocked: This link was blocked because it contains malware that will forward all of your incoming messages and calls to 1 (XXX) XXX-XXXX. Scammers often provide malicious links that look legitimate via email, text, or chat. On iOS 26 the same call showed the normal call confirmation prompt and the carrier applied the forwarding. Repro (in response to a button tap): UIApplication.shared.open(URL(string: "tel:*21*XXXXXXXXXXX%23")!) Typing *21*XXXXXXXXXXX# into the Phone app's keypad by hand still works on iOS 27, so the capability is still there; only the in-app handoff is blocked. This breaks setup for call-screening and visual-voicemail apps whose onboarding depends on carrier forwarding (*21*, *61*, *67*, *71*, *72). It also blocks the disable codes (##21#, ##004#, *73), so users can't turn forwarding off from inside the app, which works against the user's own safety. The anti-hijack intent makes sense for links arriving from Messages, Mail or Safari. For a user tap inside an installed App Store app, a confirmation sheet ("Forward calls to ...? Allow") seems like the right balance, and disable codes should always be allowed. Filed as FB24843805. Questions: Is this block meant to apply to links opened by an installed app in response to a user tap? Is there a supported API, entitlement or URL form to hand a forwarding code to the Phone app with user confirmation? Our current workaround is to copy the code to the clipboard and ask the user to paste it into the keypad, which is a real drop-off point for our (mostly older) users. If you're affected too, please file your own feedback and reference FB24843805.
Replies
3
Boosts
1
Views
828
Activity
4w
Siri announces GenericHandle Value instead of custom caller Name
Hello fellow developers, I’ve been working with the CallKit framework in iOS, specifically handling incoming calls. One issue I’ve encountered is that Siri when "read caller name" is enabled announces the caller name/surname set via localizedCallerName and then reads the generic handle value (usually alphanumeric) too! Has anyone encountered a similar situation or if there’s a solution to prioritize the localizedCallerName over the generic handle value without using CXHandleType.emailAddress? Alternatively, any insights or workarounds you know would be greatly appreciated. TLDR: even when I correctly configure the localizedCallerName property, Siri persists in reading the CXHandleType.generic. The original Implementation with CXHandleType.generic: The issue arises when using CXHandleType.generic for alphanumeric IDs (or even URLs as stated by documentation https://developer.apple.com/documentation/callkit/cxhandle). Despite correctly setting the localizedCallerName, Siri continues to announce the generic handle value. Expected Behavior: Siri should read only the localizedCallerName when set and ignore the generic handle value when announcing incoming calls. Workaround: Currently, the only workaround is to use CXHandleType.emailAddress for alphanumeric IDs. However, this is not ideal since it repurposes an email-related handle type for a different purpose. Steps to Reproduce: Create a CallKit app that handles incoming calls (example app from documentation can be used too). On incoming call create CXCallUpdate object Create a CXHandle with CXHandleType.generic and an alphanumeric value (e.g., “ABC123”). Pass the CXHandle to the CXCallUpdate objects' remoteHandle. Set the localizedCallerName property of the CXCallUpdate object with a custom caller name/surname. Report the call with reportNewIncomingCallWithUUID Observe that Siri reads both the localizedCallerName and the generic handle value during call announcements. While we are here a Feature Request: Developers should be able to provide a user-friendly caller name without resorting to workarounds like using CXHandleType.emailAddress. I kindly request that Apple consider enhancing Siri’s behavior in the following ways: Allow developers to suppress the reading of generic handle values while still using the correct handle type. Introduce additional type options for call announcements that don't read the generic value. Both of the above. Thank you for your help! 🙌
Replies
3
Boosts
0
Views
1.4k
Activity
Sep ’26
Dual SIM call uses wrong default line
Hello, I am investigating call behaviour on a dual SIM iPhone. Observed behavior: A specific line is selected in Settings > Cellular > Default Voice Line. Our app initiates the native call flow by opening a phone-number URL scheme with the destination number. The native Phone app does not always place the call using the selected default line. Expected behaviour: The native Phone app should place the call using the line selected in Settings > Cellular > Default Voice Line Questions: In this flow, is line selection fully controlled by iOS? Is there any supported way for an app to ensure the native Phone app respects the selected default line? Is this a known limitation or known issue on dual SIM devices? Any clarification on expected iOS behaviour would be appreciated.
Replies
3
Boosts
0
Views
672
Activity
Sep ’26
CallKit does not activate audio session with higher probability after upgrading to iOS 18.4.1
Hi, We've noticed that this issue occurs more frequently after upgrading to iOS 18.4.1 and can result in one-way audio. Our app uses CallKit with WebRTC to establish VoIP connections. However, on iOS 18.4.1, CallKit no longer triggers: func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) We're currently comparing the occurrence rate across different iOS versions to better understand the impact. Could you please help analyze the root cause of this issue?
Replies
40
Boosts
1
Views
5.7k
Activity
Sep ’26