Snap for 11967491 from 413076efd674d5c558cd754253082fb0a78e8b5c to 24Q3-release
Change-Id: I0b563b9f97044be9c6d4366199dec232c9a48bcd
diff --git a/src/com/android/server/telecom/CallAudioRouteController.java b/src/com/android/server/telecom/CallAudioRouteController.java
index 820219d..76555c3 100644
--- a/src/com/android/server/telecom/CallAudioRouteController.java
+++ b/src/com/android/server/telecom/CallAudioRouteController.java
@@ -53,6 +53,7 @@
import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.flags.FeatureFlags;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -76,6 +77,9 @@
ROUTE_MAP.put(AudioRoute.TYPE_STREAMING, CallAudioState.ROUTE_STREAMING);
}
+ /** Valid values for the first argument for SWITCH_BASELINE_ROUTE */
+ public static final int INCLUDE_BLUETOOTH_IN_BASELINE = 1;
+
private final CallsManager mCallsManager;
private final Context mContext;
private AudioManager mAudioManager;
@@ -91,6 +95,8 @@
private AudioRoute mStreamingRoute;
private Set<AudioRoute> mStreamingRoutes;
private Map<AudioRoute, BluetoothDevice> mBluetoothRoutes;
+ private Pair<Integer, String> mActiveBluetoothDevice;
+ private Map<Integer, String> mActiveDeviceCache;
private Map<Integer, AudioRoute> mTypeRoutes;
private PendingAudioRoute mPendingAudioRoute;
private AudioRoute.Factory mAudioRouteFactory;
@@ -260,9 +266,13 @@
handleSwitchSpeaker();
break;
case SWITCH_BASELINE_ROUTE:
- case USER_SWITCH_BASELINE_ROUTE:
address = (String) ((SomeArgs) msg.obj).arg2;
- handleSwitchBaselineRoute(address);
+ handleSwitchBaselineRoute(msg.arg1 == INCLUDE_BLUETOOTH_IN_BASELINE,
+ address);
+ break;
+ case USER_SWITCH_BASELINE_ROUTE:
+ handleSwitchBaselineRoute(msg.arg1 == INCLUDE_BLUETOOTH_IN_BASELINE,
+ null);
break;
case SPEAKER_ON:
handleSpeakerOn();
@@ -312,6 +322,11 @@
public void initialize() {
mAvailableRoutes = new HashSet<>();
mBluetoothRoutes = new LinkedHashMap<>();
+ mActiveDeviceCache = new HashMap<>();
+ mActiveDeviceCache.put(AudioRoute.TYPE_BLUETOOTH_SCO, null);
+ mActiveDeviceCache.put(AudioRoute.TYPE_BLUETOOTH_HA, null);
+ mActiveDeviceCache.put(AudioRoute.TYPE_BLUETOOTH_LE, null);
+ mActiveBluetoothDevice = null;
mTypeRoutes = new ArrayMap<>();
mStreamingRoutes = new HashSet<>();
mPendingAudioRoute = new PendingAudioRoute(this, mAudioManager, mBluetoothRouteManager);
@@ -805,11 +820,16 @@
Log.i(this, "handle switch to bluetooth with address %s", address);
AudioRoute bluetoothRoute = null;
BluetoothDevice bluetoothDevice = null;
- for (AudioRoute route : getAvailableRoutes()) {
- if (Objects.equals(address, route.getBluetoothAddress())) {
- bluetoothRoute = route;
- bluetoothDevice = mBluetoothRoutes.get(route);
- break;
+ if (address == null) {
+ bluetoothRoute = getArbitraryBluetoothDevice();
+ bluetoothDevice = mBluetoothRoutes.get(bluetoothRoute);
+ } else {
+ for (AudioRoute route : getAvailableRoutes()) {
+ if (Objects.equals(address, route.getBluetoothAddress())) {
+ bluetoothRoute = route;
+ bluetoothDevice = mBluetoothRoutes.get(route);
+ break;
+ }
}
}
@@ -825,6 +845,20 @@
}
}
+ /**
+ * Retrieve the active BT device, if available, otherwise return the most recently tracked
+ * active device, or null if none are available.
+ * @return {@link AudioRoute} of the BT device.
+ */
+ private AudioRoute getArbitraryBluetoothDevice() {
+ if (mActiveBluetoothDevice != null) {
+ return getBluetoothRoute(mActiveBluetoothDevice.first, mActiveBluetoothDevice.second);
+ } else if (!mBluetoothRoutes.isEmpty()) {
+ return mBluetoothRoutes.keySet().stream().toList().get(mBluetoothRoutes.size() - 1);
+ }
+ return null;
+ }
+
private void handleSwitchHeadset() {
AudioRoute headsetRoute = mTypeRoutes.get(AudioRoute.TYPE_WIRED);
if (headsetRoute != null && getAvailableRoutes().contains(headsetRoute)) {
@@ -842,8 +876,8 @@
}
}
- private void handleSwitchBaselineRoute(String btAddressToExclude) {
- routeTo(mIsActive, getBaseRoute(true, btAddressToExclude));
+ private void handleSwitchBaselineRoute(boolean includeBluetooth, String btAddressToExclude) {
+ routeTo(mIsActive, getBaseRoute(includeBluetooth, btAddressToExclude));
}
private void handleSpeakerOn() {
@@ -1085,7 +1119,7 @@
public AudioRoute getBaseRoute(boolean includeBluetooth, String btAddressToExclude) {
AudioRoute destRoute = getPreferredAudioRouteFromStrategy();
- if (destRoute == null) {
+ if (destRoute == null || (destRoute.getBluetoothAddress() != null && !includeBluetooth)) {
destRoute = getPreferredAudioRouteFromDefault(includeBluetooth, btAddressToExclude);
}
if (destRoute != null && !getAvailableRoutes().contains(destRoute)) {
@@ -1243,6 +1277,39 @@
mIsScoAudioConnected = value;
}
+ /**
+ * Update the active bluetooth device being tracked (as well as for individual profiles).
+ * We need to keep track of active devices for individual profiles because of potential
+ * inconsistencies found in BluetoothStateReceiver#handleActiveDeviceChanged. When multiple
+ * profiles are paired, we could have a scenario where an active device A is replaced
+ * with an active device B (from a different profile), which is then removed as an active
+ * device shortly after, causing device A to be reactive. It's possible that the active device
+ * changed intent is never received again for device A so an active device cache is necessary
+ * to track these devices at a profile level.
+ * @param device {@link Pair} containing the BT audio route type (i.e. SCO/HA/LE) and the
+ * address of the device.
+ */
+ public void updateActiveBluetoothDevice(Pair<Integer, String> device) {
+ mActiveDeviceCache.put(device.first, device.second);
+ // Update most recently active device if address isn't null (meaning some device is active).
+ if (device.second != null) {
+ mActiveBluetoothDevice = device;
+ } else {
+ // If a device was removed, check to ensure that no other device is still considered
+ // active.
+ boolean hasActiveDevice = false;
+ for (String address : mActiveDeviceCache.values()) {
+ if (address != null) {
+ hasActiveDevice = true;
+ break;
+ }
+ }
+ if (!hasActiveDevice) {
+ mActiveBluetoothDevice = null;
+ }
+ }
+ }
+
@VisibleForTesting
public void setActive(boolean active) {
if (active) {
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 79ce5a3..c3c0c1c 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -167,10 +167,17 @@
ParcelableConference conference, Session.Info sessionInfo) {
Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE,
mPackageAbbreviation);
+ UserHandle callingUserHandle = Binder.getCallingUserHandle();
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
logIncoming("handleCreateConferenceComplete %s", callId);
+ // Check status hints image for cross user access
+ if (conference.getStatusHints() != null) {
+ Icon icon = conference.getStatusHints().getIcon();
+ conference.getStatusHints().setIcon(StatusHints.
+ validateAccountIconUserBoundary(icon, callingUserHandle));
+ }
Call call = mCallIdMapper.getCall(callId);
if (mScheduledFutureMap.containsKey(call)) {
ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
diff --git a/src/com/android/server/telecom/PendingAudioRoute.java b/src/com/android/server/telecom/PendingAudioRoute.java
index f9cdc35..396aca0 100644
--- a/src/com/android/server/telecom/PendingAudioRoute.java
+++ b/src/com/android/server/telecom/PendingAudioRoute.java
@@ -18,6 +18,7 @@
import static com.android.server.telecom.CallAudioRouteAdapter.PENDING_ROUTE_FAILED;
import static com.android.server.telecom.CallAudioRouteAdapter.SWITCH_BASELINE_ROUTE;
+import static com.android.server.telecom.CallAudioRouteController.INCLUDE_BLUETOOTH_IN_BASELINE;
import android.bluetooth.BluetoothDevice;
import android.media.AudioManager;
@@ -96,7 +97,7 @@
if (message.first == PENDING_ROUTE_FAILED) {
// Fallback to base route
mCallAudioRouteController.sendMessageWithSessionInfo(
- SWITCH_BASELINE_ROUTE, 0, btAddressToExclude);
+ SWITCH_BASELINE_ROUTE, INCLUDE_BLUETOOTH_IN_BASELINE, btAddressToExclude);
return;
}
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 0a8ce5a..3c97d41 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -20,6 +20,7 @@
import static com.android.server.telecom.AudioRoute.TYPE_BLUETOOTH_SCO;
import static com.android.server.telecom.CallAudioRouteAdapter.BT_DEVICE_REMOVED;
import static com.android.server.telecom.CallAudioRouteAdapter.SWITCH_BASELINE_ROUTE;
+import static com.android.server.telecom.CallAudioRouteController.INCLUDE_BLUETOOTH_IN_BASELINE;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -257,7 +258,7 @@
BT_DEVICE_REMOVED, route.getType(), device);
}
mCallAudioRouteAdapter.sendMessageWithSessionInfo(
- SWITCH_BASELINE_ROUTE, 0, (String) null);
+ SWITCH_BASELINE_ROUTE, INCLUDE_BLUETOOTH_IN_BASELINE, (String) null);
}
private final LinkedHashMap<String, BluetoothDevice> mHfpDevicesByAddress =
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index 9168388..f76391c 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -236,10 +236,15 @@
BluetoothDeviceManager.getDeviceTypeString(deviceType));
if (Flags.useRefactoredAudioRouteSwitching()) {
+ CallAudioRouteController audioRouteController = (CallAudioRouteController)
+ mCallAudioRouteAdapter;
if (device == null) {
+ audioRouteController.updateActiveBluetoothDevice(new Pair(audioRouteType, null));
mCallAudioRouteAdapter.sendMessageWithSessionInfo(BT_ACTIVE_DEVICE_GONE,
audioRouteType);
} else {
+ audioRouteController.updateActiveBluetoothDevice(
+ new Pair(audioRouteType, device.getAddress()));
mCallAudioRouteAdapter.sendMessageWithSessionInfo(BT_ACTIVE_DEVICE_PRESENT,
audioRouteType, device.getAddress());
if (deviceType == BluetoothDeviceManager.DEVICE_TYPE_HEARING_AID