Merge "Removing logging (issue 6583911)" into jb-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 20c4a9d..dbeb7bc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -74,7 +74,7 @@
             android:stateNotNeeded="true"
             android:theme="@style/Theme"
             android:windowSoftInputMode="adjustPan"
-            android:screenOrientation="portrait">
+            android:screenOrientation="nosensor">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.HOME" />
diff --git a/res/layout-port/search_bar.xml b/res/layout-port/search_bar.xml
index 0ccbe02..85da2f1 100644
--- a/res/layout-port/search_bar.xml
+++ b/res/layout-port/search_bar.xml
@@ -32,6 +32,7 @@
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         android:layout_toLeftOf="@+id/voice_button_container"
+        android:paddingLeft="8dp"
         android:onClick="onClickSearchButton"
         android:focusable="true"
         android:clickable="true"
@@ -54,6 +55,7 @@
         android:layout_gravity="center_vertical"
         android:layout_alignParentRight="true"
         android:layout_alignParentTop="true"
+        android:paddingRight="8dp"
         android:gravity="right"
         android:onClick="onClickVoiceButton"
         android:focusable="true"
diff --git a/res/layout-sw600dp-port/all_apps_cling.xml b/res/layout-sw600dp-port/all_apps_cling.xml
index 8bf8d15..0498224 100644
--- a/res/layout-sw600dp-port/all_apps_cling.xml
+++ b/res/layout-sw600dp-port/all_apps_cling.xml
@@ -41,11 +41,10 @@
     <Button
         style="@style/ClingButton"
         android:id="@+id/cling_dismiss"
-        android:layout_width="118dp"
-        android:layout_height="54dp"
+        android:minWidth="168dp"
         android:textSize="24sp"
-        android:layout_marginBottom="27dp"
+        android:layout_marginTop="235dp"
         android:layout_marginRight="36dp"
-        android:layout_gravity="bottom|right"
+        android:layout_gravity="top|right"
         android:onClick="dismissAllAppsCling" />
 </com.android.launcher2.Cling>
diff --git a/res/layout-sw600dp-port/folder_cling.xml b/res/layout-sw600dp-port/folder_cling.xml
index d154a5b..e3a9caa 100644
--- a/res/layout-sw600dp-port/folder_cling.xml
+++ b/res/layout-sw600dp-port/folder_cling.xml
@@ -42,8 +42,7 @@
     <Button
         style="@style/ClingButton"
         android:id="@+id/cling_dismiss"
-        android:layout_width="118dp"
-        android:layout_height="54dp"
+        android:minWidth="168dp"
         android:textSize="24sp"
         android:layout_marginBottom="27dp"
         android:layout_marginRight="36dp"
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index eeeed61..e94d780 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -18,8 +18,6 @@
 <!-- QSB -->
     <dimen name="toolbar_button_vertical_padding">12dip</dimen>
     <dimen name="toolbar_button_horizontal_padding">4dip</dimen>
-    <dimen name="search_bar_padding_left">0dp</dimen>
-    <dimen name="search_bar_padding_right">0dp</dimen>
 
 <!-- Workspace -->
     <dimen name="hotseat_cell_width">64dp</dimen>
diff --git a/res/values-port/styles.xml b/res/values-port/styles.xml
index 386653e..ab6a1eb 100644
--- a/res/values-port/styles.xml
+++ b/res/values-port/styles.xml
@@ -18,12 +18,6 @@
 -->
 
 <resources>
-<!-- QSB -->
-    <style name="SearchButton.Voice">
-        <item name="android:paddingLeft">8dp</item>
-        <item name="android:paddingRight">8dp</item>
-    </style>
-
 <!-- AppsCustomize -->
     <style name="TabIndicator.AppsCustomize">
         <item name="android:maxWidth">130dp</item>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 19d2152..c2b88d5 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -75,13 +75,13 @@
     <string name="cab_widget_selection_text" msgid="962527270506951955">"Выбран 1 виджет"</string>
     <string name="cab_folder_selection_text" msgid="8916111874189565067">"Выбрана 1 папка"</string>
     <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"Выбран 1 ярлык"</string>
