am 381fa3fb: Merge remote-tracking branch \'goog/ub-now-lunchbox\' into release

* commit '381fa3fb2d990f7976a898c16f3675dbb325b848':
  Import translations. DO NOT MERGE
  Fix black flash during rotation of -1 screen with GEL.
  Fix bug: Scroll position reported incorrectly to live wallpapers
  Add callback for "Widgets" button click in launcher
  handle shortcut restore for missing packages
  Import translations. DO NOT MERGE
  Catch exceptions if Exif is malformed
  Disable Set Wallpaper button while loading image
  Disabled the wallpaper when completely in -1 Now space.
  Import translations. DO NOT MERGE
  Fix back button behavior for "App info" when launched by Launcher3.
  Import translations. DO NOT MERGE
  Import translations. DO NOT MERGE
  Import translations. DO NOT MERGE
diff --git a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
index 1622742..2a0188a 100644
--- a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
+++ b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
@@ -20,6 +20,7 @@
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     style="?android:actionButtonStyle"
+    android:id="@+id/set_wallpaper_button"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
     <TextView style="?android:actionBarTabTextStyle"
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index ee7b819..23fbe73 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -75,6 +75,7 @@
 
     protected CropView mCropView;
     protected Uri mUri;
+    private View mSetWallpaperButton;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -111,10 +112,12 @@
                         cropImageAndSetWallpaper(imageUri, null, finishActivityWhenDone);
                     }
                 });
+        mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
 
         // Load image in background
         final BitmapRegionTileSource.UriBitmapSource bitmapSource =
                 new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024);
+        mSetWallpaperButton.setVisibility(View.INVISIBLE);
         Runnable onLoad = new Runnable() {
             public void run() {
                 if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) {
@@ -122,6 +125,8 @@
                             getString(R.string.wallpaper_load_fail),
                             Toast.LENGTH_LONG).show();
                     finish();
+                } else {
+                    mSetWallpaperButton.setVisibility(View.VISIBLE);
                 }
             }
         };
