Preventing multiple calls to loadLabel for the same info within a single load.

- Fixing mind boggling bug where we weren't even using the label cache earlier.

Change-Id: I605abf4d589ad02b2426d20adfe9cd1773cc84fd
diff --git a/src/com/android/launcher2/AllAppsList.java b/src/com/android/launcher2/AllAppsList.java
index 4c9bc5e..051b0bd 100644
--- a/src/com/android/launcher2/AllAppsList.java
+++ b/src/com/android/launcher2/AllAppsList.java
@@ -91,7 +91,7 @@
 
         if (matches.size() > 0) {
             for (ResolveInfo info : matches) {
-                add(new ApplicationInfo(context.getPackageManager(), info, mIconCache));
+                add(new ApplicationInfo(context.getPackageManager(), info, mIconCache, null));
             }
         }
     }
@@ -142,10 +142,10 @@
                         info.activityInfo.applicationInfo.packageName,
                         info.activityInfo.name);
                 if (applicationInfo == null) {
-                    add(new ApplicationInfo(context.getPackageManager(), info, mIconCache));
+                    add(new ApplicationInfo(context.getPackageManager(), info, mIconCache, null));
                 } else {
                     mIconCache.remove(applicationInfo.componentName);
-                    mIconCache.getTitleAndIcon(applicationInfo, info);
+                    mIconCache.getTitleAndIcon(applicationInfo, info, null);
                     modified.add(applicationInfo);
                 }
             }
diff --git a/src/com/android/launcher2/ApplicationInfo.java b/src/com/android/launcher2/ApplicationInfo.java
index ac571ea..1fc1d1f 100644
--- a/src/com/android/launcher2/ApplicationInfo.java
+++ b/src/com/android/launcher2/ApplicationInfo.java
@@ -19,12 +19,13 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.graphics.Bitmap;
 import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 
 /**
  * Represents an app in AllAppsView.
@@ -66,7 +67,8 @@
     /**
      * Must not hold the Context.
      */
-    public ApplicationInfo(PackageManager pm, ResolveInfo info, IconCache iconCache) {
+    public ApplicationInfo(PackageManager pm, ResolveInfo info, IconCache iconCache,
+            HashMap<Object, CharSequence> labelCache) {
         final String packageName = info.activityInfo.applicationInfo.packageName;
 
         this.componentName = new ComponentName(packageName, info.activityInfo.name);
@@ -88,9 +90,9 @@
             Log.d(TAG, "PackageManager.getApplicationInfo failed for " + packageName);
         }
 
-        iconCache.getTitleAndIcon(this, info);
+        iconCache.getTitleAndIcon(this, info, labelCache);
     }
-    
+
     public ApplicationInfo(ApplicationInfo info) {
         super(info);
         componentName = info.componentName;
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index bf6caee..2977383 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -125,9 +125,10 @@
     /**
      * Fill in "application" with the icon and label for "info."
      */
-    public void getTitleAndIcon(ApplicationInfo application, ResolveInfo info) {
+    public void getTitleAndIcon(ApplicationInfo application, ResolveInfo info,
+            HashMap<Object, CharSequence> labelCache) {
         synchronized (mCache) {
-            CacheEntry entry = cacheLocked(application.componentName, info);
+            CacheEntry entry = cacheLocked(application.componentName, info, labelCache);
 
             application.title = entry.title;
             application.iconBitmap = entry.icon;
@@ -143,7 +144,7 @@
                 return mDefaultIcon;
             }
 
-            CacheEntry entry = cacheLocked(component, resolveInfo);
+            CacheEntry entry = cacheLocked(component, resolveInfo, null);
             return entry.icon;
         }
     }
@@ -154,7 +155,7 @@
                 return null;
             }
 
-            CacheEntry entry = cacheLocked(component, resolveInfo);
+            CacheEntry entry = cacheLocked(component, resolveInfo, null);
             return entry.icon;
         }
     }
@@ -163,14 +164,22 @@
         return mDefaultIcon == icon;
     }
 