-    <string name="permlab_install_shortcut" msgid="1201690825493376489">"устанавливать ярлыки"</string>
+    <string name="permlab_install_shortcut" msgid="1201690825493376489">"Установка ярлыков"</string>
     <string name="permdesc_install_shortcut" msgid="8634424803272077038">"Приложение сможет самостоятельно добавлять ярлыки."</string>
     <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"удалять ярлыки"</string>
     <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"Приложение сможет самостоятельно удалять ярлыки."</string>
-    <string name="permlab_read_settings" msgid="3452408290738106747">"считывать настройки и ярлыки главного экрана"</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"Просмотр настроек и ярлыков главного экрана"</string>
     <string name="permdesc_read_settings" msgid="5788109303585403679">"Приложение получит доступ к данным о настройках и ярлыках на главном экране."</string>
-    <string name="permlab_write_settings" msgid="1360567537236705628">"изменять настройки и ярлыки главного экрана"</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"Изменение настроек и ярлыков главного экрана"</string>
     <string name="permdesc_write_settings" msgid="8530105489115785531">"Приложение сможет изменять настройки и ярлыки на главном экране."</string>
     <string name="gadget_error_text" msgid="8359351016167075858">"Не удалось загрузить виджет"</string>
     <string name="uninstall_system_app_text" msgid="6429814133777046491">"Это системное приложение, его нельзя удалить."</string>
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
index a463d73..02789de 100644
--- a/res/values-sw600dp/config.xml
+++ b/res/values-sw600dp/config.xml
@@ -13,4 +13,8 @@
     <integer name="folder_max_count_x">-1</integer>
     <integer name="folder_max_count_y">-1</integer>
     <integer name="folder_max_num_items">-1</integer>
+
+    <!-- Camera distance for the overscroll effect. We use a higher value here because the 
+         workspace screens run nearly flush to the edge of the screen-->
+    <integer name="config_cameraDistance">14000</integer>
 </resources>
diff --git a/res/values-sw720dp/config.xml b/res/values-sw720dp/config.xml
index 7a6f6d8..97a6e9f 100644
--- a/res/values-sw720dp/config.xml
+++ b/res/values-sw720dp/config.xml
@@ -12,4 +12,7 @@
     <bool name="config_useDropTargetDownTransition">true</bool>
     <!-- Whether or not to fade the side pages -->
     <bool name="config_workspaceFadeAdjacentScreens">true</bool>
+
+    <!-- Camera distance for the overscroll effect -->
+    <integer name="config_cameraDistance">6500</integer>
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index a8d80fe..423a3a9 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -67,6 +67,9 @@
     <integer name="config_dragFadeOutAlpha">80</integer>
     <integer name="config_dragFadeOutDuration">250</integer>
 
+    <!-- Camera distance for the overscroll effect -->
+    <integer name="config_cameraDistance">6500</integer>
+
     <!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y
          >= folder_max_num_items. When these are set to -1, they are automatically determined. -->
     <integer name="folder_max_count_x">4</integer>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7cc8960..274c72f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -30,8 +30,6 @@
     <dimen name="qsb_bar_height">40dp</dimen>
     <dimen name="qsb_padding_left">0dp</dimen>
     <dimen name="qsb_padding_right">0dp</dimen>
-    <dimen name="search_bar_padding_left">8dp</dimen>
-    <dimen name="search_bar_padding_right">8dp</dimen>
     <dimen name="search_bar_height">40dp</dimen>
     <dimen name="workspace_max_gap">16dp</dimen>
     <dimen name="folder_cell_width">74dp</dimen>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 08c98c9..ee91d73 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -123,8 +123,6 @@
         <item name="android:orientation">horizontal</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">match_parent</item>
