Merge "Support TYPE_BUS for call audio routing." into main
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 5a6f0ea..529bc79 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -1571,8 +1571,22 @@
}
UserHandle userHandle = getUserFromCall(call);
if (mBTInCallServiceConnections.containsKey(userHandle)) {
- Log.i(this, "onDisconnectedTonePlaying: Unbinding BT service");
- mBTInCallServiceConnections.get(userHandle).disconnect();
+ Log.i(this, "onDisconnectedTonePlaying: Schedule unbind BT service");
+ final InCallServiceConnection connection =
+ mBTInCallServiceConnections.get(userHandle);
+
+ // Similar to in onCallRemoved when we unbind from the other ICS, we need to
+ // delay unbinding from the BT ICS because we need to give the ICS a
+ // moment to finish the onCallRemoved signal it got just prior.
+ mHandler.postDelayed(new Runnable("ICC.oDCTP", mLock) {
+ @Override
+ public void loggedRun() {
+ Log.i(this, "onDisconnectedTonePlaying: unbinding");
+ connection.disconnect();
+ }
+ }.prepare(), mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
+ mContext.getContentResolver()));
+
mBTInCallServiceConnections.remove(userHandle);
}
// Ensure that BT ICS instance is cleaned up
@@ -2743,21 +2757,39 @@
info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
IInCallService inCallService = entry.getValue();
- componentsUpdated.add(componentName);
+ boolean isDisconnectingBtIcs = info.getType() == IN_CALL_SERVICE_TYPE_BLUETOOTH
+ && call.getState() == CallState.DISCONNECTED;
- if (info.getType() == IN_CALL_SERVICE_TYPE_BLUETOOTH
- && call.getState() == CallState.DISCONNECTED
- && !mDisconnectedToneBtFutures.containsKey(call.getId())) {
- CompletableFuture<Void> disconnectedToneFuture = new CompletableFuture<Void>()
- .completeOnTimeout(null, DISCONNECTED_TONE_TIMEOUT,
- TimeUnit.MILLISECONDS);
- mDisconnectedToneBtFutures.put(call.getId(), disconnectedToneFuture);
- mDisconnectedToneBtFutures.get(call.getId()).thenRunAsync(() -> {
- Log.i(this, "updateCall: Sending call disconnected update to BT ICS.");
- updateCallToIcs(inCallService, info, parcelableCall, componentName);
- mDisconnectedToneBtFutures.remove(call.getId());
- }, new LoggedHandlerExecutor(mHandler, "ICC.uC", mLock));
+ if (isDisconnectingBtIcs) {
+ // If this is the first we heard about the disconnect for the BT ICS, then we
+ // will setup a future to notify the disconnet later.
+ if (!mDisconnectedToneBtFutures.containsKey(call.getId())) {
+ // Create the base future with timeout, we will chain more operations on to
+ // this.
+ CompletableFuture<Void> disconnectedToneFuture =
+ new CompletableFuture<Void>()
+ .completeOnTimeout(null, DISCONNECTED_TONE_TIMEOUT,
+ TimeUnit.MILLISECONDS);
+ // Note: DO NOT chain async work onto this future; using thenRun ensures
+ // when disconnectedToneFuture is completed that the chained work is run
+ // synchronously.
+ disconnectedToneFuture.thenRun(() -> {
+ Log.i(this,
+ "updateCall: (deferred) Sending call disconnected update "
+ + "to BT ICS.");
+ updateCallToIcs(inCallService, info, parcelableCall, componentName);
+ mDisconnectedToneBtFutures.remove(call.getId());
+ });
+ mDisconnectedToneBtFutures.put(call.getId(), disconnectedToneFuture);
+ } else {
+ // If we have already cached a disconnect signal for the BT ICS, don't sent
+ // any other updates (ie due to extras or whatnot) to the BT ICS. If we do
+ // then it will hear about the disconnect in advance and not play the call
+ // end tone.
+ Log.i(this, "updateCall: skip update for disconnected call to BT ICS");
+ }
} else {
+ componentsUpdated.add(componentName);
updateCallToIcs(inCallService, info, parcelableCall, componentName);
}
}