Merge "Import revised translations."
diff --git a/res/layout-land/hotseat.xml b/res/layout-land/hotseat.xml
index f82d541..dca30bf 100644
--- a/res/layout-land/hotseat.xml
+++ b/res/layout-land/hotseat.xml
@@ -18,7 +18,7 @@
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
     android:background="@drawable/hotseat_bg_panel"
     launcher:cellCountX="1"
-    launcher:cellCountY="-1">
+    launcher:cellCountY="5">
     <com.android.launcher2.CellLayout
         android:id="@+id/layout"
         android:layout_width="match_parent"
diff --git a/res/layout-port/hotseat.xml b/res/layout-port/hotseat.xml
index 53f3c20..19da944 100644
--- a/res/layout-port/hotseat.xml
+++ b/res/layout-port/hotseat.xml
@@ -17,7 +17,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
     android:background="@drawable/hotseat_bg_panel"
-    launcher:cellCountX="-1"
+    launcher:cellCountX="5"
     launcher:cellCountY="1">
     <com.android.launcher2.CellLayout
         android:id="@+id/layout"
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 85465b4..ea761ce 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -22,8 +22,8 @@
 <!-- Workspace -->
     <dimen name="workspace_cell_width">106dp</dimen>
     <dimen name="workspace_cell_height">74dp</dimen>
-    <dimen name="hotseat_cell_width">68dp</dimen>
-    <dimen name="hotseat_cell_height">74dp</dimen>
+    <dimen name="hotseat_cell_width">64dp</dimen>
+    <dimen name="hotseat_cell_height">58dp</dimen>
     <!-- Block spacing on each side of the screen -->
     <dimen name="workspace_left_padding">0dp</dimen>
     <dimen name="workspace_right_padding">0dp</dimen>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index eab4044..641f8ea 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -19,7 +19,7 @@
     <dimen name="qsb_bar_height">40dp</dimen>
     <dimen name="workspace_cell_width">80dp</dimen>
     <dimen name="workspace_cell_height">100dp</dimen>
-    <dimen name="hotseat_cell_width">80dp</dimen>
+    <dimen name="hotseat_cell_width">64dp</dimen>
     <dimen name="hotseat_cell_height">64dp</dimen>
     <dimen name="workspace_width_gap">-1dp</dimen>
     <dimen name="workspace_height_gap">-1dp</dimen>
@@ -37,7 +37,7 @@
 
 <!-- AllApps/Customize/AppsCustomize -->
     <dimen name="apps_customize_tab_bar_height">56dp</dimen>
-    <dimen name="app_icon_size">56dp</dimen>
+    <dimen name="app_icon_size">48dp</dimen>
     <!-- The width can be 72dp because we don't have L/R padding -->
     <dimen name="apps_customize_cell_width">72dp</dimen>
     <dimen name="apps_customize_cell_height">80dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e8c8d00..3928fa4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -45,8 +45,8 @@
     <string name="widgets_tab_label">Widgets</string>
 
     <!-- AppsCustomize pane -->
-    <!-- Message to tell the user to long-press on a widget to add it [CHAR_LIMIT=50] -->
-    <string name="long_press_widget_to_add">Long-press to pick up a widget</string>
+    <!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
+    <string name="long_press_widget_to_add">Touch &amp; hold to pick up a widget</string>
     <!-- Market button text.  The market button text is removed in Launcher.java 
          in the Phone UI. [CHAR LIMIT=32] -->
     <string name="market">Shop</string>
@@ -194,6 +194,9 @@
     <!-- Widgets: -->
     <skip />    
 
+    <!-- The Google Apps folder name -->
+    <string name="google_apps_folder_name">Google Apps</string>
+
     <!-- Text to show user in place of a gadget when we can't display it properly -->
     <string name="gadget_error_text">Problem loading widget</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 15ca427..be9b0fd 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -39,18 +39,18 @@
     </style>
 
     <style name="WorkspaceIcon.Portrait">
