From 823fd5090209017a029460e7dbd8ab9d51d013dd Mon Sep 17 00:00:00 2001
From: Sunny Goyal <sunnygoyal@google.com>
Date: Tue, 4 Aug 2015 11:40:13 -0700
Subject: [PATCH] Creating a cache of users to avoid multiple calls to
 UserManager

Bug: 22805101
Change-Id: I9cd270efd74fdd34a7eb738fc25797e6f1bf2487
---
 .../android/launcher3/LauncherAppState.java   |  3 +++
 src/com/android/launcher3/LauncherModel.java  |  1 +
 .../launcher3/compat/UserManagerCompat.java   | 25 ++++++++++++-----
 .../compat/UserManagerCompatV16.java          |  4 +++
 .../compat/UserManagerCompatV17.java          | 24 +++++++++++++++++
 .../launcher3/compat/UserManagerCompatVL.java | 27 +++++++++++++++++++
 .../model/AbstractUserComparator.java         | 22 ++-------------
 .../launcher3/model/AppNameComparator.java    |  2 --
 8 files changed, 80 insertions(+), 28 deletions(-)

diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index b285a683c..52f85ea42 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -20,11 +20,13 @@ import android.app.SearchManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.UserManager;
 import android.util.Log;
 
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.compat.LauncherAppsCompat;
 import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.compat.UserManagerCompat;
 import com.android.launcher3.util.Thunk;
 
 import java.lang.ref.WeakReference;
@@ -100,6 +102,7 @@ public class LauncherAppState {
         filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED);
 
         sContext.registerReceiver(mModel, filter);
+        UserManagerCompat.getInstance(sContext).enableAndResetCache();
     }
 
     /**
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index c6fa8acf6..f029561a3 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1288,6 +1288,7 @@ public class LauncherModel extends BroadcastReceiver
             }
         } else if (LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED.equals(action)
                 || LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
+            UserManagerCompat.getInstance(context).enableAndResetCache();
             forceReload();
         }
     }
diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java
index a79d94646..2ff1e7b74 100644
--- a/src/com/android/launcher3/compat/UserManagerCompat.java
+++ b/src/com/android/launcher3/compat/UserManagerCompat.java
@@ -28,16 +28,29 @@ public abstract class UserManagerCompat {
     protected UserManagerCompat() {
     }
 
+    private static final Object sInstanceLock = new Object();
+    private static UserManagerCompat sInstance;
+
     public static UserManagerCompat getInstance(Context context) {
-        if (Utilities.isLmpOrAbove()) {
-            return new UserManagerCompatVL(context);
-        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            return new UserManagerCompatV17(context);
-        } else {
-            return new UserManagerCompatV16();
+        synchronized (sInstanceLock) {
+            if (sInstance == null) {
+                if (Utilities.isLmpOrAbove()) {
+                    sInstance = new UserManagerCompatVL(context.getApplicationContext());
+                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+                    sInstance = new UserManagerCompatV17(context.getApplicationContext());
+                } else {
+                    sInstance = new UserManagerCompatV16();
+                }
+            }
+            return sInstance;
         }
     }
 
+    /**
+     * Creates a cache for users.
+     */
+    public abstract void enableAndResetCache();
+
     public abstract List<UserHandleCompat> getUserProfiles();
     public abstract long getSerialNumberForUser(UserHandleCompat user);
     public abstract UserHandleCompat getUserForSerialNumber(long serialNumber);
diff --git a/src/com/android/launcher3/compat/UserManagerCompatV16.java b/src/com/android/launcher3/compat/UserManagerCompatV16.java
index ffe698c8b..85aee57e8 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatV16.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatV16.java
@@ -53,4 +53,8 @@ public class UserManagerCompatV16 extends UserManagerCompat {
     public long getUserCreationTime(UserHandleCompat user) {
         return 0;
     }
+
+    @Override
+    public void enableAndResetCache() {
+    }
 }
diff --git a/src/com/android/launcher3/compat/UserManagerCompatV17.java b/src/com/android/launcher3/compat/UserManagerCompatV17.java
index c42c00c7d..1687569f3 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatV17.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatV17.java
@@ -21,8 +21,12 @@ import android.content.Context;
 import android.os.Build;
 import android.os.UserManager;
 
