From 87c7f4116d35f94d62697cd6e16498d8baf60a06 Mon Sep 17 00:00:00 2001 From: Kyunglyul Hyun Date: Thu, 13 Aug 2020 23:42:51 +0900 Subject: [PATCH] MediaRouter: Create BluetoothRouteProvider for each user The bluetooth service manages the active device for each user and sent broadcast for each user. BluetoothRouteProvider was singleton and listened broadcast from the owner (uid=0) only , which failed to catch correct events when the foreground user is not the owner. This CL fixes that by creating BluetoothRouteProvider per user and listening to the events of each user. Bug: 162541640 Test: manually open the output switcher and check bluetooth state with switching users and run cts Change-Id: Iabab6f7830ce0224b7f73a7c5cfb863aebf5562b (cherry picked from commit 715b6488aeaa99b9949532d8a4608c3576f853f4) --- .../server/media/BluetoothRouteProvider.java | 25 +++++++++++-------- .../server/media/MediaRouter2ServiceImpl.java | 3 ++- .../media/SystemMediaRoute2Provider.java | 10 +++++--- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java index 3a4dfaf9bfcd8..0b3cdae9231eb 100644 --- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java +++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java @@ -34,6 +34,7 @@ import android.content.IntentFilter; import android.media.AudioManager; import android.media.AudioSystem; import android.media.MediaRoute2Info; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.Slog; @@ -55,7 +56,6 @@ class BluetoothRouteProvider { 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; @SuppressWarnings("WeakerAccess") /* synthetic access */ // Maps hardware address to BluetoothRouteInfo @@ -79,19 +79,21 @@ class BluetoothRouteProvider { private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver(); private final BluetoothProfileListener mProfileListener = new BluetoothProfileListener(); - static synchronized BluetoothRouteProvider getInstance(@NonNull Context context, + /** + * Create an instance of {@link BluetoothRouteProvider}. + * It may return {@code null} if Bluetooth is not supported on this hardware platform. + */ + @Nullable + static BluetoothRouteProvider createInstance(@NonNull Context context, @NonNull BluetoothRoutesUpdatedListener listener) { Objects.requireNonNull(context); Objects.requireNonNull(listener); - if (sInstance == null) { - BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); - if (btAdapter == null) { - return null; - } - sInstance = new BluetoothRouteProvider(context, btAdapter, listener); + BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); + if (btAdapter == null) { + return null; } - return sInstance; + return new BluetoothRouteProvider(context, btAdapter, listener); } private BluetoothRouteProvider(Context context, BluetoothAdapter btAdapter, @@ -103,7 +105,7 @@ class BluetoothRouteProvider { buildBluetoothRoutes(); } - public void start() { + public void start(UserHandle user) { mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP); mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID); @@ -118,7 +120,8 @@ class BluetoothRouteProvider { addEventReceiver(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED, deviceStateChangedReceiver); - mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, null); + mContext.registerReceiverAsUser(mBroadcastReceiver, user, + mIntentFilter, null, null); } /** diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 875bfdffafcd4..1114fe0d9bf8e 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -1176,7 +1176,8 @@ class MediaRouter2ServiceImpl { super(Looper.getMainLooper(), null, true); mServiceRef = new WeakReference<>(service); mUserRecord = userRecord; - mSystemProvider = new SystemMediaRoute2Provider(service.mContext); + mSystemProvider = new SystemMediaRoute2Provider(service.mContext, + UserHandle.of(userRecord.mUserId)); mRouteProviders.add(mSystemProvider); mWatcher = new MediaRoute2ProviderWatcher(service.mContext, this, this, mUserRecord.mUserId); diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index 2c089ca8300ea..4f7af9469668d 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -45,6 +45,7 @@ import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.Slog; @@ -99,7 +100,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } }; - SystemMediaRoute2Provider(Context context) { + SystemMediaRoute2Provider(Context context, UserHandle user) { super(sComponentName); mIsSystemRouteProvider = true; @@ -117,7 +118,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { updateDeviceRoute(newAudioRoutes); // .getInstance returns null if there is no bt adapter available - mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> { + mBtRouteProvider = BluetoothRouteProvider.createInstance(context, (routes) -> { publishProviderState(); boolean sessionInfoChanged; @@ -130,11 +131,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { IntentFilter intentFilter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION); intentFilter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION); - mContext.registerReceiver(new AudioManagerBroadcastReceiver(), intentFilter); + mContext.registerReceiverAsUser(new AudioManagerBroadcastReceiver(), user, + intentFilter, null, null); if (mBtRouteProvider != null) { mHandler.post(() -> { - mBtRouteProvider.start(); + mBtRouteProvider.start(user); notifyProviderState(); }); }