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

Commit 6c113b6d authored by Rubin Xu's avatar Rubin Xu
Browse files

Do not crash if attempt to launch app from locked profile

Handle the case of a locked profile with unified challenge as a
first-class state: attempts to open work apps in this state will
result in a confirm credential operation, instead of letting the
app launch directly which will result in crashes.

Test: atest ActivityStartInterceptorTest
Test: 1. Turn off a work profile with unified challenge.
      2. Manually turn on profile (without unlocking), run
      adb shell  am broadcast -a com.android.server.pm.DISABLE_QUIET_MODE_AFTER_UNLOCK \
          --ei android.intent.extra.USER_ID 10
      3. Attempt to launch a work app.
Bug: 72178550
Bug: 138560482
Change-Id: I85f796fe3edeb3c1d6c0dd6d2143d2f44ac22ea7
parent e90c8636
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -241,7 +241,8 @@ public abstract class ActivityManagerInternal {


    /**
    /**
     * Returns whether the given user requires credential entry at this time. This is used to
     * Returns whether the given user requires credential entry at this time. This is used to
     * intercept activity launches for work apps when the Work Challenge is present.
     * intercept activity launches for locked work apps due to work challenge being triggered or
     * when the profile user is yet to be unlocked.
     */
     */
    public abstract boolean shouldConfirmCredentials(@UserIdInt int userId);
    public abstract boolean shouldConfirmCredentials(@UserIdInt int userId);


+12 −8
Original line number Original line Diff line number Diff line
@@ -2218,19 +2218,23 @@ class UserController implements Handler.Callback {


    /**
    /**
     * Returns whether the given user requires credential entry at this time. This is used to
     * Returns whether the given user requires credential entry at this time. This is used to
     * intercept activity launches for work apps when the Work Challenge is present.
     * intercept activity launches for locked work apps due to work challenge being triggered
     * or when the profile user is yet to be unlocked.
     */
     */
    protected boolean shouldConfirmCredentials(@UserIdInt int userId) {
    protected boolean shouldConfirmCredentials(@UserIdInt int userId) {
        synchronized (mLock) {
        if (getStartedUserState(userId) == null) {
            if (mStartedUsers.get(userId) == null) {
            return false;
            return false;
        }
        }
        }
        if (!getUserInfo(userId).isManagedProfile()) {
        if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
            return false;
            return false;
        }
        }
        if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
            final KeyguardManager km = mInjector.getKeyguardManager();
            final KeyguardManager km = mInjector.getKeyguardManager();
            return km.isDeviceLocked(userId) && km.isDeviceSecure(userId);
            return km.isDeviceLocked(userId) && km.isDeviceSecure(userId);
        } else {
            // For unified challenge, need to confirm credential if user is RUNNING_LOCKED.
            return isUserRunning(userId, ActivityManager.FLAG_AND_LOCKED);
        }
    }
    }


    boolean isLockScreenDisabled(@UserIdInt int userId) {
    boolean isLockScreenDisabled(@UserIdInt int userId) {
+2 −2
Original line number Original line Diff line number Diff line
@@ -178,7 +178,7 @@ class ActivityStartInterceptor {
            // before issuing the work challenge.
            // before issuing the work challenge.
            return true;
            return true;
        }
        }
        return interceptWorkProfileChallengeIfNeeded();
        return interceptLockedManagedProfileIfNeeded();
    }
    }


    private boolean hasCrossProfileAnimation() {
    private boolean hasCrossProfileAnimation() {
@@ -296,7 +296,7 @@ class ActivityStartInterceptor {
        return true;
        return true;
    }
    }


    private boolean interceptWorkProfileChallengeIfNeeded() {
    private boolean interceptLockedManagedProfileIfNeeded() {
        final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mAInfo, mUserId);
        final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mAInfo, mUserId);
        if (interceptingIntent == null) {
        if (interceptingIntent == null) {
            return false;
            return false;
+1 −1
Original line number Original line Diff line number Diff line
@@ -246,7 +246,7 @@ public class ActivityStartInterceptorTest {
    }
    }


    @Test
    @Test
    public void testWorkChallenge() {
    public void testLockedManagedProfile() {
        // GIVEN that the user the activity is starting as is currently locked
        // GIVEN that the user the activity is starting as is currently locked
        when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
        when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);