Merge "Adding null check to prevent crash when factory resetting device. (5214968)"
diff --git a/res/drawable-hdpi/portal_container_holo.9.png b/res/drawable-hdpi/portal_container_holo.9.png
index 20e8808..a2272c9 100644
--- a/res/drawable-hdpi/portal_container_holo.9.png
+++ b/res/drawable-hdpi/portal_container_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_container_holo.9.png b/res/drawable-mdpi/portal_container_holo.9.png
index 90fb1d1..daa1773 100644
--- a/res/drawable-mdpi/portal_container_holo.9.png
+++ b/res/drawable-mdpi/portal_container_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/portal_container_holo.9.png b/res/drawable-xhdpi/portal_container_holo.9.png
index 3c8193b..0c9c518 100644
--- a/res/drawable-xhdpi/portal_container_holo.9.png
+++ b/res/drawable-xhdpi/portal_container_holo.9.png
Binary files differ
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index 7597bc7..814c968 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -42,7 +42,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_centerHorizontal="true"
-        android:paddingTop="@dimen/folder_content_name_gap"
+        android:paddingTop="@dimen/folder_name_padding"
+        android:paddingBottom="@dimen/folder_name_padding"
         android:background="#00000000"
         android:hint="@string/folder_hint_text"
         android:textSize="14sp"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 509b7f1..0d44db8 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -96,7 +96,7 @@
     <dimen name="folder_preview_size">64dp</dimen>
     <!-- The amount that the preview contents are inset from the preview background -->
     <dimen name="folder_preview_padding">4dp</dimen>
-    <dimen name="folder_content_name_gap">4dp</dimen>
+    <dimen name="folder_name_padding">10dp</dimen>
     <dimen name="folder_width_gap">0dp</dimen>
     <dimen name="folder_height_gap">0dp</dimen>
 </resources>
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 1fcfebc..a0342cf 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -97,7 +97,6 @@
     private int mFolderNameHeight;
     private Rect mHitRect = new Rect();
     private Rect mTempRect = new Rect();
-    private boolean mFirstOpen = true;
     private boolean mDragInProgress = false;
     private boolean mDeleteFolderOnDropCompleted = false;
     private boolean mSuppressFolderDeletion = false;
@@ -364,12 +363,6 @@
     }
 
     public void animateOpen() {
-        if (mFirstOpen) {
-            setLayerType(LAYER_TYPE_HARDWARE, null);
-            buildLayer();
-            mFirstOpen = false;
-        }
-
         positionAndSizeAsIcon();
 
         if (!(getParent() instanceof DragLayer)) return;
@@ -410,25 +403,14 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 mState = STATE_OPEN;
-                setLayerType(LAYER_TYPE_NONE, null);
-                enableHardwareLayersForChildren();
             }
         });
         oa.setDuration(mExpandDuration);
         oa.start();
     }
 
-    void enableHardwareLayersForChildren() {
-        ArrayList<View> children = getItemsInReadingOrder();
-        for (View child: children) {
-            child.setLayerType(LAYER_TYPE_HARDWARE, null);
-        }
-    }
-
     public void animateClosed() {
         if (!(getParent() instanceof DragLayer)) return;
-        setLayerType(LAYER_TYPE_HARDWARE, null);
-        buildLayer();
 
         ObjectAnimator oa;
         if (mMode == PARTIAL_GROW) {
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 060bd66..1f72299 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -108,6 +108,10 @@
 
     // sFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()
     static final HashMap<Long, FolderInfo> sFolders = new HashMap<Long, FolderInfo>();
+
+    // sDbIconCache is the set of ItemInfos that need to have their icons updated in the database
+    static final HashMap<Object, byte[]> sDbIconCache = new HashMap<Object, byte[]>();
+
     // </ only access in worker thread >
 
     private IconCache mIconCache;
@@ -205,6 +209,9 @@
                     if (item != modelItem) {
                         // the modelItem needs to match up perfectly with item if our model is to be
                         // consistent with the database-- for now, just require modelItem == item
+                        Log.e(TAG, "item: " + ((item != null) ? item.toString() : "null"));
+                        Log.e(TAG, "modelItem: " + ((modelItem != null) ? modelItem.toString() :
+                            "null"));
                         throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
                                 "doesn't match original");
                     }
@@ -251,6 +258,9 @@
                     if (item != modelItem) {
                         // the modelItem needs to match up perfectly with item if our model is to be
                         // consistent with the database-- for now, just require modelItem == item
+                        Log.e(TAG, "item: " + ((item != null) ? item.toString() : "null"));
+                        Log.e(TAG, "modelItem: " + ((modelItem != null) ? modelItem.toString() :
+                            "null"));
                         throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
                             "doesn't match original");
                     }
