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

Commit 75f0a07f authored by Bookatz's avatar Bookatz
Browse files

UserInfo: FULL and SYSTEM flags

Introduces two new UserInfo flags:

SYSTEM - refers to the system user, i.e. user 0. Although
UserManagerService already knows which user is the system, this flag
will be useful in other contexts.

FULL - refers to a non-profile human user.

Right now, for every user, one of the following flag combos are true:
SYSTEM (user 0 on a headless-user-0 device)
SYSTEM | FULL (user 0 on a regular device)
FULL (secondary user)
MANAGED_PROFILE (profile users)

Test: Manual verification via "pm list users" of new flags when adding a new user
Test: Manual verification via "pm list users" of new flags for pre-existing users
Test: Later cls will test the functionality as it is introduced
Bug: 134605778
Change-Id: Ife92bfa8a91cc4567d825da8e6a1b3894b088b22
parent 6a87d678
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -24,6 +24,18 @@ import android.os.UserManager;

/**
 * Per-user information.
 *
 * <p>There are 3 base properties of users: {@link #FLAG_SYSTEM}, {@link #FLAG_FULL}, and
 * {@link #FLAG_MANAGED_PROFILE}. Every user must have one of the following combination of these
 * flags:
 * <ul>
 *    <li>FLAG_SYSTEM (user {@link UserHandle#USER_SYSTEM} on a headless-user-0 device)</li>
 *    <li>FLAG_SYSTEM and FLAG_FULL (user {@link UserHandle#USER_SYSTEM} on a regular device)</li>
 *    <li>FLAG_FULL (non-profile secondary user)</li>
 *    <li>FLAG_MANAGED_PROFILE (profile users)</li>
 * </ul>
 * Users can have also have additional flags (such as FLAG_GUEST) as appropriate.
 *
 * @hide
 */
