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

Commit acf3858b authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Optimize UserHandle.of()

There will be more calls to *ForUser() APIs over time by mainline modules.
Let's avoid creating new objects in common cases.

Bug: 142134660
Fix: 140429319
Test: atest cts/tests/app/src/android/app/cts/UserHandleTest.java
Change-Id: Ie71850bd08a8d9831232ddb40807ae49e3a56841
parent 496d47ab
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -2033,10 +2033,18 @@ package android.os {
  public final class UserHandle implements android.os.Parcelable {
    method public static int getAppId(int);
    method public int getIdentifier();
    method public static int getUid(int, int);
    method public static int getUserId(int);
    method public static boolean isApp(int);
    method public static int myUserId();
    method public static android.os.UserHandle of(int);
    field @NonNull public static final android.os.UserHandle ALL;
    field @NonNull public static final android.os.UserHandle CURRENT;
    field public static final int MIN_SECONDARY_USER_ID = 10; // 0xa
    field @NonNull public static final android.os.UserHandle SYSTEM;
    field public static final int USER_ALL = -1; // 0xffffffff
    field public static final int USER_NULL = -10000; // 0xffffd8f0
    field public static final int USER_SYSTEM = 0; // 0x0
  }

  public class UserManager {
+56 −3
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ public final class UserHandle implements Parcelable {

    /** @hide A user id to indicate all users on the device */
    @UnsupportedAppUsage
    @TestApi
    public static final @UserIdInt int USER_ALL = -1;

    /** @hide A user handle to indicate all users on the device */
@@ -69,8 +70,11 @@ public final class UserHandle implements Parcelable {

    /** @hide An undefined user id */
    @UnsupportedAppUsage
    @TestApi
    public static final @UserIdInt int USER_NULL = -10000;

    private static final @NonNull UserHandle NULL = new UserHandle(USER_NULL);

    /**
     * @hide A user id constant to indicate the "owner" user of the device
     * @deprecated Consider using either {@link UserHandle#USER_SYSTEM} constant or
@@ -91,6 +95,7 @@ public final class UserHandle implements Parcelable {

    /** @hide A user id constant to indicate the "system" user of the device */
    @UnsupportedAppUsage
    @TestApi
    public static final @UserIdInt int USER_SYSTEM = 0;

    /** @hide A user serial constant to indicate the "system" user of the device */
@@ -109,6 +114,27 @@ public final class UserHandle implements Parcelable {
    @UnsupportedAppUsage
    public static final boolean MU_ENABLED = true;

    /** @hide */
    @TestApi
    public static final int MIN_SECONDARY_USER_ID = 10;

    /**
     * Arbitrary user handle cache size. We use the cache even when {@link #MU_ENABLED} is false
     * anyway, so we can always assume in CTS that UserHandle.of(10) returns a cached instance
     * even on non-multiuser devices.
     */
    private static final int NUM_CACHED_USERS = 4;

    private static final UserHandle[] CACHED_USER_INFOS = new UserHandle[NUM_CACHED_USERS];

    static {
        // Not lazily initializing the cache, so that we can share them across processes.
        // (We'll create them in zygote.)
        for (int i = 0; i < CACHED_USER_INFOS.length; i++) {
            CACHED_USER_INFOS[i] = new UserHandle(MIN_SECONDARY_USER_ID + i);
        }
    }

    /** @hide */
    @UnsupportedAppUsage
    public static final int ERR_GID = -1;
@@ -209,6 +235,7 @@ public final class UserHandle implements Parcelable {
     * @hide
     */
    @UnsupportedAppUsage
    @TestApi
    public static @UserIdInt int getUserId(int uid) {
        if (MU_ENABLED) {
            return uid / PER_USER_RANGE;
@@ -229,9 +256,31 @@ public final class UserHandle implements Parcelable {
    }

    /** @hide */
    @TestApi
    @SystemApi
    public static UserHandle of(@UserIdInt int userId) {
        return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId);
        if (userId == USER_SYSTEM) {
            return SYSTEM; // Most common.
        }
        // These are sequential; so use a switch. Maybe they'll be optimized to a table lookup.
        switch (userId) {
            case USER_ALL:
                return ALL;

            case USER_CURRENT:
                return CURRENT;

            case USER_CURRENT_OR_SELF:
                return CURRENT_OR_SELF;
        }
        if (userId >= MIN_SECONDARY_USER_ID
                && userId < (MIN_SECONDARY_USER_ID + CACHED_USER_INFOS.length)) {
            return CACHED_USER_INFOS[userId - MIN_SECONDARY_USER_ID];
        }
        if (userId == USER_NULL) { // Not common.
            return NULL;
        }
        return new UserHandle(userId);
    }

    /**
@@ -239,6 +288,7 @@ public final class UserHandle implements Parcelable {
     * @hide
     */
    @UnsupportedAppUsage
    @TestApi
    public static int getUid(@UserIdInt int userId, @AppIdInt int appId) {
        if (MU_ENABLED) {
            return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);
@@ -404,6 +454,7 @@ public final class UserHandle implements Parcelable {
     * @hide
     */
    @SystemApi
    @TestApi
    public static @UserIdInt int myUserId() {
        return getUserId(Process.myUid());
    }
@@ -513,7 +564,9 @@ public final class UserHandle implements Parcelable {
    public static final @android.annotation.NonNull Parcelable.Creator<UserHandle> CREATOR
            = new Parcelable.Creator<UserHandle>() {
        public UserHandle createFromParcel(Parcel in) {
            return new UserHandle(in);
            // Try to avoid allocation; use of() here. Keep this and the constructor below
            // in sync.
            return UserHandle.of(in.readInt());
        }

        public UserHandle[] newArray(int size) {
@@ -532,6 +585,6 @@ public final class UserHandle implements Parcelable {
     * positioned at the location in the buffer where it was written.
     */
    public UserHandle(Parcel in) {
        mHandle = in.readInt();
        mHandle = in.readInt(); // Keep this and createFromParcel() in sync.
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -209,7 +209,8 @@ public class UserManagerService extends IUserManager.Stub {
            | UserInfo.FLAG_DEMO;

    @VisibleForTesting
    static final int MIN_USER_ID = 10;
    static final int MIN_USER_ID = UserHandle.MIN_SECONDARY_USER_ID;

    // We need to keep process uid within Integer.MAX_VALUE.
    @VisibleForTesting
    static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;