Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f265073f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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
parents 6296e112 cf655c66
Loading
Loading
Loading
Loading
+38 −22
Original line number Diff line number Diff line
@@ -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
            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);
                    }

                UserRecord newUser = mUserRecords.get(userId);
                if (newUser != null) {
                    newUser.mHandler.sendMessage(
                            obtainMessage(UserHandler::start, newUser.mHandler));
                }
            }
        }
@@ -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) {
+71 −38
Original line number Diff line number Diff line
@@ -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() {
    /**
     * 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 onReceive(Context context, Intent intent) {
                if (intent.getAction().equals(Intent.ACTION_USER_SWITCHED)) {
                    switchUser();
                }
                            public void onUserSwitchComplete(int newUserId) {
                                updateRunningUserAndProfiles(newUserId);
                            }
        }, filter);

        switchUser();
                        },
                        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
            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);
                    }

                UserRecord newUser = mUserRecords.get(userId);
                if (newUser != null) {
                    newUser.mHandler.sendEmptyMessage(UserHandler.MSG_START);
                }
            }
        }
        mService2.switchUser();
        mService2.updateRunningUserAndProfiles(newActiveUserId);
    }

    void clientDied(ClientRecord clientRecord) {
@@ -776,7 +796,9 @@ 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)
            userRecord
                    .mHandler
                    .obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId)
                    .sendToTarget();
        }
    }
@@ -863,8 +885,12 @@ 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)
                            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");