-        <item name="android:paddingLeft">@dimen/search_bar_padding_left</item>
-        <item name="android:paddingRight">@dimen/search_bar_padding_right</item>
     </style>
     <style name="SearchButton">
         <item name="android:layout_gravity">center_vertical</item>
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 5c0f6b6..5f81d9c 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -310,6 +310,8 @@
     private boolean mInTransition;
     private ArrayList<AsyncTaskPageData> mDeferredSyncWidgetPageItems =
         new ArrayList<AsyncTaskPageData>();
+    private ArrayList<Runnable> mDeferredPrepareLoadWidgetPreviewsTasks =
+        new ArrayList<Runnable>();
 
     // Used for drawing shortcut previews
     BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
@@ -547,13 +549,14 @@
         // TODO: this isn't ideal, but we actually need to delay here. This call is triggered
         // by a broadcast receiver, and in order for it to work correctly, we need to know that
         // the AppWidgetService has already received and processed the same broadcast. Since there
-        // is no guarantee about ordering of broadcast receipt, we just delay here. Ideally,
-        // we should have a more precise way of ensuring the AppWidgetService is up to date.
+        // is no guarantee about ordering of broadcast receipt, we just delay here. This is a
+        // workaround until we add a callback from AppWidgetService to AppWidgetHost when widget
+        // packages are added, updated or removed.
         postDelayed(new Runnable() {
            public void run() {
                updatePackages();
            }
-        }, 500);
+        }, 1500);
     }
 
     public void updatePackages() {
@@ -574,6 +577,9 @@
                 if (minSpanX <= LauncherModel.getCellCountX() &&
                         minSpanY <= LauncherModel.getCellCountY()) {
                     mWidgets.add(widget);
+                } else {
+                    Log.e(TAG, "Widget " + widget.provider + " can not fit on this device (" +
+                            widget.minWidth + ", " + widget.minHeight + ")");
                 }
             } else {
                 Log.e(TAG, "Widget " + widget.provider + " has invalid dimensions (" +
@@ -911,12 +917,16 @@
 
     @Override
     public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
-        Log.d(TAG, "6549598 onLauncherTransitionEnd");
+        Log.d(TAG, "6549598 onLauncherTransitionEnd mDeferredSyncWidgetPageItems.size(): " + mDeferredSyncWidgetPageItems.size());
         mInTransition = false;
         for (AsyncTaskPageData d : mDeferredSyncWidgetPageItems) {
             onSyncWidgetPageItems(d);
         }
         mDeferredSyncWidgetPageItems.clear();
+        for (Runnable r : mDeferredPrepareLoadWidgetPreviewsTasks) {
+            r.run();
+        }
+        mDeferredPrepareLoadWidgetPreviewsTasks.clear();
         mForceDrawAllChildrenNextFrame = !toWorkspace;
     }
 
@@ -1000,6 +1010,7 @@
             }
         }
         mDeferredSyncWidgetPageItems.clear();
+        mDeferredPrepareLoadWidgetPreviewsTasks.clear();
     }
 
     public void setContentType(ContentType type) {
@@ -1074,7 +1085,7 @@
     }
 
     public void syncAppsPageItems(int page, boolean immediate) {
-        Log.d(TAG, "6549598 syncAppsPageItems page: " + page);
+        Log.d(TAG, "6549598 syncAppsPageItems page: " + page + " mNumAppsPages: " + mNumAppsPages);
         // ensure that we have the right number of items on the pages
         int numCells = mCellCountX * mCellCountY;
         int startIndex = page * numCells;
@@ -1488,8 +1499,12 @@
                     loadWidgetPreviewsInBackground(null, data);
                     onSyncWidgetPageItems(data);
                 } else {
-                    prepareLoadWidgetPreviewsTask(page, items,
-                            maxPreviewWidth, maxPreviewHeight, mWidgetCountX);
+                    if (mInTransition) {
+                        mDeferredPrepareLoadWidgetPreviewsTasks.add(this);
+                    } else {
+                        prepareLoadWidgetPreviewsTask(page, items,
+                                maxPreviewWidth, maxPreviewHeight, mWidgetCountX);
+                    }
                 }
             }
         });
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index d3afc3b..6bd97a2 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -392,6 +393,7 @@
 
             // Make sure the current page is loaded (we start loading the side pages after the
             // transition to prevent slowing down the animation)
