Merge changes from topic "cherrypick_work_profile_fix" into tm-qpr-dev am: f265073fee

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20467946

Change-Id: I53297e723444caa1039f4f7089a3f236b5cffe20
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-11-16 03:14:49 +00:00
committed by Automerger Merge Worker
2 changed files with 88 additions and 48 deletions

View File

@@ -58,6 +58,8 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.function.pooled.PooledLambda; 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.io.PrintWriter;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@@ -87,6 +89,7 @@ class MediaRouter2ServiceImpl {
private static final int PACKAGE_IMPORTANCE_FOR_DISCOVERY = IMPORTANCE_FOREGROUND_SERVICE; private static final int PACKAGE_IMPORTANCE_FOR_DISCOVERY = IMPORTANCE_FOREGROUND_SERVICE;
private final Context mContext; private final Context mContext;
private final UserManagerInternal mUserManagerInternal;
private final Object mLock = new Object(); private final Object mLock = new Object();
final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1); final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1);
final ActivityManager mActivityManager; final ActivityManager mActivityManager;
@@ -99,7 +102,7 @@ class MediaRouter2ServiceImpl {
@GuardedBy("mLock") @GuardedBy("mLock")
private final ArrayMap<IBinder, ManagerRecord> mAllManagerRecords = new ArrayMap<>(); private final ArrayMap<IBinder, ManagerRecord> mAllManagerRecords = new ArrayMap<>();
@GuardedBy("mLock") @GuardedBy("mLock")
private int mCurrentUserId = -1; private int mCurrentActiveUserId = -1;
private final ActivityManager.OnUidImportanceListener mOnUidImportanceListener = private final ActivityManager.OnUidImportanceListener mOnUidImportanceListener =
(uid, importance) -> { (uid, importance) -> {
@@ -125,12 +128,13 @@ class MediaRouter2ServiceImpl {
} }
}; };
MediaRouter2ServiceImpl(Context context) { /* package */ MediaRouter2ServiceImpl(Context context) {
mContext = context; mContext = context;
mActivityManager = mContext.getSystemService(ActivityManager.class); mActivityManager = mContext.getSystemService(ActivityManager.class);
mActivityManager.addOnUidImportanceListener(mOnUidImportanceListener, mActivityManager.addOnUidImportanceListener(mOnUidImportanceListener,
PACKAGE_IMPORTANCE_FOR_DISCOVERY); PACKAGE_IMPORTANCE_FOR_DISCOVERY);
mPowerManager = mContext.getSystemService(PowerManager.class); mPowerManager = mContext.getSystemService(PowerManager.class);
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
IntentFilter screenOnOffIntentFilter = new IntentFilter(); IntentFilter screenOnOffIntentFilter = new IntentFilter();
screenOnOffIntentFilter.addAction(ACTION_SCREEN_ON); screenOnOffIntentFilter.addAction(ACTION_SCREEN_ON);
@@ -601,24 +605,23 @@ class MediaRouter2ServiceImpl {
} }
} }
// TODO(b/136703681): Review this is handling multi-user properly. /* package */ void updateRunningUserAndProfiles(int newActiveUserId) {
void switchUser(int userId) {
synchronized (mLock) { synchronized (mLock) {
if (mCurrentUserId != userId) { if (mCurrentActiveUserId != newActiveUserId) {
final int oldUserId = mCurrentUserId; mCurrentActiveUserId = newActiveUserId;
mCurrentUserId = userId; // do this first for (int i = 0; i < mUserRecords.size(); i++) {
int userId = mUserRecords.keyAt(i);
UserRecord oldUser = mUserRecords.get(oldUserId); UserRecord userRecord = mUserRecords.valueAt(i);
if (oldUser != null) { if (isUserActiveLocked(userId)) {
oldUser.mHandler.sendMessage( // userId corresponds to the active user, or one of its profiles. We
obtainMessage(UserHandler::stop, oldUser.mHandler)); // ensure the associated structures are initialized.
disposeUserIfNeededLocked(oldUser); // since no longer current user userRecord.mHandler.sendMessage(
obtainMessage(UserHandler::start, userRecord.mHandler));
} else {
userRecord.mHandler.sendMessage(
obtainMessage(UserHandler::stop, userRecord.mHandler));
disposeUserIfNeededLocked(userRecord);
} }
UserRecord newUser = mUserRecords.get(userId);
if (newUser != null) {
newUser.mHandler.sendMessage(
obtainMessage(UserHandler::start, newUser.mHandler));
} }
} }
} }
@@ -636,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 //// ***Locked methods related to MediaRouter2
//// - Should have @NonNull/@Nullable on all arguments //// - Should have @NonNull/@Nullable on all arguments
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@GuardedBy("mLock")
private void registerRouter2Locked(@NonNull IMediaRouter2 router, int uid, int pid, private void registerRouter2Locked(@NonNull IMediaRouter2 router, int uid, int pid,
@NonNull String packageName, int userId, boolean hasConfigureWifiDisplayPermission, @NonNull String packageName, int userId, boolean hasConfigureWifiDisplayPermission,
boolean hasModifyAudioRoutingPermission) { boolean hasModifyAudioRoutingPermission) {
@@ -668,6 +681,7 @@ class MediaRouter2ServiceImpl {
userRecord.mHandler, routerRecord)); userRecord.mHandler, routerRecord));
} }
@GuardedBy("mLock")
private void unregisterRouter2Locked(@NonNull IMediaRouter2 router, boolean died) { private void unregisterRouter2Locked(@NonNull IMediaRouter2 router, boolean died) {
RouterRecord routerRecord = mAllRouterRecords.remove(router.asBinder()); RouterRecord routerRecord = mAllRouterRecords.remove(router.asBinder());
if (routerRecord == null) { if (routerRecord == null) {
@@ -890,6 +904,7 @@ class MediaRouter2ServiceImpl {
return sessionInfos; return sessionInfos;
} }
@GuardedBy("mLock")
private void registerManagerLocked(@NonNull IMediaRouter2Manager manager, private void registerManagerLocked(@NonNull IMediaRouter2Manager manager,
int uid, int pid, @NonNull String packageName, int userId) { int uid, int pid, @NonNull String packageName, int userId) {
final IBinder binder = manager.asBinder(); final IBinder binder = manager.asBinder();
@@ -1124,13 +1139,14 @@ class MediaRouter2ServiceImpl {
//// - Should have @NonNull/@Nullable on all arguments //// - Should have @NonNull/@Nullable on all arguments
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@GuardedBy("mLock")
private UserRecord getOrCreateUserRecordLocked(int userId) { private UserRecord getOrCreateUserRecordLocked(int userId) {
UserRecord userRecord = mUserRecords.get(userId); UserRecord userRecord = mUserRecords.get(userId);
if (userRecord == null) { if (userRecord == null) {
userRecord = new UserRecord(userId); userRecord = new UserRecord(userId);
mUserRecords.put(userId, userRecord); mUserRecords.put(userId, userRecord);
userRecord.init(); userRecord.init();
if (userId == mCurrentUserId) { if (isUserActiveLocked(userId)) {
userRecord.mHandler.sendMessage( userRecord.mHandler.sendMessage(
obtainMessage(UserHandler::start, userRecord.mHandler)); obtainMessage(UserHandler::start, userRecord.mHandler));
} }
@@ -1138,12 +1154,13 @@ class MediaRouter2ServiceImpl {
return userRecord; return userRecord;
} }
@GuardedBy("mLock")
private void disposeUserIfNeededLocked(@NonNull UserRecord userRecord) { private void disposeUserIfNeededLocked(@NonNull UserRecord userRecord) {
// If there are no records left and the user is no longer current then go ahead // 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 // 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 // then leave it alone since we might be connected to a route or want to query
// the same route information again soon. // the same route information again soon.
if (userRecord.mUserId != mCurrentUserId if (!isUserActiveLocked(userRecord.mUserId)
&& userRecord.mRouterRecords.isEmpty() && userRecord.mRouterRecords.isEmpty()
&& userRecord.mManagerRecords.isEmpty()) { && userRecord.mManagerRecords.isEmpty()) {
if (DEBUG) { if (DEBUG) {

View File

@@ -63,7 +63,9 @@ import android.util.SparseArray;
import android.util.TimeUtils; import android.util.TimeUtils;
import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.Watchdog; import com.android.server.Watchdog;
import com.android.server.pm.UserManagerInternal;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -104,9 +106,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// State guarded by mLock. // State guarded by mLock.
private final Object mLock = new Object(); private final Object mLock = new Object();
private final UserManagerInternal mUserManagerInternal;
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>(); private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>(); private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>();
private int mCurrentUserId = -1; private int mCurrentActiveUserId = -1;
private final IAudioService mAudioService; private final IAudioService mAudioService;
private final AudioPlayerStateMonitor mAudioPlayerStateMonitor; private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
private final Handler mHandler = new Handler(); private final Handler mHandler = new Handler();
@@ -132,6 +135,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
mBluetoothA2dpRouteId = mBluetoothA2dpRouteId =
res.getString(com.android.internal.R.string.bluetooth_a2dp_audio_route_id); res.getString(com.android.internal.R.string.bluetooth_a2dp_audio_route_id);
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
mAudioService = IAudioService.Stub.asInterface( mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE)); ServiceManager.getService(Context.AUDIO_SERVICE));
mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(context); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(context);
@@ -235,11 +239,11 @@ public final class MediaRouterService extends IMediaRouterService.Stub
new UserSwitchObserver() { new UserSwitchObserver() {
@Override @Override
public void onUserSwitchComplete(int newUserId) { public void onUserSwitchComplete(int newUserId) {
switchUser(newUserId); updateRunningUserAndProfiles(newUserId);
} }
}, },
TAG); TAG);
switchUser(ActivityManager.getCurrentUser()); updateRunningUserAndProfiles(ActivityManager.getCurrentUser());
} }
@Override @Override
@@ -459,7 +463,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
pw.println("MEDIA ROUTER SERVICE (dumpsys media_router)"); pw.println("MEDIA ROUTER SERVICE (dumpsys media_router)");
pw.println(); pw.println();
pw.println("Global state"); pw.println("Global state");
pw.println(" mCurrentUserId=" + mCurrentUserId); pw.println(" mCurrentUserId=" + mCurrentActiveUserId);
synchronized (mLock) { synchronized (mLock) {
final int count = mUserRecords.size(); final int count = mUserRecords.size();
@@ -713,25 +717,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) { synchronized (mLock) {
if (mCurrentUserId != userId) { if (mCurrentActiveUserId != newActiveUserId) {
final int oldUserId = mCurrentUserId; mCurrentActiveUserId = newActiveUserId;
mCurrentUserId = userId; // do this first for (int i = 0; i < mUserRecords.size(); i++) {
int userId = mUserRecords.keyAt(i);
UserRecord oldUser = mUserRecords.get(oldUserId); UserRecord userRecord = mUserRecords.valueAt(i);
if (oldUser != null) { if (isUserActiveLocked(userId)) {
oldUser.mHandler.sendEmptyMessage(UserHandler.MSG_STOP); // userId corresponds to the active user, or one of its profiles. We
disposeUserIfNeededLocked(oldUser); // since no longer current user // ensure the associated structures are initialized.
} userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START);
} else {
UserRecord newUser = mUserRecords.get(userId); userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_STOP);
if (newUser != null) { disposeUserIfNeededLocked(userRecord);
newUser.mHandler.sendEmptyMessage(UserHandler.MSG_START);
} }
} }
} }
mService2.switchUser(userId); }
mService2.updateRunningUserAndProfiles(newActiveUserId);
} }
void clientDied(ClientRecord clientRecord) { void clientDied(ClientRecord clientRecord) {
@@ -786,7 +796,9 @@ public final class MediaRouterService extends IMediaRouterService.Stub
clientRecord.mGroupId = groupId; clientRecord.mGroupId = groupId;
if (groupId != null) { if (groupId != null) {
userRecord.addToGroup(groupId, clientRecord); userRecord.addToGroup(groupId, clientRecord);
userRecord.mHandler.obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId) userRecord
.mHandler
.obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId)
.sendToTarget(); .sendToTarget();
} }
} }
@@ -873,8 +885,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub
clientRecord.mUserRecord.mClientGroupMap.get(clientRecord.mGroupId); clientRecord.mUserRecord.mClientGroupMap.get(clientRecord.mGroupId);
if (group != null) { if (group != null) {
group.mSelectedRouteId = routeId; group.mSelectedRouteId = routeId;
clientRecord.mUserRecord.mHandler.obtainMessage( clientRecord
UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, clientRecord.mGroupId) .mUserRecord
.mHandler
.obtainMessage(
UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED,
clientRecord.mGroupId)
.sendToTarget(); .sendToTarget();
} }
} }
@@ -907,7 +923,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, userRecord + ": Initialized"); Slog.d(TAG, userRecord + ": Initialized");
} }
if (userRecord.mUserId == mCurrentUserId) { if (isUserActiveLocked(userRecord.mUserId)) {
userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START); userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START);
} }
} }
@@ -917,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 // 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 // then leave it alone since we might be connected to a route or want to query
// the same route information again soon. // the same route information again soon.
if (userRecord.mUserId != mCurrentUserId if (!isUserActiveLocked(userRecord.mUserId) && userRecord.mClientRecords.isEmpty()) {
&& userRecord.mClientRecords.isEmpty()) {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, userRecord + ": Disposed"); Slog.d(TAG, userRecord + ": Disposed");
} }
@@ -927,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) { private void initializeClientLocked(ClientRecord clientRecord) {
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, clientRecord + ": Registered"); Slog.d(TAG, clientRecord + ": Registered");