diff options
| -rw-r--r-- | services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java | 61 | ||||
| -rw-r--r-- | services/core/java/com/android/server/media/MediaRouterService.java | 82 |
2 files changed, 93 insertions, 50 deletions
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index d2b460e4fb51..1dd796504ea3 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -58,6 +58,8 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.function.pooled.PooledLambda; +import com.android.server.LocalServices; +import com.android.server.pm.UserManagerInternal; import java.io.PrintWriter; import java.lang.ref.WeakReference; @@ -87,6 +89,7 @@ class MediaRouter2ServiceImpl { private static final int PACKAGE_IMPORTANCE_FOR_DISCOVERY = IMPORTANCE_FOREGROUND_SERVICE; private final Context mContext; + private final UserManagerInternal mUserManagerInternal; private final Object mLock = new Object(); final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1); final ActivityManager mActivityManager; @@ -99,7 +102,7 @@ class MediaRouter2ServiceImpl { @GuardedBy("mLock") private final ArrayMap<IBinder, ManagerRecord> mAllManagerRecords = new ArrayMap<>(); @GuardedBy("mLock") - private int mCurrentUserId = -1; + private int mCurrentActiveUserId = -1; private final ActivityManager.OnUidImportanceListener mOnUidImportanceListener = (uid, importance) -> { @@ -125,12 +128,13 @@ class MediaRouter2ServiceImpl { } }; - MediaRouter2ServiceImpl(Context context) { + /* package */ MediaRouter2ServiceImpl(Context context) { mContext = context; mActivityManager = mContext.getSystemService(ActivityManager.class); mActivityManager.addOnUidImportanceListener(mOnUidImportanceListener, PACKAGE_IMPORTANCE_FOR_DISCOVERY); mPowerManager = mContext.getSystemService(PowerManager.class); + mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); IntentFilter screenOnOffIntentFilter = new IntentFilter(); screenOnOffIntentFilter.addAction(ACTION_SCREEN_ON); @@ -608,7 +612,7 @@ class MediaRouter2ServiceImpl { synchronized (mLock) { pw.println(indent + "mNextRouterOrManagerId=" + mNextRouterOrManagerId.get()); - pw.println(indent + "mCurrentUserId=" + mCurrentUserId); + pw.println(indent + "mCurrentActiveUserId=" + mCurrentActiveUserId); pw.println(indent + "UserRecords:"); if (mUserRecords.size() > 0) { @@ -621,24 +625,23 @@ class MediaRouter2ServiceImpl { } } - // TODO(b/136703681): Review this is handling multi-user properly. - void switchUser(int userId) { + /* package */ void updateRunningUserAndProfiles(int newActiveUserId) { synchronized (mLock) { - if (mCurrentUserId != userId) { - final int oldUserId = mCurrentUserId; - mCurrentUserId = userId; // do this first - - UserRecord oldUser = mUserRecords.get(oldUserId); - if (oldUser != null) { - oldUser.mHandler.sendMessage( - obtainMessage(UserHandler::stop, oldUser.mHandler)); - disposeUserIfNeededLocked(oldUser); // since no longer current user - } - - UserRecord newUser = mUserRecords.get(userId); - if (newUser != null) { - newUser.mHandler.sendMessage( - obtainMessage(UserHandler::start, newUser.mHandler)); + if (mCurrentActiveUserId != newActiveUserId) { + mCurrentActiveUserId = newActiveUserId; + for (int i = 0; i < mUserRecords.size(); i++) { + int userId = mUserRecords.keyAt(i); + UserRecord userRecord = mUserRecords.valueAt(i); + if (isUserActiveLocked(userId)) { + // userId corresponds to the active user, or one of its profiles. We + // ensure the associated structures are initialized. + userRecord.mHandler.sendMessage( + obtainMessage(UserHandler::start, userRecord.mHandler)); + } else { + userRecord.mHandler.sendMessage( + obtainMessage(UserHandler::stop, userRecord.mHandler)); + disposeUserIfNeededLocked(userRecord); + } } } } @@ -656,11 +659,21 @@ class MediaRouter2ServiceImpl { } } + /** + * Returns {@code true} if the given {@code userId} corresponds to the active user or a profile + * of the active user, returns {@code false} otherwise. + */ + @GuardedBy("mLock") + private boolean isUserActiveLocked(int userId) { + return mUserManagerInternal.getProfileParentId(userId) == mCurrentActiveUserId; + } + //////////////////////////////////////////////////////////////// //// ***Locked methods related to MediaRouter2 //// - Should have @NonNull/@Nullable on all arguments //////////////////////////////////////////////////////////////// + @GuardedBy("mLock") private void registerRouter2Locked(@NonNull IMediaRouter2 router, int uid, int pid, @NonNull String packageName, int userId, boolean hasConfigureWifiDisplayPermission, boolean hasModifyAudioRoutingPermission) { @@ -688,6 +701,7 @@ class MediaRouter2ServiceImpl { userRecord.mHandler, routerRecord)); } + @GuardedBy("mLock") private void unregisterRouter2Locked(@NonNull IMediaRouter2 router, boolean died) { RouterRecord routerRecord = mAllRouterRecords.remove(router.asBinder()); if (routerRecord == null) { @@ -910,6 +924,7 @@ class MediaRouter2ServiceImpl { return sessionInfos; } + @GuardedBy("mLock") private void registerManagerLocked(@NonNull IMediaRouter2Manager manager, int uid, int pid, @NonNull String packageName, int userId) { final IBinder binder = manager.asBinder(); @@ -1145,13 +1160,14 @@ class MediaRouter2ServiceImpl { //// - Should have @NonNull/@Nullable on all arguments //////////////////////////////////////////////////////////// + @GuardedBy("mLock") private UserRecord getOrCreateUserRecordLocked(int userId) { UserRecord userRecord = mUserRecords.get(userId); if (userRecord == null) { userRecord = new UserRecord(userId); mUserRecords.put(userId, userRecord); userRecord.init(); - if (userId == mCurrentUserId) { + if (isUserActiveLocked(userId)) { userRecord.mHandler.sendMessage( obtainMessage(UserHandler::start, userRecord.mHandler)); } @@ -1159,12 +1175,13 @@ class MediaRouter2ServiceImpl { return userRecord; } + @GuardedBy("mLock") private void disposeUserIfNeededLocked(@NonNull UserRecord userRecord) { // If there are no records left and the user is no longer current then go ahead // and purge the user record and all of its associated state. If the user is current // then leave it alone since we might be connected to a route or want to query // the same route information again soon. - if (userRecord.mUserId != mCurrentUserId + if (!isUserActiveLocked(userRecord.mUserId) && userRecord.mRouterRecords.isEmpty() && userRecord.mManagerRecords.isEmpty()) { if (DEBUG) { diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index d7d0b42aa0a7..511026e71d23 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -63,7 +63,9 @@ import android.util.SparseArray; import android.util.TimeUtils; import com.android.internal.util.DumpUtils; +import com.android.server.LocalServices; import com.android.server.Watchdog; +import com.android.server.pm.UserManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -104,9 +106,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub // State guarded by mLock. private final Object mLock = new Object(); + private final UserManagerInternal mUserManagerInternal; private final SparseArray<UserRecord> mUserRecords = new SparseArray<>(); private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>(); - private int mCurrentUserId = -1; + private int mCurrentActiveUserId = -1; private final IAudioService mAudioService; private final AudioPlayerStateMonitor mAudioPlayerStateMonitor; private final Handler mHandler = new Handler(); @@ -132,6 +135,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub mBluetoothA2dpRouteId = res.getString(com.android.internal.R.string.bluetooth_a2dp_audio_route_id); + mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mAudioService = IAudioService.Stub.asInterface( ServiceManager.getService(Context.AUDIO_SERVICE)); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(context); @@ -164,11 +168,11 @@ public final class MediaRouterService extends IMediaRouterService.Stub new UserSwitchObserver() { @Override public void onUserSwitchComplete(int newUserId) { - switchUser(newUserId); + updateRunningUserAndProfiles(newUserId); } }, TAG); - switchUser(ActivityManager.getCurrentUser()); + updateRunningUserAndProfiles(ActivityManager.getCurrentUser()); } @Override @@ -388,7 +392,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub pw.println("MEDIA ROUTER SERVICE (dumpsys media_router)"); pw.println(); pw.println("Global state"); - pw.println(" mCurrentUserId=" + mCurrentUserId); + pw.println(" mCurrentUserId=" + mCurrentActiveUserId); synchronized (mLock) { final int count = mUserRecords.size(); @@ -645,25 +649,31 @@ public final class MediaRouterService extends IMediaRouterService.Stub } } - void switchUser(int userId) { + /** + * Starts all {@link UserRecord user records} associated with the active user (whose ID is + * {@code newActiveUserId}) or the active user's profiles. + * + * <p>All other records are stopped, and those without associated client records are removed. + */ + private void updateRunningUserAndProfiles(int newActiveUserId) { synchronized (mLock) { - if (mCurrentUserId != userId) { - final int oldUserId = mCurrentUserId; - mCurrentUserId = userId; // do this first - - UserRecord oldUser = mUserRecords.get(oldUserId); - if (oldUser != null) { - oldUser.mHandler.sendEmptyMessage(UserHandler.MSG_STOP); - disposeUserIfNeededLocked(oldUser); // since no longer current user - } - - UserRecord newUser = mUserRecords.get(userId); - if (newUser != null) { - newUser.mHandler.sendEmptyMessage(UserHandler.MSG_START); + if (mCurrentActiveUserId != newActiveUserId) { + mCurrentActiveUserId = newActiveUserId; + for (int i = 0; i < mUserRecords.size(); i++) { + int userId = mUserRecords.keyAt(i); + UserRecord userRecord = mUserRecords.valueAt(i); + if (isUserActiveLocked(userId)) { + // userId corresponds to the active user, or one of its profiles. We + // ensure the associated structures are initialized. + userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START); + } else { + userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_STOP); + disposeUserIfNeededLocked(userRecord); + } } } } - mService2.switchUser(userId); + mService2.updateRunningUserAndProfiles(newActiveUserId); } void clientDied(ClientRecord clientRecord) { @@ -718,8 +728,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub clientRecord.mGroupId = groupId; if (groupId != null) { userRecord.addToGroup(groupId, clientRecord); - userRecord.mHandler.obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId) - .sendToTarget(); + userRecord + .mHandler + .obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId) + .sendToTarget(); } } @@ -805,9 +817,13 @@ public final class MediaRouterService extends IMediaRouterService.Stub clientRecord.mUserRecord.mClientGroupMap.get(clientRecord.mGroupId); if (group != null) { group.mSelectedRouteId = routeId; - clientRecord.mUserRecord.mHandler.obtainMessage( - UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, clientRecord.mGroupId) - .sendToTarget(); + clientRecord + .mUserRecord + .mHandler + .obtainMessage( + UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, + clientRecord.mGroupId) + .sendToTarget(); } } } @@ -839,7 +855,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub if (DEBUG) { Slog.d(TAG, userRecord + ": Initialized"); } - if (userRecord.mUserId == mCurrentUserId) { + if (isUserActiveLocked(userRecord.mUserId)) { userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START); } } @@ -849,8 +865,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub // and purge the user record and all of its associated state. If the user is current // then leave it alone since we might be connected to a route or want to query // the same route information again soon. - if (userRecord.mUserId != mCurrentUserId - && userRecord.mClientRecords.isEmpty()) { + if (!isUserActiveLocked(userRecord.mUserId) && userRecord.mClientRecords.isEmpty()) { if (DEBUG) { Slog.d(TAG, userRecord + ": Disposed"); } @@ -859,6 +874,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub } } + /** + * Returns {@code true} if the given {@code userId} corresponds to the active user or a profile + * of the active user, returns {@code false} otherwise. + */ + private boolean isUserActiveLocked(int userId) { + return mUserManagerInternal.getProfileParentId(userId) == mCurrentActiveUserId; + } + private void initializeClientLocked(ClientRecord clientRecord) { if (DEBUG) { Slog.d(TAG, clientRecord + ": Registered"); @@ -898,7 +921,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) { - BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, android.bluetooth.BluetoothDevice.class); + BluetoothDevice btDevice = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, + android.bluetooth.BluetoothDevice.class); synchronized (mLock) { mActiveBluetoothDevice = btDevice; mGlobalBluetoothA2dpOn = btDevice != null; |