am eac828e0: Merge "Don\'t lose icons when migrating from different-sized hotseats." into ub-now-lunchbox

* commit 'eac828e0fec7085d0d6b670d578eaaf36ae2e3ca':
  Don't lose icons when migrating from different-sized hotseats.
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index 561c4bb..bbbd910 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -141,7 +141,21 @@
         final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() {
             protected Void doInBackground(Void...args) {
                 if (!isCancelled()) {
-                    bitmapSource.loadInBackground();
+                    try {
+                        bitmapSource.loadInBackground();
+                    } catch (SecurityException securityException) {
+                        if (isDestroyed()) {
+                            // Temporarily granted permissions are revoked when the activity
+                            // finishes, potentially resulting in a SecurityException here.
+                            // Even though {@link #isDestroyed} might also return true in different
+                            // situations where the configuration changes, we are fine with
+                            // catching these cases here as well.
+                            cancel(false);
+                        } else {
+                            // otherwise it had a different cause and we throw it further
+                            throw securityException;
+                        }
+                    }
                 }
                 return null;
             }
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index da222f1..5e8cca8 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -31,7 +31,7 @@
 /**
  * Represents an app in AllAppsView.
  */
-class AppInfo extends ItemInfo {
+public class AppInfo extends ItemInfo {
     private static final String TAG = "Launcher3.AppInfo";
 
     /**
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index d45e4e4..42e2ec3 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -23,7 +23,7 @@
 /**
  * Represents a folder containing shortcuts or apps.
  */
-class FolderInfo extends ItemInfo {
+public class FolderInfo extends ItemInfo {
 
     /**
      * Whether this folder has been opened
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c22a6bf..986fa21 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -96,6 +96,7 @@
 import android.widget.Toast;
 
 import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.PagedView.PageSwitchListener;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -119,7 +120,7 @@
  */
 public class Launcher extends Activity
         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
-                   View.OnTouchListener {
+                   View.OnTouchListener, PageSwitchListener {
     static final String TAG = "Launcher";
     static final boolean LOGD = false;
 
@@ -1010,7 +1011,7 @@
             // It is also poassible that onShow will instead be called slightly after first layout
             // if PagedView#setRestorePage was set to the custom content page in onCreate().
             if (mWorkspace.isOnOrMovingToCustomContent()) {
-                mWorkspace.getCustomContentCallbacks().onShow();
+                mWorkspace.getCustomContentCallbacks().onShow(true);
             }
         }
         mWorkspace.updateInteractionForState();
@@ -1054,8 +1055,9 @@
     }
 
     public interface CustomContentCallbacks {
-        // Custom content is completely shown
-        public void onShow();
+        // Custom content is completely shown. {@code fromResume} indicates whether this was caused
+        // by a onResume or by scrolling otherwise.
+        public void onShow(boolean fromResume);
 
         // Custom content is completely hidden
         public void onHide();
@@ -1068,9 +1070,6 @@
         return false;
     }
 
-    protected void startSettings() {
-    }
-
     public interface QSBScroller {
         public void setScrollY(int scrollY);
     }
@@ -1233,6 +1232,7 @@
         mLauncherView = findViewById(R.id.launcher);
         mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
         mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
+        mWorkspace.setPageSwitchListener(this);
         mPageIndicators = mDragLayer.findViewById(R.id.page_indicator);
 
         mLauncherView.setSystemUiVisibility(
@@ -1255,7 +1255,7 @@
             @Override
             public void onClick(View arg0) {
                 if (!mWorkspace.isSwitchingState()) {
-                    showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+                    onClickAddWidgetButton(arg0);
                 }
             }
         });
@@ -1266,7 +1266,7 @@
             @Override
             public void onClick(View arg0) {
                 if (!mWorkspace.isSwitchingState()) {
-                    startWallpaper();
+                    onClickWallpaperPicker(arg0);
                 }
             }
         });
@@ -1278,9 +1278,9 @@
                 @Override
                 public void onClick(View arg0) {
                     if (!mWorkspace.isSwitchingState()) {
-                        startSettings();
+                        onClickSettingsButton(arg0);
                     }
-                    }
+                }
             });
             settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
         } else {
@@ -2260,12 +2260,6 @@
         sFolders.remove(folder.id);
     }
 
-    protected void startWallpaper() {
-        final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
-        pickWallpaper.setComponent(getWallpaperPickerComponent());
-        startActivityForResult(pickWallpaper, REQUEST_PICK_WALLPAPER);
-    }
-
     protected ComponentName getWallpaperPickerComponent() {
         return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName());
     }
