Merge "Resolve separate binding for BT ICS." into main
diff --git a/res/values/config.xml b/res/values/config.xml
index 9375798..ae5d88e 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -80,12 +80,16 @@
callers are combined into a single toggle. -->
<bool name="combine_options_to_block_unavailable_and_unknown_callers">true</bool>
- <!-- System bluetooth stack package name -->
- <string name="system_bluetooth_stack">com.android.bluetooth</string>
-
<!-- When true, skip fetching quick reply response -->
<bool name="skip_loading_canned_text_response">false</bool>
<!-- When true, skip fetching incoming caller info -->
<bool name="skip_incoming_caller_info_query">false</bool>
+
+ <string-array name="system_bluetooth_stack_package_name" translatable="false">
+ <!-- AOSP -->
+ <item>com.android.bluetooth</item>
+ <!-- Used for internal targets -->
+ <item>com.google.android.bluetooth</item>
+ </string-array>
</resources>
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 7e5f6de..002ba11 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -4816,12 +4816,20 @@
}
/**
+ * @return The binding {@link CompletableFuture} for the BT ICS.
+ */
+ public CompletableFuture<Boolean> getBtIcsFuture() {
+ return mBtIcsFuture;
+ }
+
+ /**
* Wait for bluetooth {@link android.telecom.InCallService} binding completion or timeout. Used
* for audio routing operations for a ringing call.
*/
public void waitForBtIcs() {
if (mBtIcsFuture != null) {
try {
+ Log.i(this, "waitForBtIcs: waiting for BT service to bind");
mBtIcsFuture.get();
} catch (InterruptedException | ExecutionException e) {
// ignore
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index e5678a0..1f1ca9d 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -20,6 +20,8 @@
import android.content.Context;
import android.media.IAudioService;
import android.media.ToneGenerator;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.UserHandle;
import android.telecom.CallAudioState;
import android.telecom.Log;
@@ -36,6 +38,7 @@
import java.util.HashSet;
import java.util.Set;
import java.util.LinkedHashSet;
+import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@@ -66,9 +69,13 @@
private Call mStreamingCall;
private Call mForegroundCall;
+ private CompletableFuture<Boolean> mCallRingingFuture;
+ private Thread mBtIcsBindingThread;
private boolean mIsTonePlaying = false;
private boolean mIsDisconnectedTonePlaying = false;
private InCallTonePlayer mHoldTonePlayer;
+ private final HandlerThread mHandlerThread;
+ private final Handler mHandler;
public CallAudioManager(CallAudioRouteAdapter callAudioRouteAdapter,
CallsManager callsManager,
@@ -105,6 +112,9 @@
mBluetoothStateReceiver = bluetoothStateReceiver;
mDtmfLocalTonePlayer = dtmfLocalTonePlayer;
mFeatureFlags = featureFlags;
+ mHandlerThread = new HandlerThread(this.getClass().getSimpleName());
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
mPlayerFactory.setCallAudioManager(this);
mCallAudioModeStateMachine.setCallAudioManager(this);
@@ -750,14 +760,42 @@
private void onCallEnteringRinging() {
if (mRingingCalls.size() == 1) {
- // Wait until the BT ICS binding completed to request further audio route change
- for (Call ringingCall: mRingingCalls) {
- ringingCall.waitForBtIcs();
+ Log.i(this, "onCallEnteringRinging: mFeatureFlags.separatelyBindToBtIncallService() ? %s",
+ mFeatureFlags.separatelyBindToBtIncallService());
+ Log.i(this, "onCallEnteringRinging: mRingingCalls.getFirst().getBtIcsFuture() = %s",
+ mRingingCalls.getFirst().getBtIcsFuture());
+ if (mFeatureFlags.separatelyBindToBtIncallService()
+ && mRingingCalls.getFirst().getBtIcsFuture() != null) {
+ mCallRingingFuture = mRingingCalls.getFirst().getBtIcsFuture()
+ .thenComposeAsync((completed) -> {
+ mCallAudioModeStateMachine.sendMessageWithArgs(
+ CallAudioModeStateMachine.NEW_RINGING_CALL,
+ makeArgsForModeStateMachine());
+ return CompletableFuture.completedFuture(completed);
+ }, new LoggedHandlerExecutor(mHandler, "CAM.oCER", mCallsManager.getLock()))
+ .exceptionally((throwable) -> {
+ Log.e(this, throwable, "Error while executing BT ICS future");
+ // Fallback on performing computation on a separate thread.
+ handleBtBindingWaitFallback();
+ return null;
+ });
+ } else {
+ mCallAudioModeStateMachine.sendMessageWithArgs(
+ CallAudioModeStateMachine.NEW_RINGING_CALL,
+ makeArgsForModeStateMachine());
}
+ }
+ }
+
+ private void handleBtBindingWaitFallback() {
+ // Wait until the BT ICS binding completed to request further audio route change
+ mBtIcsBindingThread = new Thread(() -> {
+ mRingingCalls.getFirst().waitForBtIcs();
mCallAudioModeStateMachine.sendMessageWithArgs(
CallAudioModeStateMachine.NEW_RINGING_CALL,
makeArgsForModeStateMachine());
- }
+ });
+ mBtIcsBindingThread.start();
}
private void onCallEnteringHold() {
@@ -889,12 +927,14 @@
// we will not play a disconnect tone.
if (call.isHandoverInProgress()) {
Log.i(LOG_TAG, "Omitting tone because %s is being handed over.", call);
+ completeDisconnectToneFuture(call);
return;
}
if (mForegroundCall != null && call != mForegroundCall && mCalls.size() > 1) {
Log.v(LOG_TAG, "Omitting tone because we are not foreground" +
" and there is another call.");
+ completeDisconnectToneFuture(call);
return;
}
@@ -935,6 +975,8 @@
mCallsManager.onDisconnectedTonePlaying(call, true);
mIsDisconnectedTonePlaying = true;
}
+ } else {
+ completeDisconnectToneFuture(call);
}
}
}
@@ -1022,6 +1064,14 @@
oldState == CallState.ON_HOLD;
}
+ private void completeDisconnectToneFuture(Call call) {
+ CompletableFuture<Void> disconnectedToneFuture = mCallsManager.getInCallController()
+ .getDisconnectedToneBtFutures().get(call.getId());
+ if (disconnectedToneFuture != null) {
+ disconnectedToneFuture.complete(null);
+ }
+ }
+
@VisibleForTesting
public Set<Call> getTrackedCalls() {
return mCalls;
@@ -1031,4 +1081,9 @@
public SparseArray<LinkedHashSet<Call>> getCallStateToCalls() {
return mCallStateToCalls;
}
+
+ @VisibleForTesting
+ public CompletableFuture<Boolean> getCallRingingFuture() {
+ return mCallRingingFuture;
+ }
}
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 0744502..dcf3e55 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -1035,7 +1035,8 @@
if (result.shouldAllowCall) {
if (mFeatureFlags.separatelyBindToBtIncallService()) {
- incomingCall.setBtIcsFuture(mInCallController.bindToBTService(incomingCall));
+ mInCallController.bindToBTService(incomingCall, null);
+ incomingCall.setBtIcsFuture(mInCallController.getBtBindingFuture(incomingCall));
setCallState(incomingCall, CallState.RINGING, "successful incoming call");
}
incomingCall.setPostCallPackageName(
diff --git a/src/com/android/server/telecom/DefaultDialerCache.java b/src/com/android/server/telecom/DefaultDialerCache.java
index d819780..44b426a 100644
--- a/src/com/android/server/telecom/DefaultDialerCache.java
+++ b/src/com/android/server/telecom/DefaultDialerCache.java
@@ -176,7 +176,7 @@
UserHandle.USER_ALL);
}
- public String getBTInCallServicePackage() {
+ public String[] getBTInCallServicePackages() {
return mRoleManagerAdapter.getBTInCallService();
}
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index e625bbe..f3c84ba 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -370,7 +370,8 @@
// not be running (handled in getUserFromCall).
UserHandle userToBind = isManagedProfile ? userFromCall : UserHandle.CURRENT;
if ((mInCallServiceInfo.mType == IN_CALL_SERVICE_TYPE_NON_UI
- || mInCallServiceInfo.mType == IN_CALL_SERVICE_TYPE_CAR_MODE_UI) && (
+ || mInCallServiceInfo.mType == IN_CALL_SERVICE_TYPE_CAR_MODE_UI
+ || mInCallServiceInfo.mType == IN_CALL_SERVICE_TYPE_BLUETOOTH) && (
mUserHandleToUseForBinding != null)) {
//guarding change for non-UI/carmode-UI services which may not be present for
// work profile.
@@ -1080,6 +1081,7 @@
if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())) {
synchronized (mLock) {
int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+ String changedPackage = intent.getData().getSchemeSpecificPart();
UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
boolean isManagedProfile = um.isManagedProfile(userHandle.getIdentifier());
@@ -1109,12 +1111,36 @@
childManagedProfileUser);
List<InCallServiceBindingConnection> componentsToBindForUser = null;
List<InCallServiceBindingConnection> componentsToBindForChild = null;
+ // Separate binding for BT logic.
+ boolean isBluetoothPkg = isBluetoothPackage(changedPackage);
+ Call callToConnectWith = mCallIdMapper.getCalls().isEmpty()
+ ? null
+ : mCallIdMapper.getCalls().iterator().next();
+
+ // Bind to BT service if there's an available call. When the flag isn't
+ // enabled, the service will be included as part of
+ // getNonUiInCallServiceBindingConnectionList.
+ if (mFeatureFlags.separatelyBindToBtIncallService()
+ && isBluetoothPkg && callToConnectWith != null) {
+ // mNonUIInCallServiceConnections will always contain a key for
+ // userHandle and/or the child user if there is an ongoing call with
+ // that user, regardless if there aren't any non-UI ICS bound.
+ if (isUserKeyPresent) {
+ bindToBTService(callToConnectWith, userHandle);
+ }
+ if (isChildUserKeyPresent) {
+ // This will try to use the ICS found in the parent if one isn't
+ // available for the child.
+ bindToBTService(callToConnectWith, childManagedProfileUser);
+ }
+ }
if(isUserKeyPresent) {
componentsToBindForUser =
getNonUiInCallServiceBindingConnectionList(intent,
userHandle, null);
}
+
if (isChildUserKeyPresent) {
componentsToBindForChild =
getNonUiInCallServiceBindingConnectionList(intent,
@@ -1127,11 +1153,11 @@
isUserKeyPresent, isChildUserKeyPresent, isManagedProfile,
userHandle.getIdentifier());
- if (isUserKeyPresent && componentsToBindForUser != null) {
+ if (isUserKeyPresent && !componentsToBindForUser.isEmpty()) {
mNonUIInCallServiceConnections.get(userHandle).
addConnections(componentsToBindForUser);
}
- if (isChildUserKeyPresent && componentsToBindForChild != null) {
+ if (isChildUserKeyPresent && !componentsToBindForChild.isEmpty()) {
mNonUIInCallServiceConnections.get(childManagedProfileUser).
addConnections(componentsToBindForChild);
}
@@ -1186,6 +1212,10 @@
private static final int IN_CALL_SERVICE_TYPE_COMPANION = 5;
private static final int IN_CALL_SERVICE_TYPE_BLUETOOTH = 6;
+ // Timeout value to be used to ensure future completion for mDisconnectedToneBtFutures. This is
+ // set to 4 seconds to account for the exceptional case (TONE_CONGESTION).
+ private static final int DISCONNECTED_TONE_TIMEOUT = 4000;
+
private static final int[] LIVE_CALL_STATES = { CallState.ACTIVE, CallState.PULLING,
CallState.DISCONNECTING };
@@ -1233,7 +1263,10 @@
// in-call service.
// The future will complete with true if bluetooth in-call service succeeds, false if it timed
// out.
- private CompletableFuture<Boolean> mBtBindingFuture = CompletableFuture.completedFuture(true);
+ private Map<UserHandle, CompletableFuture<Boolean>> mBtBindingFuture = new ArrayMap<>();
+ // Future used to delay terminating the BT InCallService before the call disconnect tone
+ // finishes playing.
+ private Map<String, CompletableFuture<Void>> mDisconnectedToneBtFutures = new ArrayMap<>();
private final CarModeTracker mCarModeTracker;
@@ -1256,6 +1289,8 @@
private boolean mIsStartCallDelayScheduled = false;
+ private boolean mDisconnectedToneStartedPlaying = false;
+
/**
* A list of call IDs which are currently using the camera.
*/
@@ -1375,27 +1410,29 @@
addCall(call);
if (mFeatureFlags.separatelyBindToBtIncallService()) {
- boolean bindBTService = false;
- boolean bindOtherServices = false;
+ boolean bindingToBtRequired = false;
+ boolean bindingToOtherServicesRequired = false;
if (!isBoundAndConnectedToBTService(userFromCall)) {
Log.i(this, "onCallAdded: %s; not bound or connected to BT ICS.", call);
- bindBTService = true;
- bindToBTService(call);
+ bindingToBtRequired = true;
+ bindToBTService(call, null);
}
if (!isBoundAndConnectedToServices(userFromCall)) {
Log.i(this, "onCallAdded: %s; not bound or connected to other ICS.", call);
// We are not bound, or we're not connected.
- bindOtherServices = true;
- bindToOtherServices(call);
+ bindingToOtherServicesRequired = true;
+ bindToServices(call);
}
- if (!bindBTService || !bindOtherServices) {
+ // If either BT service are already bound or other services are already bound, attempt
+ // to add the new call to the connected incall services.
+ if (!bindingToBtRequired || !bindingToOtherServicesRequired) {
addCallToConnectedServices(call, userFromCall);
}
} else {
if (!isBoundAndConnectedToServices(userFromCall)) {
Log.i(this, "onCallAdded: %s; not bound or connected.", call);
// We are not bound, or we're not connected.
- bindToServices(call, false);
+ bindToServices(call);
} else {
addCallToConnectedServices(call, userFromCall);
}
@@ -1507,17 +1544,31 @@
@Override
public void onDisconnectedTonePlaying(Call call, boolean isTonePlaying) {
Log.i(this, "onDisconnectedTonePlaying: %s -> %b", call, isTonePlaying);
-
if (mFeatureFlags.separatelyBindToBtIncallService()) {
synchronized (mLock) {
- mPendingEndToneCall.remove(call);
- if (!mPendingEndToneCall.isEmpty()) {
- return;
- }
- UserHandle userHandle = getUserFromCall(call);
- if (mBTInCallServiceConnections.containsKey(userHandle)) {
- mBTInCallServiceConnections.get(userHandle).disconnect();
- mBTInCallServiceConnections.remove(userHandle);
+ if (isTonePlaying) {
+ mDisconnectedToneStartedPlaying = true;
+ } else if (mDisconnectedToneStartedPlaying) {
+ mDisconnectedToneStartedPlaying = false;
+ if (mDisconnectedToneBtFutures.containsKey(call.getId())) {
+ Log.i(this, "onDisconnectedTonePlaying: completing BT "
+ + "disconnected tone future");
+ mDisconnectedToneBtFutures.get(call.getId()).complete(null);
+ }
+ mPendingEndToneCall.remove(call);
+ if (!mPendingEndToneCall.isEmpty()) {
+ return;
+ }
+ UserHandle userHandle = getUserFromCall(call);
+ if (mBTInCallServiceConnections.containsKey(userHandle)) {
+ Log.i(this, "onDisconnectedTonePlaying: Unbinding BT service");
+ mBTInCallServiceConnections.get(userHandle).disconnect();
+ mBTInCallServiceConnections.remove(userHandle);
+ }
+ // Ensure that BT ICS instance is cleaned up
+ if (mBTInCallServices.remove(userHandle) != null) {
+ updateCombinedInCallServiceMap(userHandle);
+ }
}
}
}
@@ -1969,6 +2020,8 @@
}
getCombinedInCallServiceMap().remove(userHandle);
if (mFeatureFlags.separatelyBindToBtIncallService()) {
+ // Note that the BT ICS will be repopulated as part of the combined map if the
+ // BT ICS is still bound (disconnected tone hasn't finished playing).
updateCombinedInCallServiceMap(userHandle);
}
}
@@ -1979,34 +2032,49 @@
*
* @param call The newly added call that triggered the binding to the in-call services.
*/
- public CompletableFuture<Boolean> bindToBTService(Call call) {
+ public void bindToBTService(Call call, UserHandle userHandle) {
+ Log.i(this, "bindToBtService");
+ UserHandle userToBind = userHandle == null
+ ? getUserFromCall(call)
+ : userHandle;
+ UserManager um = mContext.getSystemService(UserManager.class);
+ UserHandle parentUser = mFeatureFlags.profileUserSupport()
+ ? um.getProfileParent(userToBind) : null;
+
+ if (!mFeatureFlags.profileUserSupport()
+ && um.isManagedProfile(userToBind.getIdentifier())) {
+ parentUser = um.getProfileParent(userToBind);
+ }
+
// Track the call if we don't already know about it.
addCall(call);
- UserHandle userFromCall = getUserFromCall(call);
-
- List<InCallServiceInfo> infos = getInCallServiceComponents(userFromCall,
+ List<InCallServiceInfo> infos = getInCallServiceComponents(userToBind,
IN_CALL_SERVICE_TYPE_BLUETOOTH);
+ boolean serviceUnavailableForUser = false;
if (infos.size() == 0 || infos.get(0) == null) {
- Log.w(this, "No available BT service");
- mBtBindingFuture = CompletableFuture.completedFuture(false);
- return mBtBindingFuture;
+ Log.i(this, "No available BT ICS for user (%s). Trying with parent instead.",
+ userToBind);
+ serviceUnavailableForUser = true;
+ // Check if the service is available under the parent user instead.
+ if (parentUser != null) {
+ infos = getInCallServiceComponents(parentUser, IN_CALL_SERVICE_TYPE_BLUETOOTH);
+ }
+ if (infos.size() == 0 || infos.get(0) == null) {
+ Log.w(this, "No available BT ICS to bind to for user %s or its parent %s.",
+ userToBind, parentUser);
+ mBtBindingFuture.put(userToBind, CompletableFuture.completedFuture(false));
+ return;
+ }
}
- mBtBindingFuture = new CompletableFuture<Boolean>().completeOnTimeout(false,
- mTimeoutsAdapter.getCallBindBluetoothInCallServicesDelay(
- mContext.getContentResolver()), TimeUnit.MILLISECONDS);
- new InCallServiceBindingConnection(infos.get(0)).connect(call);
- return mBtBindingFuture;
- }
- /**
- * Binds to all the UI-providing InCallService as well as system-implemented non-UI
- * InCallServices except BT InCallServices. Method-invoker must check
- * {@link #isBoundAndConnectedToServices(UserHandle)} before invoking.
- *
- * @param call The newly added call that triggered the binding to the in-call services.
- */
- public void bindToOtherServices(Call call) {
- bindToServices(call, true);
+ mBtBindingFuture.put(userToBind, new CompletableFuture<Boolean>().completeOnTimeout(false,
+ mTimeoutsAdapter.getCallBindBluetoothInCallServicesDelay(
+ mContext.getContentResolver()), TimeUnit.MILLISECONDS));
+ InCallServiceBindingConnection btIcsBindingConnection =
+ new InCallServiceBindingConnection(infos.get(0),
+ serviceUnavailableForUser ? parentUser : userToBind);
+ mBTInCallServiceConnections.put(userToBind, btIcsBindingConnection);
+ btIcsBindingConnection.connect(call);
}
/**
@@ -2016,11 +2084,9 @@
*
* @param call The newly added call that triggered the binding to the in-call
* services.
- * @param skipBTServices Boolean variable to specify if the binding to BT InCallService should
- * be skipped
*/
@VisibleForTesting
- public void bindToServices(Call call, boolean skipBTServices) {
+ public void bindToServices(Call call) {
UserHandle userFromCall = getUserFromCall(call);
UserManager um = mContext.getSystemService(UserManager.class);
UserHandle parentUser = mFeatureFlags.profileUserSupport()
@@ -2085,7 +2151,7 @@
// Only connect to the non-ui InCallServices if we actually connected to the main UI
// one, or if the call is self-managed (in which case we'd still want to keep Wear, BT,
// etc. informed.
- connectToNonUiInCallServices(call, skipBTServices);
+ connectToNonUiInCallServices(call);
mBindingFuture = new CompletableFuture<Boolean>().completeOnTimeout(false,
mTimeoutsAdapter.getCallRemoveUnbindInCallServicesDelay(
mContext.getContentResolver()),
@@ -2100,7 +2166,7 @@
packageChangedFilter, null, null);
}
- private void updateNonUiInCallServices(Call call, boolean skipBTService) {
+ private void updateNonUiInCallServices(Call call) {
UserHandle userFromCall = getUserFromCall(call);
UserManager um = mContext.getSystemService(UserManager.class);
@@ -2155,10 +2221,10 @@
nonUIInCalls));
}
- private void connectToNonUiInCallServices(Call call, boolean skipBTService) {
+ private void connectToNonUiInCallServices(Call call) {
UserHandle userFromCall = getUserFromCall(call);
if (!mNonUIInCallServiceConnections.containsKey(userFromCall)) {
- updateNonUiInCallServices(call, skipBTService);
+ updateNonUiInCallServices(call);
}
mNonUIInCallServiceConnections.get(userFromCall).connect(call);
}
@@ -2427,10 +2493,8 @@
return IN_CALL_SERVICE_TYPE_DEFAULT_DIALER_UI;
}
- String bluetoothPackage = mDefaultDialerCache.getBTInCallServicePackage();
- if (mFeatureFlags.separatelyBindToBtIncallService()
- && serviceInfo.packageName != null
- && serviceInfo.packageName.equals(bluetoothPackage)
+ boolean processingBluetoothPackage = isBluetoothPackage(serviceInfo.packageName);
+ if (mFeatureFlags.separatelyBindToBtIncallService() && processingBluetoothPackage
&& (hasControlInCallPermission || hasAppOpsPermittedManageOngoingCalls)) {
return IN_CALL_SERVICE_TYPE_BLUETOOTH;
}
@@ -2477,11 +2541,13 @@
IInCallService inCallService = IInCallService.Stub.asInterface(service);
if (mFeatureFlags.separatelyBindToBtIncallService()
&& info.getType() == IN_CALL_SERVICE_TYPE_BLUETOOTH) {
- if (mBtBindingFuture.isDone()) {
+ if (!mBtBindingFuture.containsKey(userHandle)
+ || mBtBindingFuture.get(userHandle).isDone()) {
+ Log.i(this, "onConnected: BT binding future timed out.");
// Binding completed after the timeout. Clean up this binding
return false;
} else {
- mBtBindingFuture.complete(true);
+ mBtBindingFuture.get(userHandle).complete(true);
}
mBTInCallServices.put(userHandle, new Pair<>(info, inCallService));
} else {
@@ -2652,12 +2718,20 @@
IInCallService inCallService = entry.getValue();
componentsUpdated.add(componentName);
- try {
- inCallService.updateCall(
- sanitizeParcelableCallForService(info, parcelableCall));
- } catch (RemoteException exception) {
- Log.w(this, "Call status update did not send to: "
- + componentName +" successfully with error " + exception);
+ 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));
+ } else {
+ updateCallToIcs(inCallService, info, parcelableCall, componentName);
}
}
Log.i(this, "Components updated: %s", componentsUpdated);
@@ -2667,12 +2741,27 @@
}
}
+ private void updateCallToIcs(IInCallService inCallService, InCallServiceInfo info,
+ ParcelableCall parcelableCall, ComponentName componentName) {
+ try {
+ inCallService.updateCall(
+ sanitizeParcelableCallForService(info, parcelableCall));
+ } catch (RemoteException exception) {
+ Log.w(this, "Call status update did not send to: "
+ + componentName + " successfully with error " + exception);
+ }
+ }
+
/**
* Adds the call to the list of calls tracked by the {@link InCallController}.
* @param call The call to add.
*/
@VisibleForTesting
public void addCall(Call call) {
+ if (call == null) {
+ return;
+ }
+
if (mCallIdMapper.getCalls().size() == 0) {
mAppOpsManager.startWatchingActive(new String[] { OPSTR_RECORD_AUDIO },
java.lang.Runnable::run, this);
@@ -2683,12 +2772,12 @@
if (mCallIdMapper.getCallId(call) == null) {
mCallIdMapper.addCall(call);
call.addListener(mCallListener);
+ if (mFeatureFlags.separatelyBindToBtIncallService()) {
+ mPendingEndToneCall.add(call);
+ }
}
maybeTrackMicrophoneUse(isMuted());
- if (mFeatureFlags.separatelyBindToBtIncallService()) {
- mPendingEndToneCall.add(call);
- }
}
/**
@@ -2718,6 +2807,23 @@
}
/**
+ * @return A future that is pending whenever we are in the middle of binding to the BT
+ * incall service.
+ */
+ public CompletableFuture<Boolean> getBtBindingFuture(Call call) {
+ UserHandle userHandle = getUserFromCall(call);
+ return mBtBindingFuture.get(userHandle);
+ }
+
+ /**
+ * @return A future that is pending whenever we are in the process of sending the call
+ * disconnected state to the BT ICS so that the disconnect tone can finish playing.
+ */
+ public Map<String, CompletableFuture<Void>> getDisconnectedToneBtFutures() {
+ return mDisconnectedToneBtFutures;
+ }
+
+ /**
* Dumps the state of the {@link InCallController}.
*
* @param pw The {@code IndentingPrintWriter} to write the state to.
@@ -3174,7 +3280,10 @@
}
}
}
- return false;
+ // If early binding for BT ICS is enabled, ensure that it is included into consideration as
+ // a bound non-UI ICS.
+ return mFeatureFlags.separatelyBindToBtIncallService() && !mBTInCallServices.isEmpty()
+ && isBluetoothPackage(packageName);
}
private void updateCombinedInCallServiceMap(UserHandle user) {
@@ -3208,4 +3317,13 @@
}
}
}
+
+ private boolean isBluetoothPackage(String packageName) {
+ for (String pkgName : mDefaultDialerCache.getBTInCallServicePackages()) {
+ if (pkgName.equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/src/com/android/server/telecom/RoleManagerAdapter.java b/src/com/android/server/telecom/RoleManagerAdapter.java
index 9f515e6..1b5c71b 100644
--- a/src/com/android/server/telecom/RoleManagerAdapter.java
+++ b/src/com/android/server/telecom/RoleManagerAdapter.java
@@ -71,7 +71,7 @@
* bt in-call service role.
* @return the package name of the package filling the role, {@code null} otherwise.
*/
- String getBTInCallService();
+ String[] getBTInCallService();
/**
* Override the {@link android.app.role.RoleManager} bt in-call service package with another
diff --git a/src/com/android/server/telecom/RoleManagerAdapterImpl.java b/src/com/android/server/telecom/RoleManagerAdapterImpl.java
index 33ec466..ded4d9c 100644
--- a/src/com/android/server/telecom/RoleManagerAdapterImpl.java
+++ b/src/com/android/server/telecom/RoleManagerAdapterImpl.java
@@ -78,9 +78,9 @@
}
@Override
- public String getBTInCallService() {
+ public String[] getBTInCallService() {
if (mOverrideBTInCallService != null) {
- return mOverrideBTInCallService;
+ return new String [] {mOverrideBTInCallService};
}
return getBluetoothInCallServicePackageName();
}
@@ -166,8 +166,8 @@
return roleHolders.get(0);
}
- private String getBluetoothInCallServicePackageName() {
- return mContext.getResources().getString(R.string.system_bluetooth_stack);
+ private String[] getBluetoothInCallServicePackageName() {
+ return mContext.getResources().getStringArray(R.array.system_bluetooth_stack_package_name);
}
/**
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 230bb09..20320f2 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -1672,7 +1672,13 @@
&& accountExtra != null && accountExtra.getBoolean(
PhoneAccount.EXTRA_SKIP_CALL_FILTERING,
false)) {
- mCallsManager.getInCallController().bindToServices(null, false);
+ if (mFeatureFlags.separatelyBindToBtIncallService()) {
+ mCallsManager.getInCallController().bindToBTService(
+ null, null);
+ }
+ // Should be able to run this as is even if above flag is
+ // enabled (BT binding should be skipped automatically).
+ mCallsManager.getInCallController().bindToServices(null);
}
}
} finally {
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java b/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
index 97405a3..1d641ba 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioManagerTest.java
@@ -16,6 +16,8 @@
package com.android.server.telecom.tests;
+import static com.android.server.telecom.tests.TelecomSystemTest.TEST_TIMEOUT;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -34,6 +36,8 @@
import static org.mockito.Mockito.when;
import android.media.ToneGenerator;
+import android.os.Handler;
+import android.os.Looper;
import android.telecom.DisconnectCause;
import android.util.SparseArray;
@@ -67,6 +71,7 @@
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@RunWith(JUnit4.class)
@@ -423,9 +428,12 @@
Call call = mock(Call.class);
ArgumentCaptor<CallAudioModeStateMachine.MessageArgs> captor = makeNewCaptor();
when(call.getState()).thenReturn(CallState.RINGING);
+ handleWaitForBtIcsBinding(call);
// Make sure appropriate messages are sent when we add a RINGING call
mCallAudioManager.onCallAdded(call);
+ mCallAudioManager.getCallRingingFuture().join();
+ waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
assertEquals(call, mCallAudioManager.getForegroundCall());
verify(mCallAudioRouteStateMachine).sendMessageWithSessionInfo(
@@ -556,10 +564,14 @@
Call call = createAudioProcessingCall();
+
when(call.getState()).thenReturn(CallState.SIMULATED_RINGING);
+ handleWaitForBtIcsBinding(call);
mCallAudioManager.onCallStateChanged(call, CallState.AUDIO_PROCESSING,
CallState.SIMULATED_RINGING);
+ mCallAudioManager.getCallRingingFuture().join();
+ waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
verify(mPlayerFactory, never()).createPlayer(any(Call.class), anyInt());
CallAudioModeStateMachine.MessageArgs expectedArgs = new Builder()
.setHasActiveOrDialingCalls(false)
@@ -810,9 +822,12 @@
private Call createSimulatedRingingCall() {
Call call = mock(Call.class);
when(call.getState()).thenReturn(CallState.SIMULATED_RINGING);
+ handleWaitForBtIcsBinding(call);
ArgumentCaptor<CallAudioModeStateMachine.MessageArgs> captor = makeNewCaptor();
mCallAudioManager.onCallAdded(call);
+ mCallAudioManager.getCallRingingFuture().join();
+ waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
assertEquals(call, mCallAudioManager.getForegroundCall());
@@ -838,8 +853,11 @@
private Call createIncomingCall() {
Call call = mock(Call.class);
when(call.getState()).thenReturn(CallState.RINGING);
+ handleWaitForBtIcsBinding(call);
mCallAudioManager.onCallAdded(call);
+ mCallAudioManager.getCallRingingFuture().join();
+ waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
assertEquals(call, mCallAudioManager.getForegroundCall());
ArgumentCaptor<CallAudioModeStateMachine.MessageArgs> captor =
ArgumentCaptor.forClass(CallAudioModeStateMachine.MessageArgs.class);
@@ -924,4 +942,10 @@
assertEquals(expected.isTonePlaying, actual.isTonePlaying);
assertEquals(expected.foregroundCallIsVoip, actual.foregroundCallIsVoip);
}
+
+ private void handleWaitForBtIcsBinding(Call call) {
+ when(mFlags.separatelyBindToBtIncallService()).thenReturn(true);
+ CompletableFuture<Boolean> btBindingFuture = CompletableFuture.completedFuture(true);
+ when(call.getBtIcsFuture()).thenReturn(btBindingFuture);
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index e7f2d83..6f5b4e7 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -3610,8 +3610,6 @@
.setShouldAllowCall(true)
.setShouldReject(false)
.build();
- when(mInCallController.bindToBTService(eq(call))).thenReturn(
- CompletableFuture.completedFuture(true));
when(mInCallController.isBoundAndConnectedToBTService(any(UserHandle.class)))
.thenReturn(false);
@@ -3619,7 +3617,7 @@
InOrder inOrder = inOrder(mInCallController, call, mInCallController);
- inOrder.verify(mInCallController).bindToBTService(eq(call));
+ inOrder.verify(mInCallController).bindToBTService(eq(call), eq(null));
inOrder.verify(call).setState(eq(CallState.RINGING), anyString());
}
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index 6c07c79..6af31ae 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -225,7 +225,7 @@
when(mDefaultDialerCache.getSystemDialerApplication()).thenReturn(SYS_PKG);
when(mDefaultDialerCache.getSystemDialerComponent()).thenReturn(
new ComponentName(SYS_PKG, SYS_CLASS));
- when(mDefaultDialerCache.getBTInCallServicePackage()).thenReturn(BT_PKG);
+ when(mDefaultDialerCache.getBTInCallServicePackages()).thenReturn(new String[] {BT_PKG});
mEmergencyCallHelper = new EmergencyCallHelper(mMockContext, mDefaultDialerCache,
mTimeoutsAdapter);
when(mMockCallsManager.getRoleManagerAdapter()).thenReturn(mMockRoleManagerAdapter);
@@ -409,7 +409,7 @@
.thenReturn(300_000L);
setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext).bindServiceAsUser(
@@ -444,7 +444,7 @@
Intent queryIntent = new Intent(InCallService.SERVICE_INTERFACE);
setupMockPackageManager(false /* default */, true /* system */, false /* external calls */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext).bindServiceAsUser(
@@ -483,7 +483,7 @@
anyInt(), eq(mUserHandle))).thenReturn(true);
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Query for the different InCallServices
ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -546,7 +546,7 @@
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Query for the different InCallServices
ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -608,7 +608,7 @@
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext, times(1)).bindServiceAsUser(
@@ -639,7 +639,7 @@
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext, times(1)).bindServiceAsUser(
@@ -672,7 +672,7 @@
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext, times(1)).bindServiceAsUser(
@@ -701,7 +701,7 @@
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext, times(1)).bindServiceAsUser(
@@ -751,7 +751,7 @@
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
setupMockPackageManagerLocationPermission(SYS_PKG, false /* granted */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Query for the different InCallServices
ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -833,7 +833,7 @@
.thenReturn(true);
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Query for the different InCallServices
ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -914,7 +914,7 @@
when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(DEF_PKG);
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
@@ -961,7 +961,7 @@
mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);
// Now bind; we should only bind to one app.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Bind InCallServices
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1044,7 +1044,7 @@
.thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
mInCallController.addCall(mMockCall);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// There will be 4 calls for the various types of ICS.
verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
@@ -1213,7 +1213,7 @@
public void testBindToService_IncludeExternal() throws Exception {
setupMocks(true /* isExternalCall */);
setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Query for the different InCallServices
ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1264,7 +1264,7 @@
when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
@@ -1313,7 +1313,7 @@
mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);
// Now bind; we should only bind to one app.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Bind InCallServices
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1332,7 +1332,7 @@
public void testNoBindToInvalidService_CarModeUI() throws Exception {
setupMocks(true /* isExternalCall */);
setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
when(mMockPackageManager.checkPermission(
matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
@@ -1384,7 +1384,7 @@
anyInt(), any(AttributionSource.class), nullable(String.class)));
// Now bind; we should bind to the system dialer and app op non ui app.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Bind InCallServices
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1428,7 +1428,7 @@
when(mDefaultDialerCache.getDefaultDialerApplication(CURRENT_USER_ID)).thenReturn(null);
// we should bind to only the non ui app.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Bind InCallServices
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1461,7 +1461,7 @@
matches(DEF_PKG))).thenReturn(PackageManager.PERMISSION_DENIED);
when(mMockCall.getName()).thenReturn("evil");
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Bind InCallServices
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1498,7 +1498,7 @@
setupMocks(true /* isExternalCall */);
setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
// Bind to default dialer.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Uninstall an unrelated app.
mSystemStateListener.onPackageUninstalled("com.joe.stuff");
@@ -1522,7 +1522,7 @@
setupMocks(true /* isExternalCall */);
setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
// Bind to default dialer.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Enable car mode and enter car mode at default priority.
when(mMockSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(true);
@@ -1590,7 +1590,7 @@
setupMockPackageManager(true /* default */, true /* nonui */, false /* appop_nonui */ ,
true /* system */, false /* external calls */,
false /* self mgd in default*/, false /* self mgd in car*/);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
@@ -1659,7 +1659,7 @@
// Bind; we should not bind to anything right now; the dialer does not support self
// managed calls.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Bind InCallServices; make sure no binding took place. InCallController handles not
// binding initially, but the rebind (see next test case) will always happen.
@@ -1698,7 +1698,7 @@
// Bind; we should not bind to anything right now; the dialer does not support self
// managed calls.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Bind InCallServices; make sure no binding took place.
verify(mMockContext, never()).bindServiceAsUser(
@@ -1800,7 +1800,7 @@
assertFalse(mUserHandle.equals(UserHandle.USER_CURRENT));
when(mMockCurrentUserManager.isManagedProfile()).thenReturn(false);
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
// Bind InCallService on UserHandle.CURRENT and not the user from the call (mUserHandle)
ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -1821,7 +1821,7 @@
when(mMockCall.getAssociatedUser()).thenReturn(testUser);
// Bind to ICS. The mapping should've been inserted with the testUser as the key.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
assertTrue(mInCallController.getInCallServiceConnections().containsKey(testUser));
// Set the target phone account. Simulates the flow when the user has chosen which sim to
@@ -1849,7 +1849,7 @@
when(mMockCall.isIncoming()).thenReturn(true);
// Bind to ICS. The mapping should've been inserted with the testUser as the key.
- mInCallController.bindToServices(mMockCall, false);
+ mInCallController.bindToServices(mMockCall);
assertTrue(mInCallController.getInCallServiceConnections().containsKey(testUser));
// Remove the call. This invokes getUserFromCall to remove the ICS mapping.
@@ -1951,7 +1951,7 @@
true /*includeSelfManagedCallsInNonUi*/);
//pass in call by child/profile user
- mInCallController.bindToServices(mMockChildUserCall, false);
+ mInCallController.bindToServices(mMockChildUserCall);
// Verify that queryIntentServicesAsUser is also called with parent handle
// Query for the different InCallServices
ArgumentCaptor<Integer> userIdCaptor = ArgumentCaptor.forClass(Integer.class);
@@ -1974,7 +1974,7 @@
setupMocks(false /* isExternalCall */);
setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
Intent expectedIntent = new Intent(InCallService.SERVICE_INTERFACE);
- expectedIntent.setPackage(mDefaultDialerCache.getBTInCallServicePackage());
+ expectedIntent.setPackage(mDefaultDialerCache.getBTInCallServicePackages()[0]);
LinkedList<ResolveInfo> resolveInfo = new LinkedList<ResolveInfo>();
resolveInfo.add(getBluetoothResolveinfo());
when(mFeatureFlags.separatelyBindToBtIncallService()).thenReturn(true);
@@ -1990,7 +1990,7 @@
}).when(mMockPackageManager).queryIntentServicesAsUser(any(Intent.class), anyInt(),
anyInt());
- mInCallController.bindToBTService(mMockCall);
+ mInCallController.bindToBTService(mMockCall, null);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext).bindServiceAsUser(captor.capture(), any(ServiceConnection.class),
diff --git a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
index d1dd20c..dc5f325 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomServiceImplTest.java
@@ -1167,7 +1167,7 @@
verify(mFakePhoneAccountRegistrar).getPhoneAccount(
TEL_PA_HANDLE_16, TEL_PA_HANDLE_16.getUserHandle());
- verify(mInCallController, never()).bindToServices(any(), anyBoolean());
+ verify(mInCallController, never()).bindToServices(any());
addCallTestHelper(TelecomManager.ACTION_INCOMING_CALL,
CallIntentProcessor.KEY_IS_INCOMING_CALL, extras,
TEL_PA_HANDLE_16, false);
@@ -1189,7 +1189,7 @@
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
- verify(mInCallController, never()).bindToServices(eq(null), anyBoolean());
+ verify(mInCallController, never()).bindToServices(eq(null));
}
@SmallTest
@@ -1207,7 +1207,7 @@
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
- verify(mInCallController).bindToServices(eq(null), anyBoolean());
+ verify(mInCallController).bindToServices(eq(null));
}
@SmallTest
@@ -1225,7 +1225,7 @@
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
- verify(mInCallController, never()).bindToServices(eq(null), anyBoolean());
+ verify(mInCallController, never()).bindToServices(eq(null));
}
@SmallTest
@@ -1244,7 +1244,7 @@
mTSIBinder.addNewIncomingCall(TEL_PA_HANDLE_16, extras, CALLING_PACKAGE);
- verify(mInCallController, never()).bindToServices(eq(null), anyBoolean());
+ verify(mInCallController, never()).bindToServices(eq(null));
}
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index a8663d6..4463d65 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -516,6 +516,7 @@
when(mRoleManagerAdapter.getCallCompanionApps()).thenReturn(Collections.emptyList());
when(mRoleManagerAdapter.getDefaultCallScreeningApp(any(UserHandle.class)))
.thenReturn(null);
+ when(mRoleManagerAdapter.getBTInCallService()).thenReturn(new String[] {"bt_pkg"});
when(mFeatureFlags.useRefactoredAudioRouteSwitching()).thenReturn(false);
mTelecomSystem = new TelecomSystem(
mComponentContextFixture.getTestDouble(),