+            Log.d(LOG_TAG, "6549598 onLauncherTransitionPrepare currentPage: " + mAppsCustomizePane.getCurrentPage());
             mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage(), true);
 
             if (!LauncherApplication.isScreenLarge()) {
@@ -434,6 +436,7 @@
             mAppsCustomizePane.showAllAppsCling();
             // Make sure adjacent pages are loaded (we wait until after the transition to
             // prevent slowing down the animation)
+            Log.d(LOG_TAG, "6549598 onLauncherTransitionEnd currentPage: " + mAppsCustomizePane.getCurrentPage());
             mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
 
             if (!LauncherApplication.isScreenLarge()) {
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index db65a31..1163f9e 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -100,6 +100,8 @@
     private boolean mSuppressFolderDeletion = false;
     private boolean mItemAddedBackToSelfViaIcon = false;
     FolderEditText mFolderName;
+    private float mFolderIconPivotX;
+    private float mFolderIconPivotY;
 
     private boolean mIsEditingName = false;
     private InputMethodManager mInputMethodManager;
@@ -839,20 +841,24 @@
         int folderPivotY = height / 2 + (centeredTop - top);
         setPivotX(folderPivotX);
         setPivotY(folderPivotY);
-        int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
+        mFolderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
                 (1.0f * folderPivotX / width));
-        int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
+        mFolderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
                 (1.0f * folderPivotY / height));
 
-        mFolderIcon.setPivotX(folderIconPivotX);
-        mFolderIcon.setPivotY(folderIconPivotY);
-
         lp.width = width;
         lp.height = height;
         lp.x = left;
         lp.y = top;
     }
 
