Merge "Updating promise icon's bitmap and label when onBadgingChanged is received" into ub-now-porkchop
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 90b33c5..591d9b6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,7 +20,7 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.launcher3">
-    <uses-sdk android:targetSdkVersion="19" android:minSdkVersion="16"/>
+    <uses-sdk android:targetSdkVersion="21" android:minSdkVersion="16"/>
 
     <permission
         android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 931501c..00f0cf3 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -57,7 +57,7 @@
 
     /** Marker action used to discover a package which defines launcher customization */
     static final String ACTION_LAUNCHER_CUSTOMIZATION =
-            "com.android.launcher3.action.LAUNCHER_CUSTOMIZATION";
+            "android.autoinstalls.config.action.PLAY_AUTO_INSTALL";
 
     private static final String LAYOUT_RES = "default_layout";
 
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index a27e519..1890af4 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -461,7 +461,7 @@
 
         Animator openFolderAnim = null;
         final Runnable onCompleteRunnable;
-        if (!Utilities.isLmp()) {
+        if (!Utilities.isLmpOrAbove()) {
             positionAndSizeAsIcon();
             centerAboutIcon();
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index da1afaa..eb505a3 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1650,7 +1650,7 @@
         // TODO(sansid): use the APIs directly when compiling against L sdk.
         // Currently we use reflection to access the flags and the API to set the transparency
         // on the System bars.
-        if (Utilities.isLmp()) {
+        if (Utilities.isLmpOrAbove()) {
             try {
                 getWindow().getAttributes().systemUiVisibility |=
                         (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
@@ -2809,7 +2809,7 @@
 
             Bundle optsBundle = null;
             if (useLaunchAnimation) {
-                ActivityOptions opts = Utilities.isLmp() ?
+                ActivityOptions opts = Utilities.isLmpOrAbove() ?
                         ActivityOptions.makeCustomAnimation(this, R.anim.task_open_enter, R.anim.no_anim) :
                         ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
                 optsBundle = opts.toBundle();
@@ -2920,7 +2920,7 @@
 
         ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(mFolderIconImageView, alpha,
                 scaleX, scaleY);
-        if (Utilities.isLmp()) {
+        if (Utilities.isLmpOrAbove()) {
             oa.setInterpolator(new LogDecelerateInterpolator(100, 0));
         }
         oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
@@ -3194,7 +3194,7 @@
             mStateAnimation = null;
         }
 
-        boolean material = Utilities.isLmp();
+        boolean material = Utilities.isLmpOrAbove();
 
         final Resources res = getResources();
 
@@ -3376,7 +3376,7 @@
                     dispatchOnLauncherTransitionStart(toView, animated, false);
 
                     revealView.setAlpha(initAlpha);
-                    if (Utilities.isLmp()) {
+                    if (Utilities.isLmpOrAbove()) {
                         for (int i = 0; i < layerViews.size(); i++) {
                             View v = layerViews.get(i);
                             if (v != null) {
@@ -3431,7 +3431,7 @@
             mStateAnimation = null;
         }
 
-        boolean material = Utilities.isLmp();
+        boolean material = Utilities.isLmpOrAbove();
         Resources res = getResources();
 
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime);
@@ -3632,9 +3632,11 @@
                     }
 
                     // Reset page transforms
-                    page.setTranslationX(0);
-                    page.setTranslationY(0);
-                    page.setAlpha(1);
+                    if (page != null) {
+                        page.setTranslationX(0);
+                        page.setTranslationY(0);
+                        page.setAlpha(1);
+                    }
                     content.setCurrentPage(content.getNextPage());
 
                     mAppsCustomizeContent.updateCurrentPageScroll();
@@ -3651,7 +3653,7 @@
                     dispatchOnLauncherTransitionStart(fromView, animated, false);
                     dispatchOnLauncherTransitionStart(toView, animated, false);
 
-                    if (Utilities.isLmp()) {
+                    if (Utilities.isLmpOrAbove()) {
                         for (int i = 0; i < layerViews.size(); i++) {
                             View v = layerViews.get(i);
                             if (v != null) {
@@ -5003,7 +5005,7 @@
             if (mModel.canMigrateFromOldLauncherDb(this)) {
                 launcherClings.showMigrationCling();
             } else {
-                launcherClings.showLongPressCling(false);
+                launcherClings.showLongPressCling(true);
             }
         }
     }
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index 50528b1..5c6535a 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -46,6 +46,11 @@
     public static final int FLAG_UI_NOT_READY = 4;
 
     /**
+     * Indicates that the widget restore has started.
+     */
+    public static final int FLAG_RESTORE_STARTED = 8;
+
+    /**
      * Indicates that the widget hasn't been instantiated yet.
      */
     static final int NO_ID = -1;
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index c372b47..d2cf8f5 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -86,6 +86,7 @@
         implements LauncherAppsCompat.OnAppsChangedCallbackCompat {
     static final boolean DEBUG_LOADERS = false;
     private static final boolean DEBUG_RECEIVER = false;
+    private static final boolean REMOVE_UNRESTORED_ICONS = true;
 
     static final String TAG = "Launcher.Model";
 
@@ -1899,7 +1900,8 @@
 
             synchronized (sBgLock) {
                 clearSBgDataStructures();
-                PackageInstallerCompat.getInstance(mContext).updateActiveSessionCache();
+                final HashSet<String> installingPkgs = PackageInstallerCompat
+                        .getInstance(mContext).updateAndGetActiveSessionCache();
 
                 final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
                 final ArrayList<Long> restoredRows = new ArrayList<Long>();
@@ -2028,6 +2030,25 @@
                                             // installed later.
                                             Launcher.addDumpLog(TAG,
                                                     "package not yet restored: " + cn, true);
+
+                                            if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 0) {
+                                                // Restore has started once.
+                                            } else if (installingPkgs.contains(cn.getPackageName())) {
+                                                // App restore has started. Update the flag
+                                                promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;
+                                                ContentValues values = new ContentValues();
+                                                values.put(LauncherSettings.Favorites.RESTORED,
+                                                        promiseType);
+                                                String where = BaseColumns._ID + "= ?";
+                                                String[] args = {Long.toString(id)};
+                                                contentResolver.update(contentUri, values, where, args);
+
+                                            } else if (REMOVE_UNRESTORED_ICONS) {
+                                                Launcher.addDumpLog(TAG,
+                                                        "Unrestored package removed: " + cn, true);
+                                                itemsToRemove.add(id);
+                                                continue;
+                                            }
                                         } else if (isSdCardReady) {
                                             // Do not wait for external media load anymore.
                                             // Log the invalid package, and remove it
@@ -2235,6 +2256,19 @@
                                         appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
                                                 component);
                                         appWidgetInfo.restoreStatus = restoreStatus;
+
+                                        if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) != 0) {
+                                            // Restore has started once.
+                                        } else if (installingPkgs.contains(component.getPackageName())) {
+                                            // App restore has started. Update the flag
+                                            appWidgetInfo.restoreStatus |=
+                                                    LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
+                                        } else if (REMOVE_UNRESTORED_ICONS) {
+                                            Launcher.addDumpLog(TAG,
+                                                    "Unrestored package removed: " + component, true);
+                                            itemsToRemove.add(id);
+                                            continue;
+                                        }
                                     }
 
                                     appWidgetInfo.id = id;
@@ -2263,19 +2297,17 @@
                                         break;
                                     }
 
-                                    if (isProviderReady) {
-                                        String providerName = provider.provider.flattenToString();
-                                        if (!providerName.equals(savedProvider) ||
-                                                (appWidgetInfo.restoreStatus != restoreStatus)) {
-                                            ContentValues values = new ContentValues();
-                                            values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,
-                                                    providerName);
-                                            values.put(LauncherSettings.Favorites.RESTORED,
-                                                    appWidgetInfo.restoreStatus);
-                                            String where = BaseColumns._ID + "= ?";
-                                            String[] args = {Long.toString(id)};
-                                            contentResolver.update(contentUri, values, where, args);
-                                        }
+                                    String providerName = appWidgetInfo.providerName.flattenToString();
+                                    if (!providerName.equals(savedProvider) ||
+                                            (appWidgetInfo.restoreStatus != restoreStatus)) {
+                                        ContentValues values = new ContentValues();
+                                        values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,
+                                                providerName);
+                                        values.put(LauncherSettings.Favorites.RESTORED,
+                                                appWidgetInfo.restoreStatus);
+                                        String where = BaseColumns._ID + "= ?";
+                                        String[] args = {Long.toString(id)};
+                                        contentResolver.update(contentUri, values, where, args);
                                     }
                                     sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
                                     sBgAppWidgets.add(appWidgetInfo);
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 9abfb7f..5b27f84 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -55,6 +55,11 @@
     public static final int FLAG_INSTALL_SESSION_ACTIVE = 4;
 
     /**
+     * Indicates that the widget restore has started.
+     */
+    public static final int FLAG_RESTORE_STARTED = 8;
+
+    /**
      * The intent used to start the application.
      */
     Intent intent;
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index f20f261..80d4b22 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -103,11 +103,10 @@
     }
 
     /**
-     * Indicates if the device is running LMP or not.
-     * TODO(sansid): Change the check to a VERSION_CODES code check once we have a version for L.
+     * Indicates if the device is running LMP or higher.
      */
-    public static boolean isLmp() {
-        return "L".equals(Build.VERSION.CODENAME);
+    public static boolean isLmpOrAbove() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.L;
     }
 
     /**
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 7b4e432..774996e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1107,7 +1107,7 @@
         case MotionEvent.ACTION_UP:
             if (mTouchState == TOUCH_STATE_REST) {
                 final CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
-                if (!currentPage.lastDownOnOccupiedCell()) {
+                if (currentPage != null && !currentPage.lastDownOnOccupiedCell()) {
                     onWallpaperTap(ev);
                 }
             }
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
index 5997e7b..6512d42 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
@@ -38,9 +38,8 @@
 
     public static AppWidgetManagerCompat getInstance(Context context) {
         synchronized (sInstanceLock) {
-            // TODO change this to use api version once L gets an API number.
             if (sInstance == null) {
-                if (Utilities.isLmp()) {
+                if (Utilities.isLmpOrAbove()) {
                     sInstance = new AppWidgetManagerCompatVL(context.getApplicationContext());
                 } else {
                     sInstance = new AppWidgetManagerCompatV16(context.getApplicationContext());
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index e3879ee..6efcc00 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -23,6 +23,8 @@
 import android.os.Build;
 import android.os.Bundle;
 
+import com.android.launcher3.Utilities;
+
 import java.util.List;
 
 public abstract class LauncherAppsCompat {
@@ -48,9 +50,8 @@
 
     public static LauncherAppsCompat getInstance(Context context) {
         synchronized (sInstanceLock) {
-            // STOPSHIP(kennyguy) change this to use api version once L gets an API number.
             if (sInstance == null) {
-                if ("L".equals(Build.VERSION.CODENAME)) {
+                if (Utilities.isLmpOrAbove()) {
                     sInstance = new LauncherAppsCompatVL(context.getApplicationContext());
                 } else {
                     sInstance = new LauncherAppsCompatV16(context.getApplicationContext());
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index c4a9783..e0d28b5 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -82,11 +82,7 @@
         synchronized (mCallbacks) {
             mCallbacks.put(callback, wrappedCallback);
         }
-        try {
-            mLauncherApps.registerCallback(wrappedCallback);
-        } catch (Throwable e) {
-            // STOPSHIP(kennyguy): Remove when LRW71 hits googlefood
-        }
+        mLauncherApps.registerCallback(wrappedCallback);
     }
 
     public void removeOnAppsChangedCallback(
@@ -96,11 +92,7 @@
             wrappedCallback = mCallbacks.remove(callback);
         }
         if (wrappedCallback != null) {
-            try {
-                mLauncherApps.unregisterCallback(wrappedCallback);
-            } catch (Throwable e) {
-                // STOPSHIP(kennyguy): Remove when LRW71 hits googlefood
-            }
+            mLauncherApps.unregisterCallback(wrappedCallback);
         }
     }
 
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompat.java b/src/com/android/launcher3/compat/PackageInstallerCompat.java
index 0ae52bd..0eb8754 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompat.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompat.java
@@ -20,6 +20,8 @@
 
 import com.android.launcher3.Utilities;
 
+import java.util.HashSet;
+
 public abstract class PackageInstallerCompat {
 
     public static final int STATUS_INSTALLED = 0;
@@ -32,7 +34,7 @@
     public static PackageInstallerCompat getInstance(Context context) {
         synchronized (sInstanceLock) {
             if (sInstance == null) {
-                if (Utilities.isLmp()) {
+                if (Utilities.isLmpOrAbove()) {
                     sInstance = new PackageInstallerCompatVL(context);
                 } else {
                     sInstance = new PackageInstallerCompatV16(context) { };
@@ -42,7 +44,7 @@
         }
     }
 
-    public abstract void updateActiveSessionCache();
+    public abstract HashSet<String> updateAndGetActiveSessionCache();
 
     public abstract void onPause();
 
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatV16.java b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
index 4cc6fc1..1910d22 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
@@ -29,6 +29,7 @@
 import org.json.JSONTokener;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 
 public class PackageInstallerCompatV16 extends PackageInstallerCompat {
 
@@ -76,9 +77,6 @@
     @Override
     public void onStop() { }
 
-    @Override
-    public void updateActiveSessionCache() { }
-
     private void replayUpdates() {
         if (DEBUG) Log.d(TAG, "updates resumed");
         LauncherAppState app = LauncherAppState.getInstanceNoCreate();
@@ -169,4 +167,9 @@
         }
         return value;
     }
+
+    @Override
+    public HashSet<String> updateAndGetActiveSessionCache() {
+        return new HashSet<String>();
+    }
 }
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
index 557a9a3..a84bf02 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
@@ -59,11 +59,16 @@
     }
 
     @Override
-    public void updateActiveSessionCache() {
+    public HashSet<String> updateAndGetActiveSessionCache() {
+        HashSet<String> activePackages = new HashSet<String>();
         UserHandleCompat user = UserHandleCompat.myUserHandle();
         for (SessionInfo info : mInstaller.getAllSessions()) {
             addSessionInfoToCahce(info, user);
+            if (info.getAppPackageName() != null) {
+                activePackages.add(info.getAppPackageName());
+            }
         }
+        return activePackages;
     }
 
     private void addSessionInfoToCahce(SessionInfo info, UserHandleCompat user) {
diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java
index 8effb81..1374b4e 100644
--- a/src/com/android/launcher3/compat/UserManagerCompat.java
+++ b/src/com/android/launcher3/compat/UserManagerCompat.java
@@ -20,6 +20,8 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 
+import com.android.launcher3.Utilities;
+
 import java.util.List;
 
 public abstract class UserManagerCompat {
@@ -27,8 +29,7 @@
     }
 
     public static UserManagerCompat getInstance(Context context) {
-        // TODO change this to use api version once L gets an API number.
-        if ("L".equals(Build.VERSION.CODENAME)) {
+        if (Utilities.isLmpOrAbove()) {
             return new UserManagerCompatVL(context);
         } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
             return new UserManagerCompatV17(context);