-    private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info) {
+    private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info,
+            HashMap<Object, CharSequence> labelCache) {
         CacheEntry entry = mCache.get(componentName);
         if (entry == null) {
             entry = new CacheEntry();
 
             mCache.put(componentName, entry);
 
-            entry.title = info.loadLabel(mPackageManager).toString();
+            if (labelCache != null && labelCache.containsKey(info)) {
+                entry.title = labelCache.get(info).toString();
+            } else {
+                entry.title = info.loadLabel(mPackageManager).toString();
+                if (labelCache != null) {
+                    labelCache.put(info, entry.title);
+                }
+            }
             if (entry.title == null) {
                 entry.title = info.activityInfo.name;
             }
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 64b38c0..33e350f 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -630,10 +630,12 @@
         private boolean mIsLaunching;
         private boolean mStopped;
         private boolean mLoadAndBindStepFinished;
+        private HashMap<Object, CharSequence> mLabelCache;
 
         LoaderTask(Context context, boolean isLaunching) {
             mContext = context;
             mIsLaunching = isLaunching;
+            mLabelCache = new HashMap<Object, CharSequence>();
         }
 
         boolean isLaunching() {
@@ -888,7 +890,7 @@
 
                             if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                                 info = getShortcutInfo(manager, intent, context, c, iconIndex,
-                                        titleIndex);
+                                        titleIndex, mLabelCache);
                             } else {
                                 info = getShortcutInfo(c, context, iconTypeIndex,
                                         iconPackageIndex, iconResourceIndex, iconIndex,
@@ -1249,7 +1251,7 @@
 
                     final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
                     Collections.sort(apps,
-                            new ResolveInfo.DisplayNameComparator(packageManager));
+                            new LauncherModel.ShortcutNameComparator(packageManager, mLabelCache));
                     if (DEBUG_LOADERS) {
                         Log.d(TAG, "sort took "
                                 + (SystemClock.uptimeMillis()-sortTime) + "ms");
@@ -1261,7 +1263,8 @@
                 startIndex = i;
                 for (int j=0; i<N && j<batchSize; j++) {
                     // This builds the icon bitmaps.
-                    mAllAppsList.add(new ApplicationInfo(packageManager, apps.get(i), mIconCache));
+                    mAllAppsList.add(new ApplicationInfo(packageManager, apps.get(i),
+                            mIconCache, mLabelCache));
                     i++;
                 }
 
@@ -1446,7 +1449,7 @@
      * doesn't have a Cursor, but
      */
     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context) {
-        return getShortcutInfo(manager, intent, context, null, -1, -1);
+        return getShortcutInfo(manager, intent, context, null, -1, -1, null);
     }
 
     /**
@@ -1455,7 +1458,7 @@
      * If c is not null, then it will be used to fill in missing data like the title and icon.
      */
     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context,
-            Cursor c, int iconIndex, int titleIndex) {
+            Cursor c, int iconIndex, int titleIndex, HashMap<Object, CharSequence> labelCache) {
         Bitmap icon = null;
         final ShortcutInfo info = new ShortcutInfo();
 
@@ -1490,7 +1493,14 @@
 
         // from the resource
         if (resolveInfo != null) {
-            info.title = resolveInfo.activityInfo.loadLabel(manager);
+            if (labelCache != null && labelCache.containsKey(resolveInfo)) {
+                info.title = labelCache.get(resolveInfo);
+            } else {
+                info.title = resolveInfo.activityInfo.loadLabel(manager);
+                if (labelCache != null) {
+                    labelCache.put(resolveInfo, info.title);
+                }
+            }
         }
         // from the db
         if (info.title == null) {
@@ -1766,17 +1776,31 @@
     };
     public static class ShortcutNameComparator implements Comparator<ResolveInfo> {
         private PackageManager mPackageManager;
-        private HashMap<Object, String> mLabelCache;
+        private HashMap<Object, CharSequence> mLabelCache;
         ShortcutNameComparator(PackageManager pm) {
             mPackageManager = pm;
-            mLabelCache = new HashMap<Object, String>();
+            mLabelCache = new HashMap<Object, CharSequence>();
+        }
+        ShortcutNameComparator(PackageManager pm, HashMap<Object, CharSequence> labelCache) {
+            mPackageManager = pm;
+            mLabelCache = labelCache;
         }
         public final int compare(ResolveInfo a, ResolveInfo b) {
-            String labelA, labelB;
-            if (mLabelCache.containsKey(a)) labelA = mLabelCache.get(a);
-            else labelA = a.loadLabel(mPackageManager).toString();
-            if (mLabelCache.containsKey(b)) labelB = mLabelCache.get(b);
-            else labelB = b.loadLabel(mPackageManager).toString();
+            CharSequence labelA, labelB;
+            if (mLabelCache.containsKey(a)) {
+                labelA = mLabelCache.get(a);
+            } else {
+                labelA = a.loadLabel(mPackageManager).toString();
+
+                mLabelCache.put(a, labelA);
+            }
+            if (mLabelCache.containsKey(b)) {
+                labelB = mLabelCache.get(b);
+            } else {
+                labelB = b.loadLabel(mPackageManager).toString();
+
+                mLabelCache.put(b, labelB);
+            }
             return sCollator.compare(labelA, labelB);
         }
     };
@@ -1789,14 +1813,22 @@
         }
         public final int compare(Object a, Object b) {
             String labelA, labelB;
-            if (mLabelCache.containsKey(a)) labelA = mLabelCache.get(a);
-            else labelA = (a instanceof AppWidgetProviderInfo) ?
+            if (mLabelCache.containsKey(a)) {
+                labelA = mLabelCache.get(a);
+            } else {
+                labelA = (a instanceof AppWidgetProviderInfo) ?
                     ((AppWidgetProviderInfo) a).label :
                     ((ResolveInfo) a).loadLabel(mPackageManager).toString();
-            if (mLabelCache.containsKey(b)) labelB = mLabelCache.get(b);
-            else labelB = (b instanceof AppWidgetProviderInfo) ?
+                mLabelCache.put(a, labelA);
+            }
+            if (mLabelCache.containsKey(b)) {
+                labelB = mLabelCache.get(b);
+            } else {
+                labelB = (b instanceof AppWidgetProviderInfo) ?
                     ((AppWidgetProviderInfo) b).label :
                     ((ResolveInfo) b).loadLabel(mPackageManager).toString();
+                mLabelCache.put(b, labelB);
+            }
             return sCollator.compare(labelA, labelB);
         }
     };
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index a48a4ef..3ae978d 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -103,16 +103,6 @@
         setTag(info);
     }
 
-    public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager,
-            IconCache modelIconCache, HolographicOutlineHelper holoOutlineHelper) {
-        mHolographicOutlineHelper = holoOutlineHelper;
-        ComponentName cn = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
-        mIcon = modelIconCache.getIcon(cn, info);
-        setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
-        setText(info.loadLabel(packageManager));
-        setTag(info);
-    }
-
     public void setHolographicOutline(Bitmap holoOutline) {
         mHolographicOutline = holoOutline;
         getHolographicOutlineView().invalidate();
@@ -120,8 +110,8 @@
 
     @Override
     public void setAlpha(float alpha) {
-        final float viewAlpha = mHolographicOutlineHelper.viewAlphaInterpolator(alpha);
-        final float holographicAlpha = mHolographicOutlineHelper.highlightAlphaInterpolator(alpha);
+        final float viewAlpha = HolographicOutlineHelper.viewAlphaInterpolator(alpha);
+        final float holographicAlpha = HolographicOutlineHelper.highlightAlphaInterpolator(alpha);
         int newViewAlpha = (int) (viewAlpha * 255);
         int newHolographicAlpha = (int) (holographicAlpha * 255);
         if ((mAlpha != newViewAlpha) || (mHolographicAlpha != newHolographicAlpha)) {