@@ -392,6 +402,11 @@
                 cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
                         LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
 
+                if (sItemsIdMap.containsKey(item.id)) {
+                    // we should not be adding new items in the db with the same id
+                    throw new RuntimeException("Error: ItemInfo id (" + item.id + ") passed to " +
+                        "addItemToDatabase already exists." + item.toString());
+                }
                 sItemsIdMap.put(item.id, item);
                 switch (item.itemType) {
                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
@@ -456,7 +471,10 @@
                 if (item != modelItem) {
                     // the modelItem needs to match up perfectly with item if our model is to be
                     // consistent with the database-- for now, just require modelItem == item
-                    throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
+                    Log.e(TAG, "item: " + ((item != null) ? item.toString() : "null"));
+                    Log.e(TAG, "modelItem: " + ((modelItem != null) ? modelItem.toString() :
+                        "null"));
+                    throw new RuntimeException("Error: ItemInfo passed to updateItemInDatabase " +
                         "doesn't match original");
                 }
             }
@@ -488,6 +506,7 @@
                             break;
                     }
                     sItemsIdMap.remove(item.id);
+                    sDbIconCache.remove(item);
                 }
             });
     }
@@ -664,13 +683,11 @@
         private boolean mStopped;
         private boolean mLoadAndBindStepFinished;
         private HashMap<Object, CharSequence> mLabelCache;
-        private HashMap<Object, byte[]> mDbIconCache;
 
         LoaderTask(Context context, boolean isLaunching) {
             mContext = context;
             mIsLaunching = isLaunching;
             mLabelCache = new HashMap<Object, CharSequence>();
-            mDbIconCache = new HashMap<Object, byte[]>();
         }
 
         boolean isLaunching() {
@@ -736,9 +753,6 @@
             final Callbacks cbk = mCallbacks.get();
             final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
 
-            // We update the icons in the database afterwards in case they have changed
-            mDbIconCache.clear();
-
             keep_running: {
                 // Elevate priority when Home launches for the first time to avoid
                 // starving at boot time. Staring at a blank home is not cool.
@@ -783,10 +797,10 @@
 
             // Update the saved icons if necessary
             if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");
-            for (Object key : mDbIconCache.keySet()) {
-                updateSavedIcon(mContext, (ShortcutInfo) key, mDbIconCache.get(key));
+            for (Object key : sDbIconCache.keySet()) {
+                updateSavedIcon(mContext, (ShortcutInfo) key, sDbIconCache.get(key));
             }
-            mDbIconCache.clear();
+            sDbIconCache.clear();
 
             // Clear out this reference, otherwise we end up holding it until all of the
             // callback runnables are done.
@@ -886,6 +900,7 @@
             sAppWidgets.clear();
             sFolders.clear();
             sItemsIdMap.clear();
+            sDbIconCache.clear();
 
             final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
 
@@ -989,7 +1004,7 @@
 
                                 // now that we've loaded everthing re-save it with the
                                 // icon in case it disappears somehow.
-                                queueIconToBeChecked(mDbIconCache, info, c, iconIndex);
+                                queueIconToBeChecked(sDbIconCache, info, c, iconIndex);
                             } else {
                                 // Failed to load the shortcut, probably because the
                                 // activity manager couldn't resolve it (maybe the app