@@ -271,6 +276,9 @@
             }
         } catch (IOException e) {
             Log.w(LOGTAG, "Getting exif data failed", e);
+        } catch (NullPointerException e) {
+            // Sometimes the ExifInterface has an internal NPE if Exif data isn't valid
+            Log.w(LOGTAG, "Getting exif data failed", e);
         } finally {
             Utils.closeSilently(bis);
             Utils.closeSilently(is);
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index c54e477..aa43def 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -90,6 +90,7 @@
     private static final String DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb2.jpg";
 
     private View mSelectedTile;
+    private View mSetWallpaperButton;
     private boolean mIgnoreNextTap;
     private OnClickListener mThumbnailOnClickListener;
 
@@ -146,11 +147,13 @@
                 onLoad = null;
             } else {
                 mFirstClick = false;
+                a.mSetWallpaperButton.setVisibility(View.INVISIBLE);
                 onLoad = new Runnable() {
                     public void run() {
                         if (mBitmapSource != null &&
                                 mBitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
                             a.selectTile(mView);
+                            a.mSetWallpaperButton.setVisibility(View.VISIBLE);
                         } else {
                             ViewGroup parent = (ViewGroup) mView.getParent();
                             if (parent != null) {
@@ -466,6 +469,7 @@
                         }
                     }
                 });
+        mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
 
         // CAB for deleting items
         mActionModeCallback = new ActionMode.Callback() {
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
index cdc5cdc..764156d 100644
--- a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -245,6 +245,9 @@
             try {
                 ei.readExif(mPath);
                 return true;
+            } catch (NullPointerException e) {
+                Log.w("BitmapRegionTileSource", "reading exif failed", e);
+                return false;
             } catch (IOException e) {
                 Log.w("BitmapRegionTileSource", "getting decoder failed", e);
                 return false;
@@ -311,6 +314,9 @@
             } catch (IOException e) {
                 Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
                 return false;
+            } catch (NullPointerException e) {
+                Log.e("BitmapRegionTileSource", "Failed to read EXIF for URI " + mUri, e);
+                return false;
             } finally {
                 Utils.closeSilently(is);
             }
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 2465534..2015158 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -26,6 +26,27 @@
     <!-- no translation found for uid_name (7820867637514617527) -->
     <skip />
     <string name="folder_name" msgid="7371454440695724752"></string>
+    <!-- no translation found for wallpaper_instructions (563973358787555519) -->
+    <skip />
+    <!-- no translation found for image_load_fail (2821429163328561136) -->
+    <skip />
+    <!-- no translation found for wallpaper_load_fail (1261270681127096352) -->
+    <skip />
+    <!-- no translation found for number_of_items_selected:zero (7464587177007785408) -->
+    <!-- no translation found for number_of_items_selected:one (142482526010824029) -->
+    <!-- no translation found for number_of_items_selected:other (1418352074806573570) -->
+    <!-- no translation found for wallpaper_accessibility_name (1655953108132967972) -->
+    <skip />
+    <!-- no translation found for announce_selection (8338254712932127413) -->
+    <skip />
+    <!-- no translation found for wallpaper_delete (8095005658756613921) -->
+    <skip />
+    <!-- no translation found for pick_image (1272073934062909527) -->
+    <skip />
+    <!-- no translation found for pick_wallpaper (8179698221502010609) -->
+    <skip />
+    <!-- no translation found for crop_wallpaper (8334345984491368009) -->
+    <skip />
     <!-- no translation found for activity_not_found (8071924732094499514) -->
     <skip />
     <!-- no translation found for widgets_tab_label (2921133187116603919) -->
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 50bbe51..70d44ce 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -505,11 +505,11 @@
     }
 
     /**
-     * To be overridden by subclasses to create the custom content and call
+     * To be overridden by subclasses to populate the custom content container and call
      * {@link #addToCustomContentPage}. This will only be invoked if
      * {@link #hasCustomContentToLeft()} is {@code true}.
      */
-    protected void addCustomContentToLeft() {
+    protected void populateCustomContentContainer() {
     }
 
     /**
@@ -539,8 +539,8 @@
 
         if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) {
             // Create the custom content page and call the subclass to populate it.
-            mWorkspace.createCustomContentPage();
-            addCustomContentToLeft();
+            mWorkspace.createCustomContentContainer();
+            populateCustomContentContainer();
         } else if (mWorkspace.hasCustomContent() && !hasCustomContentToLeft()) {
             mWorkspace.removeCustomContentPage();
         }
@@ -1033,12 +1033,6 @@
         }
     }
 
-    protected void onFinishBindingItems() {
-        if (mWorkspace != null && hasCustomContentToLeft() && mWorkspace.hasCustomContent()) {
-            addCustomContentToLeft();
-        }
-    }
-
     QSBScroller mQsbScroller = new QSBScroller() {
         int scrollY = 0;
 
@@ -2373,7 +2367,7 @@
                 final String shortcutClass = intent.getComponent().getClassName();
 
                 if (shortcutClass.equals(WidgetAdder.class.getName())) {
-                    showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+                    onClickAddWidgetButton();
                     return;
                 } else if (shortcutClass.equals(MemoryDumpActivity.class.getName())) {
                     MemoryDumpActivity.startDump(this);
@@ -2466,6 +2460,14 @@
         showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false);
     }
 
+    /**
+     * Event handler for the (Add) Widgets button that appears after a long press
+     * on the home screen.
+     */
+    protected void onClickAddWidgetButton() {
+        showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+    }
+
     public void onTouchDownAllAppsButton(View v) {
         // Provide the same haptic feedback that the system offers for virtual keys.
         v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
@@ -2522,7 +2524,8 @@
         String packageName = componentName.getPackageName();
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |
+                Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
         startActivitySafely(null, intent, "startApplicationDetailsActivity");
     }
 
@@ -2877,7 +2880,7 @@
                 mWorkspaceBackgroundDrawable : null);
     }
 
