summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java61
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java82
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;