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

Commit 90e467e1 authored by Jigar Thakkar's avatar Jigar Thakkar
Browse files

Enable stopping user with delayed locking for private profile

This change adds a new user property allowLeavingUserUnlockedWhenStopped
that enables the profile to be stopped with delayed locking (i.e.
without the storage being locked). The implementation for quiet mode for
private profiles is also changed to use the stopUserWithDelayedLocking.

Bug: 312184187
Test: atest UserControllerTest, atest UserManagerTest, atest
UserManagerServiceUserTypeTest, atest
UserManagerServiceUserPropertiesTest

Change-Id: I0d44d24d31a4ed9160e73f82a0c93bed28497a33
parent 3cff53a3
Loading
Loading
Loading
Loading
+69 −6
Original line number Original line Diff line number Diff line
@@ -68,6 +68,8 @@ public final class UserProperties implements Parcelable {
            "authAlwaysRequiredToDisableQuietMode";
            "authAlwaysRequiredToDisableQuietMode";
    private static final String ATTR_DELETE_APP_WITH_PARENT = "deleteAppWithParent";
    private static final String ATTR_DELETE_APP_WITH_PARENT = "deleteAppWithParent";
    private static final String ATTR_ALWAYS_VISIBLE = "alwaysVisible";
    private static final String ATTR_ALWAYS_VISIBLE = "alwaysVisible";
    private static final String ATTR_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING =
            "allowStoppingUserWithDelayedLocking";


    private static final String ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY =
    private static final String ATTR_CROSS_PROFILE_CONTENT_SHARING_STRATEGY =
            "crossProfileContentSharingStrategy";
            "crossProfileContentSharingStrategy";
@@ -89,7 +91,8 @@ public final class UserProperties implements Parcelable {
            INDEX_SHOW_IN_QUIET_MODE,
            INDEX_SHOW_IN_QUIET_MODE,
            INDEX_SHOW_IN_SHARING_SURFACES,
            INDEX_SHOW_IN_SHARING_SURFACES,
            INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE,
            INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE,
            INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY
            INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY,
            INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING,
    })
    })
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    private @interface PropertyIndex {
    private @interface PropertyIndex {
@@ -110,6 +113,7 @@ public final class UserProperties implements Parcelable {
    private static final int INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE = 13;
    private static final int INDEX_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE = 13;
    private static final int INDEX_SHOW_IN_SHARING_SURFACES = 14;
    private static final int INDEX_SHOW_IN_SHARING_SURFACES = 14;
    private static final int INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = 15;
    private static final int INDEX_CROSS_PROFILE_CONTENT_SHARING_STRATEGY = 15;
    private static final int INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING = 16;
    /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */
    /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */
    private long mPropertiesPresent = 0;
    private long mPropertiesPresent = 0;


@@ -450,6 +454,7 @@ public final class UserProperties implements Parcelable {
            setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy());
            setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy());
            setDeleteAppWithParent(orig.getDeleteAppWithParent());
            setDeleteAppWithParent(orig.getDeleteAppWithParent());
            setAlwaysVisible(orig.getAlwaysVisible());
            setAlwaysVisible(orig.getAlwaysVisible());
            setAllowStoppingUserWithDelayedLocking(orig.getAllowStoppingUserWithDelayedLocking());
        }
        }
        if (hasManagePermission) {
        if (hasManagePermission) {
            // Add items that require MANAGE_USERS or stronger.
            // Add items that require MANAGE_USERS or stronger.
@@ -725,6 +730,11 @@ public final class UserProperties implements Parcelable {
        this.mUpdateCrossProfileIntentFiltersOnOTA = val;
        this.mUpdateCrossProfileIntentFiltersOnOTA = val;
        setPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA);
        setPresent(INDEX_UPDATE_CROSS_PROFILE_INTENT_FILTERS_ON_OTA);
    }
    }
    /**
     Indicate if {@link com.android.server.pm.CrossProfileIntentFilter}s need to be updated during
     OTA update between user-parent
     */
    private boolean mUpdateCrossProfileIntentFiltersOnOTA;


    /**
    /**
     * Returns whether a profile shares media with its parent user.
     * Returns whether a profile shares media with its parent user.
@@ -786,12 +796,38 @@ public final class UserProperties implements Parcelable {
    }
    }
    private boolean mAuthAlwaysRequiredToDisableQuietMode;
    private boolean mAuthAlwaysRequiredToDisableQuietMode;


    /*
    /**
     Indicate if {@link com.android.server.pm.CrossProfileIntentFilter}s need to be updated during
     * Returns whether a user (usually a profile) is allowed to leave the CE storage unlocked when
     OTA update between user-parent
     * stopped.
     *
     * <p> Setting this property to true will enable the user's CE storage to remain unlocked when
     * the user is stopped using
     * {@link com.android.server.am.ActivityManagerService#stopUserWithDelayedLocking(int,
     * boolean, IStopUserCallback)}.
     *
     * <p> When this property is false, delayed locking may still be applicable at a global
     * level for all users via the {@code config_multiuserDelayUserDataLocking}. That is, delayed
     * locking for a user can happen if either the device configuration is set or if this property
     * is set. When both, the config and the property value is false, the user storage is always
     * locked when the user is stopped.
     * @hide
     */
     */
    private boolean mUpdateCrossProfileIntentFiltersOnOTA;
    public boolean getAllowStoppingUserWithDelayedLocking() {

        if (isPresent(INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING)) {
            return mAllowStoppingUserWithDelayedLocking;
        }
        if (mDefaultProperties != null) {
            return mDefaultProperties.mAllowStoppingUserWithDelayedLocking;
        }
        throw new SecurityException(
                "You don't have permission to query allowStoppingUserWithDelayedLocking");
    }
    /** @hide */
    public void setAllowStoppingUserWithDelayedLocking(boolean val) {
        this.mAllowStoppingUserWithDelayedLocking = val;
        setPresent(INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING);
    }
    private boolean mAllowStoppingUserWithDelayedLocking;


    /**
    /**
     * Returns the user's {@link CrossProfileIntentFilterAccessControlLevel}.
     * Returns the user's {@link CrossProfileIntentFilterAccessControlLevel}.
@@ -899,6 +935,8 @@ public final class UserProperties implements Parcelable {
                + ", mCredentialShareableWithParent=" + isCredentialShareableWithParent()
                + ", mCredentialShareableWithParent=" + isCredentialShareableWithParent()
                + ", mAuthAlwaysRequiredToDisableQuietMode="
                + ", mAuthAlwaysRequiredToDisableQuietMode="
                + isAuthAlwaysRequiredToDisableQuietMode()
                + isAuthAlwaysRequiredToDisableQuietMode()
                + ", mAllowStoppingUserWithDelayedLocking="
                + getAllowStoppingUserWithDelayedLocking()
                + ", mDeleteAppWithParent=" + getDeleteAppWithParent()
                + ", mDeleteAppWithParent=" + getDeleteAppWithParent()
                + ", mAlwaysVisible=" + getAlwaysVisible()
                + ", mAlwaysVisible=" + getAlwaysVisible()
                + ", mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy()
                + ", mCrossProfileContentSharingStrategy=" + getCrossProfileContentSharingStrategy()
@@ -929,6 +967,8 @@ public final class UserProperties implements Parcelable {
                + isCredentialShareableWithParent());
                + isCredentialShareableWithParent());
        pw.println(prefix + "    mAuthAlwaysRequiredToDisableQuietMode="
        pw.println(prefix + "    mAuthAlwaysRequiredToDisableQuietMode="
                + isAuthAlwaysRequiredToDisableQuietMode());
                + isAuthAlwaysRequiredToDisableQuietMode());
        pw.println(prefix + "    mAllowStoppingUserWithDelayedLocking="
                + getAllowStoppingUserWithDelayedLocking());
        pw.println(prefix + "    mDeleteAppWithParent=" + getDeleteAppWithParent());
        pw.println(prefix + "    mDeleteAppWithParent=" + getDeleteAppWithParent());
        pw.println(prefix + "    mAlwaysVisible=" + getAlwaysVisible());
        pw.println(prefix + "    mAlwaysVisible=" + getAlwaysVisible());
        pw.println(prefix + "    mCrossProfileContentSharingStrategy="
        pw.println(prefix + "    mCrossProfileContentSharingStrategy="
@@ -1005,6 +1045,9 @@ public final class UserProperties implements Parcelable {
                case ATTR_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE:
                case ATTR_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE:
                    setAuthAlwaysRequiredToDisableQuietMode(parser.getAttributeBoolean(i));
                    setAuthAlwaysRequiredToDisableQuietMode(parser.getAttributeBoolean(i));
                    break;
                    break;
                case ATTR_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING:
                    setAllowStoppingUserWithDelayedLocking(parser.getAttributeBoolean(i));
                    break;
                case ATTR_DELETE_APP_WITH_PARENT:
                case ATTR_DELETE_APP_WITH_PARENT:
                    setDeleteAppWithParent(parser.getAttributeBoolean(i));
                    setDeleteAppWithParent(parser.getAttributeBoolean(i));
                    break;
                    break;
@@ -1079,6 +1122,10 @@ public final class UserProperties implements Parcelable {
            serializer.attributeBoolean(null, ATTR_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE,
            serializer.attributeBoolean(null, ATTR_AUTH_ALWAYS_REQUIRED_TO_DISABLE_QUIET_MODE,
                    mAuthAlwaysRequiredToDisableQuietMode);
                    mAuthAlwaysRequiredToDisableQuietMode);
        }
        }
        if (isPresent(INDEX_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING)) {
            serializer.attributeBoolean(null, ATTR_ALLOW_STOPPING_USER_WITH_DELAYED_LOCKING,
                    mAllowStoppingUserWithDelayedLocking);
        }
        if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) {
        if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) {
            serializer.attributeBoolean(null, ATTR_DELETE_APP_WITH_PARENT,
            serializer.attributeBoolean(null, ATTR_DELETE_APP_WITH_PARENT,
                    mDeleteAppWithParent);
                    mDeleteAppWithParent);
@@ -1110,6 +1157,7 @@ public final class UserProperties implements Parcelable {
        dest.writeBoolean(mMediaSharedWithParent);
        dest.writeBoolean(mMediaSharedWithParent);
        dest.writeBoolean(mCredentialShareableWithParent);
        dest.writeBoolean(mCredentialShareableWithParent);
        dest.writeBoolean(mAuthAlwaysRequiredToDisableQuietMode);
        dest.writeBoolean(mAuthAlwaysRequiredToDisableQuietMode);
        dest.writeBoolean(mAllowStoppingUserWithDelayedLocking);
        dest.writeBoolean(mDeleteAppWithParent);
        dest.writeBoolean(mDeleteAppWithParent);
        dest.writeBoolean(mAlwaysVisible);
        dest.writeBoolean(mAlwaysVisible);
        dest.writeInt(mCrossProfileContentSharingStrategy);
        dest.writeInt(mCrossProfileContentSharingStrategy);
@@ -1136,6 +1184,7 @@ public final class UserProperties implements Parcelable {
        mMediaSharedWithParent = source.readBoolean();
        mMediaSharedWithParent = source.readBoolean();
        mCredentialShareableWithParent = source.readBoolean();
        mCredentialShareableWithParent = source.readBoolean();
        mAuthAlwaysRequiredToDisableQuietMode = source.readBoolean();
        mAuthAlwaysRequiredToDisableQuietMode = source.readBoolean();
        mAllowStoppingUserWithDelayedLocking = source.readBoolean();
        mDeleteAppWithParent = source.readBoolean();
        mDeleteAppWithParent = source.readBoolean();
        mAlwaysVisible = source.readBoolean();
        mAlwaysVisible = source.readBoolean();
        mCrossProfileContentSharingStrategy = source.readInt();
        mCrossProfileContentSharingStrategy = source.readInt();
@@ -1183,6 +1232,7 @@ public final class UserProperties implements Parcelable {
        private boolean mMediaSharedWithParent = false;
        private boolean mMediaSharedWithParent = false;
        private boolean mCredentialShareableWithParent = false;
        private boolean mCredentialShareableWithParent = false;
        private boolean mAuthAlwaysRequiredToDisableQuietMode = false;
        private boolean mAuthAlwaysRequiredToDisableQuietMode = false;
        private boolean mAllowStoppingUserWithDelayedLocking = false;
        private boolean mDeleteAppWithParent = false;
        private boolean mDeleteAppWithParent = false;
        private boolean mAlwaysVisible = false;
        private boolean mAlwaysVisible = false;
        private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy =
        private @CrossProfileContentSharingStrategy int mCrossProfileContentSharingStrategy =
@@ -1302,6 +1352,16 @@ public final class UserProperties implements Parcelable {
            return this;
            return this;
        }
        }


        /** Sets the value for {@link #mAllowStoppingUserWithDelayedLocking}
         * @hide
         */
        public Builder setAllowStoppingUserWithDelayedLocking(
                boolean allowStoppingUserWithDelayedLocking) {
            mAllowStoppingUserWithDelayedLocking =
                    allowStoppingUserWithDelayedLocking;
            return this;
        }

        /** Sets the value for {@link #mDeleteAppWithParent}
        /** Sets the value for {@link #mDeleteAppWithParent}
         * @hide
         * @hide
         */
         */