@@ -2369,51 +2363,13 @@
 
         Object tag = v.getTag();
         if (tag instanceof ShortcutInfo) {
-            // Open shortcut
-            final ShortcutInfo shortcut = (ShortcutInfo) tag;
-            final Intent intent = shortcut.intent;
-
-            // Check for special shortcuts
-            if (intent.getComponent() != null) {
-                final String shortcutClass = intent.getComponent().getClassName();
-
-                if (shortcutClass.equals(WidgetAdder.class.getName())) {
-                    onClickAddWidgetButton();
-                    return;
-                } else if (shortcutClass.equals(MemoryDumpActivity.class.getName())) {
-                    MemoryDumpActivity.startDump(this);
-                    return;
-                } else if (shortcutClass.equals(ToggleWeightWatcher.class.getName())) {
-                    toggleShowWeightWatcher();
-                    return;
-                }
-            }
-
-            // Start activities
-            int[] pos = new int[2];
-            v.getLocationOnScreen(pos);
-            intent.setSourceBounds(new Rect(pos[0], pos[1],
-                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
-
-            boolean success = startActivitySafely(v, intent, tag);
-
-            mStats.recordLaunch(intent, shortcut);
-
-            if (success && v instanceof BubbleTextView) {
-                mWaitingForResume = (BubbleTextView) v;
-                mWaitingForResume.setStayPressed(true);
-            }
+            onClickAppShortcut(v);
         } else if (tag instanceof FolderInfo) {
             if (v instanceof FolderIcon) {
-                FolderIcon fi = (FolderIcon) v;
-                handleFolderClick(fi);
+                onClickFolderIcon(v);
             }
         } else if (v == mAllAppsButton) {
-            if (isAllAppsVisible()) {
-                showWorkspace(true);
-            } else {
-                onClickAllAppsButton(v);
-            }
+            onClickAllAppsButton(v);
         }
     }
 
@@ -2467,18 +2423,133 @@
      *
      * @param v The view that was clicked.
      */
-    public void onClickAllAppsButton(View v) {
-        showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false);
+    protected void onClickAllAppsButton(View v) {
+        if (LOGD) Log.d(TAG, "onClickAllAppsButton");
+        if (isAllAppsVisible()) {
+            showWorkspace(true);
+        } else {
+            showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false);
+        }
+    }
+
+    /**
+     * Event handler for an app shortcut click.
+     *
+     * @param v The view that was clicked. Must be a tagged with a {@link ShortcutInfo}.
+     */
+    protected void onClickAppShortcut(View v) {
+        if (LOGD) Log.d(TAG, "onClickAppShortcut");
+        Object tag = v.getTag();
+        if (!(tag instanceof ShortcutInfo)) {
+            throw new IllegalArgumentException("Input must be a Shortcut");
+        }
+
+        // Open shortcut
+        final ShortcutInfo shortcut = (ShortcutInfo) tag;
+        final Intent intent = shortcut.intent;
+
+        // Check for special shortcuts
+        if (intent.getComponent() != null) {
+            final String shortcutClass = intent.getComponent().getClassName();
+
+            if (shortcutClass.equals(MemoryDumpActivity.class.getName())) {
+                MemoryDumpActivity.startDump(this);
+                return;
+            } else if (shortcutClass.equals(ToggleWeightWatcher.class.getName())) {
+                toggleShowWeightWatcher();
+                return;
+            }
+        }
+
+        // Start activities
+        int[] pos = new int[2];
+        v.getLocationOnScreen(pos);
+        intent.setSourceBounds(new Rect(pos[0], pos[1],
+                pos[0] + v.getWidth(), pos[1] + v.getHeight()));
+
+        boolean success = startActivitySafely(v, intent, tag);
+
+        mStats.recordLaunch(intent, shortcut);
+
+        if (success && v instanceof BubbleTextView) {
+            mWaitingForResume = (BubbleTextView) v;
+            mWaitingForResume.setStayPressed(true);
+        }
+    }
+
+    /**
+     * Event handler for a folder icon click.
+     *
+     * @param v The view that was clicked. Must be an instance of {@link FolderIcon}.
+     */
+    protected void onClickFolderIcon(View v) {
+        if (LOGD) Log.d(TAG, "onClickFolder");
+        if (!(v instanceof FolderIcon)){
+            throw new IllegalArgumentException("Input must be a FolderIcon");
+        }
+
+        FolderIcon folderIcon = (FolderIcon) v;
+        final FolderInfo info = folderIcon.getFolderInfo();
+        Folder openFolder = mWorkspace.getFolderForTag(info);
+
+        // If the folder info reports that the associated folder is open, then verify that
+        // it is actually opened. There have been a few instances where this gets out of sync.
+        if (info.opened && openFolder == null) {
+            Log.d(TAG, "Folder info marked as open, but associated folder is not open. Screen: "
+                    + info.screenId + " (" + info.cellX + ", " + info.cellY + ")");
+            info.opened = false;
+        }
+
+        if (!info.opened && !folderIcon.getFolder().isDestroyed()) {
+            // Close any open folder
+            closeFolder();
+            // Open the requested folder
+            openFolder(folderIcon);
+        } else {
+            // Find the open folder...
+            int folderScreen;
+            if (openFolder != null) {
+                folderScreen = mWorkspace.getPageForView(openFolder);
+                // .. and close it
+                closeFolder(openFolder);
+                if (folderScreen != mWorkspace.getCurrentPage()) {
+                    // Close any folder open on the current screen
+                    closeFolder();
+                    // Pull the folder onto this screen
+                    openFolder(folderIcon);
+                }
+            }
+        }
     }
 
     /**
      * Event handler for the (Add) Widgets button that appears after a long press
      * on the home screen.
      */