-    void updateWallpaperVisibility(boolean visible) {
+    protected void changeWallpaperVisiblity(boolean visible) {
         int wpflags = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0;
         int curflags = getWindow().getAttributes().flags
                 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -3787,9 +3790,9 @@
 
         // Create the custom content page (this call updates mDefaultScreen which calls
         // setCurrentPage() so ensure that all pages are added before calling this).
-        // The actual content of the custom page will be added during onFinishBindingItems().
-        if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) {
-            mWorkspace.createCustomContentPage();
+        if (hasCustomContentToLeft()) {
+            mWorkspace.createCustomContentContainer();
+            populateCustomContentContainer();
         }
     }
 
@@ -4071,13 +4074,6 @@
             mWorkspace.getUniqueComponents(true, null);
             mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null);
         }
-
-        mWorkspace.post(new Runnable() {
-            @Override
-            public void run() {
-                onFinishBindingItems();
-            }
-        });
     }
 
     public boolean isAllAppsButtonRank(int rank) {
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 57cdfb9..74eefca 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -842,6 +842,10 @@
             }
             values.put(Favorites.APPWIDGET_ID, favorite.appWidgetId);
         }
+
+        // Let LauncherModel know we've been here.
+        values.put(LauncherSettings.Favorites.RESTORED, 1);
+
         return values;
     }
 
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 2102a1f..6839bb3 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1714,6 +1714,7 @@
                 clearSBgDataStructures();
 
                 final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
+                final ArrayList<Long> restoredRows = new ArrayList<Long>();
                 final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
                 if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
                 final Cursor c = contentResolver.query(contentUri, null, null, null, null);
@@ -1754,6 +1755,8 @@
                             (LauncherSettings.Favorites.SPANX);
                     final int spanYIndex = c.getColumnIndexOrThrow(
                             LauncherSettings.Favorites.SPANY);
+                    final int restoredIndex = c.getColumnIndexOrThrow(
+                            LauncherSettings.Favorites.RESTORED);
                     //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
                     //final int displayModeIndex = c.getColumnIndexOrThrow(
                     //        LauncherSettings.Favorites.DISPLAY_MODE);
@@ -1769,6 +1772,7 @@
                         AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false);
                         try {
                             int itemType = c.getInt(itemTypeIndex);
+                            boolean restored = 0 != c.getInt(restoredIndex);
 
                             switch (itemType) {
                             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
@@ -1779,24 +1783,44 @@
                                     intent = Intent.parseUri(intentDescription, 0);
                                     ComponentName cn = intent.getComponent();
                                     if (cn != null && !isValidPackageComponent(manager, cn)) {
-                                        if (!mAppsCanBeOnRemoveableStorage) {
-                                            // Log the invalid package, and remove it from the db
-                                            Launcher.addDumpLog(TAG, "Invalid package removed: " + cn, true);
-                                            itemsToRemove.add(id);
+                                        if (restored) {
+                                            // might be installed later
+                                            Launcher.addDumpLog(TAG,
+                                                    "package not yet restored: " + cn, true);
                                         } else {
-                                            // If apps can be on external storage, then we just
-                                            // leave them for the user to remove (maybe add
-                                            // visual treatment to it)
-                                            Launcher.addDumpLog(TAG, "Invalid package found: " + cn, true);
+                                            if (!mAppsCanBeOnRemoveableStorage) {
+                                                // Log the invalid package, and remove it
+                                                Launcher.addDumpLog(TAG,
+                                                        "Invalid package removed: " + cn, true);
+                                                itemsToRemove.add(id);
+                                            } else {
+                                                // If apps can be on external storage, then we just
+                                                // leave them for the user to remove (maybe add
+                                                // visual treatment to it)
+                                                Launcher.addDumpLog(TAG,
+                                                        "Invalid package found: " + cn, true);
+                                            }
+                                            continue;
                                         }
-                                        continue;
+                                    } else if (restored) {
+                                        // no special handling necessary for this restored item
+                                        restoredRows.add(id);
+                                        restored = false;
                                     }
                                 } catch (URISyntaxException e) {
-                                    Launcher.addDumpLog(TAG, "Invalid uri: " + intentDescription, true);
+                                    Launcher.addDumpLog(TAG,
+                                            "Invalid uri: " + intentDescription, true);
                                     continue;
                                 }
 
-                                if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+                                if (restored) {
+                                    Launcher.addDumpLog(TAG,
+                                            "constructing info for partially restored package",
+                                            true);
+                                    info = getRestoredItemInfo(c, titleIndex);
+                                    intent = getRestoredItemIntent(c, context, intent);
+                                } else if (itemType ==
+                                        LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                                     info = getShortcutInfo(manager, intent, context, c, iconIndex,
                                             titleIndex, mLabelCache);
                                 } else {
@@ -1890,6 +1914,11 @@
                                         break;
                                 }
 
+                                if (restored) {
+                                    // no special handling required for restored folders
+                                    restoredRows.add(id);
+                                }
+
                                 sBgItemsIdMap.put(folderInfo.id, folderInfo);
                                 sBgFolders.put(folderInfo.id, folderInfo);
                                 break;
@@ -1990,6 +2019,25 @@
                     }
                 }
 
