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

Commit a52dc3eb authored by Kenny Guy's avatar Kenny Guy
Browse files

Add concepts of related users and managed profiles to user manager.

Related users are a group that will share things like notifications.
Managed profiles are a profile of another user.

Change-Id: I2d0532f1abf939810f0fa3fc7c77ad13fa567833
parent e666350e
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -63,6 +63,15 @@ public class UserInfo implements Parcelable {
     */
    public static final int FLAG_INITIALIZED = 0x00000010;

    /**
     * Indicates that this user is a profile of another user, for example holding a users
     * corporate data.
     */
    public static final int FLAG_MANAGED_PROFILE = 0x00000020;


    public static final int NO_RELATED_GROUP_ID = -1;

    public int id;
    public int serialNumber;
    public String name;
@@ -70,6 +79,7 @@ public class UserInfo implements Parcelable {
    public int flags;
    public long creationTime;
    public long lastLoggedInTime;
    public int relatedGroupId;

    /** User is only partially created. */
    public boolean partial;
@@ -83,6 +93,7 @@ public class UserInfo implements Parcelable {
        this.name = name;
        this.flags = flags;
        this.iconPath = iconPath;
        this.relatedGroupId = NO_RELATED_GROUP_ID;
    }

    public boolean isPrimary() {
@@ -101,6 +112,10 @@ public class UserInfo implements Parcelable {
        return (flags & FLAG_RESTRICTED) == FLAG_RESTRICTED;
    }

    public boolean isManagedProfile() {
        return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
    }

    public UserInfo() {
    }

@@ -113,6 +128,7 @@ public class UserInfo implements Parcelable {
        creationTime = orig.creationTime;
        lastLoggedInTime = orig.lastLoggedInTime;
        partial = orig.partial;
        relatedGroupId = orig.relatedGroupId;
    }

    public UserHandle getUserHandle() {
@@ -137,6 +153,7 @@ public class UserInfo implements Parcelable {
        dest.writeLong(creationTime);
        dest.writeLong(lastLoggedInTime);
        dest.writeInt(partial ? 1 : 0);
        dest.writeInt(relatedGroupId);
    }

    public static final Parcelable.Creator<UserInfo> CREATOR
@@ -158,5 +175,6 @@ public class UserInfo implements Parcelable {
        creationTime = source.readLong();
        lastLoggedInTime = source.readLong();
        partial = source.readInt() != 0;
        relatedGroupId = source.readInt();
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -28,11 +28,13 @@ import android.graphics.Bitmap;
 */
interface IUserManager {
    UserInfo createUser(in String name, int flags);
    UserInfo createRelatedUser(in String name, int flags, int relatedUserId);
    boolean removeUser(int userHandle);
    void setUserName(int userHandle, String name);
    void setUserIcon(int userHandle, in Bitmap icon);
    Bitmap getUserIcon(int userHandle);
    List<UserInfo> getUsers(boolean excludeDying);
    List<UserInfo> getRelatedUsers(int userHandle);
    UserInfo getUserInfo(int userHandle);
    boolean isRestricted();
    void setGuestEnabled(boolean enable);
+37 −0
Original line number Diff line number Diff line
@@ -407,6 +407,27 @@ public class UserManager {
        }
    }

    /**
     * Creates a user with the specified name and options.
     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
     *
     * @param name the user's name
     * @param flags flags that identify the type of user and other properties.
     * @see UserInfo
     * @param relatedUserId new user will be related to this user id.
     *
     * @return the UserInfo object for the created user, or null if the user could not be created.
     * @hide
     */
    public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
        try {
            return mService.createRelatedUser(name, flags, relatedUserId);
        } catch (RemoteException re) {
            Log.w(TAG, "Could not create a user", re);
            return null;
        }
    }

    /**
     * Return the number of users currently created on the device.
     */
@@ -430,6 +451,22 @@ public class UserManager {
        }
    }

    /**
     * Returns information for all users related to userId
     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
     * @param userHandle users related to this user id will be returned.
     * @return the list of related users.
     * @hide
     */
    public List<UserInfo> getRelatedUsers(int userHandle) {
        try {
            return mService.getRelatedUsers(userHandle);
        } catch (RemoteException re) {
            Log.w(TAG, "Could not get user list", re);
            return null;
        }
    }

    /**
     * Returns information for all users on this device.
     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+69 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ public class UserManagerService extends IUserManager.Stub {
    private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
    private static final String ATTR_PARTIAL = "partial";
    private static final String ATTR_USER_VERSION = "version";
    private static final String ATTR_RELATED_GROUP_ID = "relatedGroupId";
    private static final String TAG_USERS = "users";
    private static final String TAG_USER = "user";
    private static final String TAG_RESTRICTIONS = "restrictions";
@@ -257,6 +258,29 @@ public class UserManagerService extends IUserManager.Stub {
        }
    }

    @Override
    public List<UserInfo> getRelatedUsers(int userId) {
        checkManageUsersPermission("query users");
        synchronized (mPackagesLock) {
            UserInfo user = getUserInfoLocked(userId);
            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
            for (int i = 0; i < mUsers.size(); i++) {
                UserInfo ui = mUsers.valueAt(i);
                if (!areRelatedUsers(user, ui)) {
                    continue;
                }
                users.add(ui);
            }
            return users;
        }
    }

    private boolean areRelatedUsers(UserInfo user1, UserInfo user2) {
        return user1.relatedGroupId != UserInfo.NO_RELATED_GROUP_ID &&
                user1.relatedGroupId == user2.relatedGroupId &&
                user1.id != user2.id;
    }

    @Override
    public UserInfo getUserInfo(int userId) {
        checkManageUsersPermission("query user");
@@ -662,6 +686,10 @@ public class UserManagerService extends IUserManager.Stub {
            if (userInfo.partial) {
                serializer.attribute(null, ATTR_PARTIAL, "true");
            }
            if (userInfo.relatedGroupId != UserInfo.NO_RELATED_GROUP_ID) {
                serializer.attribute(null, ATTR_RELATED_GROUP_ID,
                        Integer.toString(userInfo.relatedGroupId));
            }

            serializer.startTag(null, TAG_NAME);
            serializer.text(userInfo.name);
@@ -745,6 +773,7 @@ public class UserManagerService extends IUserManager.Stub {
        long salt = 0L;
        String pinHash = null;
        int failedAttempts = 0;
        int relatedGroupId = UserInfo.NO_RELATED_GROUP_ID;
        long lastAttemptTime = 0L;
        boolean partial = false;
        Bundle restrictions = new Bundle();
@@ -782,6 +811,8 @@ public class UserManagerService extends IUserManager.Stub {
                pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
                failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
                lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
                relatedGroupId = readIntAttribute(parser, ATTR_RELATED_GROUP_ID,
                        UserInfo.NO_RELATED_GROUP_ID);
                String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
                if ("true".equals(valueString)) {
                    partial = true;
@@ -820,6 +851,7 @@ public class UserManagerService extends IUserManager.Stub {
            userInfo.creationTime = creationTime;
            userInfo.lastLoggedInTime = lastLoggedInTime;
            userInfo.partial = partial;
            userInfo.relatedGroupId = relatedGroupId;
            mUserRestrictions.append(id, restrictions);
            if (salt != 0L) {
                RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
@@ -934,10 +966,40 @@ public class UserManagerService extends IUserManager.Stub {
        }
    }

    private int getNextRelatedGroupIdLocked() {
        int maxGroupId = UserInfo.NO_RELATED_GROUP_ID;
        for (int i = 0; i < mUsers.size(); i++) {
            UserInfo ui = mUsers.valueAt(i);
            if (maxGroupId < ui.relatedGroupId) {
                maxGroupId = ui.relatedGroupId;
            }
        }
        return maxGroupId + 1;
    }

    @Override
    public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
        checkManageUsersPermission("Only the system can create users");
        if (relatedUserId != UserHandle.USER_OWNER) {
            Slog.w(LOG_TAG, "Only user owner can have related users");
            return null;
        }
        synchronized (mPackagesLock) {
            UserInfo relatedUser = getUserInfoLocked(relatedUserId);
            if (relatedUser == null) {
                return null;
            }
            return createUserInternal(name, flags, relatedUser);
        }
    }

    @Override
    public UserInfo createUser(String name, int flags) {
        checkManageUsersPermission("Only the system can create users");
        return createUserInternal(name, flags, null);
    }

    private UserInfo createUserInternal(String name, int flags, UserInfo relatedUser) {
        final long ident = Binder.clearCallingIdentity();
        final UserInfo userInfo;
        try {
@@ -954,6 +1016,13 @@ public class UserManagerService extends IUserManager.Stub {
                    Environment.getUserSystemDirectory(userInfo.id).mkdirs();
                    mUsers.put(userId, userInfo);
                    writeUserListLocked();
                    if (relatedUser != null) {
                        if (relatedUser.relatedGroupId == UserInfo.NO_RELATED_GROUP_ID) {
                            relatedUser.relatedGroupId = getNextRelatedGroupIdLocked();
                        }
                        userInfo.relatedGroupId = relatedUser.relatedGroupId;
                        writeUserLocked(relatedUser);
                    }
                    writeUserLocked(userInfo);
                    mPm.createNewUserLILPw(userId, userPath);
                    userInfo.partial = false;