+import com.android.launcher3.util.LongArrayMap;
+
 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
 public class UserManagerCompatV17 extends UserManagerCompatV16 {
+
+    protected LongArrayMap<UserHandleCompat> mUsers;
     protected UserManager mUserManager;
 
     UserManagerCompatV17(Context context) {
@@ -30,11 +34,31 @@ public class UserManagerCompatV17 extends UserManagerCompatV16 {
     }
 
     public long getSerialNumberForUser(UserHandleCompat user) {
+        synchronized (this) {
+            if (mUsers != null) {
+                int index = mUsers.indexOfValue(user);
+                return (index >= 0) ? mUsers.keyAt(index) : 0;
+            }
+        }
         return mUserManager.getSerialNumberForUser(user.getUser());
     }
 
     public UserHandleCompat getUserForSerialNumber(long serialNumber) {
+        synchronized (this) {
+            if (mUsers != null) {
+                return mUsers.get(serialNumber);
+            }
+        }
         return UserHandleCompat.fromUser(mUserManager.getUserForSerialNumber(serialNumber));
     }
+
+    @Override
+    public void enableAndResetCache() {
+        synchronized (this) {
+            mUsers = new LongArrayMap<UserHandleCompat>();
+            UserHandleCompat myUser = UserHandleCompat.myUserHandle();
+            mUsers.put(mUserManager.getSerialNumberForUser(myUser.getUser()), myUser);
+        }
+    }
 }
 
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index dd7a72617..04cd0fdb4 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -24,7 +24,10 @@ import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.UserHandle;
+
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.util.LongArrayMap;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -42,8 +45,32 @@ public class UserManagerCompatVL extends UserManagerCompatV17 {
         mContext = context;
     }
 
+    @Override
+    public void enableAndResetCache() {
+        synchronized (this) {
+            mUsers = new LongArrayMap<UserHandleCompat>();
+            List<UserHandle> users = mUserManager.getUserProfiles();
+            if (users != null) {
+                for (UserHandle user : users) {
+                    mUsers.put(mUserManager.getSerialNumberForUser(user),
+                            UserHandleCompat.fromUser(user));
+                }
+            }
+        }
+    }
+
     @Override
     public List<UserHandleCompat> getUserProfiles() {
+        synchronized (this) {
+            if (mUsers != null) {
+                List<UserHandleCompat> users = new ArrayList<>();
+                for (UserHandleCompat user : mUsers) {
+                    users.add(user);
+                }
+                return users;
+            }
+        }
+
         List<UserHandle> users = mUserManager.getUserProfiles();
         if (users == null) {
             return Collections.emptyList();
diff --git a/src/com/android/launcher3/model/AbstractUserComparator.java b/src/com/android/launcher3/model/AbstractUserComparator.java
index cf47ce648..bd28560f3 100644
--- a/src/com/android/launcher3/model/AbstractUserComparator.java
+++ b/src/com/android/launcher3/model/AbstractUserComparator.java
@@ -22,14 +22,12 @@ import com.android.launcher3.compat.UserHandleCompat;
 import com.android.launcher3.compat.UserManagerCompat;
 
 import java.util.Comparator;
-import java.util.HashMap;
 
 /**
  * A comparator to arrange items based on user profiles.
  */
 public abstract class AbstractUserComparator<T extends ItemInfo> implements Comparator<T> {
 
-    private HashMap<UserHandleCompat, Long> mUserSerialCache = new HashMap<>();
     private final UserManagerCompat mUserManager;
     private final UserHandleCompat mMyUser;
 
@@ -43,25 +41,9 @@ public abstract class AbstractUserComparator<T extends ItemInfo> implements Comp
         if (mMyUser.equals(lhs.user)) {
             return -1;
         } else {
-            Long aUserSerial = getAndCacheUserSerial(lhs.user);
-            Long bUserSerial = getAndCacheUserSerial(rhs.user);
+            Long aUserSerial = mUserManager.getSerialNumberForUser(lhs.user);
+            Long bUserSerial = mUserManager.getSerialNumberForUser(rhs.user);
             return aUserSerial.compareTo(bUserSerial);
         }
     }
-
-    /**
-     * Returns the user serial for this user, using a cached serial if possible.
-     */
-    private Long getAndCacheUserSerial(UserHandleCompat user) {
-        Long userSerial = mUserSerialCache.get(user);
-        if (userSerial == null) {
-            userSerial = mUserManager.getSerialNumberForUser(user);
-            mUserSerialCache.put(user, userSerial);
-        }
-        return userSerial;
-    }
-
-    public void clearUserCache() {
-        mUserSerialCache.clear();
-    }
 }
diff --git a/src/com/android/launcher3/model/AppNameComparator.java b/src/com/android/launcher3/model/AppNameComparator.java
index c4b74d4dc..5f80037dc 100644
--- a/src/com/android/launcher3/model/AppNameComparator.java
+++ b/src/com/android/launcher3/model/AppNameComparator.java
@@ -68,8 +68,6 @@ public class AppNameComparator {
      * Returns a locale-aware comparator that will alphabetically order a list of applications.
      */
     public Comparator<ItemInfo> getAppInfoComparator() {
-        // Clear the user serial cache so that we get serials as needed in the comparator
-        mAppInfoComparator.clearUserCache();
         return mAppInfoComparator;
     }
 
-- 
GitLab