From c1a4a0dbfa06a2e09e64499ad5de7451f3ee55f4 Mon Sep 17 00:00:00 2001 From: Kweku Adams Date: Fri, 4 Nov 2022 20:09:07 +0000 Subject: [PATCH] Use a single lock and add a flag. Using separate locks adds a little bit of overhead to the get method. Switch to a single lock to minimize the performance cost. Also add a control flag to disable caching in the future, if so desired. Bug: 257054989 Test: atest CorePerfTests:AccountManagerPerfTest Change-Id: I5bbcc54f28cbe3c434995af8b3452debfc68c4ee --- core/java/android/content/pm/UserPackage.java | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/core/java/android/content/pm/UserPackage.java b/core/java/android/content/pm/UserPackage.java index e75f55174b4c1..7ca92c3d47774 100644 --- a/core/java/android/content/pm/UserPackage.java +++ b/core/java/android/content/pm/UserPackage.java @@ -33,17 +33,19 @@ import java.util.Objects; * @hide */ public final class UserPackage { + private static final boolean ENABLE_CACHING = true; + @UserIdInt public final int userId; public final String packageName; - @GuardedBy("sCache") + private static final Object sCacheLock = new Object(); + @GuardedBy("sCacheLock") private static final SparseArrayMap sCache = new SparseArrayMap<>(); - private static final Object sUserIdLock = new Object(); private static final class NoPreloadHolder { /** Set of userIDs to cache objects for. */ - @GuardedBy("sUserIdLock") + @GuardedBy("sCacheLock") private static int[] sUserIds = new int[]{UserHandle.getUserId(Process.myUid())}; } @@ -80,13 +82,16 @@ public final class UserPackage { /** Return an instance of this class representing the given userId + packageName combination. */ @NonNull public static UserPackage of(@UserIdInt int userId, @NonNull String packageName) { - synchronized (sUserIdLock) { + if (!ENABLE_CACHING) { + return new UserPackage(userId, packageName); + } + + synchronized (sCacheLock) { if (!ArrayUtils.contains(NoPreloadHolder.sUserIds, userId)) { // Don't cache objects for invalid userIds. return new UserPackage(userId, packageName); } - } - synchronized (sCache) { + UserPackage up = sCache.get(userId, packageName); if (up == null) { packageName = packageName.intern(); @@ -99,23 +104,27 @@ public final class UserPackage { /** Remove the specified app from the cache. */ public static void removeFromCache(@UserIdInt int userId, @NonNull String packageName) { - synchronized (sCache) { + if (!ENABLE_CACHING) { + return; + } + + synchronized (sCacheLock) { sCache.delete(userId, packageName); } } /** Indicate the list of valid user IDs on the device. */ public static void setValidUserIds(@NonNull int[] userIds) { - userIds = userIds.clone(); - synchronized (sUserIdLock) { - NoPreloadHolder.sUserIds = userIds; + if (!ENABLE_CACHING) { + return; } - synchronized (sCache) { + + userIds = userIds.clone(); + synchronized (sCacheLock) { + NoPreloadHolder.sUserIds = userIds; + for (int u = sCache.numMaps() - 1; u >= 0; --u) { final int userId = sCache.keyAt(u); - // Not holding sUserIdLock is intentional here. We don't modify the elements within - // the array and so even if this method is called multiple times with different sets - // of user IDs, we want to adjust the cache based on each new array. if (!ArrayUtils.contains(userIds, userId)) { sCache.deleteAt(u); }