Status Update
Comments
an...@google.com <an...@google.com>
an...@google.com <an...@google.com> #2
Can you please double check the link to your git repository for the repro? It leads to a 404
dk...@3cx.com <dk...@3cx.com> #3
an...@google.com <an...@google.com> #4
After looking at the code, what surprises me is that it works on Android 12.
The correct way to achieve this is to never return false in the KeepOnScreenCondition
. Otherwise, the time between the condition being false and the new activity being visible will let the splash screen activity appear
The condition is evaluated for the current view tree only, so as soon as you start the next activity, it will be ignored and the splash screen will be removed.
an...@google.com <an...@google.com> #5
I'm marking this as working as intended, but please let me know if it doesn't work.
st...@gmail.com <st...@gmail.com> #6
We are facing exactly the same issue in our app, at least on a Pixel 6a with the current Android 14 build U1B2.230922.006. As the originator of this issue already pointed out in the description, after switching to endpoint Speaker it is not possible to switch back to Bluetooth directly. While the call to requestCallEndpointChange appears to be successful (OutcomeReceiver.onResult is invoked by the system, not OutcomeReceiver.onError), the audio actually stays on Speaker and neither Connection.onCallEndpointChanged nor Connection.onCallAudioStateChanged are invoked by the system. This is most definitely an Android 14 issue that needs to be fixed by Google.
Here is another (very simplistic) sample project with which you can reproduce the issue, it doesn't really send/receive audio, it simply uses a self-managed ConnectionService/Connection and changes the audio endpoints:
To reproduce:
- Connect a BT device (headset) to the phone and start the app
- Press the DIAL button for "Call 1". This will create a self-managed telecom.Connection. Below is the output from our Pixel 6a in logcat. As you can see three endpoints are available (EARPIECE, SPEAKER, BLUETOOTH) and BT is preselected. Also, callbacks Connection.onCallEndpointChanged and Connection.onCallAudioStateChanged are invoked by the system, confirming the BT endpoint as selected.
2023-10-11 10:41:28.757 9039-9039 SelfManagedConnection com...anagedconnectionservicesample D onAvailableCallEndpointsChanged() - available endpoints:
[CallEndpoint Name: Speaker, Type: SPEAKER, Identifier: b750ef67-e99e-41ca-986b-a52120043d37]
[CallEndpoint Name: Earpiece, Type: EARPIECE, Identifier: ffc47c25-0352-48f9-8267-fe7fd89458df]
[CallEndpoint Name: MID, Type: BLUETOOTH, Identifier: 9137e6ba-c0ab-4181-bf04-85253a5cf009]
2023-10-11 10:41:28.759 9039-9039 TelecomFramework com...anagedconnectionservicesample I SelfManagedConnectionService: onCallEndpointChanged TC@1_1 [CallEndpoint Name: MID, Type: BLUETOOTH, Identifier: 9137e6ba-c0ab-4181-bf04-85253a5cf009]: (BSR.oR->BRM.pM_200->CARSM.pM_BT_AUDIO_CONNECTED)->CS.oCEC->H.CS.cASC(cast)@E-AVU
2023-10-11 10:41:28.759 9039-9039 SelfManagedConnection com...anagedconnectionservicesample D onCallEndpointChanged([CallEndpoint Name: MID, Type: BLUETOOTH, Identifier: 9137e6ba-c0ab-4181-bf04-85253a5cf009])
2023-10-11 10:41:28.762 9039-9055 Compatibil...geReporter com...anagedconnectionservicesample D Compat change id reported: 263076149; UID 10292; state: ENABLED
2023-10-11 10:41:28.771 9039-9039 Compatibil...geReporter com...anagedconnectionservicesample D Compat change id reported: 265103382; UID 10292; state: ENABLED
2023-10-11 10:41:28.778 9039-9039 TelecomFramework com...anagedconnectionservicesample I SelfManagedConnectionService: onAudioStateChanged TC@1_1 [AudioState isMuted: false, route: BLUETOOTH, supportedRouteMask: EARPIECE, BLUETOOTH, SPEAKER, activeBluetoothDevice: [XX:XX:XX:XX:41:A4], supportedBluetoothDevices: [2C:4D:79:10:41:A4]]: (BSR.oR->BRM.pM_200->CARSM.pM_BT_AUDIO_CONNECTED)->CS.cASC->H.CS.cASC(cast)@E-AVU
2023-10-11 10:41:28.780 9039-9039 SelfManagedConnection com...anagedconnectionservicesample D onCallAudioStateChanged to [AudioState isMuted: false, route: BLUETOOTH, supportedRouteMask: EARPIECE, BLUETOOTH, SPEAKER, activeBluetoothDevice: [XX:XX:XX:XX:41:A4], supportedBluetoothDevices: [2C:4D:79:10:41:A4]] for call Call_1
2023-10-11 10:41:37.659 9039-9039 Compatibil...geReporter com...anagedconnectionservicesample D Compat change id reported: 171228096; UID 10292; state: ENABLED
- Now select "Speaker-phone" from the dropdown menu. The log shows that the requestCallEndpointChange operation appears to be successful (OutcomeReceiver.onResult is invoked by the system, not OutcomeReceiver.onError), and again the system invokes the two callbacks Connection.onCallEndpointChanged and Connection.onCallAudioStateChanged, confirming the switch to the SPEAKER endpoint.
2023-10-11 10:41:40.521 9039-9039 MainActivity com...anagedconnectionservicesample D onItemSelected - selectedAudioRoute=Speaker-phone
2023-10-11 10:41:40.521 9039-9039 MainActivity com...anagedconnectionservicesample D onItemSelected() - requestCallEndpointChange to endpoint [CallEndpoint Name: Speaker, Type: SPEAKER, Identifier: b750ef67-e99e-41ca-986b-a52120043d37]
2023-10-11 10:41:40.550 9039-9039 MainActivity com...anagedconnectionservicesample D OutcomeReceiver.onResult(null) - requestCallEndpointChange appears to have been successful
2023-10-11 10:41:40.551 9039-9039 TelecomFramework com...anagedconnectionservicesample I SelfManagedConnectionService: onCallEndpointChanged TC@1_1 [CallEndpoint Name: Speaker, Type: SPEAKER, Identifier: b750ef67-e99e-41ca-986b-a52120043d37]: (CSW.rCEC->CARSM.pM_USER_SWITCH_SPEAKER)->CS.oCEC->H.CS.cASC(cms/cast)@E-AVs
2023-10-11 10:41:40.552 9039-9039 SelfManagedConnection com...anagedconnectionservicesample D onCallEndpointChanged([CallEndpoint Name: Speaker, Type: SPEAKER, Identifier: b750ef67-e99e-41ca-986b-a52120043d37])
2023-10-11 10:41:40.553 9039-9039 TelecomFramework com...anagedconnectionservicesample I SelfManagedConnectionService: onAudioStateChanged TC@1_1 [AudioState isMuted: false, route: SPEAKER, supportedRouteMask: EARPIECE, BLUETOOTH, SPEAKER, activeBluetoothDevice: [null], supportedBluetoothDevices: [2C:4D:79:10:41:A4]]: (CSW.rCEC->CARSM.pM_USER_SWITCH_SPEAKER)->CS.cASC->H.CS.cASC(cms/cast)@E-AVs
2023-10-11 10:41:40.554 9039-9039 SelfManagedConnection com...anagedconnectionservicesample D onCallAudioStateChanged to [AudioState isMuted: false, route: SPEAKER, supportedRouteMask: EARPIECE, BLUETOOTH, SPEAKER, activeBluetoothDevice: [null], supportedBluetoothDevices: [2C:4D:79:10:41:A4]] for call Call_1
2023-10-11 10:41:40.829 9039-9039 WindowOnBackDispatcher com...anagedconnectionservicesample W sendCancelIfRunning: isInProgress=falsecallback=android.view.ViewRootImpl$$ExternalSyntheticLambda17@cd7eb95
2023-10-11 10:41:40.832 9039-9070 OpenGLRenderer com...anagedconnectionservicesample D endAllActiveAnimators on 0xb400007d32e350f0 (DropDownListView) with handle 0xb400007d62e3e380
- Now select "Bluetooth" from the drop-down menu, to switch back to BT. As you can see in the log, again the requestCallEndpointChange operation appears to be successful (OutcomeReceiver.onResult is invoked by the system, not OutcomeReceiver.onError). However, the actual switch to the BT endpoint is never really executed by the system. It never invokes the Connection.onCallEndpointChanged and Connection.onCallAudioStateChanged callbacks, which confirms that the endpoint switch is actually not really executed by the system.
2023-10-11 10:41:52.911 9039-9039 MainActivity com...anagedconnectionservicesample D onItemSelected - selectedAudioRoute=Bluetooth
2023-10-11 10:41:52.911 9039-9039 MainActivity com...anagedconnectionservicesample D onItemSelected() - requestCallEndpointChange to endpoint [CallEndpoint Name: MID, Type: BLUETOOTH, Identifier: 9137e6ba-c0ab-4181-bf04-85253a5cf009]
2023-10-11 10:41:52.914 9039-9039 MainActivity com...anagedconnectionservicesample D OutcomeReceiver.onResult(null) - requestCallEndpointChange appears to have been successful
2023-10-11 10:41:53.214 9039-9039 WindowOnBackDispatcher com...anagedconnectionservicesample W sendCancelIfRunning: isInProgress=falsecallback=android.view.ViewRootImpl$$ExternalSyntheticLambda17@6d228b0
2023-10-11 10:41:53.217 9039-9070 OpenGLRenderer com...anagedconnectionservicesample D endAllActiveAnimators on 0xb400007d32e3ab10 (DropDownListView) with handle 0xb400007d62e39370
st...@gmail.com <st...@gmail.com> #8 Restricted
an...@google.com <an...@google.com> #9
You need to implement the InCallService in order to get updates of the ongoing call.
Please read the doc of it:
You can use command adb bugreport
to generate the bug report of an issue so that we can figure out if telecom bind to your InCallService properly.
dk...@3cx.com <dk...@3cx.com> #10
According to the documentation, InCallService
is used to "Become the Default Phone App". Our app is merely a VoIP application without a goal to replace the system dialer, thus we don't use InCallService
at all. Instead, we use Telecom API to seamlessly integrate our VoIP calls into the Android calls ecosystem.
st...@gmail.com <st...@gmail.com> #11
st...@gmail.com <st...@gmail.com> #12 Restricted
an...@google.com <an...@google.com> #13
The default dialer is not enabled for provide an UI for the 3rd-party calls:
10-11 10:41:28.146 I Telecom : InCallController: defaultDialer: [ComponentInfo{com.google.android.dialer/com.android.incallui.InCallServiceImpl} supportsExternal? false supportsSelfMg?false]: TSI.pC->CM.fOCP->CM.sOCPA->CM.dSMCP->CM.dSPA->CM.pASP(cms)@AUs
So for your calls, actually there's no available in-call UI for it and naturally we can't update the call endpoint updates for users.
A VoIP application must provide their own dialer or use another dialer that can support self-managed calls, and also declare PhoneAccount#EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE
.
Please read
st...@gmail.com <st...@gmail.com> #14
I'm sorry, I might be wrong, but it seems to me like there is a misunderstanding about the issue that we are trying to point out here.
Our application is a VoIP call app, that has it's own in-call UI. It does NOT try to replace or to use any other dialer's UI, be it provided by the system or a 3rd-party app. To that end it uses a self-managed ConnectionService implementation, which is implemented as documented here:
Under "Registering a Phone Account" it says
Your app should create a new instance of PhoneAccount which meets the following requirements:
- Has PhoneAccount#CAPABILITY_SELF_MANAGED (set using PhoneAccount.Builder#setCapabilities(int)). This indicates to Telecom that your app will report calls but that it provides a primary UI for the calls by itself.
- Provide a unique identifier for the PhoneAccount via the PhoneAccountHandle#getId() attribute. As per the PhoneAccountHandle documentation, you should NOT use an identifier which contains PII or other sensitive information. A typical choice is a UUID.
There is no mention of PhoneAccount#EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE
here, or anywhere else in the documentation, except for the
Our ConnectionService implementation is not new, our app has been in the Play Store for years now. For changing the audio route up until now it is using the methods of android.telecom.Connection
which use CallAudioState
(i.e. getCallAudioState
, onCallAudioStateChanged
, setAudioRoute
, requestBluetoothAudio
). These methods still work correctly on Android 14, without the issue that this ticket is about. However, they have now been deprecated with Android 14, instead we are told to use the new CallEndpoint
API for the audio routing. It says so
A VoIP app can implement a ConnectionService to ensure that its calls are integrated into the Android platform. There are numerous benefits to using the Telecom APIs for a VoIP app:
- Call concurrency is handled - the user is able to swap between calls in different apps and on the mobile network.
- Simplified audio routing - the platform provides your app with a unified list of the audio routes which are available (e.g. Connection.onAvailableCallEndpointsChanged(List)) and a standardized way to switch audio routes (e.g. Connection.requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver) ).
[...]
and also in the API documentation, e.g. for
This method was deprecated in API level 34. Use requestCallEndpointChange(android.telecom.CallEndpoint, java.util.concurrent.Executor, android.os.OutcomeReceiver) instead.
Again, no mention of a requirement for PhoneAccount#EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE
or any other special requirements. This reads like the new android.telecom.Connection
methods using CallEndpoint
are just simply meant as a replacement for the deprecated methods, without the need for any additional adjustments.
Now, given all that, what both the ticket originator and I complain about it simply this:
The new Connection.requestCallEndpointChange
method does not work correctly in one specific scenario: when switching from SPEAKER to BLUETOOTH. It works correctly when switching from EARPIECE to BLUETOOTH, or when switching from SPEAKER to EARPIECE and then to BLUETOOTH. Just not when trying to switch from SPEAKER to BLUETOOTH directly. For more details please see our earlier comments and the two sample applications we provided.
And by the way: I just tried your suggestion and provided the PhoneAccount with the PhoneAccount#EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE
extra set to false
. With that Connection.requestCallEndpointChange
doesn't work at all anymore, it just results in an error:
android.telecom.CallEndpointException: The operation was not completed on time (code: 2)
which is probably no surprise, as nothing handles the requestCallEndpointChange anymore. And setting the PhoneAccount#EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE
extra to true
results in the same behavior as when not setting it at all, including the issue as explained above.
an...@google.com <an...@google.com> #15
Hi,
There are 2 problem of your issue:
-
As We mentioned before, as long as your app have its own UI for the call, you should implement an InCallService. It will not only get you update to state chagnes of your calls, it will also provide your way to manage calls. The information of your app UI should come from the InCallService. We can't find the implementation of it from your app. For changing the audio route, the proper API should be
.InCallService#requestCallEndpointChange is an example of the declaration for your service in manifest file.Here -
However, we do hope
Connection#requestCallEndpointChange
work. From the bug report you provided, we can't find detailed information about what caused the operation failed due to the failure happened too early and the combined log lost relative record about that. We can only find that you successfully useConnection#requestCallEndpointChange
to change the audio route from bluetooth to speaker:
10:41:40.538 - AUDIO_ROUTE_SPEAKER:CSW.rCEC->CARSM.pM_USER_SWITCH_SPEAKER(cms)@AVs
Please try to generate the bug report right after you reproduced your issue. For clarification of your issue, maybe you can also try to provide a video so that we can avoid misunderstanding.
Also We want to emphasize again that even if Connection#requestCallEndpointChange
can work properly, you still need the InCallService to get call audio route updates since the audio route switching may take some time.
dk...@3cx.com <dk...@3cx.com> #16
As per your request I captured another bug report on a different phone (Pixel 5 with Android 14 build UP1A.231005.007):
As you can clearly see, my first switch from Bluetooth (the initial route) to the speaker was properly handled by the system:
10-31 17:18:48.815 10090 10696 10696 I MainActivity: requesting to change endpoint to [CallEndpoint Name: Speaker, Type: SPEAKER, Identifier: 466ed391-dce5-408a-849e-445aeacfafdf]
10-31 17:18:48.817 1000 2035 3664 I Telecom : CallAudioRouteStateMachine: Message received: USER_SWITCH_SPEAKER=1104, arg1=0: CSW.rCEC->CARSM.pM_USER_SWITCH_SPEAKER(cet)@AV4
...
10-31 17:18:48.835 1000 2035 3664 I Telecom : InCallController: Calling onCallEndpointChanged: CSW.rCEC->CARSM.pM_USER_SWITCH_SPEAKER(cet)@AV4
10-31 17:18:48.836 1000 2035 3664 D BluetoothAdapter: getActiveDevices(profile= HEADSET)
10-31 17:18:48.837 10090 10696 10696 I MainActivity: endpoint change succeeded!
Then I tried to switch back to Bluetooth, and the call "succeeded" immediately without actually doing something. There are no any actions seen between "requesting to change endpoint" and "endpoint change succeeded":
10-31 17:18:55.859 10090 10696 10696 I MainActivity: requesting to change endpoint to [CallEndpoint Name: Snom C300, Type: BLUETOOTH, Identifier: 8780b62b-177a-45a5-b0f4-d61b28204946]
10-31 17:18:55.862 10090 10696 10696 I MainActivity: endpoint change succeeded!
My second attempt at 17:19:02.784 was ignored too.
The audio remained on the speaker.
lo...@gmail.com <lo...@gmail.com> #18
dk...@3cx.com <dk...@3cx.com> #19
I agree with the other commenter that the CallEndpoint
API is supposed to be a drop-in replacement for the CallAudioState
-based methods, just with a slightly different interface. It is a surprise that the same scenario works well with the old methods and doesn't work with the new ones.
vi...@google.com <vi...@google.com> #20
The issue has been fixed and it will become available in a future Android release. Please keep an eye on the release notes(
Description
Are you an Android developer?
Yes
Which Android Developer Preview build are you using?
U1B1.230908.003
Is this a regression from Android 13 to 14?
The issue doesn't occur with deprecated methods of
android.telecom.Connection
which useCallAudioState
(getCallAudioState
,onCallAudioStateChanged
,setAudioRoute
,requestBluetoothAudio
) even when called on Android 14, but the new methodandroid.telecom.Connection.requestCallEndpointChange
utilizingCallEndpoint
fails to select a Bluetooth device in the scenario described below.What device are you using?
Pixel 6 Pro
What are the steps to reproduce the problem?
The sample project attached.
OutcomeReceiver.onResult
is called byrequestCallEndpointChange
which means that the operation succeeded, but neither isConnection.onCallEndpointChanged
called, nor doesConnection.getCurrentCallEndpoint()
return the new route.It seems that it fails to select the Bluetooth device when it was already selected one step before. However, there is a workaround: you can switch to some other route, e.g. from Speaker go to Earpiece and only after that select the Bluetooth device - and it works.
Issue Category:
Telecom Framework
What was the expected result?
The sound should have been routed to the Bluetooth device after my request.
Can you provide the API document where this expected behavior is explained?
What was the actual result?
The sound keeps going through the current route (Speaker), Bluetooth endpoint wasn't set active