Merge changes from topic "cherrypick_work_profile_fix" into tm-qpr-dev
* changes: Add support for profiles in MediaRouterService Use UserSwitchObserver to detect switches in the running user
This commit is contained in:
committed by
Android (Google) Code Review
commit
f265073fee
@@ -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);
|
||||
@@ -601,25 +605,23 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO(b/136703681): Review this is handling multi-user properly.
|
||||
void switchUser() {
|
||||
/* package */ void updateRunningUserAndProfiles(int newActiveUserId) {
|
||||
synchronized (mLock) {
|
||||
int userId = ActivityManager.getCurrentUser();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -637,11 +639,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) {
|
||||
@@ -669,6 +681,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) {
|
||||
@@ -891,6 +904,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();
|
||||
@@ -1125,13 +1139,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));
|
||||
}
|
||||
@@ -1139,12 +1154,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) {
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package com.android.server.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.UserSwitchObserver;
|
||||
import android.bluetooth.BluetoothA2dp;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -61,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;
|
||||
@@ -102,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();
|
||||
@@ -130,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);
|
||||
@@ -217,18 +223,27 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
|
||||
}
|
||||
|
||||
public void systemRunning() {
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
|
||||
mContext.registerReceiver(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction().equals(Intent.ACTION_USER_SWITCHED)) {
|
||||
switchUser();
|
||||
}
|
||||
}
|
||||
}, filter);
|
||||
|
||||
switchUser();
|
||||
/**
|
||||
* Initializes the MediaRouter service.
|
||||
*
|
||||
* @throws RemoteException If an error occurs while registering the {@link UserSwitchObserver}.
|
||||
*/
|
||||
@RequiresPermission(
|
||||
anyOf = {
|
||||
"android.permission.INTERACT_ACROSS_USERS",
|
||||
"android.permission.INTERACT_ACROSS_USERS_FULL"
|
||||
})
|
||||
public void systemRunning() throws RemoteException {
|
||||
ActivityManager.getService()
|
||||
.registerUserSwitchObserver(
|
||||
new UserSwitchObserver() {
|
||||
@Override
|
||||
public void onUserSwitchComplete(int newUserId) {
|
||||
updateRunningUserAndProfiles(newUserId);
|
||||
}
|
||||
},
|
||||
TAG);
|
||||
updateRunningUserAndProfiles(ActivityManager.getCurrentUser());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -448,7 +463,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();
|
||||
@@ -702,26 +717,31 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
void switchUser() {
|
||||
/**
|
||||
* 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) {
|
||||
int userId = ActivityManager.getCurrentUser();
|
||||
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();
|
||||
mService2.updateRunningUserAndProfiles(newActiveUserId);
|
||||
}
|
||||
|
||||
void clientDied(ClientRecord clientRecord) {
|
||||
@@ -776,8 +796,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -863,9 +885,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -897,7 +923,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);
|
||||
}
|
||||
}
|
||||
@@ -907,8 +933,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");
|
||||
}
|
||||
@@ -917,6 +942,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");
|
||||
|
||||
Reference in New Issue
Block a user