+                if (restoredRows.size() > 0) {
+                    ContentProviderClient updater = contentResolver.acquireContentProviderClient(
+                            LauncherSettings.Favorites.CONTENT_URI);
+                    // Update restored items that no longer require special handling
+                    try {
+                        StringBuilder selectionBuilder = new StringBuilder();
+                        selectionBuilder.append(LauncherSettings.Favorites._ID);
+                        selectionBuilder.append(" IN (");
+                        selectionBuilder.append(TextUtils.join(", ", restoredRows));
+                        selectionBuilder.append(")");
+                        ContentValues values = new ContentValues();
+                        values.put(LauncherSettings.Favorites.RESTORED, 0);
+                        updater.update(LauncherSettings.Favorites.CONTENT_URI,
+                                values, selectionBuilder.toString(), null);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Could not update restored rows");
+                    }
+                }
+
                 if (loadedOldDb) {
                     long maxScreenId = 0;
                     // If we're importing we use the old screen order.
@@ -2737,6 +2785,40 @@
     }
 
     /**
+     * Make an ShortcutInfo object for a restored application or shortcut item that points
+     * to a package that is not yet installed on the system.
+     */
+    public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex) {
+        final ShortcutInfo info = new ShortcutInfo();
+        info.usingFallbackIcon = true;
+        info.setIcon(getFallbackIcon());
+        if (cursor != null) {
+            info.title =  cursor.getString(titleIndex);
+        } else {
+            info.title = "";
+        }
+        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+        return info;
+    }
+
+    /**
+     * Make an Intent object for a restored application or shortcut item that points
+     * to the market page for the item.
+     */
+    private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {
+        ComponentName componentName = intent.getComponent();
+        Intent marketIntent = new Intent(Intent.ACTION_VIEW);
+        Uri marketUri = new Uri.Builder()
+                .scheme("market")
+                .authority("details")
+                .appendQueryParameter("id", componentName.getPackageName())
+                .build();
+        Log.d(TAG, "manufactured intent uri: " + marketUri.toString());
+        marketIntent.setData(marketUri);
+        return marketIntent;
+    }
+
+    /**
      * This is called from the code that adds shortcuts from the intent receiver.  This
      * doesn't have a Cursor, but
      */
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 52bcf98..cec9167 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -68,7 +68,7 @@
 
     private static final String DATABASE_NAME = "launcher.db";
 
-    private static final int DATABASE_VERSION = 15;
+    private static final int DATABASE_VERSION = 16;
 
     static final String OLD_AUTHORITY = "com.android.launcher2.settings";
     static final String AUTHORITY = ProviderConfig.AUTHORITY;
@@ -409,7 +409,8 @@
                     "uri TEXT," +
                     "displayMode INTEGER," +
                     "appWidgetProvider TEXT," +
-                    "modified INTEGER NOT NULL DEFAULT 0" +
+                    "modified INTEGER NOT NULL DEFAULT 0," +
+                    "restored INTEGER NOT NULL DEFAULT 0" +
                     ");");
             addWorkspacesTable(db);
 
@@ -716,7 +717,6 @@
                 }
             }
 