-        <item name="android:drawablePadding">4dp</item>
+        <item name="android:drawablePadding">8dp</item>
         <item name="android:paddingLeft">4dp</item>
         <item name="android:paddingRight">4dp</item>
-        <item name="android:paddingTop">4dp</item>
+        <item name="android:paddingTop">8dp</item>
         <item name="android:paddingBottom">4dp</item>
     </style>
 
     <style name="WorkspaceIcon.Landscape">
-        <item name="android:drawablePadding">0dp</item>
+        <item name="android:drawablePadding">4dp</item>
         <item name="android:paddingLeft">4dp</item>
         <item name="android:paddingRight">4dp</item>
-        <item name="android:paddingTop">2dp</item>
+        <item name="android:paddingTop">6dp</item>
         <item name="android:paddingBottom">4dp</item>
     </style>
 
@@ -66,18 +66,18 @@
 
     <style name="WorkspaceIcon.Portrait.AppsCustomize">
         <item name="android:background">@null</item>
-        <item name="android:paddingTop">0dp</item>
+        <item name="android:paddingTop">4dp</item>
         <item name="android:paddingBottom">0dp</item>
         <item name="android:paddingLeft">0dp</item>
         <item name="android:paddingRight">0dp</item>
-        <item name="android:drawablePadding">4dp</item>
+        <item name="android:drawablePadding">8dp</item>
         <item name="android:includeFontPadding">false</item>
     </style>
     <style name="WorkspaceIcon.Landscape.AppsCustomize">
         <item name="android:background">@null</item>
-        <item name="android:paddingTop">0dp</item>
+        <item name="android:paddingTop">4dp</item>
         <item name="android:paddingBottom">0dp</item>
-        <item name="android:drawablePadding">2dp</item>
+        <item name="android:drawablePadding">6dp</item>
         <item name="android:includeFontPadding">false</item>
     </style>
 
diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace.xml
index d509490..f6e363c 100644
--- a/res/xml/default_workspace.xml
+++ b/res/xml/default_workspace.xml
@@ -26,16 +26,47 @@
         launcher:screen="2"
         launcher:x="0"
         launcher:y="3" />
+    <folder
+        launcher:screen="2"
+        launcher:x="3"
+        launcher:y="3"
+        launcher:title="@string/google_apps_folder_name">
+        <favorite
+            launcher:packageName="com.google.android.apps.plus"
+            launcher:className="com.google.android.apps.plus.phone.HomeActivity" />
+        <favorite
+            launcher:packageName="com.google.android.gm"
+            launcher:className="com.google.android.gm.ConversationListActivityGmail" />
+        <favorite
+            launcher:packageName="com.google.android.apps.maps"
+            launcher:className="com.google.android.maps.MapsActivity" />
+        <favorite
+            launcher:packageName="com.google.android.youtube"
+            launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" />
+        <favorite
+            launcher:packageName="com.google.android.music"
+            launcher:className="com.android.music.activitymanagement.TopLevelActivity" />
+        <favorite
+            launcher:packageName="com.google.android.videos"
+            launcher:className="com.google.android.youtube.videos.honeycomb.VideosActivity" />
+        <favorite
+            launcher:packageName="com.google.android.apps.books"
+            launcher:className="com.google.android.apps.books.app.BooksActivity" />
+        <favorite
+            launcher:packageName="com.android.vending"
+            launcher:className="com.android.vending.AssetBrowserActivity" />
+        <favorite
+            launcher:packageName="com.google.android.calendar"
+            launcher:className="com.android.calendar.AllInOneActivity" />
+        <favorite
+            launcher:packageName="com.google.android.gallery3d"
+            launcher:className="com.android.gallery3d.app.Gallery" />
+        <favorite
+            launcher:packageName="com.android.settings"
+            launcher:className="com.android.settings.Settings" />
+    </folder>
 
     <!-- Right screen [3] -->
