Merge "Show promise app icon progress in All Apps and setup market intent on clicking promise app icon in All Apps." into ub-launcher3-master
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index f9a6742..add0185 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -39,7 +39,6 @@
 import com.android.launcher3.IconCache.ItemInfoUpdateReceiver;
 import com.android.launcher3.badge.BadgeInfo;
 import com.android.launcher3.badge.BadgeRenderer;
-import com.android.launcher3.folder.FolderIcon;
 import com.android.launcher3.folder.FolderIconPreviewVerifier;
 import com.android.launcher3.graphics.DrawableFactory;
 import com.android.launcher3.graphics.HolographicOutlineHelper;
@@ -181,6 +180,10 @@
         // Verify high res immediately
         verifyHighRes();
 
+        if (info instanceof PromiseAppInfo) {
+            PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
+            applyProgressLevel(promiseAppInfo.level);
+        }
         applyBadgeState(info, false /* animate */);
     }
 
@@ -476,27 +479,36 @@
                     ((info.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE) ?
                             info.getInstallProgress() : 0)) : 100;
 
-            setContentDescription(progressLevel > 0 ?
-                    getContext().getString(R.string.app_downloading_title, info.title,
-                            NumberFormat.getPercentInstance().format(progressLevel * 0.01)) :
-                    getContext().getString(R.string.app_waiting_download_title, info.title));
+            PreloadIconDrawable preloadDrawable = applyProgressLevel(progressLevel);
+            if (preloadDrawable != null && promiseStateChanged) {
+                preloadDrawable.maybePerformFinishedAnimation();
+            }
+        }
+    }
+
+    public PreloadIconDrawable applyProgressLevel(int progressLevel) {
+        if (getTag() instanceof ItemInfoWithIcon) {
+            ItemInfoWithIcon info = (ItemInfoWithIcon) getTag();
+            setContentDescription(progressLevel > 0
+                    ? getContext().getString(R.string.app_downloading_title, info.title,
+                    NumberFormat.getPercentInstance().format(progressLevel * 0.01))
+                    : getContext().getString(R.string.app_waiting_download_title, info.title));
 
             if (mIcon != null) {
                 final PreloadIconDrawable preloadDrawable;
                 if (mIcon instanceof PreloadIconDrawable) {
                     preloadDrawable = (PreloadIconDrawable) mIcon;
+                    preloadDrawable.setLevel(progressLevel);
                 } else {
                     preloadDrawable = DrawableFactory.get(getContext())
                             .newPendingIcon(info.iconBitmap, getContext());
+                    preloadDrawable.setLevel(progressLevel);
                     setIcon(preloadDrawable);
                 }
-
-                preloadDrawable.setLevel(progressLevel);
-                if (promiseStateChanged) {
-                    preloadDrawable.maybePerformFinishedAnimation();
-                }
+                return preloadDrawable;
             }
         }
+        return null;
     }
 
     public void applyBadgeState(ItemInfo itemInfo, boolean animate) {
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index 34adf47..2f61a01 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -60,6 +60,12 @@
      */
     public static boolean startDetailsActivityForInfo(
             ItemInfo info, Launcher launcher, DropTargetResultCallback callback) {
+        if (info instanceof PromiseAppInfo) {
+            PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
+            launcher.startActivity(promiseAppInfo.getMarketIntent());
+            return true;
+        }
+
         boolean result = false;
         ComponentName componentName = null;
         if (info instanceof AppInfo) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7d13c88..43ff28a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2459,7 +2459,13 @@
 
     private void startAppShortcutOrInfoActivity(View v) {
         ItemInfo item = (ItemInfo) v.getTag();
-        Intent intent = item.getIntent();
+        Intent intent;
+        if (item instanceof PromiseAppInfo) {
+            PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
+            intent = promiseAppInfo.getMarketIntent();
+        } else {
+            intent = item.getIntent();
+        }
         if (intent == null) {
             throw new IllegalArgumentException("Input must have a valid intent");
         }
@@ -3768,6 +3774,22 @@
     }
 
     @Override
+    public void bindPromiseAppProgressUpdated(final PromiseAppInfo app) {
+        Runnable r = new Runnable() {
+            public void run() {
+                bindPromiseAppProgressUpdated(app);
+            }
+        };
+        if (waitUntilResume(r)) {
+            return;
+        }
+
+        if (mAppsView != null) {
+            mAppsView.updatePromiseAppProgress(app);
+        }
+    }
+
+    @Override
     public void bindWidgetsRestored(final ArrayList<LauncherAppWidgetInfo> widgets) {
         Runnable r = new Runnable() {
             public void run() {
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 707ec86..39b9dd3 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -195,6 +195,7 @@
                                   ArrayList<ItemInfo> addAnimated,
                                   ArrayList<AppInfo> addedApps);
         public void bindAppsUpdated(ArrayList<AppInfo> apps);
+        public void bindPromiseAppProgressUpdated(PromiseAppInfo app);
         public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated,
                 ArrayList<ShortcutInfo> removed, UserHandle user);
         public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
diff --git a/src/com/android/launcher3/PromiseAppInfo.java b/src/com/android/launcher3/PromiseAppInfo.java
index 04ba1d3..1749dde 100644
--- a/src/com/android/launcher3/PromiseAppInfo.java
+++ b/src/com/android/launcher3/PromiseAppInfo.java
@@ -20,6 +20,7 @@
 import android.support.annotation.NonNull;
 
 import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.util.PackageManagerHelper;
 
 public class PromiseAppInfo extends AppInfo {
 
@@ -44,4 +45,8 @@
         shortcut.status |= ShortcutInfo.FLAG_RESTORE_STARTED;
         return shortcut;
     }
+
+    public Intent getMarketIntent() {
+        return PackageManagerHelper.getMarketIntent(componentName.getPackageName());
+    }
 }
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index cc5fa8c..7219141 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -37,6 +37,7 @@
 
 import com.android.launcher3.AppInfo;
 import com.android.launcher3.BaseContainerView;
+import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeleteDropTarget;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DragSource;
@@ -45,6 +46,7 @@
 import com.android.launcher3.Insettable;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
+import com.android.launcher3.PromiseAppInfo;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
@@ -158,6 +160,17 @@
         mSearchBarController.refreshSearchResult();
     }
 
+    public void updatePromiseAppProgress(PromiseAppInfo app) {
+        int childCount = mAppsRecyclerView.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = mAppsRecyclerView.getChildAt(i);
+            if (child instanceof BubbleTextView && child.getTag() == app) {
+                BubbleTextView bubbleTextView = (BubbleTextView) child;
+                bubbleTextView.applyProgressLevel(app.level);
+            }
+        }
+    }
+
     /**
      * Removes some apps from the list.
      */
diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
index 9c5f189..f8793e0 100644
--- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
+++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
@@ -51,7 +51,7 @@
         }
 
         synchronized (apps) {
-            final ArrayList<AppInfo> updated = new ArrayList<>();
+            PromiseAppInfo updated = null;
             final ArrayList<AppInfo> removed = new ArrayList<>();
             for (int i=0; i < apps.size(); i++) {
                 final AppInfo appInfo = apps.get(i);
@@ -61,7 +61,7 @@
                         final PromiseAppInfo promiseAppInfo = (PromiseAppInfo) appInfo;
                         if (mInstallInfo.state == PackageInstallerCompat.STATUS_INSTALLING) {
                             promiseAppInfo.level = mInstallInfo.progress;
-                            updated.add(appInfo);
+                            updated = promiseAppInfo;
                         } else if (mInstallInfo.state == PackageInstallerCompat.STATUS_FAILED
                                 || mInstallInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
                             apps.removePromiseApp(appInfo);
@@ -70,13 +70,12 @@
                     }
                 }
             }
-            if (!updated.isEmpty()) {
+            if (updated != null) {
+                final PromiseAppInfo updatedPromiseApp = updated;
                 scheduleCallbackTask(new CallbackTask() {
                     @Override
                     public void execute(Callbacks callbacks) {
-                        // TODO: this currently causes unnecessary relayouts
-                        // we need to introduce a new bindPromiseAppsChanged
-                        callbacks.bindAppsUpdated(updated);
+                        callbacks.bindPromiseAppProgressUpdated(updatedPromiseApp);
                     }
                 });
             }