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

Commit e0f6225c authored by Lee Shombert's avatar Lee Shombert Committed by Android (Google) Code Review
Browse files

Merge "Binder cache for isUserUnlocked()."

parents 2c09c170 ebe2a0ba
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.PropertyInvalidatedCache;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -2150,16 +2151,38 @@ public class UserManager {
        return isUserUnlocked(user.getIdentifier());
    }

    private static final String CACHE_KEY_IS_USER_UNLOCKED_PROPERTY =
            "cache_key.is_user_unlocked";

    private final PropertyInvalidatedCache<Integer, Boolean> mIsUserUnlockedCache =
            new PropertyInvalidatedCache<Integer, Boolean>(
                32, CACHE_KEY_IS_USER_UNLOCKED_PROPERTY) {
                @Override
                protected Boolean recompute(Integer query) {
                    try {
                        return mService.isUserUnlocked(query);
                    } catch (RemoteException re) {
                        throw re.rethrowFromSystemServer();
                    }
                }
            };

    /** {@hide} */
    @UnsupportedAppUsage
    @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
            Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
    public boolean isUserUnlocked(@UserIdInt int userId) {
        try {
            return mService.isUserUnlocked(userId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        return mIsUserUnlockedCache.query(userId);
    }

    /** {@hide} */
    public void disableIsUserUnlockedCache() {
        mIsUserUnlockedCache.disableLocal();
    }

    /** {@hide} */
    public static final void invalidateIsUserUnlockedCache() {
        PropertyInvalidatedCache.invalidateCache(CACHE_KEY_IS_USER_UNLOCKED_PROPERTY);
    }

    /**
+39 −5
Original line number Diff line number Diff line
@@ -342,9 +342,43 @@ class StorageManagerService extends IStorageManager.Stub
     */
    private final Object mPackagesLock = new Object();

    /**
     * mLocalUnlockedUsers affects the return value of isUserUnlocked.  If
     * any value in the array changes, then the binder cache for
     * isUserUnlocked must be invalidated.  When adding mutating methods to
     * WatchedLockedUsers, be sure to invalidate the cache in the new
     * methods.
     */
    private class WatchedLockedUsers {
        private int[] users = EmptyArray.INT;
        public WatchedLockedUsers() {
        }
        public void append(int userId) {
            users = ArrayUtils.appendInt(users, userId);
            invalidateIsUserUnlockedCache();
        }
        public void remove(int userId) {
            users = ArrayUtils.removeInt(users, userId);
            invalidateIsUserUnlockedCache();
        }
        public boolean contains(int userId) {
            return ArrayUtils.contains(users, userId);
        }
        public int[] all() {
            return users;
        }
        @Override
        public String toString() {
            return Arrays.toString(users);
        }
        private void invalidateIsUserUnlockedCache() {
            UserManager.invalidateIsUserUnlockedCache();
        }
    }

    /** Set of users that we know are unlocked. */
    @GuardedBy("mLock")
    private int[] mLocalUnlockedUsers = EmptyArray.INT;
    private WatchedLockedUsers mLocalUnlockedUsers = new WatchedLockedUsers();
    /** Set of users that system knows are unlocked. */
    @GuardedBy("mLock")
    private int[] mSystemUnlockedUsers = EmptyArray.INT;
@@ -3042,7 +3076,7 @@ class StorageManagerService extends IStorageManager.Stub
        }

        synchronized (mLock) {
            mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
            mLocalUnlockedUsers.append(userId);
        }
    }

@@ -3058,14 +3092,14 @@ class StorageManagerService extends IStorageManager.Stub
        }

        synchronized (mLock) {
            mLocalUnlockedUsers = ArrayUtils.removeInt(mLocalUnlockedUsers, userId);
            mLocalUnlockedUsers.remove(userId);
        }
    }

    @Override
    public boolean isUserKeyUnlocked(int userId) {
        synchronized (mLock) {
            return ArrayUtils.contains(mLocalUnlockedUsers, userId);
            return mLocalUnlockedUsers.contains(userId);
        }
    }

@@ -4177,7 +4211,7 @@ class StorageManagerService extends IStorageManager.Stub
            }

            pw.println();
            pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
            pw.println("Local unlocked users: " + mLocalUnlockedUsers);
            pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));

            final ContentResolver cr = mContext.getContentResolver();
+40 −1
Original line number Diff line number Diff line
@@ -462,8 +462,42 @@ public class UserManagerService extends IUserManager.Stub {
    @GuardedBy("mUsersLock")
    private boolean mForceEphemeralUsers;

    /**
     * The member mUserStates affects the return value of isUserUnlocked.
     * If any value in mUserStates changes, then the binder cache for
     * isUserUnlocked must be invalidated.  When adding mutating methods to
     * WatchedUserStates, be sure to invalidate the cache in the new
     * methods.
     */
    private class WatchedUserStates {
        final SparseIntArray states;
        public WatchedUserStates() {
            states = new SparseIntArray();
        }
        public int get(int userId) {
            return states.get(userId);
        }
        public int get(int userId, int fallback) {
            return states.indexOfKey(userId) >= 0 ? states.get(userId) : fallback;
        }
        public void put(int userId, int state) {
            states.put(userId, state);
            invalidateIsUserUnlockedCache();
        }
        public void delete(int userId) {
            states.delete(userId);
            invalidateIsUserUnlockedCache();
        }
        @Override
        public String toString() {
            return states.toString();
        }
        private void invalidateIsUserUnlockedCache() {
            UserManager.invalidateIsUserUnlockedCache();
        }
    }
    @GuardedBy("mUserStates")
    private final SparseIntArray mUserStates = new SparseIntArray();
    private final WatchedUserStates mUserStates = new WatchedUserStates();

    private static UserManagerService sInstance;

@@ -4801,6 +4835,11 @@ public class UserManagerService extends IUserManager.Stub {
                    || (state == UserState.STATE_RUNNING_UNLOCKED);
        }

        /**
         * The return values of this method are cached in clients.  If the
         * logic in this function changes then the cache invalidation code
         * may need to be revisited.
         */
        @Override
        public boolean isUserUnlocked(@UserIdInt int userId) {
            int state;