-    <appwidget
-        launcher:packageName="com.android.music"
-        launcher:className="com.android.music.MediaAppWidgetProvider"
-        launcher:screen="3"
-        launcher:x="0"
-        launcher:y="0"
-        launcher:spanX="4"
-        launcher:spanY="1" />
 
     <!-- Far-right screen [4] -->
 
@@ -44,21 +75,28 @@
         launcher:packageName="com.android.contacts"
         launcher:className="com.android.contacts.activities.DialtactsActivity"
         launcher:container="-101"
-        launcher:screen="1"
-        launcher:x="1"
+        launcher:screen="0"
+        launcher:x="0"
         launcher:y="0" />
     <favorite
         launcher:packageName="com.android.contacts"
         launcher:className="com.android.contacts.activities.PeopleActivity"
         launcher:container="-101"
-        launcher:screen="2"
-        launcher:x="2"
+        launcher:screen="1"
+        launcher:x="1"
+        launcher:y="0" />
+    <favorite
+        launcher:packageName="com.google.android.talk"
+        launcher:className="com.google.android.talk.SigningInActivity"
+        launcher:container="-101"
+        launcher:screen="3"
+        launcher:x="3"
         launcher:y="0" />
     <favorite
         launcher:packageName="com.android.browser"
         launcher:className="com.android.browser.BrowserActivity"
         launcher:container="-101"
-        launcher:screen="3"
-        launcher:x="3"
+        launcher:screen="4"
+        launcher:x="4"
         launcher:y="0" />
 </favorites>
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index 2f5cc40..8aa7c59 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -39,7 +39,6 @@
 
     private static final String APPS_TAB_TAG = "APPS";
     private static final String WIDGETS_TAB_TAG = "WIDGETS";
-    private static final int sTabBarFadeInDuration = 150;
 
     private final LayoutInflater mLayoutInflater;
     private ViewGroup mTabs;
@@ -130,7 +129,7 @@
                 // Set the width and show the tab bar (if we have a loading graphic, we can switch
                 // it off here)
                 mTabs.getLayoutParams().width = contentWidth;
-                mTabsContainer.animate().alpha(1f).setDuration(sTabBarFadeInDuration);
+                mTabsContainer.setAlpha(1f);
             }
         }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 641e0f7..15a0642 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -292,13 +292,6 @@
         return mInfo;
     }
 
