Simplifying IconCache access code

Providing a way to access icon cache without LauncherAcitivtiyInfo.
This allows fetching LauncherActivityInfo only when required, thus
avoiding system RPC when the icon is already in cache.

Change-Id: I92918c7a0d0d0796e5f7b70d4ecb6787c52c6600
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index f7c5184..9c9dcc5 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -19,7 +19,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.Bitmap;
 import android.os.UserHandle;
 import android.util.Log;
 
@@ -33,23 +32,13 @@
 /**
  * Represents an app in AllAppsView.
  */
-public class AppInfo extends ItemInfo {
+public class AppInfo extends ItemInfoWithIcon {
 
     /**
      * The intent used to start the application.
      */
     public Intent intent;
 
-    /**
-     * A bitmap version of the application icon.
-     */
-    public Bitmap iconBitmap;
-
-    /**
-     * Indicates whether we're using a low res icon
-     */
-    boolean usingLowResIcon;
-
     public ComponentName componentName;
 
     /**
@@ -66,10 +55,6 @@
         return intent;
     }
 
-    protected Intent getRestoredIntent() {
-        return null;
-    }
-
     /**
      * Must not hold the Context.
      */
@@ -96,8 +81,8 @@
             isDisabled |= ShortcutInfo.FLAG_DISABLED_QUIET_USER;
         }
 
-        iconCache.getTitleAndIcon(this, info, useLowResIcon);
         intent = makeLaunchIntent(context, info, user);
+        iconCache.getTitleAndIcon(this, info, useLowResIcon);
     }
 
     public AppInfo(AppInfo info) {
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 3557447..b22cb7c 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -41,6 +41,7 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.support.annotation.NonNull;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -51,6 +52,7 @@
 import com.android.launcher3.graphics.LauncherIcons;
 import com.android.launcher3.model.PackageItemInfo;
 import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.Provider;
 import com.android.launcher3.util.SQLiteCacheHelper;
 import com.android.launcher3.util.Thunk;
 
@@ -409,16 +411,10 @@
 
             @Override
             public void run() {
-                if (info instanceof AppInfo) {
-                    getTitleAndIcon((AppInfo) info, null, false);
-                } else if (info instanceof ShortcutInfo) {
-                    ShortcutInfo st = (ShortcutInfo) info;
-                    getTitleAndIcon(st,
-                            st.promisedIntent != null ? st.promisedIntent : st.intent,
-                            st.user, false);
+                if (info instanceof AppInfo || info instanceof ShortcutInfo) {
+                    getTitleAndIcon((ItemInfoWithIcon) info, false);
                 } else if (info instanceof PackageItemInfo) {
-                    PackageItemInfo pti = (PackageItemInfo) info;
-                    getTitleAndIconForApp(pti, false);
+                    getTitleAndIconForApp((PackageItemInfo) info, false);
                 }
                 mMainThreadExecutor.execute(new Runnable() {
 
@@ -433,38 +429,6 @@
         return new IconLoadRequest(request, mWorkerHandler);
     }
 
-    private Bitmap getNonNullIcon(CacheEntry entry, UserHandle user) {
-        return entry.icon == null ? getDefaultIcon(user) : entry.icon;
-    }
-
-    /**
-     * Fill in "application" with the icon and label for "info."
-     */
-    public synchronized void getTitleAndIcon(AppInfo application,
-            LauncherActivityInfoCompat info, boolean useLowResIcon) {
-        UserHandle user = info == null ? application.user : info.getUser();
-        CacheEntry entry = cacheLocked(application.componentName, info, user,
-                false, useLowResIcon);
-        application.title = Utilities.trim(entry.title);
-        application.contentDescription = entry.contentDescription;
-        application.iconBitmap = getNonNullIcon(entry, user);
-        application.usingLowResIcon = entry.isLowResIcon;
-    }
-
-    /**
-     * Updates {@param application} only if a valid entry is found.
-     */
-    public synchronized void updateTitleAndIcon(AppInfo application) {
-        CacheEntry entry = cacheLocked(application.componentName, null, application.user,
-                false, application.usingLowResIcon);
-        if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) {
-            application.title = Utilities.trim(entry.title);
-            application.contentDescription = entry.contentDescription;
-            application.iconBitmap = entry.icon;
-            application.usingLowResIcon = entry.isLowResIcon;
-        }
-    }
-
     /**
      * Returns a high res icon for the given intent and user
      */
@@ -475,43 +439,59 @@
         if (component == null) {
             return getDefaultIcon(user);
         }
-
-        LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
-        CacheEntry entry = cacheLocked(component, launcherActInfo, user, true, false /* useLowRes */);
-        return entry.icon;
+        return cacheLocked(component, new ActivityInfoProvider(intent, user),
+                user, true, false /* useLowRes */).icon;
     }
 
     /**
-     * Fill in {@param shortcutInfo} with the icon and label for {@param intent}. If the
+     * Updates {@param application} only if a valid entry is found.
+     */
+    public synchronized void updateTitleAndIcon(AppInfo application) {
+        CacheEntry entry = cacheLocked(application.componentName,
+                Provider.<LauncherActivityInfoCompat>of(null),
+                application.user, false, application.usingLowResIcon);
+        if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) {
+            applyCacheEntry(entry, application);
+        }
+    }
+
+    /**
+     * Fill in {@param info} with the icon and label for {@param activityInfo}
+     */
+    public synchronized void getTitleAndIcon(ItemInfoWithIcon info,
+            LauncherActivityInfoCompat activityInfo, boolean useLowResIcon) {
+        // If we already have activity info, no need to use package icon
+        getTitleAndIcon(info, Provider.of(activityInfo), false, useLowResIcon);
+    }
+
+    /**
+     * Fill in {@param info} with the icon and label. If the
      * corresponding activity is not found, it reverts to the package icon.
      */
-    public synchronized void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent,
-            UserHandle user, boolean useLowResIcon) {
-        ComponentName component = intent.getComponent();
+    public synchronized void getTitleAndIcon(ItemInfoWithIcon info, boolean useLowResIcon) {
         // null info means not installed, but if we have a component from the intent then
         // we should still look in the cache for restored app icons.
-        if (component == null) {
-            shortcutInfo.iconBitmap = getDefaultIcon(user);
-            shortcutInfo.title = "";
-            shortcutInfo.contentDescription = "";
-            shortcutInfo.usingLowResIcon = false;
+        if (info.getTargetComponent() == null) {
+            info.iconBitmap = getDefaultIcon(info.user);
+            info.title = "";
+            info.contentDescription = "";
+            info.usingLowResIcon = false;
         } else {
-            LauncherActivityInfoCompat info = mLauncherApps.resolveActivity(intent, user);
-            getTitleAndIcon(shortcutInfo, component, info, user, true, useLowResIcon);
+            getTitleAndIcon(info, new ActivityInfoProvider(info.getIntent(), info.user),
+                    true, useLowResIcon);
         }
     }
 
     /**
      * Fill in {@param shortcutInfo} with the icon and label for {@param info}
      */
-    public synchronized void getTitleAndIcon(
-            ShortcutInfo shortcutInfo, ComponentName component, LauncherActivityInfoCompat info,
-            UserHandle user, boolean usePkgIcon, boolean useLowResIcon) {
-        CacheEntry entry = cacheLocked(component, info, user, usePkgIcon, useLowResIcon);
-        shortcutInfo.iconBitmap = getNonNullIcon(entry, user);
-        shortcutInfo.title = Utilities.trim(entry.title);
-        shortcutInfo.contentDescription = entry.contentDescription;
-        shortcutInfo.usingLowResIcon = entry.isLowResIcon;
+    private synchronized void getTitleAndIcon(
+            @NonNull ItemInfoWithIcon infoInOut,
+            @NonNull Provider<LauncherActivityInfoCompat> activityInfoProvider,
+            boolean usePkgIcon, boolean useLowResIcon) {
+        CacheEntry entry = cacheLocked(infoInOut.getTargetComponent(), activityInfoProvider,
+                infoInOut.user, usePkgIcon, useLowResIcon);
+        applyCacheEntry(entry, infoInOut);
     }
 
     /**
@@ -521,10 +501,14 @@
             PackageItemInfo infoInOut, boolean useLowResIcon) {
         CacheEntry entry = getEntryForPackageLocked(
                 infoInOut.packageName, infoInOut.user, useLowResIcon);
-        infoInOut.title = Utilities.trim(entry.title);
-        infoInOut.contentDescription = entry.contentDescription;
-        infoInOut.iconBitmap = getNonNullIcon(entry, infoInOut.user);
-        infoInOut.usingLowResIcon = entry.isLowResIcon;
+        applyCacheEntry(entry, infoInOut);
+    }
+
+    private void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
+        info.title = Utilities.trim(entry.title);
+        info.contentDescription = entry.contentDescription;
+        info.iconBitmap = entry.icon == null ? getDefaultIcon(info.user) : entry.icon;
+        info.usingLowResIcon = entry.isLowResIcon;
     }
 
     public synchronized Bitmap getDefaultIcon(UserHandle user) {
@@ -542,7 +526,9 @@
      * Retrieves the entry from the cache. If the entry is not present, it creates a new entry.
      * This method is not thread safe, it must be called from a synchronized method.
      */
-    protected CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
+    protected CacheEntry cacheLocked(
+            @NonNull ComponentName componentName,
+            @NonNull Provider<LauncherActivityInfoCompat> infoProfider,
             UserHandle user, boolean usePackageIcon, boolean useLowResIcon) {
         ComponentKey cacheKey = new ComponentKey(componentName, user);
         CacheEntry entry = mCache.get(cacheKey);
@@ -551,7 +537,13 @@
             mCache.put(cacheKey, entry);
 
             // Check the DB first.
+            LauncherActivityInfoCompat info = null;
+            boolean providerFetchedOnce = false;
+
             if (!getEntryFromDB(cacheKey, entry, useLowResIcon) || DEBUG_IGNORE_CACHE) {
+                info = infoProfider.get();
+                providerFetchedOnce = true;
+
                 if (info != null) {
                     entry.icon = LauncherIcons.createBadgedIconBitmap(
                             mIconProvider.getIcon(info, mIconDpi), info.getUser(),
@@ -576,9 +568,15 @@
                 }
             }
 
-            if (TextUtils.isEmpty(entry.title) && info != null) {
-                entry.title = info.getLabel();
-                entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+            if (TextUtils.isEmpty(entry.title)) {
+                if (info == null && !providerFetchedOnce) {
+                    info = infoProfider.get();
+                    providerFetchedOnce = true;
+                }
+                if (info != null) {
+                    entry.title = info.getLabel();
+                    entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+                }
             }
         }
         return entry;
@@ -668,37 +666,6 @@
         return entry;
     }
 
-    /**
-     * Pre-load an icon into the persistent cache.
-     *
-     * <P>Queries for a component that does not exist in the package manager
-     * will be answered by the persistent cache.
-     *
-     * @param componentName the icon should be returned for this component
-     * @param icon the icon to be persisted
-     * @param dpi the native density of the icon
-     */
-    public void preloadIcon(ComponentName componentName, Bitmap icon, int dpi, String label,
-            long userSerial, InvariantDeviceProfile idp) {
-        // TODO rescale to the correct native DPI
-        try {
-            PackageManager packageManager = mContext.getPackageManager();
-            packageManager.getActivityIcon(componentName);
-            // component is present on the system already, do nothing
-            return;
-        } catch (PackageManager.NameNotFoundException e) {
-            // pass
-        }
-
-        icon = Bitmap.createScaledBitmap(icon, idp.iconBitmapSize, idp.iconBitmapSize, true);
-        Bitmap lowResIcon = generateLowResIcon(icon, Color.TRANSPARENT);
-        ContentValues values = newContentValues(icon, lowResIcon, label,
-                componentName.getPackageName());
-        values.put(IconDB.COLUMN_COMPONENT, componentName.flattenToString());
-        values.put(IconDB.COLUMN_USER, userSerial);
-        mIconDb.insertOrReplace(values);
-    }
-
     private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
         Cursor c = null;
         try {
@@ -885,4 +852,20 @@
             return null;
         }
     }
+
+    private class ActivityInfoProvider extends Provider<LauncherActivityInfoCompat> {
+
+        private final Intent mIntent;
+        private final UserHandle mUser;
+
+        public ActivityInfoProvider(Intent intent, UserHandle user) {
+            mIntent = intent;
+            mUser = user;
+        }
+
+        @Override
+        public LauncherActivityInfoCompat get() {
+            return mLauncherApps.resolveActivity(mIntent, mUser);
+        }
+    }
 }
diff --git a/src/com/android/launcher3/ItemInfoWithIcon.java b/src/com/android/launcher3/ItemInfoWithIcon.java
new file mode 100644
index 0000000..a3d8c6a
--- /dev/null
+++ b/src/com/android/launcher3/ItemInfoWithIcon.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.graphics.Bitmap;
+
+/**
+ * Represents an ItemInfo which also holds an icon.
+ */
+public abstract class ItemInfoWithIcon extends ItemInfo {
+
+    /**
+     * A bitmap version of the application icon.
+     */
+    public Bitmap iconBitmap;
+
+    /**
+     * Indicates whether we're using a low res icon
+     */
+    public boolean usingLowResIcon;
+
+    protected ItemInfoWithIcon() { }
+
+    protected ItemInfoWithIcon(ItemInfo info) {
+        super(info);
+    }
+}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7dd8450..8e28912 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -3799,7 +3799,7 @@
 
             for (ShortcutInfo si : removed) {
                 if (si.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
-                    removedDeepShortcuts.add(ShortcutKey.fromShortcutInfo(si));
+                    removedDeepShortcuts.add(ShortcutKey.fromItemInfo(si));
                 } else {
                     removedComponents.add(si.getTargetComponent());
                 }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 0dc91e3..58a7495 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1794,8 +1794,7 @@
                     for (ShortcutInfo info : folder.contents) {
                         if (info.usingLowResIcon &&
                                 info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
-                            mIconCache.getTitleAndIcon(
-                                    info, info.getPromisedIntent(), info.user, false);
+                            mIconCache.getTitleAndIcon(info, false);
                         }
                         pos ++;
                         if (pos >= FolderIcon.NUM_ITEMS_IN_PREVIEW) {
@@ -2520,10 +2519,12 @@
             int promiseType, int itemType, CursorIconInfo iconInfo) {
         final ShortcutInfo info = new ShortcutInfo();
         info.user = Process.myUserHandle();
+        info.promisedIntent = intent;
+
         info.iconBitmap = iconInfo.loadIcon(c, info);
         // the fallback icon
         if (info.iconBitmap == null) {
-            mIconCache.getTitleAndIcon(info, intent, info.user, false /* useLowResIcon */);
+            mIconCache.getTitleAndIcon(info, false /* useLowResIcon */);
         }
 
         if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
@@ -2541,7 +2542,6 @@
 
         info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
         info.itemType = itemType;
-        info.promisedIntent = intent;
         info.status = promiseType;
         return info;
     }
@@ -2592,7 +2592,11 @@
         }
 
         final ShortcutInfo info = new ShortcutInfo();
-        mIconCache.getTitleAndIcon(info, componentName, lai, user, false, useLowResIcon);
+        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+        info.user = user;
+        info.intent = newIntent;
+
+        mIconCache.getTitleAndIcon(info, lai, useLowResIcon);
         if (mIconCache.isDefaultIcon(info.iconBitmap, user) && c != null) {
             Bitmap icon = iconInfo.loadIcon(c);
             info.iconBitmap = icon != null ? icon : mIconCache.getDefaultIcon(user);
@@ -2612,8 +2616,6 @@
             info.title = componentName.getClassName();
         }
 
-        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-        info.user = user;
         info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
         return info;
     }
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index b9010c7..05fb1ed 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -17,7 +17,6 @@
 package com.android.launcher3;
 
 import android.annotation.TargetApi;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -37,7 +36,7 @@
 /**
  * Represents a launchable icon on the workspaces and in folders.
  */
-public class ShortcutInfo extends ItemInfo {
+public class ShortcutInfo extends ItemInfoWithIcon {
 
     public static final int DEFAULT = 0;
 
@@ -77,22 +76,12 @@
     public Intent intent;
 
     /**
-     * Indicates whether we're using a low res icon
-     */
-    public boolean usingLowResIcon;
-
-    /**
      * If isShortcut=true and customIcon=false, this contains a reference to the
      * shortcut icon as an application's resource.
      */
     public Intent.ShortcutIconResource iconResource;
 
     /**
-     * The application icon.
-     */
-    public Bitmap iconBitmap;
-
-    /**
      * Indicates that the icon is disabled due to safe mode restrictions.
      */
     public static final int FLAG_DISABLED_SAFEMODE = 1 << 0;
@@ -152,16 +141,6 @@
         itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
     }
 
-    @Override
-    public Intent getIntent() {
-        return intent;
-    }
-
-    /** Returns {@link #promisedIntent}, or {@link #intent} if promisedIntent is null. */
-    public Intent getPromisedIntent() {
-        return promisedIntent != null ? promisedIntent : intent;
-    }
-
     public ShortcutInfo(ShortcutInfo info) {
         super(info);
         title = info.title;
@@ -197,7 +176,7 @@
     void onAddToDatabase(ContentWriter writer) {
         super.onAddToDatabase(writer);
         writer.put(LauncherSettings.BaseLauncherColumns.TITLE, title)
-                .put(LauncherSettings.BaseLauncherColumns.INTENT, getPromisedIntent())
+                .put(LauncherSettings.BaseLauncherColumns.INTENT, getIntent())
                 .put(LauncherSettings.Favorites.RESTORED, status);
 
         if (!usingLowResIcon) {
@@ -210,8 +189,12 @@
         }
     }
 
-    public ComponentName getTargetComponent() {
-        return getPromisedIntent().getComponent();
+    /**
+     *  Returns {@link #promisedIntent}, or {@link #intent} if promisedIntent is null.
+     */
+    @Override
+    public Intent getIntent() {
+        return promisedIntent != null ? promisedIntent : intent;
     }
 
     public boolean hasStatusFlag(int flag) {
@@ -270,19 +253,14 @@
         AppInfo appInfo = new AppInfo();
         appInfo.user = user;
         appInfo.componentName = shortcutInfo.getActivity();
-        try {
-            cache.getTitleAndIcon(appInfo, shortcutInfo.getActivityInfo(context), false);
-        } catch (NullPointerException e) {
-            // This may happen when we fail to load the activity info. Worst case ignore badging.
-            return LauncherIcons.badgeIconForUser(unbadgedBitmap, user, context);
-        }
+        cache.getTitleAndIcon(appInfo, false);
         return LauncherIcons.badgeWithBitmap(unbadgedBitmap, appInfo.iconBitmap, context);
     }
 
     /** Returns the ShortcutInfo id associated with the deep shortcut. */
     public String getDeepShortcutId() {
         return itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT ?
-                getPromisedIntent().getStringExtra(ShortcutInfoCompat.EXTRA_SHORTCUT_ID) : null;
+                getIntent().getStringExtra(ShortcutInfoCompat.EXTRA_SHORTCUT_ID) : null;
     }
 
     @Override
diff --git a/src/com/android/launcher3/compat/DeferredLauncherActivityInfo.java b/src/com/android/launcher3/compat/DeferredLauncherActivityInfo.java
deleted file mode 100644
index 4dd05bb..0000000
--- a/src/com/android/launcher3/compat/DeferredLauncherActivityInfo.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.compat;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-
-/**
- * {@link LauncherActivityInfoCompat} which loads its data only when needed.
- */
-public class DeferredLauncherActivityInfo extends LauncherActivityInfoCompat {
-
-    private final ComponentName mComponent;
-    private final UserHandle mUser;
-    private final Context mContext;
-
-    private LauncherActivityInfoCompat mActualInfo;
-
-    public DeferredLauncherActivityInfo(
-            ComponentName component, UserHandle user, Context context) {
-        mComponent = component;
-        mUser = user;
-        mContext = context;
-    }
-
-    @Override
-    public ComponentName getComponentName() {
-        return mComponent;
-    }
-
-    @Override
-    public UserHandle getUser() {
-        return mUser;
-    }
-
-    private synchronized LauncherActivityInfoCompat getActualInfo() {
-        if (mActualInfo == null) {
-            Intent intent = new Intent(Intent.ACTION_MAIN)
-                    .addCategory(Intent.CATEGORY_LAUNCHER)
-                    .setComponent(mComponent);
-            mActualInfo = LauncherAppsCompat.getInstance(mContext).resolveActivity(intent, mUser);
-        }
-        return mActualInfo;
-    }
-
-    @Override
-    public CharSequence getLabel() {
-        return getActualInfo().getLabel();
-    }
-
-    @Override
-    public Drawable getIcon(int density) {
-        return getActualInfo().getIcon(density);
-    }
-
-    @Override
-    public ApplicationInfo getApplicationInfo() {
-        return getActualInfo().getApplicationInfo();
-    }
-
-    @Override
-    public long getFirstInstallTime() {
-        return getActualInfo().getFirstInstallTime();
-    }
-}
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 05f43af..6dc5a36 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -123,7 +123,7 @@
                     break;
                 case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: {
                     // Decrement pinned shortcut count
-                    ShortcutKey pinnedShortcut = ShortcutKey.fromShortcutInfo((ShortcutInfo) item);
+                    ShortcutKey pinnedShortcut = ShortcutKey.fromItemInfo(item);
                     MutableInt count = pinnedShortcutCounts.get(pinnedShortcut);
                     Context context = LauncherAppState.getInstance().getContext();
                     if ((count == null || --count.value == 0)
@@ -155,7 +155,7 @@
                 break;
             case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: {
                 // Increment the count for the given shortcut
-                ShortcutKey pinnedShortcut = ShortcutKey.fromShortcutInfo((ShortcutInfo) item);
+                ShortcutKey pinnedShortcut = ShortcutKey.fromItemInfo(item);
                 MutableInt count = pinnedShortcutCounts.get(pinnedShortcut);
                 if (count == null) {
                     count = new MutableInt(1);
diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
index 9d693a4..46130fc 100644
--- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java
+++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
@@ -65,7 +65,7 @@
                     if (si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
                             && isValidShortcut(si) && cn != null
                             && mPackages.contains(cn.getPackageName())) {
-                        iconCache.getTitleAndIcon(si, si.getPromisedIntent(), si.user, si.usingLowResIcon);
+                        iconCache.getTitleAndIcon(si, si.usingLowResIcon);
                         updatedShortcuts.add(si);
                     }
                 }
diff --git a/src/com/android/launcher3/model/PackageItemInfo.java b/src/com/android/launcher3/model/PackageItemInfo.java
index 00470e1..e05bf1e 100644
--- a/src/com/android/launcher3/model/PackageItemInfo.java
+++ b/src/com/android/launcher3/model/PackageItemInfo.java
@@ -16,27 +16,15 @@
 
 package com.android.launcher3.model;
 
-import android.graphics.Bitmap;
-
-import com.android.launcher3.ItemInfo;
+import com.android.launcher3.ItemInfoWithIcon;
 
 /**
  * Represents a {@link Package} in the widget tray section.
  */
-public class PackageItemInfo extends ItemInfo {
+public class PackageItemInfo extends ItemInfoWithIcon {
 
     /**
-     * A bitmap version of the application icon.
-     */
-    public Bitmap iconBitmap;
-
-    /**
-     * Indicates whether we're using a low res icon.
-     */
-    public boolean usingLowResIcon;
-
-    /**
-     * Package name of the {@link ItemInfo}.
+     * Package name of the {@link PackageItemInfo}.
      */
     public String packageName;
 
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index bafa95b..f5de650 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -251,15 +251,13 @@
                                 si.status = ShortcutInfo.DEFAULT;
                                 infoUpdated = true;
                                 if (si.itemType == Favorites.ITEM_TYPE_APPLICATION) {
-                                    iconCache.getTitleAndIcon(si, si.getPromisedIntent(),
-                                            si.user, si.usingLowResIcon);
+                                    iconCache.getTitleAndIcon(si, si.usingLowResIcon);
                                 }
                             }
 
                             if (appInfo != null && Intent.ACTION_MAIN.equals(si.intent.getAction())
                                     && si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
-                                iconCache.getTitleAndIcon(
-                                        si, si.getPromisedIntent(), si.user, si.usingLowResIcon);
+                                iconCache.getTitleAndIcon(si, si.usingLowResIcon);
                                 infoUpdated = true;
                             }
 
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 3750a7e..67bec64 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -61,7 +61,7 @@
         for (ItemInfo itemInfo : dataModel.itemsIdMap) {
             if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
                 ShortcutInfo si = (ShortcutInfo) itemInfo;
-                if (si.getPromisedIntent().getPackage().equals(mPackageName)
+                if (si.getIntent().getPackage().equals(mPackageName)
                         && si.user.equals(mUser)) {
                     idsToWorkspaceShortcutInfos.addToList(si.getDeepShortcutId(), si);
                 }
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 15496b8..a214a29 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -76,8 +76,7 @@
                     && mUser.equals(itemInfo.user)) {
                 ShortcutInfo si = (ShortcutInfo) itemInfo;
                 if (isUserUnlocked) {
-                    ShortcutInfoCompat shortcut =
-                            pinnedShortcuts.get(ShortcutKey.fromShortcutInfo(si));
+                    ShortcutInfoCompat shortcut = pinnedShortcuts.get(ShortcutKey.fromItemInfo(si));
                     // We couldn't verify the shortcut during loader. If its no longer available
                     // (probably due to clear data), delete the workspace item as well
                     if (shortcut == null) {
diff --git a/src/com/android/launcher3/shortcuts/ShortcutInfoCompat.java b/src/com/android/launcher3/shortcuts/ShortcutInfoCompat.java
index acc632c..dac2160 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutInfoCompat.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutInfoCompat.java
@@ -25,8 +25,6 @@
 import android.os.UserHandle;
 
 import com.android.launcher3.ItemInfo;
-import com.android.launcher3.compat.DeferredLauncherActivityInfo;
-import com.android.launcher3.compat.LauncherActivityInfoCompat;
 import com.android.launcher3.compat.UserManagerCompat;
 
 /**
@@ -122,8 +120,4 @@
     public String toString() {
         return mShortcutInfo.toString();
     }
-
-    public LauncherActivityInfoCompat getActivityInfo(Context context) {
-        return new DeferredLauncherActivityInfo(getActivity(), getUserHandle(), context);
-    }
 }
diff --git a/src/com/android/launcher3/shortcuts/ShortcutKey.java b/src/com/android/launcher3/shortcuts/ShortcutKey.java
index 8f72666..e86bfb2 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutKey.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutKey.java
@@ -4,7 +4,7 @@
 import android.content.Intent;
 import android.os.UserHandle;
 
-import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.ItemInfo;
 import com.android.launcher3.util.ComponentKey;
 
 /**
@@ -32,7 +32,7 @@
         return new ShortcutKey(intent.getPackage(), user, shortcutId);
     }
 
-    public static ShortcutKey fromShortcutInfo(ShortcutInfo info) {
-        return fromIntent(info.getPromisedIntent(), info.user);
+    public static ShortcutKey fromItemInfo(ItemInfo info) {
+        return fromIntent(info.getIntent(), info.user);
     }
 }
diff --git a/src/com/android/launcher3/util/ItemInfoMatcher.java b/src/com/android/launcher3/util/ItemInfoMatcher.java
index b6e0e6e..42de284 100644
--- a/src/com/android/launcher3/util/ItemInfoMatcher.java
+++ b/src/com/android/launcher3/util/ItemInfoMatcher.java
@@ -100,7 +100,7 @@
             @Override
             public boolean matches(ItemInfo info, ComponentName cn) {
                 return info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
-                        keys.contains(ShortcutKey.fromShortcutInfo((ShortcutInfo) info));
+                        keys.contains(ShortcutKey.fromItemInfo(info));
             }
         };
     }