+    float getPivotXForIconAnimation() {
+        return mFolderIconPivotX;
+    }
+    float getPivotYForIconAnimation() {
+        return mFolderIconPivotY;
+    }
+
     private void setupContentForNumItems(int count) {
         setupContentDimensions(count);
 
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index d643084..4919b57 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -321,12 +321,7 @@
         // This will animate the first item from it's position as an icon into its
         // position as the first item in the preview
         animateFirstItem(animateDrawable, INITIAL_ITEM_ANIMATION_DURATION);
-
-        postDelayed(new Runnable() {
-            public void run() {
-                addItem(destInfo);
-            }
-        }, INITIAL_ITEM_ANIMATION_DURATION);
+        addItem(destInfo);
     }
 
     public void onDragExit(Object dragInfo) {
diff --git a/src/com/android/launcher2/HolographicLinearLayout.java b/src/com/android/launcher2/HolographicLinearLayout.java
index a40c727..0f997d5 100644
--- a/src/com/android/launcher2/HolographicLinearLayout.java
+++ b/src/com/android/launcher2/HolographicLinearLayout.java
@@ -68,6 +68,7 @@
 
     void invalidatePressedFocusedStates() {
         mHolographicHelper.invalidatePressedFocusedStates(mImageView);
+        invalidate();
     }
 
     @Override
diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java
index e05127b..b454afd 100644
--- a/src/com/android/launcher2/InstallShortcutReceiver.java
+++ b/src/com/android/launcher2/InstallShortcutReceiver.java
@@ -185,7 +185,9 @@
                     if (newAppsScreen == screen) {
                         newApps = sharedPrefs.getStringSet(NEW_APPS_LIST_KEY, newApps);
                     }
-                    newApps.add(intent.toUri(0).toString());
+                    synchronized (newApps) {
+                        newApps.add(intent.toUri(0).toString());
+                    }
                     final Set<String> savedNewApps = newApps;
                     new Thread("setNewAppsThread") {
                         public void run() {
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 3354d49..28dfd65 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -48,6 +48,9 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -278,6 +281,10 @@
     // when we scroll to that page on resume.
     private int mNewShortcutAnimatePage = -1;
     private ArrayList<View> mNewShortcutAnimateViews = new ArrayList<View>();
+    private ImageView mFolderIconImageView;
+    private Bitmap mFolderIconBitmap;
+    private Canvas mFolderIconCanvas;
+    private Rect mRectForFolderAnimation = new Rect();
 
     private BubbleTextView mWaitingForResume;
 
@@ -374,6 +381,13 @@
         IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         registerReceiver(mCloseSystemDialogsReceiver, filter);
 
+        updateGlobalIcons();
+
+        // On large interfaces, we want the screen to auto-rotate based on the current orientation
+        unlockScreenOrientation(true);
+    }
+
+    private void updateGlobalIcons() {
         boolean searchVisible = false;
         boolean voiceVisible = false;
         // If we have a saved version of these external icons, we load them up immediately
@@ -396,9 +410,6 @@
             updateAppMarketIcon(sAppMarketIcon[coi]);
         }
         mSearchDropTargetBar.onSearchPackagesChanged(searchVisible, voiceVisible);
-
-        // On large interfaces, we want the screen to auto-rotate based on the current orientation
-        unlockScreenOrientation(true);
     }
 
     private void checkForLocaleChange() {
@@ -686,27 +697,11 @@
         // Consequently, the widgets will be inflated in the orientation of the foreground activity
         // (framework issue). On resuming, we ensure that any widgets are inflated for the current
         // orientation.
-        reinflateWidgetsIfNecessary();
-    }
+        getWorkspace().reinflateWidgetsIfNecessary();
 
-    void reinflateWidgetsIfNecessary() {
-        for (LauncherAppWidgetInfo info: LauncherModel.getWidgets()) {
-            LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView;
-            if (lahv != null && lahv.orientationChangedSincedInflation()) {
-                AppWidgetProviderInfo pInfo = lahv.getAppWidgetInfo();
-
-                // Remove the current widget which is inflated with the wrong orientation
-                getWorkspace().getParentCellLayoutForView(lahv).removeView(lahv);
-                // Re-inflate the widget using the correct orientation
-                AppWidgetHostView widget = mAppWidgetHost.createView(this, info.appWidgetId, pInfo);
-
-                // Add the new widget back
-                widget.setTag(info);
-                info.hostView = widget;
-                getWorkspace().addInScreen(widget, info.container, info.screen,
-                        info.cellX, info.cellY, info.spanX, info.spanY);
-            }
-        }
+        // Again, as with the above scenario, it's possible that one or more of the global icons
+        // were updated in the wrong orientation.
+        updateGlobalIcons();
     }
 
     @Override
@@ -1238,17 +1233,6 @@
                         // some communication back with the app.
                         mWorkspace.postDelayed(mBuildLayersRunnable, 500);
 
-                        // We had to enable the wallpaper visibility when launching apps from all
-                        // apps (so that the transitions would be the same as when launching from
-                        // workspace) so take this time to see if we need to re-disable the
-                        // wallpaper visibility to ensure performance.
-                        mWorkspace.post(new Runnable() {
-                            @Override
-                            public void run() {
-                                disableWallpaperIfInAllApps();
-                            }
-                        });
-
                         observer.removeOnPreDrawListener(this);
                         return true;
                     }
@@ -1892,8 +1876,7 @@
                     (SearchManager) getSystemService(Context.SEARCH_SERVICE);
             ComponentName activityName = searchManager.getGlobalSearchActivity();
             Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             if (activityName != null) {
                 intent.setPackage(activityName.getPackageName());
             }