-    void onOpen() {
-        // When the folder opens, we need to refresh the GridView's selection by
-        // forcing a layout
-        // TODO: find out if this is still necessary
-        mContent.requestLayout();
-    }
-
     void bind(FolderInfo info) {
         mInfo = info;
         ArrayList<ShortcutInfo> children = info.contents;
@@ -849,7 +842,8 @@
 
     private void onCloseComplete() {
         DragLayer parent = (DragLayer) getParent();
-        parent.removeView(Folder.this);
+        parent.removeView(this);
+        mDragController.removeDropTarget((DropTarget) this);
         clearFocus();
 
         if (mRearrangeOnClose) {
diff --git a/src/com/android/launcher2/Hotseat.java b/src/com/android/launcher2/Hotseat.java
index 491691e..c53a743 100644
--- a/src/com/android/launcher2/Hotseat.java
+++ b/src/com/android/launcher2/Hotseat.java
@@ -27,7 +27,8 @@
 import com.android.launcher.R;
 
 public class Hotseat extends FrameLayout {
-    static final String TAG = "Hotseat";
+    private static final String TAG = "Hotseat";
+    private static final int sAllAppsButtonRank = 2; // In the middle of the dock
 
     private Launcher mLauncher;
     private CellLayout mContent;
@@ -75,6 +76,9 @@
     int getCellYFromOrder(int rank) {
         return mIsLandscape ? (mContent.getCountY() - (rank + 1)) : 0;
     }
+    public static boolean isAllAppsButtonRank(int rank) {
+        return rank == sAllAppsButtonRank;
+    }
 
     @Override
     protected void onFinishInflate() {
@@ -110,8 +114,8 @@
 
         // Note: We do this to ensure that the hotseat is always laid out in the orientation of
         // the hotseat in order regardless of which orientation they were added
-        int x = getCellXFromOrder(0);
-        int y = getCellYFromOrder(0);
+        int x = getCellXFromOrder(sAllAppsButtonRank);
+        int y = getCellYFromOrder(sAllAppsButtonRank);
         mContent.addViewToCellLayout(allAppsButton, -1, 0, new CellLayout.LayoutParams(x,y,1,1),
                 true);
     }
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index 04f97f3..1fdafc8 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -24,7 +24,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
-import android.util.Pair;
 import android.util.DisplayMetrics;
 
 import java.util.HashMap;
@@ -54,8 +53,18 @@
         mContext = context;
         mPackageManager = context.getPackageManager();
         mBubble = new Utilities.BubbleText(context);
+        int density = context.getResources().getDisplayMetrics().densityDpi;
         if (LauncherApplication.isScreenLarge()) {
-            mIconDpi = DisplayMetrics.DENSITY_HIGH;
+            if (density == DisplayMetrics.DENSITY_LOW) {
+                mIconDpi = DisplayMetrics.DENSITY_MEDIUM;
+            } else if (density == DisplayMetrics.DENSITY_MEDIUM) {
+                mIconDpi = DisplayMetrics.DENSITY_HIGH;
+            } else if (density == DisplayMetrics.DENSITY_HIGH) {
+                mIconDpi = DisplayMetrics.DENSITY_XHIGH;
+            } else if (density == DisplayMetrics.DENSITY_XHIGH) {
+                // We'll need to use a denser icon, or some sort of a mipmap
+                mIconDpi = DisplayMetrics.DENSITY_XHIGH;
+            }
         } else {
             mIconDpi = context.getResources().getDisplayMetrics().densityDpi;
         }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index c025638..bb7bdf5 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -436,6 +436,7 @@
      * a configuration step, this allows the proper animations to run after other transitions.
      */
     private boolean completeAdd(PendingAddArguments args) {
+        boolean result = false;
         switch (args.requestCode) {
             case REQUEST_PICK_APPLICATION:
                 completeAddApplication(args.intent, args.container, args.screen, args.cellX,
@@ -447,19 +448,24 @@
             case REQUEST_CREATE_SHORTCUT:
                 completeAddShortcut(args.intent, args.container, args.screen, args.cellX,
                         args.cellY);
-                return true;
+                result = true;
+                break;
             case REQUEST_PICK_APPWIDGET:
                 addAppWidgetFromPick(args.intent);
                 break;
             case REQUEST_CREATE_APPWIDGET:
                 int appWidgetId = args.intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
                 completeAddAppWidget(appWidgetId, args.container, args.screen);
-                return true;
+                result = true;
+                break;
             case REQUEST_PICK_WALLPAPER:
                 // We just wanted the activity result here so we can clear mWaitingForResult
                 break;
         }
-        return false;
+        // In any situation where we have a multi-step drop, we should reset the add info only after
+        // we complete the drop
+        resetAddInfo();
+        return result;
     }
 
     @Override
@@ -629,7 +635,6 @@
         }
 
         State state = intToState(savedState.getInt(RUNTIME_STATE, State.WORKSPACE.ordinal()));
-
         if (state == State.APPS_CUSTOMIZE) {
             showAllApps(false);
         }
@@ -910,8 +915,9 @@
                 mDragLayer.clearAllResizeFrames();
                 updateRunning();
 
-                // Reset AllApps to it's initial state
-                if (mAppsCustomizeContent != null) {
+                // Reset AllApps to it's initial state only if we are not in the middle of
+                // processing a multi-step drop
+                if (mAppsCustomizeContent != null && mPendingAddInfo.container == ItemInfo.NO_ID) {
                     mAppsCustomizeContent.reset();
                 }
             } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
@@ -1133,6 +1139,10 @@
     public void onDestroy() {
         super.onDestroy();
 
+        // Remove all pending runnables
+        mHandler.removeMessages(ADVANCE_MSG);
+        mHandler.removeMessages(0);
+
         // Stop callbacks from LauncherModel
         LauncherApplication app = ((LauncherApplication) getApplication());
         mModel.stopLoader();
@@ -1454,25 +1464,6 @@
         }
     }
 
-    public void closeFolder() {
-        Folder folder = mWorkspace.getOpenFolder();
-        if (folder != null) {
-            closeFolder(folder);
-        }
-    }
-
-    void closeFolder(Folder folder) {
-        folder.getInfo().opened = false;
-
-        ViewGroup parent = (ViewGroup) folder.getParent().getParent();
-        if (parent != null) {
-            FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
-            shrinkAndFadeInFolderIcon(fi);
-            mDragController.removeDropTarget((DropTarget)folder);
-        }
-        folder.animateClosed();
-    }
-
     /**
      * Re-listen when widgets are reset.
      */
@@ -1718,11 +1709,34 @@
         growAndFadeOutFolderIcon(folderIcon);
         info.opened = true;
 
-        mDragLayer.addView(folder);
-        mDragController.addDropTarget((DropTarget) folder);
-
+        // Just verify that the folder hasn't already been added to the DragLayer.
+        // There was a one-off crash where the folder had a parent already.
+        if (folder.getParent() == null) {
+            mDragLayer.addView(folder);
+            mDragController.addDropTarget((DropTarget) folder);
+        } else {
+            Log.w(TAG, "Opening folder (" + folder + ") which already has a parent (" +
+                    folder.getParent() + ").");
+        }
         folder.animateOpen();
-        folder.onOpen();
+    }
+
+    public void closeFolder() {
+        Folder folder = mWorkspace.getOpenFolder();
+        if (folder != null) {
+            closeFolder(folder);
+        }
+    }
+
+    void closeFolder(Folder folder) {
+        folder.getInfo().opened = false;
+
+        ViewGroup parent = (ViewGroup) folder.getParent().getParent();
+        if (parent != null) {
+            FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
+            shrinkAndFadeInFolderIcon(fi);
+        }
+        folder.animateClosed();
     }
 
     public boolean onLongClick(View v) {
@@ -2169,7 +2183,7 @@
         // Otherwise, we are not in spring loaded mode, so don't do anything.
     }
     void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, boolean extendedDelay) {
-        mWorkspace.postDelayed(new Runnable() {
+        mHandler.postDelayed(new Runnable() {
             @Override
             public void run() {
                 exitSpringLoadedDragMode();
@@ -2545,20 +2559,12 @@
     }
 
     /**
-     * Receives notifications when applications are added/removed.
+     * Receives notifications when system dialogs are to be closed.
      */
     private class CloseSystemDialogsIntentReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             closeSystemDialogs();
-            String reason = intent.getStringExtra("reason");
-            if (!"homekey".equals(reason)) {
-                boolean animate = true;
-                if (mPaused || "lock".equals(reason)) {
-                    animate = false;
-                }
-                showWorkspace(animate);
-            }
         }
     }
 
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 63e8077..206de14 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -816,26 +816,37 @@
 
         // check & update map of what's occupied; used to discard overlapping/invalid items
         private boolean checkItemPlacement(ItemInfo occupied[][][], ItemInfo item) {
-            if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+            int containerIndex = item.screen;
+            if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+                // We use the last index to refer to the hotseat
+                containerIndex = Launcher.SCREEN_COUNT;
+                // Return early if we detect that an item is under the hotseat button
+                if (Hotseat.isAllAppsButtonRank(item.screen)) {
+                    return false;
+                }
+            } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                // Skip further checking if it is not the hotseat or workspace container
                 return true;
             }
+
             for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
                 for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
-                    if (occupied[item.screen][x][y] != null) {
+                    if (occupied[containerIndex][x][y] != null) {
                         Log.e(TAG, "Error loading shortcut " + item
-                            + " into cell (" + item.screen + ":"
+                            + " into cell (" + containerIndex + "-" + item.screen + ":"
                             + x + "," + y
                             + ") occupied by "
-                            + occupied[item.screen][x][y]);
+                            + occupied[containerIndex][x][y]);
                         return false;
                     }
                 }
             }
             for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
                 for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
-                    occupied[item.screen][x][y] = item;
+                    occupied[containerIndex][x][y] = item;
                 }
             }
