Merge "Focus doesn't leave folders without also closing them." into ub-launcher3-burnaby-polish
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
index 2d496a5..6baac6a 100644
--- a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -159,6 +159,7 @@
         public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
         private State mState = State.NOT_LOADED;
 
+        /** Returns whether loading was successful. */
         public boolean loadInBackground(InBitmapProvider bitmapProvider) {
             ExifInterface ei = new ExifInterface();
             if (readExif(ei)) {
@@ -193,7 +194,7 @@
                         try {
                             mPreview = loadPreviewBitmap(opts);
                         } catch (IllegalArgumentException e) {
-                            Log.d(TAG, "Unable to reusage bitmap", e);
+                            Log.d(TAG, "Unable to reuse bitmap", e);
                             opts.inBitmap = null;
                             mPreview = null;
                         }
@@ -202,6 +203,10 @@
                 if (mPreview == null) {
                     mPreview = loadPreviewBitmap(opts);
                 }
+                if (mPreview == null) {
+                    mState = State.ERROR_LOADING;
+                    return false;
+                }
 
                 // Verify that the bitmap can be used on GL surface
                 try {
@@ -212,7 +217,7 @@
                     Log.d(TAG, "Image cannot be rendered on a GL surface", e);
                     mState = State.ERROR_LOADING;
                 }
-                return true;
+                return mState == State.LOADED;
             }
         }
 
@@ -310,7 +315,7 @@
                 Bitmap b = BitmapFactory.decodeStream(is, null, options);
                 Utils.closeSilently(is);
                 return b;
-            } catch (FileNotFoundException e) {
+            } catch (FileNotFoundException | OutOfMemoryError e) {
                 Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
                 return null;
             }
@@ -412,7 +417,8 @@
                         "Failed to create preview of apropriate size! "
                         + " in: %dx%d, out: %dx%d",
                         mWidth, mHeight,
-                        preview.getWidth(), preview.getHeight()));
+                        preview == null ? -1 : preview.getWidth(),
+                        preview == null ? -1 : preview.getHeight()));
             }
         }
     }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index c0ad516..ccbfba1 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -245,7 +245,9 @@
         hotseatCellHeightPx = iconSizePx;
 
         // Folder
-        folderCellWidthPx = Math.min(cellWidthPx + 6 * edgeMarginPx,
+        int folderCellPadding = isTablet || isLandscape ? 6 * edgeMarginPx : 3 * edgeMarginPx;
+        // Don't let the folder get too close to the edges of the screen.
+        folderCellWidthPx = Math.min(cellWidthPx + folderCellPadding,
                 (availableWidthPx - 4 * edgeMarginPx) / inv.numFolderColumns);
         folderCellHeightPx = cellHeightPx + edgeMarginPx;
         folderBackgroundOffset = -edgeMarginPx;
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index f50c07e..8c831b9 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -641,7 +641,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 setLayerType(LAYER_TYPE_NONE, null);
-                close();
+                close(true);
             }
             @Override
             public void onAnimationStart(Animator animation) {
@@ -655,7 +655,7 @@
         oa.start();
     }
 
-    public void close() {
+    public void close(boolean wasAnimated) {
         // TODO: Clear all active animations.
         DragLayer parent = (DragLayer) getParent();
         if (parent != null) {
@@ -663,7 +663,9 @@
         }
         mDragController.removeDropTarget(this);
         clearFocus();
-        mFolderIcon.requestFocus();
+        if (wasAnimated) {
+            mFolderIcon.requestFocus();
+        }
 
         if (mRearrangeOnClose) {
             rearrangeChildren();
@@ -1145,10 +1147,10 @@
                         // addInScreenFromBind() to ensure that hotseat items are placed correctly.
                         mLauncher.getWorkspace().addInScreenFromBind(newIcon, mInfo.container,
                                 mInfo.screenId, mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY);
-                    }
 
-                    // Focus the newly created child
-                    newIcon.requestFocus();
+                        // Focus the newly created child
+                        newIcon.requestFocus();
+                    }
                 }
             }
         };
@@ -1316,7 +1318,11 @@
             rearrangeChildren();
         }
         if (getItemCount() <= 1) {
-            replaceFolderWithFinalItem();
+            if (mInfo.opened) {
+                mLauncher.closeFolder(this, true);
+            } else {
+                replaceFolderWithFinalItem();
+            }
         }
     }
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 9824e3e..0721cd2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -3226,7 +3226,7 @@
         if (animate) {
             folder.animateClosed();
         } else {
-            folder.close();
+            folder.close(false);
         }
 
         // Notify the accessibility manager that this folder "window" has disappeared and no