@@ -1901,8 +1884,7 @@
             overridePendingTransition(R.anim.fade_in_fast, R.anim.fade_out_fast);
         } catch (ActivityNotFoundException e) {
             Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             startActivitySafely(null, intent, "onClickVoiceButton");
         }
     }
@@ -2040,6 +2022,56 @@
         }
     }
 
+    /**
+     * 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.
+     */
+    private void copyFolderIconToImage(FolderIcon fi) {
+        final int width = fi.getMeasuredWidth();
+        final int height = fi.getMeasuredHeight();
+
+        // Lazy load ImageView, Bitmap and Canvas
+        if (mFolderIconImageView == null) {
+            mFolderIconImageView = new ImageView(this);
+        }
+        if (mFolderIconBitmap == null || mFolderIconBitmap.getWidth() != width ||
+                mFolderIconBitmap.getHeight() != height) {
+            mFolderIconBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+            mFolderIconCanvas = new Canvas(mFolderIconBitmap);
+        }
+
+        DragLayer.LayoutParams lp;
+        if (mFolderIconImageView.getLayoutParams() instanceof DragLayer.LayoutParams) {
+            lp = (DragLayer.LayoutParams) mFolderIconImageView.getLayoutParams();
+        } else {
+            lp = new DragLayer.LayoutParams(width, height);
+        }
+
+        mDragLayer.getViewRectRelativeToSelf(fi, mRectForFolderAnimation);
+        lp.customPosition = true;
+        lp.x = mRectForFolderAnimation.left;
+        lp.y = mRectForFolderAnimation.top;
+        lp.width = width;
+        lp.height = height;
+
+        mFolderIconCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
+        fi.draw(mFolderIconCanvas);
+        mFolderIconImageView.setImageBitmap(mFolderIconBitmap);
+        if (fi.mFolder != null) {
+            mFolderIconImageView.setPivotX(fi.mFolder.getPivotXForIconAnimation());
+            mFolderIconImageView.setPivotY(fi.mFolder.getPivotYForIconAnimation());
+        }
+        // Just in case this image view is still in the drag layer from a previous animation,
+        // we remove it and re-add it.
+        if (mDragLayer.indexOfChild(mFolderIconImageView) != -1) {
+            mDragLayer.removeView(mFolderIconImageView);
+        }
+        mDragLayer.addView(mFolderIconImageView, lp);
+        if (fi.mFolder != null) {
+            fi.mFolder.bringToFront();
+        }
+    }
+
     private void growAndFadeOutFolderIcon(FolderIcon fi) {
         if (fi == null) return;
         PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
@@ -2053,31 +2085,38 @@
             cl.setFolderLeaveBehindCell(lp.cellX, lp.cellY);
         }
 
-        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(fi, alpha, scaleX, scaleY);
+        // Push an ImageView copy of the FolderIcon into the DragLayer and hide the original
+        copyFolderIconToImage(fi);
+        fi.setVisibility(View.INVISIBLE);
+
+        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(mFolderIconImageView, alpha,
+                scaleX, scaleY);
         oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
         oa.start();
     }
 
-    private void shrinkAndFadeInFolderIcon(FolderIcon fi) {
+    private void shrinkAndFadeInFolderIcon(final FolderIcon fi) {
         if (fi == null) return;
         PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
         PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
         PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
 
-        FolderInfo info = (FolderInfo) fi.getTag();
-        CellLayout cl = null;
-        if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
-            cl = (CellLayout) fi.getParent().getParent();
-        }
+        final CellLayout cl = (CellLayout) fi.getParent().getParent();
 
-        final CellLayout layout = cl;
-        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(fi, alpha, scaleX, scaleY);
+        // We remove and re-draw the FolderIcon in-case it has changed
+        mDragLayer.removeView(mFolderIconImageView);
+        copyFolderIconToImage(fi);
+        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(mFolderIconImageView, alpha,
+                scaleX, scaleY);
         oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                if (layout != null) {
-                    layout.clearFolderLeaveBehind();
+                if (cl != null) {
+                    cl.clearFolderLeaveBehind();
+                    // Remove the ImageView copy of the FolderIcon and make the original visible.
+                    mDragLayer.removeView(mFolderIconImageView);
+                    fi.setVisibility(View.VISIBLE);
                 }
             }
         });