+
             return true;
         }
 
@@ -858,8 +869,9 @@
             final Cursor c = contentResolver.query(
                     LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
 
+            // +1 for the hotseat (it can be larger than the workspace)
             final ItemInfo occupied[][][] =
-                    new ItemInfo[Launcher.SCREEN_COUNT][mCellCountX][mCellCountY];
+                    new ItemInfo[Launcher.SCREEN_COUNT + 1][mCellCountX + 1][mCellCountY + 1];
 
             try {
                 final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
@@ -1511,7 +1523,7 @@
         // the db
         if (icon == null) {
             if (c != null) {
-                icon = getIconFromCursor(c, iconIndex);
+                icon = getIconFromCursor(c, iconIndex, context);
             }
         }
         // the fallback icon
@@ -1581,7 +1593,7 @@
             }
             // the db
             if (icon == null) {
-                icon = getIconFromCursor(c, iconIndex);
+                icon = getIconFromCursor(c, iconIndex, context);
             }
             // the fallback icon
             if (icon == null) {
@@ -1590,7 +1602,7 @@
             }
             break;
         case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
-            icon = getIconFromCursor(c, iconIndex);
+            icon = getIconFromCursor(c, iconIndex, context);
             if (icon == null) {
                 icon = getFallbackIcon();
                 info.customIcon = false;
@@ -1609,14 +1621,15 @@
         return info;
     }
 
-    Bitmap getIconFromCursor(Cursor c, int iconIndex) {
+    Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {
         if (false) {
             Log.d(TAG, "getIconFromCursor app="
                     + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));
         }
         byte[] data = c.getBlob(iconIndex);
         try {
-            return BitmapFactory.decodeByteArray(data, 0, data.length);
+            return Utilities.createIconBitmap(
+                    BitmapFactory.decodeByteArray(data, 0, data.length), context);
         } catch (Exception e) {
             return null;
         }
diff --git a/src/com/android/launcher2/LauncherProvider.java b/src/com/android/launcher2/LauncherProvider.java
index 6ca16de..53f7b42 100644
--- a/src/com/android/launcher2/LauncherProvider.java
+++ b/src/com/android/launcher2/LauncherProvider.java
@@ -737,7 +737,7 @@
                         // hotset. This screen can't be at position 0 because AllApps is in the
                         // zeroth position.
                         if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
-                                Integer.valueOf(screen) <= 0) {
+                                Hotseat.isAllAppsButtonRank(Integer.valueOf(screen))) {
                             throw new RuntimeException("Invalid screen position for hotseat item");
                         }
 
diff --git a/src/com/android/launcher2/Utilities.java b/src/com/android/launcher2/Utilities.java
index c63c822..b537f7a 100644
--- a/src/com/android/launcher2/Utilities.java
+++ b/src/com/android/launcher2/Utilities.java
@@ -76,8 +76,32 @@
     }
 
     /**
-     * Returns a bitmap suitable for the all apps view.  The bitmap will be a power
-     * of two sized ARGB_8888 bitmap that can be used as a gl texture.
+     * Returns a bitmap suitable for the all apps view. Used to convert pre-ICS
+     * icon bitmaps that are stored in the database (which were 74x74 pixels at hdpi size)
+     * to the proper size (48dp)
+     */
+    static Bitmap createIconBitmap(Bitmap icon, Context context) {
+        int textureWidth = sIconTextureWidth;
+        int textureHeight = sIconTextureHeight;
+        int sourceWidth = icon.getWidth();
+        int sourceHeight = icon.getHeight();
+        if (sourceWidth > textureWidth && sourceHeight > textureHeight) {
+            // Icon is bigger than it should be; clip it (solves the GB->ICS migration case)
+            return Bitmap.createBitmap(icon,
+                    (sourceWidth - textureWidth) / 2,
+                    (sourceHeight - textureHeight) / 2,
+                    textureWidth, textureHeight);
+        } else if (sourceWidth == textureWidth && sourceHeight == textureHeight) {
+            // Icon is the right size, no need to change it
+            return icon;
+        } else {
+            // Icon is too small, render to a larger bitmap
+            return createIconBitmap(new BitmapDrawable(icon), context);
+        }
+    }
+
+    /**
+     * Returns a bitmap suitable for the all apps view.
      */
     static Bitmap createIconBitmap(Drawable icon, Context context) {
         synchronized (sCanvas) { // we share the statics :-(
@@ -103,7 +127,7 @@
             int sourceWidth = icon.getIntrinsicWidth();
             int sourceHeight = icon.getIntrinsicHeight();
 
-            if (sourceWidth > 0 && sourceWidth > 0) {
+            if (sourceWidth > 0 && sourceHeight > 0) {
                 // There are intrinsic sizes.
                 if (width < sourceWidth || height < sourceHeight) {
                     // It's too big, scale it down.
diff --git a/tests/stress/Android.mk b/tests/stress/Android.mk
index da22bb9..68289bd 100644
--- a/tests/stress/Android.mk
+++ b/tests/stress/Android.mk
@@ -28,6 +28,4 @@
 
 LOCAL_INSTRUMENTATION_FOR := Launcher2
 
-LOCAL_SDK_VERSION := current
-
 include $(BUILD_PACKAGE)
diff --git a/tests/stress/AndroidManifest.xml b/tests/stress/AndroidManifest.xml
index ce5dbe4..0df3a9d 100644
--- a/tests/stress/AndroidManifest.xml
+++ b/tests/stress/AndroidManifest.xml
@@ -17,8 +17,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.launcher.stress.launcherrotation">
 
-    <uses-sdk android:minSdkVersion="8" />
-
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java b/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java
index 3d787f2..d21fd53 100644
--- a/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java
+++ b/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java
@@ -22,7 +22,7 @@
 import android.content.pm.ActivityInfo;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.TimedTest;
+import android.test.RepetitiveTest;
 import android.util.Log;
 
 /**
@@ -31,6 +31,7 @@
 public class LauncherRotationStressTest extends ActivityInstrumentationTestCase2<Launcher> {
 
     private static final int NUM_ITERATIONS = 50;
+    private static final int WAIT_TIME_MS = 500;
     private static final String LOG_TAG = "LauncherRotationStressTest";
 
     public LauncherRotationStressTest() {
@@ -47,22 +48,16 @@
         super.tearDown();
     }
 
-    @TimedTest(includeDetailedStats=true)
+    @RepetitiveTest(numIterations=NUM_ITERATIONS)
     public void testLauncherRotationStress() throws Exception {
         Launcher launcher = getActivity();
-        for (int i = 0; i < NUM_ITERATIONS; i++) {
-            Log.i(LOG_TAG, "Starting LauncherRotationStressTest " + (i + 1) + " of " +
-                  NUM_ITERATIONS);
-            getInstrumentation().waitForIdleSync();
-            SystemClock.sleep(500);
-            launcher.setRequestedOrientation(
-                    ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-            getInstrumentation().waitForIdleSync();
-            SystemClock.sleep(500);
-            launcher.setRequestedOrientation(
-                    ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-            Log.i(LOG_TAG, "Finished LauncherRotationStressTest " + (i + 1) + " of " +
-                  NUM_ITERATIONS);
-        }
+        getInstrumentation().waitForIdleSync();
+        SystemClock.sleep(WAIT_TIME_MS);
+        launcher.setRequestedOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+        getInstrumentation().waitForIdleSync();
+        SystemClock.sleep(WAIT_TIME_MS);
+        launcher.setRequestedOrientation(
+                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
     }
 }