-
             if (version < 15) {
                 db.beginTransaction();
                 try {
@@ -735,6 +735,23 @@
                 }
             }
 
+
+            if (version < 16) {
+                db.beginTransaction();
+                try {
+                    // Insert new column for holding restore status
+                    db.execSQL("ALTER TABLE favorites " +
+                            "ADD COLUMN restored INTEGER NOT NULL DEFAULT 0;");
+                    db.setTransactionSuccessful();
+                    version = 16;
+                } catch (SQLException ex) {
+                    // Old version remains, which means we wipe old data
+                    Log.e(TAG, ex.getMessage(), ex);
+                } finally {
+                    db.endTransaction();
+                }
+            }
+
             if (version != DATABASE_VERSION) {
                 Log.w(TAG, "Destroying all old data.");
                 db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 988e5ef..f4ee300 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -275,5 +275,11 @@
          * @see android.provider.LiveFolders#DISPLAY_MODE_LIST
          */
         static final String DISPLAY_MODE = "displayMode";
+
+        /**
+         * Boolean indicating that his item was restored and not yet successfully bound.
+         * <P>Type: INTEGER</P>
+         */
+        static final String RESTORED = "restored";
     }
 }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 359fd86..751b4c6 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -209,6 +209,10 @@
     private boolean mWorkspaceFadeInAdjacentScreens;
 
     WallpaperOffsetInterpolator mWallpaperOffset;
+    private boolean mWallpaperIsLiveWallpaper;
+    private int mNumPagesForWallpaperParallax;
+    private float mLastSetWallpaperOffsetSteps = 0;
+
     private Runnable mDelayedResizeRunnable;
     private Runnable mDelayedSnapToPageRunnable;
     private Point mDisplaySize = new Point();
@@ -421,7 +425,7 @@
         setClipChildren(false);
         setClipToPadding(false);
         setChildrenDrawnWithCacheEnabled(true);
-        
+
         setMinScale(mOverviewModeShrinkFactor);
         setupLayoutTransition();
 
@@ -562,7 +566,7 @@
         return screenId;
     }
 
-    public void createCustomContentPage() {
+    public void createCustomContentContainer() {
         CellLayout customScreen = (CellLayout)
                 mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, null);
         customScreen.disableBackground();
@@ -1347,7 +1351,14 @@
                 // Don't use up all the wallpaper parallax until you have at least
                 // MIN_PARALLAX_PAGE_SPAN pages
                 int numScrollingPages = getNumScreensExcludingEmptyAndCustom();
-                int parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1);
+                int parallaxPageSpan;
+                if (mWallpaperIsLiveWallpaper) {
+                    parallaxPageSpan = numScrollingPages - 1;
+                } else {
+                    parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1);
+                }
+                mNumPagesForWallpaperParallax = parallaxPageSpan;
+
                 // On RTL devices, push the wallpaper offset to the right if we don't have enough
                 // pages (ie if numScrollingPages < MIN_PARALLAX_PAGE_SPAN)
                 int padding = isLayoutRtl() ? parallaxPageSpan - numScrollingPages + 1 : 0;
@@ -1391,7 +1402,11 @@
 
         private void setWallpaperOffsetSteps() {
             // Set wallpaper offset steps (1 / (number of screens - 1))
-            mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f);
+            float xOffset = 1.0f / mNumPagesForWallpaperParallax;
+            if (xOffset != mLastSetWallpaperOffsetSteps) {
+                mWallpaperManager.setWallpaperOffsetSteps(xOffset, 1.0f);
+                mLastSetWallpaperOffsetSteps = xOffset;
+            }
         }
 
         public void setFinalX(float x) {
@@ -1700,6 +1715,10 @@
         if (LauncherAppState.getInstance().hasWallpaperChangedSinceLastCheck()) {
             setWallpaperDimension();
         }
+        mWallpaperIsLiveWallpaper = mWallpaperManager.getWallpaperInfo() != null;
+        // Force the wallpaper offset steps to be set again, because another app might have changed
+        // them
+        mLastSetWallpaperOffsetSteps = 0f;
     }
 
     @Override