summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kyunglyul Hyun <klhyun@google.com> 2020-06-22 04:30:30 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-06-22 04:30:30 +0000
commit4b6472722e763d1aa9ba4abcb302a671d2fb9354 (patch)
tree07d420d40a3b3c5f1e3db452bdd18396769cd1ab
parent98e874e58590a3dd76e6c5aa5d5bc42bdf01ecfe (diff)
parente1b8006e2bedf8a7ae2c4cf489ab424804b77730 (diff)
Merge "Handle multiple active bluetooth devices" into rvc-dev
-rw-r--r--media/java/android/media/MediaRouter2Manager.java2
-rw-r--r--services/core/java/com/android/server/media/BluetoothRouteProvider.java126
2 files changed, 94 insertions, 34 deletions
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 773263865135..ce036deb6164 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -344,6 +344,8 @@ public final class MediaRouter2Manager {
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
Objects.requireNonNull(route, "route must not be null");
+ Log.v(TAG, "Transferring routing session. session= " + sessionInfo + ", route=" + route);
+
synchronized (mRoutesLock) {
if (!mRoutes.containsKey(route.getId())) {
Log.w(TAG, "transfer: Ignoring an unknown route id=" + route.getId());
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index 4def7db76bc5..25d54db0f839 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -17,6 +17,8 @@
package com.android.server.media;
import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_AUDIO;
+import static android.bluetooth.BluetoothAdapter.STATE_CONNECTED;
+import static android.bluetooth.BluetoothAdapter.STATE_DISCONNECTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -33,6 +35,7 @@ import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.MediaRoute2Info;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
@@ -48,6 +51,8 @@ import java.util.Objects;
class BluetoothRouteProvider {
private static final String TAG = "BTRouteProvider";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
private static BluetoothRouteProvider sInstance;
@@ -55,7 +60,7 @@ class BluetoothRouteProvider {
// Maps hardware address to BluetoothRouteInfo
final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
@SuppressWarnings("WeakerAccess") /* synthetic access */
- BluetoothRouteInfo mSelectedRoute = null;
+ final List<BluetoothRouteInfo> mActiveRoutes = new ArrayList<>();
@SuppressWarnings("WeakerAccess") /* synthetic access */
BluetoothA2dp mA2dpProfile;
@SuppressWarnings("WeakerAccess") /* synthetic access */
@@ -104,7 +109,7 @@ class BluetoothRouteProvider {
// Bluetooth on/off broadcasts
addEventReceiver(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedReceiver());
- DeviceStateChangedRecevier deviceStateChangedReceiver = new DeviceStateChangedRecevier();
+ DeviceStateChangedReceiver deviceStateChangedReceiver = new DeviceStateChangedReceiver();
addEventReceiver(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED, deviceStateChangedReceiver);
addEventReceiver(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED, deviceStateChangedReceiver);
addEventReceiver(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
@@ -168,14 +173,16 @@ class BluetoothRouteProvider {
@Nullable
MediaRoute2Info getSelectedRoute() {
- return (mSelectedRoute == null) ? null : mSelectedRoute.route;
+ // For now, active routes can be multiple only when a pair of hearing aid devices is active.
+ // Let the first active device represent them.
+ return (mActiveRoutes.isEmpty() ? null : mActiveRoutes.get(0).route);
}
@NonNull
List<MediaRoute2Info> getTransferableRoutes() {
List<MediaRoute2Info> routes = getAllBluetoothRoutes();
- if (mSelectedRoute != null) {
- routes.remove(mSelectedRoute.route);
+ for (BluetoothRouteInfo btRoute : mActiveRoutes) {
+ routes.remove(btRoute.route);
}
return routes;
}
@@ -185,8 +192,14 @@ class BluetoothRouteProvider {
List<MediaRoute2Info> routes = new ArrayList<>();
List<String> routeIds = new ArrayList<>();
+ MediaRoute2Info selectedRoute = getSelectedRoute();
+ if (selectedRoute != null) {
+ routes.add(selectedRoute);
+ routeIds.add(selectedRoute.getId());
+ }
+
for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
- // A pair of hearing aid devices or the same hardware address
+ // A pair of hearing aid devices or having the same hardware address
if (routeIds.contains(btRoute.route.getId())) {
continue;
}
@@ -225,13 +238,20 @@ class BluetoothRouteProvider {
return false;
}
mVolumeMap.put(routeType, volume);
- if (mSelectedRoute == null || mSelectedRoute.route.getType() != routeType) {
- return true;
+
+ boolean shouldNotify = false;
+ for (BluetoothRouteInfo btRoute : mActiveRoutes) {
+ if (btRoute.route.getType() != routeType) {
+ continue;
+ }
+ btRoute.route = new MediaRoute2Info.Builder(btRoute.route)
+ .setVolume(volume)
+ .build();
+ shouldNotify = true;
+ }
+ if (shouldNotify) {
+ notifyBluetoothRoutesUpdated();
}
- mSelectedRoute.route = new MediaRoute2Info.Builder(mSelectedRoute.route)
- .setVolume(volume)
- .build();
- notifyBluetoothRoutesUpdated();
return true;
}
@@ -297,6 +317,53 @@ class BluetoothRouteProvider {
btRoute.route = builder.build();
}
+ private void clearActiveRoutes() {
+ if (DEBUG) {
+ Log.d(TAG, "Clearing active routes");
+ }
+ for (BluetoothRouteInfo btRoute : mActiveRoutes) {
+ setRouteConnectionState(btRoute, STATE_DISCONNECTED);
+ }
+ mActiveRoutes.clear();
+ }
+
+ private void addActiveRoute(BluetoothRouteInfo btRoute) {
+ if (DEBUG) {
+ Log.d(TAG, "Adding active route: " + btRoute.route);
+ }
+ if (btRoute == null || mActiveRoutes.contains(btRoute)) {
+ return;
+ }
+ setRouteConnectionState(btRoute, STATE_CONNECTED);
+ mActiveRoutes.add(btRoute);
+ }
+
+ private void removeActiveRoute(BluetoothRouteInfo btRoute) {
+ if (DEBUG) {
+ Log.d(TAG, "Removing active route: " + btRoute.route);
+ }
+ if (mActiveRoutes.remove(btRoute)) {
+ setRouteConnectionState(btRoute, STATE_DISCONNECTED);
+ }
+ }
+
+ private void findAndSetActiveHearingAidDevices() {
+ if (DEBUG) {
+ Log.d(TAG, "Setting active hearing aid devices");
+ }
+
+ BluetoothHearingAid hearingAidProfile = mHearingAidProfile;
+ if (hearingAidProfile == null) {
+ return;
+ }
+ List<BluetoothDevice> activeDevices = hearingAidProfile.getActiveDevices();
+ for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+ if (activeDevices.contains(btRoute.btDevice)) {
+ addActiveRoute(btRoute);
+ }
+ }
+ }
+
interface BluetoothRoutesUpdatedListener {
void onBluetoothRoutesUpdated(@NonNull List<MediaRoute2Info> routes);
}
@@ -333,7 +400,6 @@ class BluetoothRouteProvider {
default:
return;
}
- //TODO(b/157708273): Handle two active devices in the binaural case.
for (BluetoothDevice device : proxy.getConnectedDevices()) {
BluetoothRouteInfo btRoute = mBluetoothRoutes.get(device.getAddress());
if (btRoute == null) {
@@ -341,9 +407,7 @@ class BluetoothRouteProvider {
mBluetoothRoutes.put(device.getAddress(), btRoute);
}
if (activeDevices.contains(device)) {
- mSelectedRoute = btRoute;
- setRouteConnectionState(mSelectedRoute,
- MediaRoute2Info.CONNECTION_STATE_CONNECTED);
+ addActiveRoute(btRoute);
}
}
notifyBluetoothRoutesUpdated();
@@ -395,26 +459,23 @@ class BluetoothRouteProvider {
}
}
- private class DeviceStateChangedRecevier implements BluetoothEventReceiver {
+ private class DeviceStateChangedReceiver implements BluetoothEventReceiver {
@Override
public void onReceive(Context context, Intent intent, BluetoothDevice device) {
switch (intent.getAction()) {
case BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED:
+ clearActiveRoutes();
+ if (device != null) {
+ addActiveRoute(mBluetoothRoutes.get(device.getAddress()));
+ }
+ notifyBluetoothRoutesUpdated();
+ break;
case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED:
- if (mSelectedRoute == null
- || !mSelectedRoute.btDevice.equals(device)) {
- if (mSelectedRoute != null) {
- setRouteConnectionState(mSelectedRoute,
- MediaRoute2Info.CONNECTION_STATE_DISCONNECTED);
- }
- mSelectedRoute = (device == null) ? null
- : mBluetoothRoutes.get(device.getAddress());
- if (mSelectedRoute != null) {
- setRouteConnectionState(mSelectedRoute,
- MediaRoute2Info.CONNECTION_STATE_CONNECTED);
- }
- notifyBluetoothRoutesUpdated();
+ clearActiveDevices();
+ if (device != null) {
+ findAndSetActiveHearingAidDevices();
}
+ notifyBluetoothRoutesUpdated();
break;
case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
handleConnectionStateChanged(BluetoothProfile.A2DP, intent, device);
@@ -444,10 +505,7 @@ class BluetoothRouteProvider {
if (btRoute != null) {
btRoute.connectedProfiles.delete(profile);
if (btRoute.connectedProfiles.size() == 0) {
- mBluetoothRoutes.remove(device.getAddress());
- if (mSelectedRoute != null && mSelectedRoute.btDevice.equals(device)) {
- mSelectedRoute = null;
- }
+ removeActiveRoute(mBluetoothRoutes.remove(device.getAddress()));
notifyBluetoothRoutesUpdated();
}
}