Merge "Updating the wallpaperpicker thumb selection feedback" into ub-now-queens
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index 38d2fa5..ac9a125 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -18,10 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 
 import com.android.launcher3.compat.LauncherActivityInfoCompat;
 import com.android.launcher3.compat.LauncherAppsCompat;
@@ -101,10 +97,8 @@
         final List<LauncherActivityInfoCompat> matches = launcherApps.getActivityList(packageName,
                 user);
 
-        if (matches.size() > 0) {
-            for (LauncherActivityInfoCompat info : matches) {
-                add(new AppInfo(context, info, user, mIconCache, null));
-            }
+        for (LauncherActivityInfoCompat info : matches) {
+            add(new AppInfo(context, info, user, mIconCache, null));
         }
     }
 
@@ -149,9 +143,7 @@
 
             // Find enabled activities and add them to the adapter
             // Also updates existing activities with new labels/icons
-            int count = matches.size();
-            for (int i = 0; i < count; i++) {
-                final LauncherActivityInfoCompat info = matches.get(i);
+            for (final LauncherActivityInfoCompat info : matches) {
                 AppInfo applicationInfo = findApplicationInfoLocked(
                         info.getComponentName().getPackageName(), user,
                         info.getComponentName().getClassName());
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index bb71d77..06f9f29 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -29,7 +29,6 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.Log;
@@ -122,7 +121,7 @@
                 android.R.mipmap.sym_def_app_icon);
     }
 
