Merge "Disabling the desaturation of fast scroll items." into ub-launcher3-burnaby-polish
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index b717b59..9af5f16 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -123,6 +123,7 @@
                 new View.OnClickListener() {
                     @Override
                     public void onClick(View v) {
+                        actionBar.hide();
                         boolean finishActivityWhenDone = true;
                         // Never fade on finish because we return to the app that started us (e.g.
                         // Photos), not the home screen.
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 0d3439d..2b05477 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -46,7 +46,7 @@
     <string name="permdesc_read_settings" msgid="5833423719057558387">"Permet à l\'application de lire les paramètres et les raccourcis de l\'écran d\'accueil."</string>
     <string name="permlab_write_settings" msgid="3574213698004620587">"enregistrer les paramètres de la page d\'accueil et des raccourcis"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"Permet à l\'application de modifier les paramètres et les raccourcis de l\'écran d\'accueil."</string>
-    <string name="msg_no_phone_permission" msgid="9208659281529857371">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas autorisée à faire des appels téléphoniques"</string>
+    <string name="msg_no_phone_permission" msgid="9208659281529857371">"L\'application <xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas autorisée à faire des appels téléphoniques"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"Problème lors du chargement du widget"</string>
     <string name="gadget_setup_text" msgid="8274003207686040488">"Configuration"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"Impossible de désinstaller cette application, car il s\'agit d\'une application système."</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 0b47a61..b42e021 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -46,7 +46,7 @@
     <string name="permdesc_read_settings" msgid="5833423719057558387">"允许应用读取主屏幕中的设置和快捷方式。"</string>
     <string name="permlab_write_settings" msgid="3574213698004620587">"写入主屏幕设置和快捷方式"</string>
     <string name="permdesc_write_settings" msgid="5440712911516509985">"允许应用更改主屏幕中的设置和快捷方式。"</string>
-    <string name="msg_no_phone_permission" msgid="9208659281529857371">"不允许使用<xliff:g id="APP_NAME">%1$s</xliff:g>拨打电话"</string>
+    <string name="msg_no_phone_permission" msgid="9208659281529857371">"不允许使用“<xliff:g id="APP_NAME">%1$s</xliff:g>”拨打电话"</string>
     <string name="gadget_error_text" msgid="6081085226050792095">"加载小部件时出现问题"</string>
     <string name="gadget_setup_text" msgid="8274003207686040488">"设置"</string>
     <string name="uninstall_system_app_text" msgid="4172046090762920660">"这是系统应用,无法卸载。"</string>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 70bf859..c8f5a45 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -252,6 +252,9 @@
             FastBitmapDrawable d = (FastBitmapDrawable) mIcon;
             if (isPressed() || mStayPressed) {
                 d.animateState(FastBitmapDrawable.State.PRESSED);
+            } else if (getTag() instanceof ShortcutInfo
+                    && ((ShortcutInfo) getTag()).isDisabled != 0) {
+                d.animateState(FastBitmapDrawable.State.DISABLED);
             } else {
                 d.animateState(FastBitmapDrawable.State.NORMAL);
             }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 5778763..ed6b7d7 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -104,7 +104,6 @@
     private int searchBarSpaceWidthPx;
     private int searchBarSpaceHeightNormalPx, searchBarSpaceHeightTallPx;
     private int searchBarSpaceHeightPx; // One of the above.
-    private int searchBarHeight = LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL;
 
     public DeviceProfile(Context context, InvariantDeviceProfile inv,
             Point minSize, Point maxSize,
@@ -396,6 +395,17 @@
         return visibleChildren;
     }
 
+    // TODO(twickham): b/25154513
+    public void setSearchBarHeight(int searchBarHeight) {
+        if (searchBarHeight == LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL) {
+            hotseatBarHeightPx = hotseatBarHeightShortPx;
+            searchBarSpaceHeightPx = searchBarSpaceHeightTallPx;
+        } else {
+            hotseatBarHeightPx = hotseatBarHeightNormalPx;
+            searchBarSpaceHeightPx = searchBarSpaceHeightNormalPx;
+        }
+    }
+
     public void layout(Launcher launcher) {
         FrameLayout.LayoutParams lp;
         boolean hasVerticalBarLayout = isVerticalBarLayout();
@@ -404,14 +414,6 @@
         // Layout the search bar space
         View searchBar = launcher.getSearchDropTargetBar();
         lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
-        searchBarHeight = launcher.getSearchBarHeight();
-        if (searchBarHeight == LauncherCallbacks.SEARCH_BAR_HEIGHT_TALL) {
-            hotseatBarHeightPx = hotseatBarHeightShortPx;
-            searchBarSpaceHeightPx = searchBarSpaceHeightTallPx;
-        } else {
-            hotseatBarHeightPx = hotseatBarHeightNormalPx;
-            searchBarSpaceHeightPx = searchBarSpaceHeightNormalPx;
-        }
         if (hasVerticalBarLayout) {
             // Vertical search bar space -- The search bar is fixed in the layout to be on the left
             //                              of the screen regardless of RTL
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index fb9d95a..9377bad 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -414,7 +414,7 @@
     /**
      * Creates a new UserFolder, inflated from R.layout.user_folder.
      *
-     * @param context The application's context.
+     * @param launcher The main activity.
      *
      * @return A new UserFolder.
      */
@@ -639,9 +639,8 @@
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                onCloseComplete();
                 setLayerType(LAYER_TYPE_NONE, null);
-                mState = STATE_SMALL;
+                close();
             }
             @Override
             public void onAnimationStart(Animator animation) {
@@ -655,6 +654,32 @@
         oa.start();
     }
 
+    public void close() {
+        // TODO: Clear all active animations.
+        DragLayer parent = (DragLayer) getParent();
+        if (parent != null) {
+            parent.removeView(this);
+        }
+        mDragController.removeDropTarget(this);
+        clearFocus();
+        mFolderIcon.requestFocus();
+
+        if (mRearrangeOnClose) {
+            rearrangeChildren();
+            mRearrangeOnClose = false;
+        }
+        if (getItemCount() <= 1) {
+            if (!mDragInProgress && !mSuppressFolderDeletion) {
+                replaceFolderWithFinalItem();
+            } else if (mDragInProgress) {
+                mDeleteFolderOnDropCompleted = true;
+            }
+        }
+        mSuppressFolderDeletion = false;
+        clearDragInfo();
+        mState = STATE_SMALL;
+    }
+
     public boolean acceptDrop(DragObject d) {
         final ItemInfo item = (ItemInfo) d.dragInfo;
         final int itemType = item.itemType;
@@ -1087,30 +1112,6 @@
         return mContent.getItemCount();
     }
 
-    @Thunk void onCloseComplete() {
-        DragLayer parent = (DragLayer) getParent();
-        if (parent != null) {
-            parent.removeView(this);
-        }
-        mDragController.removeDropTarget((DropTarget) this);
-        clearFocus();
-        mFolderIcon.requestFocus();
-
-        if (mRearrangeOnClose) {
-            rearrangeChildren();
-            mRearrangeOnClose = false;
-        }
-        if (getItemCount() <= 1) {
-            if (!mDragInProgress && !mSuppressFolderDeletion) {
-                replaceFolderWithFinalItem();
-            } else if (mDragInProgress) {
-                mDeleteFolderOnDropCompleted = true;
-            }
-        }
-        mSuppressFolderDeletion = false;
-        clearDragInfo();
-    }
-
     @Thunk void replaceFolderWithFinalItem() {
         // Add the last remaining child to the workspace in place of the folder
         Runnable onCompleteRunnable = new Runnable() {
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 3fc8fc0..9a75193 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -92,8 +92,7 @@
         if (packageNames.isEmpty()) {
             return;
         }
-        String spKey = LauncherAppState.getSharedPreferencesKey();
-        SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+        SharedPreferences sp = Utilities.getPrefs(context);
         synchronized(sLock) {
             Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
             if (DBG) {
@@ -176,9 +175,7 @@
         LauncherAppState app = LauncherAppState.getInstance();
         boolean launcherNotLoaded = app.getModel().getCallback() == null;
 
-        String spKey = LauncherAppState.getSharedPreferencesKey();
-        SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
-        addToInstallQueue(sp, info);
+        addToInstallQueue(Utilities.getPrefs(context), info);
         if (!mUseInstallQueue && !launcherNotLoaded) {
             flushInstallQueue(context);
         }
@@ -192,8 +189,7 @@
         flushInstallQueue(context);
     }
     static void flushInstallQueue(Context context) {
-        String spKey = LauncherAppState.getSharedPreferencesKey();
-        SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+        SharedPreferences sp = Utilities.getPrefs(context);
         ArrayList<PendingInstallShortcutInfo> installQueue = getAndClearInstallQueue(sp, context);
         if (!installQueue.isEmpty()) {
             Iterator<PendingInstallShortcutInfo> iter = installQueue.iterator();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6dc044d..d258141 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -426,8 +426,7 @@
                 app.getInvariantDeviceProfile().landscapeProfile
                 : app.getInvariantDeviceProfile().portraitProfile;
 
-        mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
-                Context.MODE_PRIVATE);
+        mSharedPrefs = Utilities.getPrefs(this);
         mIsSafeModeEnabled = getPackageManager().isSafeMode();
         mModel = app.setLauncher(this);
         mIconCache = app.getIconCache();
@@ -455,6 +454,8 @@
 
         setContentView(R.layout.launcher);
 
+        app.getInvariantDeviceProfile().landscapeProfile.setSearchBarHeight(getSearchBarHeight());
+        app.getInvariantDeviceProfile().portraitProfile.setSearchBarHeight(getSearchBarHeight());
         setupViews();
         mDeviceProfile.layout(this);
 
@@ -1907,7 +1908,7 @@
             // In all these cases, only animate if we're already on home
             mWorkspace.exitWidgetResizeMode();
 
-            closeFolder();
+            closeFolder(alreadyOnHome);
             exitSpringLoadedDragMode();
 
             // If we are already on home, then just animate back to the workspace,
@@ -1920,7 +1921,7 @@
 
             final View v = getWindow().peekDecorView();
             if (v != null && v.getWindowToken() != null) {
-                InputMethodManager imm = (InputMethodManager)getSystemService(
+                InputMethodManager imm = (InputMethodManager) getSystemService(
                         INPUT_METHOD_SERVICE);
                 imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
             }
@@ -1959,7 +1960,9 @@
                 mWorkspace.post(new Runnable() {
                     @Override
                     public void run() {
-                        mWorkspace.moveToDefaultScreen(true);
+                        if (mWorkspace != null) {
+                            mWorkspace.moveToDefaultScreen(true);
+                        }
                     }
                 });
             }
@@ -1989,7 +1992,7 @@
         outState.putInt(RUNTIME_STATE, mState.ordinal());
         // We close any open folder since it will not be re-opened, and we need to make sure
         // this state is reflected.
-        closeFolder();
+        closeFolder(false);
 
         if (mPendingAddInfo.container != ItemInfo.NO_ID && mPendingAddInfo.screenId > -1 &&
                 mWaitingForResult) {
@@ -2783,7 +2786,7 @@
             if (openFolder != null) {
                 folderScreen = mWorkspace.getPageForView(openFolder);
                 // .. and close it
-                closeFolder(openFolder);
+                closeFolder(openFolder, true);
                 if (folderScreen != mWorkspace.getCurrentPage()) {
                     // Close any folder open on the current screen
                     closeFolder();
@@ -3123,7 +3126,7 @@
         oa.start();
     }
 
-    private void shrinkAndFadeInFolderIcon(final FolderIcon fi) {
+    private void shrinkAndFadeInFolderIcon(final FolderIcon fi, boolean animate) {
         if (fi == null) return;
         PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
         PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
@@ -3149,6 +3152,9 @@
             }
         });
         oa.start();
+        if (!animate) {
+            oa.end();
+        }
     }
 
     /**
@@ -3192,30 +3198,38 @@
     }
 
     public void closeFolder() {
+        closeFolder(true);
+    }
+
+    public void closeFolder(boolean animate) {
         Folder folder = mWorkspace != null ? mWorkspace.getOpenFolder() : null;
         if (folder != null) {
             if (folder.isEditingName()) {
                 folder.dismissEditingName();
             }
-            closeFolder(folder);
+            closeFolder(folder, animate);
         }
     }
 
-    public void closeFolder(Folder folder) {
+    public void closeFolder(Folder folder, boolean animate) {
         folder.getInfo().opened = false;
 
         ViewGroup parent = (ViewGroup) folder.getParent().getParent();
         if (parent != null) {
             FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
-            shrinkAndFadeInFolderIcon(fi);
+            shrinkAndFadeInFolderIcon(fi, animate);
             if (fi != null) {
                 ((CellLayout.LayoutParams) fi.getLayoutParams()).canReorder = true;
             }
         }
-        folder.animateClosed();
+        if (animate) {
+            folder.animateClosed();
+        } else {
+            folder.close();
+        }
 
-        // Notify the accessibility manager that this folder "window" has disappeard and no
-        // longer occludeds the workspace items
+        // Notify the accessibility manager that this folder "window" has disappeared and no
+        // longer occludes the workspace items
         getDragLayer().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
     }
 
@@ -3631,17 +3645,19 @@
             opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, minHeight);
             opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, maxWidth);
             opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, minWidth);
+            if (LOGD) {
+                Log.d(TAG, "QSB widget options: maxHeight=" + maxHeight + " minHeight=" + minHeight
+                        + " maxWidth=" + maxWidth + " minWidth=" + minWidth);
+            }
 
             if (mLauncherCallbacks != null) {
                 opts.putAll(mLauncherCallbacks.getAdditionalSearchWidgetOptions());
             }
 
-            SharedPreferences sp = getSharedPreferences(
-                    LauncherAppState.getSharedPreferencesKey(), MODE_PRIVATE);
-            int widgetId = sp.getInt(QSB_WIDGET_ID, -1);
+            int widgetId = mSharedPrefs.getInt(QSB_WIDGET_ID, -1);
             AppWidgetProviderInfo widgetInfo = mAppWidgetManager.getAppWidgetInfo(widgetId);
             if (!searchProvider.provider.flattenToString().equals(
-                    sp.getString(QSB_WIDGET_PROVIDER, null))
+                    mSharedPrefs.getString(QSB_WIDGET_PROVIDER, null))
                     || (widgetInfo == null)
                     || !widgetInfo.provider.equals(searchProvider.provider)) {
                 // A valid widget is not already bound.
@@ -3659,7 +3675,7 @@
                     widgetId = -1;
                 }
 
-                sp.edit()
+                mSharedPrefs.edit()
                     .putInt(QSB_WIDGET_ID, widgetId)
                     .putString(QSB_WIDGET_PROVIDER, searchProvider.provider.flattenToString())
                     .commit();
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index f75b33c..34b8382 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -153,14 +153,10 @@
         return sLauncherProvider.get();
     }
 
-    public static String getSharedPreferencesKey() {
-        return LauncherFiles.SHARED_PREFERENCES_KEY;
-    }
-
     public WidgetPreviewLoader getWidgetCache() {
         return mWidgetCache;
     }
-    
+
     public void onWallpaperChanged() {
         mWallpaperChangedSinceLastCheck = true;
     }
diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java
index 18fe8ef..8f719e5 100644
--- a/src/com/android/launcher3/LauncherClings.java
+++ b/src/com/android/launcher3/LauncherClings.java
@@ -73,9 +73,7 @@
                     LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
                             | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
             // Set the flag to skip the folder cling
-            String spKey = LauncherAppState.getSharedPreferencesKey();
-            SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
-            SharedPreferences.Editor editor = sp.edit();
+            SharedPreferences.Editor editor = Utilities.getPrefs(mLauncher).edit();
             editor.putBoolean(Launcher.USER_HAS_MIGRATED, true);
             editor.apply();
             // Disable the migration cling
@@ -254,9 +252,7 @@
     }
 
     public static void synchonouslyMarkFirstRunClingDismissed(Context ctx) {
-        SharedPreferences prefs = ctx.getSharedPreferences(
-                LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
-        SharedPreferences.Editor editor = prefs.edit();
+        SharedPreferences.Editor editor = Utilities.getPrefs(ctx).edit();
         editor.putBoolean(WORKSPACE_CLING_DISMISSED_KEY, true);
         editor.commit();
     }
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index a6fd282..ef79cf8 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -257,17 +257,13 @@
             case LauncherSettings.Settings.METHOD_GET_BOOLEAN: {
                 Bundle result = new Bundle();
                 result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
-                        getContext().getSharedPreferences(
-                                LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE)
-                                .getBoolean(arg, extras.getBoolean(
-                                        LauncherSettings.Settings.EXTRA_DEFAULT_VALUE)));
+                        Utilities.getPrefs(getContext()).getBoolean(arg, extras.getBoolean(
+                                LauncherSettings.Settings.EXTRA_DEFAULT_VALUE)));
                 return result;
             }
             case LauncherSettings.Settings.METHOD_SET_BOOLEAN: {
                 boolean value = extras.getBoolean(LauncherSettings.Settings.EXTRA_VALUE);
-                getContext().getSharedPreferences(
-                        LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE)
-                        .edit().putBoolean(arg, value).apply();
+                Utilities.getPrefs(getContext()).edit().putBoolean(arg, value).apply();
                 if (mListener != null) {
                     mListener.onSettingsChanged(arg, value);
                 }
@@ -343,11 +339,7 @@
     }
 
     public void clearFlagEmptyDbCreated() {
-        String spKey = LauncherAppState.getSharedPreferencesKey();
-        getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE)
-            .edit()
-            .remove(EMPTY_DATABASE_CREATED)
-            .commit();
+        Utilities.getPrefs(getContext()).edit().remove(EMPTY_DATABASE_CREATED).commit();
     }
 
     /**
@@ -358,8 +350,7 @@
      *   4) The default configuration for the particular device
      */
     synchronized public void loadDefaultFavoritesIfNecessary() {
-        String spKey = LauncherAppState.getSharedPreferencesKey();
-        SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
+        SharedPreferences sp = Utilities.getPrefs(getContext());
 
         if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
             Log.d(TAG, "loading default workspace");
@@ -635,15 +626,11 @@
         }
 
         private void setFlagJustLoadedOldDb() {
-            String spKey = LauncherAppState.getSharedPreferencesKey();
-            SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
-            sp.edit().putBoolean(EMPTY_DATABASE_CREATED, false).commit();
+            Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, false).commit();
         }
 
         private void setFlagEmptyDbCreated() {
-            String spKey = LauncherAppState.getSharedPreferencesKey();
-            SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
-            sp.edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
+            Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
         }
 
         @Override
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 2ed9a25..d14d056 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -137,7 +137,7 @@
 
     public static boolean isAllowRotationPrefEnabled(Context context, boolean multiProcess) {
         SharedPreferences sharedPrefs = context.getSharedPreferences(
-                LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE | (multiProcess ?
+                LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE | (multiProcess ?
                         Context.MODE_MULTI_PROCESS : 0));
         boolean allowRotationPref = sharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, false);
         return sForceEnableRotation || allowRotationPref;
@@ -754,4 +754,9 @@
     public static int longCompare(long lhs, long rhs) {
         return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
     }
+
+    public static SharedPreferences getPrefs(Context context) {
+        return context.getSharedPreferences(
+                LauncherFiles.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE);
+    }
 }
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 603b072..10c1053 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -428,8 +428,9 @@
             float iconScale = Math.min((float) smallestSide / (appIconSize + 2 * minOffset), scale);
 
             try {
-                Drawable icon = mutateOnMainThread(mManager.loadIcon(info, mIconCache));
+                Drawable icon = mManager.loadIcon(info, mIconCache);
                 if (icon != null) {
+                    icon = mutateOnMainThread(icon);
                     int hoffset = (int) ((tileW - appIconSize * iconScale) / 2) + x;
                     int yoffset = (int) ((tileH - appIconSize * iconScale) / 2);
                     icon.setBounds(hoffset, yoffset,
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 2233ebb..2306b77 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -172,7 +172,7 @@
             return true;
         } else if (action == MOVE_TO_WORKSPACE) {
             Folder folder = mLauncher.getWorkspace().getOpenFolder();
-            mLauncher.closeFolder(folder);
+            mLauncher.closeFolder(folder, true);
             ShortcutInfo info = (ShortcutInfo) item;
             folder.getInfo().remove(info);
 
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index dc3ec3c..98d5eca 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -25,7 +25,6 @@
 import android.os.Build;
 import android.os.UserHandle;
 
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.util.LongArrayMap;
 
@@ -104,8 +103,7 @@
         if (Utilities.ATLEAST_MARSHMALLOW) {
             return mUserManager.getUserCreationTime(user.getUser());
         }
-        SharedPreferences prefs = mContext.getSharedPreferences(
-                LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
+        SharedPreferences prefs = Utilities.getPrefs(mContext);
         String key = USER_CREATION_TIME_KEY + getSerialNumberForUser(user);
         if (!prefs.contains(key)) {
             prefs.edit().putLong(key, System.currentTimeMillis()).apply();
diff --git a/src/com/android/launcher3/model/MigrateFromRestoreTask.java b/src/com/android/launcher3/model/MigrateFromRestoreTask.java
index ba33b02..786ab60 100644
--- a/src/com/android/launcher3/model/MigrateFromRestoreTask.java
+++ b/src/com/android/launcher3/model/MigrateFromRestoreTask.java
@@ -71,7 +71,7 @@
     public MigrateFromRestoreTask(Context context) {
         mContext = context;
 
-        SharedPreferences prefs = prefs(context);
+        SharedPreferences prefs = Utilities.getPrefs(context);
         Point sourceSize = parsePoint(prefs.getString(KEY_MIGRATION_SOURCE_SIZE, ""));
         mSrcX = sourceSize.x;
         mSrcY = sourceSize.y;
@@ -745,23 +745,19 @@
 
     public static void markForMigration(Context context, int srcX, int srcY,
             HashSet<String> widgets) {
-        prefs(context).edit()
+        Utilities.getPrefs(context).edit()
                 .putString(KEY_MIGRATION_SOURCE_SIZE, srcX + "," + srcY)
                 .putStringSet(KEY_MIGRATION_WIDGET_MINSIZE, widgets)
                 .apply();
     }
 
     public static boolean shouldRunTask(Context context) {
-        return !TextUtils.isEmpty(prefs(context).getString(KEY_MIGRATION_SOURCE_SIZE, ""));
+        return !TextUtils.isEmpty(Utilities.getPrefs(context).getString(KEY_MIGRATION_SOURCE_SIZE, ""));
     }
 
     public static void clearFlags(Context context) {
-        prefs(context).edit().remove(KEY_MIGRATION_SOURCE_SIZE)
+        Utilities.getPrefs(context).edit().remove(KEY_MIGRATION_SOURCE_SIZE)
                 .remove(KEY_MIGRATION_WIDGET_MINSIZE).commit();
     }
 
-    private static SharedPreferences prefs(Context context) {
-        return context.getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
-                Context.MODE_PRIVATE);
-    }
 }
diff --git a/src/com/android/launcher3/testing/ToggleWeightWatcher.java b/src/com/android/launcher3/testing/ToggleWeightWatcher.java
index 15e55ee..e08ec3a 100644
--- a/src/com/android/launcher3/testing/ToggleWeightWatcher.java
+++ b/src/com/android/launcher3/testing/ToggleWeightWatcher.java
@@ -1,13 +1,13 @@
 package com.android.launcher3.testing;
 
 import android.app.Activity;
-import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.view.View;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.util.TestingUtils;
 
 public class ToggleWeightWatcher extends Activity {
@@ -16,8 +16,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        String spKey = LauncherAppState.getSharedPreferencesKey();
-        SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE);
+        SharedPreferences sp = Utilities.getPrefs(this);
         boolean show = sp.getBoolean(TestingUtils.SHOW_WEIGHT_WATCHER, true);
 
         show = !show;
diff --git a/src/com/android/launcher3/util/FocusLogic.java b/src/com/android/launcher3/util/FocusLogic.java
index 696eabe..7f0da77 100644
--- a/src/com/android/launcher3/util/FocusLogic.java
+++ b/src/com/android/launcher3/util/FocusLogic.java
@@ -22,9 +22,6 @@
 import android.view.ViewGroup;
 
 import com.android.launcher3.CellLayout;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.ShortcutAndWidgetContainer;
 
 import java.util.Arrays;
@@ -51,7 +48,7 @@
     private static final String TAG = "FocusLogic";
     private static final boolean DEBUG = false;
 
-    // Item and page index related constant used by {@link #handleKeyEvent}.
+    /** Item and page index related constant used by {@link #handleKeyEvent}. */
     public static final int NOOP = -1;
 
     public static final int PREVIOUS_PAGE_RIGHT_COLUMN  = -2;
@@ -94,7 +91,7 @@
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_LEFT:
                 newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, -1 /*increment*/);
-                if (isRtl && newIndex == NOOP && pageIndex > 0) {
+                if (!isRtl && newIndex == NOOP && pageIndex > 0) {
                     newIndex = PREVIOUS_PAGE_RIGHT_COLUMN;
                 } else if (isRtl && newIndex == NOOP && pageIndex < pageCount - 1) {
                     newIndex = NEXT_PAGE_RIGHT_COLUMN;
@@ -102,7 +99,7 @@
                 break;
             case KeyEvent.KEYCODE_DPAD_RIGHT:
                 newIndex = handleDpadHorizontal(iconIdx, cntX, cntY, map, 1 /*increment*/);
-                if (isRtl && newIndex == NOOP && pageIndex < pageCount - 1) {
+                if (!isRtl && newIndex == NOOP && pageIndex < pageCount - 1) {
                     newIndex = NEXT_PAGE_LEFT_COLUMN;
                 } else if (isRtl && newIndex == NOOP && pageIndex > 0) {
                     newIndex = PREVIOUS_PAGE_LEFT_COLUMN;
@@ -168,8 +165,12 @@
 
         // Iterate thru the children.
         for (int i = 0; i < parent.getChildCount(); i++ ) {
-            int cx = ((CellLayout.LayoutParams) parent.getChildAt(i).getLayoutParams()).cellX;
-            int cy = ((CellLayout.LayoutParams) parent.getChildAt(i).getLayoutParams()).cellY;
+            View cell = parent.getChildAt(i);
+            if (!cell.isFocusable()) {
+                continue;
+            }
+            int cx = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellX;
+            int cy = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellY;
             matrix[invert ? (m - cx - 1) : cx][cy] = i;
         }
         if (DEBUG) {
@@ -202,8 +203,12 @@
 
         // Iterate thru the children of the top parent.
         for (int i = 0; i < iconParent.getChildCount(); i++) {
-            int cx = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellX;
-            int cy = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellY;
+            View cell = iconParent.getChildAt(i);
+            if (!cell.isFocusable()) {
+                continue;
+            }
+            int cx = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellX;
+            int cy = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellY;
             matrix[cx][cy] = i;
         }
 
@@ -256,8 +261,12 @@
 
         // Iterate thru the children of the top parent.
         for (int i = 0; i < iconParent.getChildCount(); i++) {
-            int cx = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellX;
-            int cy = ((CellLayout.LayoutParams) iconParent.getChildAt(i).getLayoutParams()).cellY;
+            View cell = iconParent.getChildAt(i);
+            if (!cell.isFocusable()) {
+                continue;
+            }
+            int cx = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellX;
+            int cy = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellY;
             if (pivotX < 0) {
                 matrix[cx - pivotX][cy] = i;
             } else {
diff --git a/src/com/android/launcher3/util/TestingUtils.java b/src/com/android/launcher3/util/TestingUtils.java
index 39b8046..665c371 100644
--- a/src/com/android/launcher3/util/TestingUtils.java
+++ b/src/com/android/launcher3/util/TestingUtils.java
@@ -13,6 +13,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 
 import java.util.HashMap;
 
@@ -39,9 +40,7 @@
 
     public static void addWeightWatcher(Launcher launcher) {
         if (MEMORY_DUMP_ENABLED) {
-            String spKey = LauncherAppState.getSharedPreferencesKey();
-            SharedPreferences sp = launcher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
-            boolean show = sp.getBoolean(SHOW_WEIGHT_WATCHER, true);
+            boolean show = Utilities.getPrefs(launcher).getBoolean(SHOW_WEIGHT_WATCHER, true);
 
             int id = launcher.getResources().getIdentifier("zzz_weight_watcher", "layout",
                     launcher.getPackageName());
diff --git a/tests/src/com/android/launcher3/RotationPreferenceTest.java b/tests/src/com/android/launcher3/RotationPreferenceTest.java
index 5f63475..0168ee6 100644
--- a/tests/src/com/android/launcher3/RotationPreferenceTest.java
+++ b/tests/src/com/android/launcher3/RotationPreferenceTest.java
@@ -4,9 +4,9 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.graphics.Rect;
-import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.Until;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
 import android.test.InstrumentationTestCase;
 
 /**
@@ -28,8 +28,7 @@
         mDevice = UiDevice.getInstance(getInstrumentation());
         mTargetContext = getInstrumentation().getTargetContext();
         mTargetPackage = mTargetContext.getPackageName();
-        mPrefs = mTargetContext.getSharedPreferences(
-                LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
+        mPrefs = Utilities.getPrefs(mTargetContext);
         mOriginalRotationValue = mPrefs.getBoolean(Utilities.ALLOW_ROTATION_PREFERENCE_KEY, false);
     }
 
@@ -73,15 +72,17 @@
                 .setPackage(mTargetPackage)
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         getInstrumentation().getContext().startActivity(homeIntent);
-        mDevice.wait(Until.hasObject(By.pkg(mTargetPackage).depth(0)), 3000);
+        mDevice.findObject(new UiSelector().packageName(mTargetPackage)).waitForExists(6000);
     }
 
     private void setRotationEnabled(boolean enabled) {
         mPrefs.edit().putBoolean(Utilities.ALLOW_ROTATION_PREFERENCE_KEY, enabled).commit();
     }
 
-    private Rect getHotseatBounds() {
-        mDevice.wait(Until.hasObject(By.res(mTargetPackage, "hotseat")), 3000);
-        return mDevice.findObject(By.res(mTargetPackage, "hotseat")).getVisibleBounds();
+    private Rect getHotseatBounds() throws Exception {
+        UiObject hotseat = mDevice.findObject(
+                new UiSelector().resourceId(mTargetPackage + ":id/hotseat"));
+        hotseat.waitForExists(6000);
+        return hotseat.getVisibleBounds();
     }
 }