@@ -2095,7 +2134,6 @@
         Folder folder = folderIcon.mFolder;
         FolderInfo info = folder.mInfo;
 
-        growAndFadeOutFolderIcon(folderIcon);
         info.opened = true;
 
         // Just verify that the folder hasn't already been added to the DragLayer.
@@ -2108,6 +2146,7 @@
                     folder.getParent() + ").");
         }
         folder.animateOpen();
+        growAndFadeOutFolderIcon(folderIcon);
     }
 
     public void closeFolder() {
@@ -2616,7 +2655,12 @@
             updateWallpaperVisibility(true);
         } else {
             // When launcher has focus again, disable the wallpaper if we are in AllApps
-            disableWallpaperIfInAllApps();
+            mWorkspace.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    disableWallpaperIfInAllApps();
+                }
+            }, 500);
         }
     }
 
@@ -3157,9 +3201,13 @@
                     View shortcut = createShortcut(info);
                     workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
                             item.cellY, 1, 1, false);
-                    if (newApps.contains(uri)) {
-                        newApps.remove(uri);
-
+                    boolean animateIconUp = false;
+                    synchronized (newApps) {
+                        if (newApps.contains(uri)) {
+                            animateIconUp = newApps.remove(uri);
+                        }
+                    }
+                    if (animateIconUp) {
                         // Prepare the view to be animated up
                         shortcut.setAlpha(0f);
                         shortcut.setScaleX(0f);
@@ -3214,7 +3262,6 @@
 
         item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
 
-        item.hostView.setAppWidget(appWidgetId, appWidgetInfo);
         item.hostView.setTag(item);
         item.onBindAppWidget(this);
 
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 1b17ef9..fc1a26d 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -377,10 +377,6 @@
         return items;
     }
 
-    static ArrayList<LauncherAppWidgetInfo> getWidgets() {
-        return sAppWidgets;
-    }
-
     /**
      * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.
      */
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index c820264..19f6a62 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -234,6 +234,7 @@
         mDirtyPageContent.ensureCapacity(32);
         mScroller = new Scroller(getContext(), new ScrollInterpolator());
         mCurrentPage = 0;
+        if (this instanceof AppsCustomizePagedView) Log.d(TAG, "6549598 init() mCurrentPage: " + mCurrentPage);
         mCenterPagesVertically = true;
 
         final ViewConfiguration configuration = ViewConfiguration.get(getContext());
@@ -317,7 +318,9 @@
             return;
         }
 
+
         mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
+        if (this instanceof AppsCustomizePagedView) Log.d(TAG, "6549598 setCurrentPage mCurrentPage: " + mCurrentPage);
         updateCurrentPageScroll();
         updateScrollingIndicator();
         notifyPageSwitchListener();
diff --git a/src/com/android/launcher2/UninstallShortcutReceiver.java b/src/com/android/launcher2/UninstallShortcutReceiver.java
index 84b1ad5..e94a17f 100644
--- a/src/com/android/launcher2/UninstallShortcutReceiver.java
+++ b/src/com/android/launcher2/UninstallShortcutReceiver.java
@@ -139,9 +139,11 @@
             boolean appRemoved;
             Set<String> newApps = new HashSet<String>();
             newApps = sharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