@@ -1352,6 +1412,7 @@ public final class UserProperties implements Parcelable {
                    mMediaSharedWithParent,
                    mMediaSharedWithParent,
                    mCredentialShareableWithParent,
                    mCredentialShareableWithParent,
                    mAuthAlwaysRequiredToDisableQuietMode,
                    mAuthAlwaysRequiredToDisableQuietMode,
                    mAllowStoppingUserWithDelayedLocking,
                    mDeleteAppWithParent,
                    mDeleteAppWithParent,
                    mAlwaysVisible,
                    mAlwaysVisible,
                    mCrossProfileContentSharingStrategy);
                    mCrossProfileContentSharingStrategy);
@@ -1372,6 +1433,7 @@ public final class UserProperties implements Parcelable {
            boolean mediaSharedWithParent,
            boolean mediaSharedWithParent,
            boolean credentialShareableWithParent,
            boolean credentialShareableWithParent,
            boolean authAlwaysRequiredToDisableQuietMode,
            boolean authAlwaysRequiredToDisableQuietMode,
            boolean allowStoppingUserWithDelayedLocking,
            boolean deleteAppWithParent,
            boolean deleteAppWithParent,
            boolean alwaysVisible,
            boolean alwaysVisible,
            @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy) {
            @CrossProfileContentSharingStrategy int crossProfileContentSharingStrategy) {
@@ -1390,6 +1452,7 @@ public final class UserProperties implements Parcelable {
        setCredentialShareableWithParent(credentialShareableWithParent);
        setCredentialShareableWithParent(credentialShareableWithParent);
        setAuthAlwaysRequiredToDisableQuietMode(
        setAuthAlwaysRequiredToDisableQuietMode(
                authAlwaysRequiredToDisableQuietMode);
                authAlwaysRequiredToDisableQuietMode);
        setAllowStoppingUserWithDelayedLocking(allowStoppingUserWithDelayedLocking);
        setDeleteAppWithParent(deleteAppWithParent);
        setDeleteAppWithParent(deleteAppWithParent);
        setAlwaysVisible(alwaysVisible);
        setAlwaysVisible(alwaysVisible);
        setCrossProfileContentSharingStrategy(crossProfileContentSharingStrategy);
        setCrossProfileContentSharingStrategy(crossProfileContentSharingStrategy);
+2 −0
Original line number Original line Diff line number Diff line
@@ -17510,6 +17510,8 @@ public class ActivityManagerService extends IActivityManager.Stub
     *         other {@code ActivityManager#USER_OP_*} codes for failure.
     *         other {@code ActivityManager#USER_OP_*} codes for failure.
     *
     *
     */
     */
    // TODO(b/302662311): Add javadoc changes corresponding to the user property that allows
    // delayed locking behavior once the private space flag is finalized.
    @Override
    @Override
    public int stopUserWithDelayedLocking(final int userId, boolean force,
    public int stopUserWithDelayedLocking(final int userId, boolean force,
            final IStopUserCallback callback) {
            final IStopUserCallback callback) {
+47 −18
Original line number Original line Diff line number Diff line
@@ -356,6 +356,8 @@ class UserController implements Handler.Callback {
     * Once total number of unlocked users reach mMaxRunningUsers, least recently used user
     * Once total number of unlocked users reach mMaxRunningUsers, least recently used user
     * will be locked.
     * will be locked.
     */
     */
    // TODO(b/302662311): Add javadoc changes corresponding to the user property that allows
    // delayed locking behavior once the private space flag is finalized.
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private boolean mDelayUserDataLocking;
    private boolean mDelayUserDataLocking;


@@ -365,11 +367,12 @@ class UserController implements Handler.Callback {
    private volatile boolean mAllowUserUnlocking;
    private volatile boolean mAllowUserUnlocking;


    /**
    /**
     * Keep track of last active users for mDelayUserDataLocking.
     * Keep track of last active users for delayUserDataLocking.
     * The latest stopped user is placed in front while the least recently stopped user in back.
     * The most recently stopped user with delayed locking is placed in front, while the least
     * recently stopped user in back.
     */
     */
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final ArrayList<Integer> mLastActiveUsers = new ArrayList<>();
    private final ArrayList<Integer> mLastActiveUsersForDelayedLocking = new ArrayList<>();


    /**
    /**
     * Map of userId to {@link UserCompletedEventType} event flags, indicating which as-yet-
     * Map of userId to {@link UserCompletedEventType} event flags, indicating which as-yet-
@@ -1011,20 +1014,21 @@ class UserController implements Handler.Callback {
        Slogf.i(TAG, "stopSingleUserLU userId=" + userId);
        Slogf.i(TAG, "stopSingleUserLU userId=" + userId);
        final UserState uss = mStartedUsers.get(userId);
        final UserState uss = mStartedUsers.get(userId);
        if (uss == null) {  // User is not started
        if (uss == null) {  // User is not started
            // If mDelayUserDataLocking is set and allowDelayedLocking is not set, we need to lock
            // If canDelayDataLockingForUser() is true and allowDelayedLocking is false, we need
            // the requested user as the client wants to stop and lock the user. On the other hand,
            // to lock the requested user as the client wants to stop and lock the user. On the
            // having keyEvictedCallback set will lead into locking user if mDelayUserDataLocking
            // other hand, having keyEvictedCallback set will lead into locking user if
            // is set as that means client wants to lock the user immediately.
            // canDelayDataLockingForUser() is true as that means client wants to lock the user
            // If mDelayUserDataLocking is not set, the user was already locked when it was stopped
            // immediately.
            // and no further action is necessary.
            // If canDelayDataLockingForUser() is false, the user was already locked when it was
            if (mDelayUserDataLocking) {
            // stopped and no further action is necessary.
            if (canDelayDataLockingForUser(userId)) {
                if (allowDelayedLocking && keyEvictedCallback != null) {
                if (allowDelayedLocking && keyEvictedCallback != null) {
                    Slogf.wtf(TAG, "allowDelayedLocking set with KeyEvictedCallback, ignore it"
                    Slogf.wtf(TAG, "allowDelayedLocking set with KeyEvictedCallback, ignore it"
                            + " and lock user:" + userId, new RuntimeException());
                            + " and lock user:" + userId, new RuntimeException());
                    allowDelayedLocking = false;
                    allowDelayedLocking = false;
                }
                }
                if (!allowDelayedLocking) {
                if (!allowDelayedLocking) {
                    if (mLastActiveUsers.remove(Integer.valueOf(userId))) {
                    if (mLastActiveUsersForDelayedLocking.remove(Integer.valueOf(userId))) {
                        // should lock the user, user is already gone
                        // should lock the user, user is already gone
                        final ArrayList<KeyEvictedCallback> keyEvictedCallbacks;
                        final ArrayList<KeyEvictedCallback> keyEvictedCallbacks;
                        if (keyEvictedCallback != null) {
                        if (keyEvictedCallback != null) {
@@ -1354,14 +1358,21 @@ class UserController implements Handler.Callback {
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private int updateUserToLockLU(@UserIdInt int userId, boolean allowDelayedLocking) {
    private int updateUserToLockLU(@UserIdInt int userId, boolean allowDelayedLocking) {
        int userIdToLock = userId;
        int userIdToLock = userId;
        if (mDelayUserDataLocking && allowDelayedLocking && !getUserInfo(userId).isEphemeral()
        // TODO: Decouple the delayed locking flows from mMaxRunningUsers or rename the property to
        // state maximum running unlocked users specifically
        if (canDelayDataLockingForUser(userIdToLock) && allowDelayedLocking
                && !getUserInfo(userId).isEphemeral()
                && !hasUserRestriction(UserManager.DISALLOW_RUN_IN_BACKGROUND, userId)) {
                && !hasUserRestriction(UserManager.DISALLOW_RUN_IN_BACKGROUND, userId)) {
            mLastActiveUsers.remove((Integer) userId); // arg should be object, not index
            // arg should be object, not index
            mLastActiveUsers.add(0, userId);
            mLastActiveUsersForDelayedLocking.remove((Integer) userId);
            int totalUnlockedUsers = mStartedUsers.size() + mLastActiveUsers.size();
            mLastActiveUsersForDelayedLocking.add(0, userId);
            int totalUnlockedUsers = mStartedUsers.size()
                    + mLastActiveUsersForDelayedLocking.size();
            if (totalUnlockedUsers > mMaxRunningUsers) { // should lock a user
            if (totalUnlockedUsers > mMaxRunningUsers) { // should lock a user
                userIdToLock = mLastActiveUsers.get(mLastActiveUsers.size() - 1);
                userIdToLock = mLastActiveUsersForDelayedLocking.get(
                mLastActiveUsers.remove(mLastActiveUsers.size() - 1);
                        mLastActiveUsersForDelayedLocking.size() - 1);
                mLastActiveUsersForDelayedLocking
                        .remove(mLastActiveUsersForDelayedLocking.size() - 1);
                Slogf.i(TAG, "finishUserStopped, stopping user:" + userId
                Slogf.i(TAG, "finishUserStopped, stopping user:" + userId
                        + " lock user:" + userIdToLock);
                        + " lock user:" + userIdToLock);
            } else {
            } else {
@@ -1373,6 +1384,24 @@ class UserController implements Handler.Callback {
        return userIdToLock;
        return userIdToLock;
    }
    }


    /**
     * Returns whether the user can have its CE storage left unlocked, even when it is stopped,
     * either due to a global device configuration or an individual user's property.
     */
    private boolean canDelayDataLockingForUser(@UserIdInt int userIdToLock) {
        if (allowBiometricUnlockForPrivateProfile()) {
            final UserProperties userProperties = getUserProperties(userIdToLock);
            return (mDelayUserDataLocking || (userProperties != null
                    && userProperties.getAllowStoppingUserWithDelayedLocking()));
        }
        return mDelayUserDataLocking;
    }

    private boolean allowBiometricUnlockForPrivateProfile() {
        return android.os.Flags.allowPrivateProfile()
                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace();
    }

    /**
    /**
     * Determines the list of users that should be stopped together with the specified
     * Determines the list of users that should be stopped together with the specified
     * {@code userId}. The returned list includes {@code userId}.
     * {@code userId}. The returned list includes {@code userId}.
@@ -3161,7 +3190,7 @@ class UserController implements Handler.Callback {
            pw.println("  mCurrentProfileIds:" + Arrays.toString(mCurrentProfileIds));
            pw.println("  mCurrentProfileIds:" + Arrays.toString(mCurrentProfileIds));
            pw.println("  mCurrentUserId:" + mCurrentUserId);
            pw.println("  mCurrentUserId:" + mCurrentUserId);
            pw.println("  mTargetUserId:" + mTargetUserId);
            pw.println("  mTargetUserId:" + mTargetUserId);
            pw.println("  mLastActiveUsers:" + mLastActiveUsers);
            pw.println("  mLastActiveUsersForDelayedLocking:" + mLastActiveUsersForDelayedLocking);
            pw.println("  mDelayUserDataLocking:" + mDelayUserDataLocking);
            pw.println("  mDelayUserDataLocking:" + mDelayUserDataLocking);
            pw.println("  mAllowUserUnlocking:" + mAllowUserUnlocking);
            pw.println("  mAllowUserUnlocking:" + mAllowUserUnlocking);
            pw.println("  shouldStopUserOnSwitch():" + shouldStopUserOnSwitch());
            pw.println("  shouldStopUserOnSwitch():" + shouldStopUserOnSwitch());
+13 −1
Original line number Original line Diff line number Diff line
@@ -1519,7 +1519,7 @@ public class UserManagerService extends IUserManager.Stub {


        try {
        try {
            if (enableQuietMode) {
            if (enableQuietMode) {
                ActivityManager.getService().stopUser(userId, /* force= */ true, null);
                stopUserForQuietMode(userId);
                LocalServices.getService(ActivityManagerInternal.class)
                LocalServices.getService(ActivityManagerInternal.class)
                        .killForegroundAppsForUser(userId);
                        .killForegroundAppsForUser(userId);
            } else {
            } else {
@@ -1547,6 +1547,18 @@ public class UserManagerService extends IUserManager.Stub {
        }
        }
    }
    }


    private void stopUserForQuietMode(int userId) throws RemoteException {
        if (android.os.Flags.allowPrivateProfile()
                && android.multiuser.Flags.enableBiometricsToUnlockPrivateSpace()) {
            // Allow delayed locking since some profile types want to be able to unlock again via
            // biometrics.
            ActivityManager.getService()
                    .stopUserWithDelayedLocking(userId, /* force= */ true, null);
            return;
        }
        ActivityManager.getService().stopUser(userId, /* force= */ true, null);
    }

    private void logQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode,
    private void logQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode,
            @Nullable String callingPackage) {
            @Nullable String callingPackage) {
        Slogf.i(LOG_TAG,
        Slogf.i(LOG_TAG,
+1 −0
Original line number Original line Diff line number Diff line
@@ -311,6 +311,7 @@ public final class UserTypeFactory {
                        .setStartWithParent(true)
                        .setStartWithParent(true)
                        .setCredentialShareableWithParent(true)
                        .setCredentialShareableWithParent(true)
                        .setAuthAlwaysRequiredToDisableQuietMode(true)
                        .setAuthAlwaysRequiredToDisableQuietMode(true)
                        .setAllowStoppingUserWithDelayedLocking(true)
                        .setMediaSharedWithParent(false)
                        .setMediaSharedWithParent(false)
                        .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE)
                        .setShowInLauncher(UserProperties.SHOW_IN_LAUNCHER_SEPARATE)
                        .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE)
                        .setShowInSettings(UserProperties.SHOW_IN_SETTINGS_SEPARATE)
Loading