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

Commit ec319aba authored by Tony Mak's avatar Tony Mak
Browse files

Introduce AMS.getLastResumedActivityUserId to fix work profile icon issue

Problem:
Work profile status bar icon feeature is relied on two callbacks
1. onForegroundProfileSwitch  (AMS.setResumedActivityLocked)
2. appTransitionStarting (WMS)

We assume callback 1 is always called before 2, but it is not the case.
These two callbacks are triggered by two handlers in two different threads,
and hence race condition happens.

Solution:
Not rely on onForegroundProfileSwitch to update mManagedProfileFocused
flag anymore. Query getLastResumedActivityUserId in appTransitionStarting.
Also, make sure mLastResumedActivity is updated before sending message
to WMS in setResumedActivityLocked.

Test: Start a work app, observe that the work icon is shown.
Test: Start a personal app, observe that work icon is gone.
Test: Dock the work app, tap on it (give it focus), observe that work
      icon is shown.
Test: Start a work app, switch user, can see the icon is gone. Switch back,
      icon is back.

Bug: 34159089

Change-Id: I2cee141d18e8b7d5607b26dd7a2fd5bc9cd0ebb3
parent 76c32a35
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -629,6 +629,11 @@ interface IActivityManager {
     */
    void setDisablePreviewScreenshots(IBinder token, boolean disable);

    /**
     * Return the user id of last resumed activity.
     */
    int getLastResumedActivityUserId();

    // WARNING: when these transactions are updated, check if they are any callers on the native
    // side. If so, make sure they are using the correct transaction ids and arguments.
    // If a transaction which will also be used on the native side is being inserted, add it
+29 −64
Original line number Diff line number Diff line
@@ -127,7 +127,6 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
    private boolean mVolumeVisible;
    private boolean mCurrentUserSetup;

    private boolean mManagedProfileFocused = false;
    private boolean mManagedProfileIconVisible = false;
    private boolean mManagedProfileInQuietMode = false;

@@ -439,30 +438,11 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
        }
    }

    private void profileChanged(int userId) {
        UserInfo user = null;
        if (userId == UserHandle.USER_CURRENT) {
            try {
                user = ActivityManager.getService().getCurrentUser();
            } catch (RemoteException e) {
                // Ignore
            }
        } else {
            user = mUserManager.getUserInfo(userId);
        }

        mManagedProfileFocused = user != null && user.isManagedProfile();
        if (DEBUG) Log.v(TAG, "profileChanged: mManagedProfileFocused: " + mManagedProfileFocused);
        // Actually update the icon later when transition starts.
    }

    private void updateManagedProfile() {
        if (DEBUG) {
            Log.v(TAG, "updateManagedProfile: mManagedProfileFocused: "
                    + mManagedProfileFocused);
        }
        try {
            final boolean showIcon;
        if (mManagedProfileFocused && !mKeyguardMonitor.isShowing()) {
            final int userId = ActivityManager.getService().getLastResumedActivityUserId();
            if (mUserManager.isManagedProfile(userId) && !mKeyguardMonitor.isShowing()) {
                showIcon = true;
                mIconController.setIcon(mSlotManagedProfile,
                        R.drawable.stat_sys_managed_profile_status,
@@ -479,6 +459,10 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
                mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
                mManagedProfileIconVisible = showIcon;
            }
        } catch (RemoteException ex) {
            Log.w(TAG, "updateManagedProfile: ", ex);
            // ignore
        }
    }

    private void updateForegroundInstantApps() {
@@ -556,35 +540,16 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
            new SynchronousUserSwitchObserver() {
                @Override
                public void onUserSwitching(int newUserId) throws RemoteException {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mUserInfoController.reloadUserInfo();
                        }
                    });
                    mHandler.post(() -> mUserInfoController.reloadUserInfo());
                }

                @Override
                public void onUserSwitchComplete(int newUserId) throws RemoteException {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                    mHandler.post(() -> {
                        updateAlarm();
                            profileChanged(newUserId);
                        updateQuietState();
                        updateManagedProfile();
                        updateForegroundInstantApps();
                        }
                    });
                }

                @Override
                public void onForegroundProfileSwitch(int newProfileId) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            profileChanged(newProfileId);
                        }
                    });
                }
            };
+20 −5
Original line number Diff line number Diff line
@@ -3212,18 +3212,18 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        mWindowManager.setFocusedApp(r.appToken, true);
        applyUpdateLockStateLocked(r);
        applyUpdateVrModeLocked(r);
        if (mLastResumedActivity != null && r.userId != mLastResumedActivity.userId) {
            mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
            mHandler.obtainMessage(
                    FOREGROUND_PROFILE_CHANGED_MSG, r.userId, 0).sendToTarget();
        }
        mLastResumedActivity = r;
        mWindowManager.setFocusedApp(r.appToken, true);
        applyUpdateLockStateLocked(r);
        applyUpdateVrModeLocked(r);
        EventLogTags.writeAmSetResumedActivity(
                r == null ? -1 : r.userId,
                r == null ? "NULL" : r.shortComponentName,
@@ -23599,6 +23599,21 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    /**
     * Return the user id of the last resumed activity.
     */
    @Override
    public @UserIdInt int getLastResumedActivityUserId() {
        enforceCallingPermission(
                permission.INTERACT_ACROSS_USERS_FULL, "getLastResumedActivityUserId()");
        synchronized (this) {
            if (mLastResumedActivity == null) {
                return mUserController.getCurrentUserIdLocked();
            }
            return mLastResumedActivity.userId;
        }
    }
    private final class SleepTokenImpl extends SleepToken {
        private final String mTag;
        private final long mAcquireTime;