-    public Drawable getFullResIcon(Resources resources, int iconId) {
+    private Drawable getFullResIcon(Resources resources, int iconId) {
         Drawable d;
         try {
             d = resources.getDrawableForDensity(iconId, mIconDpi);
@@ -390,8 +389,7 @@
             entry.title = title;
         }
         if (icon != null) {
-            entry.icon = Utilities.createIconBitmap(
-                    new BitmapDrawable(mContext.getResources(), icon), mContext);
+            entry.icon = Utilities.createIconBitmap(icon, mContext);
         }
     }
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3b903c0..aa403db 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -4719,6 +4719,26 @@
     }
 
     /**
+     * Some shortcuts were updated in the background.
+     *
+     * Implementation of the method from LauncherModel.Callbacks.
+     */
+    public void bindShortcutsUpdated(final ArrayList<ShortcutInfo> shortcuts) {
+        Runnable r = new Runnable() {
+            public void run() {
+                bindShortcutsUpdated(shortcuts);
+            }
+        };
+        if (waitUntilResume(r)) {
+            return;
+        }
+
+        if (mWorkspace != null) {
+            mWorkspace.updateShortcuts(shortcuts);
+        }
+    }
+
+    /**
      * Update the state of a package, typically related to install state.
      *
      * Implementation of the method from LauncherModel.Callbacks.
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 60eb15f..eb4210f 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -198,6 +198,7 @@
                                   ArrayList<ItemInfo> addAnimated,
                                   ArrayList<AppInfo> addedApps);
         public void bindAppsUpdated(ArrayList<AppInfo> apps);
+        public void bindShortcutsUpdated(ArrayList<ShortcutInfo> shortcuts);
         public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);
         public void updatePackageBadge(String packageName);
         public void bindComponentsRemoved(ArrayList<String> packageNames,
@@ -3059,6 +3060,43 @@
                 });
             }
 
+            // Update shortcuts which use an iconResource
+            if (mOp == OP_ADD || mOp == OP_UPDATE) {
+                final ArrayList<ShortcutInfo> iconsChanged = new ArrayList<ShortcutInfo>();
+                HashSet<String> packageSet = new HashSet<String>(Arrays.asList(packages));
+                // We need to iteration over the items here, so that we can avoid new Bitmap
+                // creation on the UI thread.
+                synchronized (sBgLock) {
+                    for (ItemInfo info : sBgWorkspaceItems) {
+                        if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
+                            ShortcutInfo si = (ShortcutInfo) info;
+                            if ((si.iconResource != null)
+                                    && packageSet.contains(si.getTargetComponent().getPackageName())){
+                                Bitmap icon = Utilities.createIconBitmap(si.iconResource.packageName,
+                                        si.iconResource.resourceName, mIconCache, context);
+                                if (icon != null) {
+                                    si.setIcon(icon);
+                                    si.usingFallbackIcon = false;
+                                    iconsChanged.add(si);
+                                    updateItemInDatabase(context, si);
+                                }
+                            }
+                        }
+                    }
+                }
+
+                if (!iconsChanged.isEmpty()) {
+                    mHandler.post(new Runnable() {
+                        public void run() {
+                            Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+                            if (callbacks == cb && cb != null) {
+                                callbacks.bindShortcutsUpdated(iconsChanged);
+                            }
+                        }
+                    });
+                }
+            }
+
             final ArrayList<String> removedPackageNames =
                     new ArrayList<String>();
             if (mOp == OP_REMOVE) {
@@ -3385,19 +3423,9 @@
         case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
             String packageName = c.getString(iconPackageIndex);
             String resourceName = c.getString(iconResourceIndex);
-            PackageManager packageManager = context.getPackageManager();
             info.customIcon = false;
             // the resource
-            try {
-                Resources resources = packageManager.getResourcesForApplication(packageName);
-                if (resources != null) {
-                    final int id = resources.getIdentifier(resourceName, null, null);
-                    icon = Utilities.createIconBitmap(
-                            mIconCache.getFullResIcon(resources, id), context);
-                }
-            } catch (Exception e) {
-                // drop this.  we have other places to look for icons
-            }
+            icon = Utilities.createIconBitmap(packageName, resourceName, mIconCache, context);
             // the db
             if (icon == null) {
                 icon = getIconFromCursor(c, iconIndex, context);
@@ -3485,24 +3513,15 @@
         boolean customIcon = false;
         ShortcutIconResource iconResource = null;
 
-        if (bitmap != null && bitmap instanceof Bitmap) {
-            icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);
+        if (bitmap instanceof Bitmap) {
+            icon = Utilities.createIconBitmap((Bitmap) bitmap, context);
             customIcon = true;
         } else {
             Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
-            if (extra != null && extra instanceof ShortcutIconResource) {
-                try {
-                    iconResource = (ShortcutIconResource) extra;
-                    final PackageManager packageManager = context.getPackageManager();
-                    Resources resources = packageManager.getResourcesForApplication(
-                            iconResource.packageName);
-                    final int id = resources.getIdentifier(iconResource.resourceName, null, null);
-                    icon = Utilities.createIconBitmap(
-                            mIconCache.getFullResIcon(resources, id),
-                            context);
-                } catch (Exception e) {
-                    Log.w(TAG, "Could not load shortcut icon: " + extra);
-                }
+            if (extra instanceof ShortcutIconResource) {
+                iconResource = (ShortcutIconResource) extra;
+                icon = Utilities.createIconBitmap(iconResource.packageName,
+                        iconResource.resourceName, mIconCache, context);
             }
         }
 
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 4b27837..44ccb6c 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -1050,7 +1050,7 @@
                     long id = c.getLong(idIndex);
                     byte[] data = c.getBlob(iconIndex);
                     try {
-                        Bitmap bitmap = Utilities.resampleIconBitmap(
+                        Bitmap bitmap = Utilities.createIconBitmap(
                                 BitmapFactory.decodeByteArray(data, 0, data.length),
                                 mContext);
                         if (bitmap != null) {
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 80d4b22..6caa1cf 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -54,8 +54,6 @@
 
     private static int sIconWidth = -1;
     private static int sIconHeight = -1;
-    public static int sIconTextureWidth = -1;
-    public static int sIconTextureHeight = -1;
 
     private static final Rect sOldBounds = new Rect();
     private static final Canvas sCanvas = new Canvas();
@@ -89,7 +87,7 @@
      * Resizes an icon drawable to the correct icon size.
      */
     static void resizeIconDrawable(Drawable icon) {
-        icon.setBounds(0, 0, sIconTextureWidth, sIconTextureHeight);
+        icon.setBounds(0, 0, sIconWidth, sIconHeight);
     }
 
     private static boolean isPropertyEnabled(String propertyName) {
@@ -110,29 +108,39 @@
     }
 
     /**
-     * Returns a bitmap suitable for the all apps view. Used to convert pre-ICS
-     * icon bitmaps that are stored in the database (which were 74x74 pixels at hdpi size)
-     * to the proper size (48dp)
+     * Returns a bitmap suitable for the all apps view. If the package or the resource do not
+     * exist, it returns null.
+     */
+    static Bitmap createIconBitmap(String packageName, String resourceName, IconCache cache,
+            Context context) {
+        PackageManager packageManager = context.getPackageManager();
+        // the resource
+        try {
+            Resources resources = packageManager.getResourcesForApplication(packageName);
+            if (resources != null) {
+                final int id = resources.getIdentifier(resourceName, null, null);
+                return createIconBitmap(
+                        resources.getDrawableForDensity(id, cache.getFullResIconDpi()), context);
+            }
+        } catch (Exception e) {
+            // Icon not found.
+        }
+        return null;
+    }
+
+    /**
+     * Returns a bitmap which is of the appropriate size to be displayed as an icon
      */
     static Bitmap createIconBitmap(Bitmap icon, Context context) {
-        int textureWidth = sIconTextureWidth;
-        int textureHeight = sIconTextureHeight;
-        int sourceWidth = icon.getWidth();
-        int sourceHeight = icon.getHeight();
-        if (sourceWidth > textureWidth && sourceHeight > textureHeight) {
-            // Icon is bigger than it should be; clip it (solves the GB->ICS migration case)
-            return Bitmap.createBitmap(icon,
-                    (sourceWidth - textureWidth) / 2,
-                    (sourceHeight - textureHeight) / 2,
-                    textureWidth, textureHeight);
-        } else if (sourceWidth == textureWidth && sourceHeight == textureHeight) {
-            // Icon is the right size, no need to change it
-            return icon;
-        } else {
-            // Icon is too small, render to a larger bitmap
-            final Resources resources = context.getResources();
-            return createIconBitmap(new BitmapDrawable(resources, icon), context);
+        synchronized (sCanvas) { // we share the statics :-(
+            if (sIconWidth == -1) {
+                initStatics(context);
+            }
         }
+        if (sIconWidth == icon.getWidth() && sIconHeight == icon.getHeight()) {
+            return icon;
+        }
+        return createIconBitmap(new BitmapDrawable(context.getResources(), icon), context);
     }
 
     /**
@@ -172,8 +180,8 @@
             }
 
             // no intrinsic size --> use default size
-            int textureWidth = sIconTextureWidth;
-            int textureHeight = sIconTextureHeight;
+            int textureWidth = sIconWidth;
+            int textureHeight = sIconHeight;
 
             final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
                     Bitmap.Config.ARGB_8888);
@@ -205,30 +213,6 @@
     }
 
     /**
-     * Returns a Bitmap representing the thumbnail of the specified Bitmap.
-     *
-     * @param bitmap The bitmap to get a thumbnail of.
-     * @param context The application's context.
-     *
-     * @return A thumbnail for the specified bitmap or the bitmap itself if the
-     *         thumbnail could not be created.
-     */
-    static Bitmap resampleIconBitmap(Bitmap bitmap, Context context) {
-        synchronized (sCanvas) { // we share the statics :-(
-            if (sIconWidth == -1) {
-                initStatics(context);
-            }
-
-            if (bitmap.getWidth() == sIconWidth && bitmap.getHeight() == sIconHeight) {
-                return bitmap;
-            } else {
-                final Resources resources = context.getResources();
-                return createIconBitmap(new BitmapDrawable(resources, bitmap), context);
-            }
-        }
-    }
-
-    /**
      * Given a coordinate relative to the descendant, find the coordinate in a parent view's
      * coordinates.
      *
@@ -330,12 +314,10 @@
     private static void initStatics(Context context) {
         final Resources resources = context.getResources();
         sIconWidth = sIconHeight = (int) resources.getDimension(R.dimen.app_icon_size);
-        sIconTextureWidth = sIconTextureHeight = sIconWidth;
     }
 
     public static void setIconSize(int widthPx) {
         sIconWidth = sIconHeight = widthPx;
-        sIconTextureWidth = sIconTextureHeight = widthPx;
     }
 
     public static void scaleRect(Rect r, float scale) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 774996e..5951be6 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -4800,6 +4800,28 @@
         }
     }
 
+
+    void updateShortcuts(ArrayList<ShortcutInfo> shortcuts) {
+        final HashSet<ShortcutInfo> updates = new HashSet<ShortcutInfo>(shortcuts);
+        mapOverItems(MAP_RECURSE, new ItemOperator() {
+            @Override
+            public boolean evaluate(ItemInfo info, View v, View parent) {
+                if (info instanceof ShortcutInfo && v instanceof BubbleTextView &&
+                        updates.contains(info)) {
+                    ShortcutInfo shortcutInfo = (ShortcutInfo) info;
+                    BubbleTextView shortcut = (BubbleTextView) v;
+                    shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache, true, false);
+
+                    if (parent != null) {
+                        parent.invalidate();
+                    }
+                }
+                // process all the shortcuts
+                return false;
+            }
+        });
+    }
+
     void updateShortcutsAndWidgets(ArrayList<AppInfo> apps) {
         // Break the appinfo list per user
         final HashMap<UserHandleCompat, ArrayList<AppInfo>> appsPerUser =