-    protected void onClickAddWidgetButton() {
+    protected void onClickAddWidgetButton(View view) {
+        if (LOGD) Log.d(TAG, "onClickAddWidgetButton");
         showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
     }
 
+    /**
+     * Event handler for the wallpaper picker button that appears after a long press
+     * on the home screen.
+     */
+    protected void onClickWallpaperPicker(View v) {
+        if (LOGD) Log.d(TAG, "onClickWallpaperPicker");
+        final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER);
+        pickWallpaper.setComponent(getWallpaperPickerComponent());
+        startActivityForResult(pickWallpaper, REQUEST_PICK_WALLPAPER);
+    }
+
+    /**
+     * Event handler for a click on the settings button that appears after a long press
+     * on the home screen.
+     */
+    protected void onClickSettingsButton(View v) {
+        if (LOGD) Log.d(TAG, "onClickSettingsButton");
+    }
+
     public void onTouchDownAllAppsButton(View v) {
         // Provide the same haptic feedback that the system offers for virtual keys.
         v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
@@ -2598,40 +2669,6 @@
         return success;
     }
 
-    private void handleFolderClick(FolderIcon folderIcon) {
-        final FolderInfo info = folderIcon.getFolderInfo();
-        Folder openFolder = mWorkspace.getFolderForTag(info);
-
-        // If the folder info reports that the associated folder is open, then verify that
-        // it is actually opened. There have been a few instances where this gets out of sync.
-        if (info.opened && openFolder == null) {
-            Log.d(TAG, "Folder info marked as open, but associated folder is not open. Screen: "
-                    + info.screenId + " (" + info.cellX + ", " + info.cellY + ")");
-            info.opened = false;
-        }
-
-        if (!info.opened && !folderIcon.getFolder().isDestroyed()) {
-            // Close any open folder
-            closeFolder();
-            // Open the requested folder
-            openFolder(folderIcon);
-        } else {
-            // Find the open folder...
-            int folderScreen;
-            if (openFolder != null) {
-                folderScreen = mWorkspace.getPageForView(openFolder);
-                // .. and close it
-                closeFolder(openFolder);
-                if (folderScreen != mWorkspace.getCurrentPage()) {
-                    // Close any folder open on the current screen
-                    closeFolder();
-                    // Pull the folder onto this screen
-                    openFolder(folderIcon);
-                }
-            }
-        }
-    }
-
     /**
      * This method draws the FolderIcon to an ImageView and then adds and positions that ImageView
      * in the DragLayer in the exact absolute location of the original FolderIcon.
@@ -2891,7 +2928,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;
@@ -4422,6 +4459,10 @@
         mWorkspace.beginDragShared(dragView, source);
     }
 
+    @Override
+    public void onPageSwitch(View newPage, int newPageIndex) {
+    }
+
     /**
      * Prints out out state for debugging.
      */
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index 28df90f..950828e 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -23,7 +23,7 @@
 /**
  * Represents a widget (either instantiated or about to be) in the Launcher.
  */
-class LauncherAppWidgetInfo extends ItemInfo {
+public class LauncherAppWidgetInfo extends ItemInfo {
 
     /**
      * Indicates that the widget hasn't been instantiated yet.
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 007fd7a..5f8f80c 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -191,8 +191,12 @@
         ContentResolver contentResolver = context.getContentResolver();
 
         mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();
-        mOldContentProviderExists = (contentResolver.acquireContentProviderClient(
-                LauncherSettings.Favorites.OLD_CONTENT_URI) != null);
+        ContentProviderClient client = contentResolver.acquireContentProviderClient(
+                LauncherSettings.Favorites.OLD_CONTENT_URI);
+        mOldContentProviderExists = (client != null);
+        if (client != null) {
+            client.release();
+        }
         mApp = app;
         mBgAllAppsList = new AllAppsList(iconCache, appFilter);
         mIconCache = iconCache;
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 79d114c..13e3ef2 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -31,7 +31,7 @@
 /**
  * Represents a launchable icon on the workspaces and in folders.
  */
-class ShortcutInfo extends ItemInfo {
+public class ShortcutInfo extends ItemInfo {
 
     /**
      * The intent used to start the application.
diff --git a/src/com/android/launcher3/WidgetAdder.java b/src/com/android/launcher3/WidgetAdder.java
deleted file mode 100644
index 79ac504..0000000
--- a/src/com/android/launcher3/WidgetAdder.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.android.launcher3;
-
-import android.app.Activity;
-
-public class WidgetAdder extends Activity {
-
-}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 567abfa..1d413f5 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1215,7 +1215,7 @@
         if (hasCustomContent() && getNextPage() == 0 && !mCustomContentShowing) {
             mCustomContentShowing = true;
             if (mCustomContentCallbacks != null) {
-                mCustomContentCallbacks.onShow();
+                mCustomContentCallbacks.onShow(false);
                 mCustomContentShowTime = System.currentTimeMillis();
                 mLauncher.updateVoiceButtonProxyVisible(false);
             }