-            do {
-                appRemoved = newApps.remove(intent.toUri(0).toString());
-            } while (appRemoved);
+            synchronized (newApps) {
+                do {
+                    appRemoved = newApps.remove(intent.toUri(0).toString());
+                } while (appRemoved);
+            }
             if (appRemoved) {
                 final Set<String> savedNewApps = newApps;
                 new Thread("setNewAppsThread-remove") {
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index ba51889..0192630 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -77,7 +77,6 @@
 
     // Y rotation to apply to the workspace screens
     private static final float WORKSPACE_OVERSCROLL_ROTATION = 24f;
-    private static float CAMERA_DISTANCE = 6500;
 
     private static final int CHILDREN_OUTLINE_FADE_OUT_DELAY = 0;
     private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
@@ -196,6 +195,7 @@
     private boolean mIsStaticWallpaper;
     private int mWallpaperTravelWidth;
     private int mSpringLoadedPageSpacing;
+    private int mCameraDistance;
 
     // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
     private static final int FOLDER_CREATION_TIMEOUT = 0;
@@ -321,6 +321,7 @@
             res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
         mSpringLoadedPageSpacing =
                 res.getDimensionPixelSize(R.dimen.workspace_spring_loaded_page_spacing);
+        mCameraDistance = res.getInteger(R.integer.config_cameraDistance);
 
         // if the value is manually specified, use that instead
         cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);
@@ -670,6 +671,29 @@
         return super.onInterceptTouchEvent(ev);
     }
 
+    protected void reinflateWidgetsIfNecessary() {
+        final int clCount = getChildCount();
+        for (int i = 0; i < clCount; i++) {
+            CellLayout cl = (CellLayout) getChildAt(i);
+            ShortcutAndWidgetContainer swc = cl.getShortcutsAndWidgets();
+            final int itemCount = swc.getChildCount();
+            for (int j = 0; j < itemCount; j++) {
+                View v = swc.getChildAt(j);
+
+                if (v.getTag() instanceof LauncherAppWidgetInfo) {
+                    LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
+                    LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView;
+                    if (lahv != null && lahv.orientationChangedSincedInflation()) {
+                        mLauncher.removeAppWidget(info);
+                        // Remove the current widget which is inflated with the wrong orientation
+                        cl.removeView(lahv);
+                        mLauncher.bindAppWidget(info);
+                    }
+                }
+            }
+        }
+    }
+
     @Override
     protected void determineScrollingStart(MotionEvent ev) {
         if (isSmall()) return;
@@ -1250,7 +1274,7 @@
             setFadeForOverScroll(Math.abs(scrollProgress));
             if (!mOverscrollTransformsSet) {
                 mOverscrollTransformsSet = true;
-                cl.setCameraDistance(mDensity * CAMERA_DISTANCE);
+                cl.setCameraDistance(mDensity * mCameraDistance);
                 cl.setPivotX(cl.getMeasuredWidth() * (index == 0 ? 0.75f : 0.25f));
                 cl.setPivotY(cl.getMeasuredHeight() * 0.5f);
                 cl.setOverscrollTransformsDirty(true);
@@ -3659,14 +3683,16 @@
                     }
                     // Remove all queued items that match the same package
                     if (newApps != null) {
-                        for (String intentStr : newApps) {
-                            try {
-                                Intent intent = Intent.parseUri(intentStr, 0);
-                                String pn = ItemInfo.getPackageName(intent);
-                                if (packageNames.contains(pn)) {
-                                    newApps.remove(intentStr);
-                                }
-                            } catch (URISyntaxException e) {}
+                        synchronized (newApps) {
+                            for (String intentStr : newApps) {
+                                try {
+                                    Intent intent = Intent.parseUri(intentStr, 0);
+                                    String pn = ItemInfo.getPackageName(intent);
+                                    if (packageNames.contains(pn)) {
+                                        newApps.remove(intentStr);
+                                    }
+                                } catch (URISyntaxException e) {}
+                            }
                         }
                     }
                 }