public class UserInfo implements Parcelable {
@@ -93,6 +105,20 @@ public class UserInfo implements Parcelable {
     */
    public static final int FLAG_DEMO = 0x00000200;

    /**
     * Indicates that this user is a non-profile human user.
     *
     * <p>When creating a new (non-system) user, this flag will always be forced true unless the
     * user is a {@link #FLAG_MANAGED_PROFILE}. If user {@link UserHandle#USER_SYSTEM} is also a
     * human user, it must also be flagged as FULL.
     */
    public static final int FLAG_FULL = 0x00000400;

    /**
     * Indicates that this user is {@link UserHandle#USER_SYSTEM}. Not applicable to created users.
     */
    public static final int FLAG_SYSTEM = 0x00000800;

    public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL;

    @UnsupportedAppUsage
+47 −8
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import android.os.storage.StorageManager;
import android.security.GateKeeper;
import android.service.gatekeeper.IGateKeeperService;
import android.stats.devicepolicy.DevicePolicyEnums;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.IntArray;
import android.util.Log;
@@ -125,6 +126,7 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Service for {@link UserManager}.
@@ -214,7 +216,7 @@ public class UserManagerService extends IUserManager.Stub {
    @VisibleForTesting
    static final int MAX_RECENTLY_REMOVED_IDS_SIZE = 100;

    private static final int USER_VERSION = 7;
    private static final int USER_VERSION = 8;

    private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms

@@ -2139,6 +2141,7 @@ public class UserManagerService extends IUserManager.Stub {
     */
    @GuardedBy({"mRestrictionsLock", "mPackagesLock"})
    private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) {
        Set<Integer> userIdsToWrite = new ArraySet<>();
        final int originalVersion = mUserVersion;
        int userVersion = mUserVersion;
        if (userVersion < 1) {
@@ -2147,7 +2150,7 @@ public class UserManagerService extends IUserManager.Stub {
            if ("Primary".equals(userData.info.name)) {
                userData.info.name =
                        mContext.getResources().getString(com.android.internal.R.string.owner_name);
                scheduleWriteUser(userData);
                userIdsToWrite.add(userData.info.id);
            }
            userVersion = 1;
        }
@@ -2157,7 +2160,7 @@ public class UserManagerService extends IUserManager.Stub {
            UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
            if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
                userData.info.flags |= UserInfo.FLAG_INITIALIZED;
                scheduleWriteUser(userData);
                userIdsToWrite.add(userData.info.id);
            }
            userVersion = 2;
        }
@@ -2182,7 +2185,7 @@ public class UserManagerService extends IUserManager.Stub {
                            && (userData.info.restrictedProfileParentId
                                    == UserInfo.NO_PROFILE_GROUP_ID)) {
                        userData.info.restrictedProfileParentId = UserHandle.USER_SYSTEM;
                        scheduleWriteUser(userData);
                        userIdsToWrite.add(userData.info.id);
                    }
                }
            }
@@ -2206,6 +2209,29 @@ public class UserManagerService extends IUserManager.Stub {
            userVersion = 7;
        }

        if (userVersion < 8) {
            // Added FLAG_FULL and FLAG_SYSTEM flags.
            synchronized (mUsersLock) {
                UserData userData = mUsers.get(UserHandle.USER_SYSTEM);
                userData.info.flags |= UserInfo.FLAG_SYSTEM;
                if (!UserManager.isHeadlessSystemUserMode()) {
                    userData.info.flags |= UserInfo.FLAG_FULL;
                }
                userIdsToWrite.add(userData.info.id);

                // Mark FULL all non-profile users except USER_SYSTEM.
                // Start index at 1 since USER_SYSTEM is the smallest userId and we're skipping it.
                for (int i = 1; i < mUsers.size(); i++) {
                    userData = mUsers.valueAt(i);
                    if ((userData.info.flags & UserInfo.FLAG_MANAGED_PROFILE) == 0) {
                        userData.info.flags |= UserInfo.FLAG_FULL;
                        userIdsToWrite.add(userData.info.id);
                    }
                }
            }
            userVersion = 8;
        }

        if (userVersion < USER_VERSION) {
            Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
                    + USER_VERSION);
@@ -2213,6 +2239,12 @@ public class UserManagerService extends IUserManager.Stub {
            mUserVersion = userVersion;

            if (originalVersion < mUserVersion) {
                for (int userId : userIdsToWrite) {
                    UserData userData = getUserDataNoChecks(userId);
                    if (userData != null) {
                        writeUserLP(userData);
                    }
                }
                writeUserListLP();
            }
        }
@@ -2220,12 +2252,15 @@ public class UserManagerService extends IUserManager.Stub {

    @GuardedBy({"mPackagesLock", "mRestrictionsLock"})
    private void fallbackToSingleUserLP() {
        int flags = UserInfo.FLAG_INITIALIZED;
        int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED;
        // In split system user mode, the admin and primary flags are assigned to the first human
        // user.
        if (!UserManager.isSplitSystemUser()) {
            flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
        }
        if (!UserManager.isHeadlessSystemUserMode()) {
            flags |= UserInfo.FLAG_FULL;
        }
        // Create the system user
        UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
        UserData userData = putUserInfo(system);
@@ -2262,14 +2297,14 @@ public class UserManagerService extends IUserManager.Stub {
        return mContext.getResources().getString(com.android.internal.R.string.owner_name);
    }

    private void scheduleWriteUser(UserData UserData) {
    private void scheduleWriteUser(UserData userData) {
        if (DBG) {
            debug("scheduleWriteUser");
        }
        // No need to wrap it within a lock -- worst case, we'll just post the same message
        // twice.
        if (!mHandler.hasMessages(WRITE_USER_MSG, UserData)) {
            Message msg = mHandler.obtainMessage(WRITE_USER_MSG, UserData);
        if (!mHandler.hasMessages(WRITE_USER_MSG, userData)) {
            Message msg = mHandler.obtainMessage(WRITE_USER_MSG, userData);
            mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY);
        }
    }
@@ -2749,6 +2784,10 @@ public class UserManagerService extends IUserManager.Stub {
                        }
                    }
                }
                if (!isManagedProfile) {
                    // New users cannot be system, and it's not a profile, so per-force it's FULL.
                    flags |= UserInfo.FLAG_FULL;
                }

                userId = getNextAvailableId();
                Environment.getUserSystemDirectory(userId).mkdirs();