Merge "Updating content of page description frequently." into ub-now-porkchop
diff --git a/WallpaperPicker/src/com/android/launcher3/Partner.java b/WallpaperPicker/src/com/android/launcher3/Partner.java
deleted file mode 100644
index 1753997..0000000
--- a/WallpaperPicker/src/com/android/launcher3/Partner.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.util.Pair;
-
-import java.io.File;
-
-/**
- * Utilities to discover and interact with partner customizations. There can
- * only be one set of customizations on a device, and it must be bundled with
- * the system.
- */
-public class Partner {
-    /** Marker action used to discover partner */
-    private static final String
-            ACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION";
-
-    public static final String RESOURCE_FOLDER = "partner_folder";
-    public static final String RESOURCE_WALLPAPERS = "partner_wallpapers";
-    public static final String RESOURCE_DEFAULT_LAYOUT = "partner_default_layout";
-
-    public static final String RESOURCE_DEFAULT_WALLPAPER_HIDDEN = "default_wallpapper_hidden";
-    public static final String RESOURCE_SYSTEM_WALLPAPER_DIR = "system_wallpaper_directory";
-
-    public static final String RESOURCE_REQUIRE_FIRST_RUN_FLOW = "requires_first_run_flow";
-
-    private static boolean sSearched = false;
-    private static Partner sPartner;
-
-    /**
-     * Find and return partner details, or {@code null} if none exists.
-     */
-    public static synchronized Partner get(PackageManager pm) {
-        if (!sSearched) {
-            Pair<String, Resources> apkInfo = Utilities.findSystemApk(ACTION_PARTNER_CUSTOMIZATION, pm);
-            if (apkInfo != null) {
-                sPartner = new Partner(apkInfo.first, apkInfo.second);
-            }
-            sSearched = true;
-        }
-        return sPartner;
-    }
-
-    private final String mPackageName;
-    private final Resources mResources;
-
-    private Partner(String packageName, Resources res) {
-        mPackageName = packageName;
-        mResources = res;
-    }
-
-    public String getPackageName() {
-        return mPackageName;
-    }
-
-    public Resources getResources() {
-        return mResources;
-    }
-
-    public boolean hasDefaultLayout() {
-        int defaultLayout = getResources().getIdentifier(Partner.RESOURCE_DEFAULT_LAYOUT,
-                "xml", getPackageName());
-        return defaultLayout != 0;
-    }
-
-    public boolean hasFolder() {
-        int folder = getResources().getIdentifier(Partner.RESOURCE_FOLDER,
-                "xml", getPackageName());
-        return folder != 0;
-    }
-
-    public boolean hideDefaultWallpaper() {
-        int resId = getResources().getIdentifier(RESOURCE_DEFAULT_WALLPAPER_HIDDEN, "bool",
-                getPackageName());
-        return resId != 0 && getResources().getBoolean(resId);
-    }
-
-    public File getWallpaperDirectory() {
-        int resId = getResources().getIdentifier(RESOURCE_SYSTEM_WALLPAPER_DIR, "string",
-                getPackageName());
-        return (resId != 0) ? new File(getResources().getString(resId)) : null;
-    }
-
-    public boolean requiresFirstRunFlow() {
-        int resId = getResources().getIdentifier(RESOURCE_REQUIRE_FIRST_RUN_FLOW, "bool",
-                getPackageName());
-        return resId != 0 && getResources().getBoolean(resId);
-    }
-}
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index cb13291..0728537 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -925,7 +925,7 @@
         Partner partner = Partner.get(pm);
         if (partner != null) {
             final Resources partnerRes = partner.getResources();
-            final int resId = partnerRes.getIdentifier(Partner.RESOURCE_WALLPAPERS, "array",
+            final int resId = partnerRes.getIdentifier(Partner.RES_WALLPAPERS, "array",
                     partner.getPackageName());
             if (resId != 0) {
                 addWallpapers(bundled, partnerRes, partner.getPackageName(), resId);
diff --git a/res/drawable-hdpi/ic_allapps.png b/res/drawable-hdpi/ic_allapps.png
index 072cf5b..b98e65f 100644
--- a/res/drawable-hdpi/ic_allapps.png
+++ b/res/drawable-hdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_allapps_pressed.png b/res/drawable-hdpi/ic_allapps_pressed.png
index af49dbb..b7eaa67 100644
--- a/res/drawable-hdpi/ic_allapps_pressed.png
+++ b/res/drawable-hdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/quantum_panel.9.png b/res/drawable-hdpi/quantum_panel.9.png
index 914961a..b4ac9c0 100644
--- a/res/drawable-hdpi/quantum_panel.9.png
+++ b/res/drawable-hdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_allapps.png b/res/drawable-mdpi/ic_allapps.png
index f3887be..f410673 100644
--- a/res/drawable-mdpi/ic_allapps.png
+++ b/res/drawable-mdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_allapps_pressed.png b/res/drawable-mdpi/ic_allapps_pressed.png
index d7ea96f..aa4f913 100644
--- a/res/drawable-mdpi/ic_allapps_pressed.png
+++ b/res/drawable-mdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/quantum_panel.9.png b/res/drawable-mdpi/quantum_panel.9.png
index b9b9506..c5a6eb7 100644
--- a/res/drawable-mdpi/quantum_panel.9.png
+++ b/res/drawable-mdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_allapps.png b/res/drawable-xhdpi/ic_allapps.png
index 6a528d5..ff3d823 100644
--- a/res/drawable-xhdpi/ic_allapps.png
+++ b/res/drawable-xhdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_allapps_pressed.png b/res/drawable-xhdpi/ic_allapps_pressed.png
index 15a8aa9..5f188f6 100644
--- a/res/drawable-xhdpi/ic_allapps_pressed.png
+++ b/res/drawable-xhdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/quantum_panel.9.png b/res/drawable-xhdpi/quantum_panel.9.png
index 1bbb937..1797ad5 100644
--- a/res/drawable-xhdpi/quantum_panel.9.png
+++ b/res/drawable-xhdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_allapps.png b/res/drawable-xxhdpi/ic_allapps.png
index ae5545d..5dbfe4c 100644
--- a/res/drawable-xxhdpi/ic_allapps.png
+++ b/res/drawable-xxhdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_allapps_pressed.png b/res/drawable-xxhdpi/ic_allapps_pressed.png
index 77b45ae..e761723 100644
--- a/res/drawable-xxhdpi/ic_allapps_pressed.png
+++ b/res/drawable-xxhdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/quantum_panel.9.png b/res/drawable-xxhdpi/quantum_panel.9.png
index 4392aa0..d7ba874 100644
--- a/res/drawable-xxhdpi/quantum_panel.9.png
+++ b/res/drawable-xxhdpi/quantum_panel.9.png
Binary files differ
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 8781874..f428350 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -97,7 +97,7 @@
     <string name="migration_cling_use_default" msgid="2626475813981258626">"DISPOSITION PAR DÉFAUT"</string>
     <string name="workspace_cling_title" msgid="5626202359865825661">"Organiser son espace personnel"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"Maintenez votre doigt sur l\'arrière-plan pour gérer les fonds d\'écran, les widgets et les paramètres."</string>
-    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fonds d\'écran, widgets, et paramètres"</string>
+    <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"Fonds d\'écran, widgets et paramètres"</string>
     <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"Maintenez le doigt sur le fond d\'écran pour personnaliser"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"J\'ai compris"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"Voici un dossier"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 4403c8b..2fb51f5 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -98,7 +98,7 @@
     <string name="workspace_cling_title" msgid="5626202359865825661">"თქვენი სივრცის ორგანიზება"</string>
     <string name="workspace_cling_move_item" msgid="528201129978005352">"თუ გსურთ ფონების, ვიჯეტების და პარამეტრების მართვა, შეეხეთ და არ აუშვათ ფონს."</string>
     <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"ფონები, ვიჯეტები, &amp; პარამეტრები"</string>
-    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"მოსარგებათ შეეხეთ &amp; დააყოვნეთ ფონზე"</string>
+    <string name="workspace_cling_longpress_description" msgid="4119994475505235248">"მოსარგებად შეეხეთ &amp; დააყოვნეთ ფონზე"</string>
     <string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"გასაგებია"</string>
     <string name="folder_cling_title" msgid="3894908818693254164">"აი, საქაღალდე"</string>
     <string name="folder_cling_create_folder" msgid="6158215559475836131">"ასეთის შესაქმნელად, შეეხეთ და დააყოვნეთ აპზე, ხოლო შემდეგ გადააჩოჩეთ შემდეგზე."</string>
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 558d8e9..a92bff1 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -366,8 +366,10 @@
                     // This code triggers requestLayout so must be posted outside of the
                     // layout pass.
                     public void run() {
-                        setDataIsReady();
-                        onDataReady(getMeasuredWidth(), getMeasuredHeight());
+                        if (isAttachedToWindow()) {
+                            setDataIsReady();
+                            onDataReady(getMeasuredWidth(), getMeasuredHeight());
+                        }
                     }
                 });
             }
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index fbdd7eb..05e8906 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -30,6 +30,8 @@
 import android.graphics.Rect;
 import android.graphics.drawable.TransitionDrawable;
 import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
 import android.os.UserManager;
 import android.util.AttributeSet;
 import android.view.View;
@@ -193,11 +195,14 @@
             isVisible = false;
         }
         if (useUninstallLabel) {
-            UserManager userManager = (UserManager)
-                getContext().getSystemService(Context.USER_SERVICE);
-            if (userManager.hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL)
-                    || userManager.hasUserRestriction(UserManager.DISALLOW_UNINSTALL_APPS)) {
-                isVisible = false;
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                UserManager userManager = (UserManager)
+                        getContext().getSystemService(Context.USER_SERVICE);
+                Bundle restrictions = userManager.getUserRestrictions();
+                if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
+                        || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
+                    isVisible = false;
+                }
             }
         }
 
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 8af2a7f..daf5556 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -69,7 +69,7 @@
     float numRows;
     float numColumns;
     float numHotseatIcons;
-    private float iconSize;
+    float iconSize;
     private float iconTextSize;
     private int iconDrawablePaddingOriginalPx;
     private float hotseatIconSize;
@@ -130,6 +130,9 @@
 
     float dragViewScale;
 
+    int allAppsShortEdgeCount = -1;
+    int allAppsLongEdgeCount = -1;
+
     private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>();
 
     DeviceProfile(String n, float w, float h, float r, float c,
@@ -152,6 +155,9 @@
         defaultNoAllAppsLayoutId = dnalId;
     }
 
+    DeviceProfile() {
+    }
+
     DeviceProfile(Context context,
                   ArrayList<DeviceProfile> profiles,
                   float minWidth, float minHeight,
@@ -218,6 +224,7 @@
             points.add(new DeviceProfileQuery(p, p.iconSize));
         }
         iconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
+
         // AllApps uses the original non-scaled icon size
         allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm);
 
@@ -240,6 +247,9 @@
         // Hotseat
         hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
 
+        // If the partner customization apk contains any grid overrides, apply them
+        applyPartnerDeviceProfileOverrides(context, dm);
+
         // Calculate the remaining vars
         updateFromConfiguration(context, res, wPx, hPx, awPx, ahPx);
         updateAvailableDimensions(context);
@@ -247,6 +257,33 @@
     }
 
     /**
+     * Apply any Partner customization grid overrides.
+     *
+     * Currently we support: all apps row / column count.
+     */
+    private void applyPartnerDeviceProfileOverrides(Context ctx, DisplayMetrics dm) {
+        Partner p = Partner.get(ctx.getPackageManager());
+        if (p != null) {
+            DeviceProfile partnerDp = p.getDeviceProfileOverride(dm);
+            if (partnerDp != null) {
+                if (partnerDp.numRows > 0 && partnerDp.numColumns > 0) {
+                    numRows = partnerDp.numRows;
+                    numColumns = partnerDp.numColumns;
+                }
+                if (partnerDp.allAppsShortEdgeCount > 0 && partnerDp.allAppsLongEdgeCount > 0) {
+                    allAppsShortEdgeCount = partnerDp.allAppsShortEdgeCount;
+                    allAppsLongEdgeCount = partnerDp.allAppsLongEdgeCount;
+                }
+                if (partnerDp.iconSize > 0) {
+                    iconSize = partnerDp.iconSize;
+                    // AllApps uses the original non-scaled icon size
+                    allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm);
+                }
+            }
+        }
+    }
+
+    /**
      * Determine the exact visual footprint of the all apps button, taking into account scaling
      * and internal padding of the drawable.
      */
@@ -380,12 +417,17 @@
         int maxRows = (isLandscape ? maxShortEdgeCellCount : maxLongEdgeCellCount);
         int maxCols = (isLandscape ? maxLongEdgeCellCount : maxShortEdgeCellCount);
 
-        allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) /
-                (allAppsCellHeightPx + allAppsCellPaddingPx);
-        allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows));
-        allAppsNumCols = (availableWidthPx) /
-                (allAppsCellWidthPx + allAppsCellPaddingPx);
-        allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols));
+        if (allAppsShortEdgeCount > 0 && allAppsLongEdgeCount > 0) {
+            allAppsNumRows = isLandscape ? allAppsShortEdgeCount : allAppsLongEdgeCount;
+            allAppsNumCols = isLandscape ? allAppsLongEdgeCount : allAppsShortEdgeCount;
+        } else {
+            allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) /
+                    (allAppsCellHeightPx + allAppsCellPaddingPx);
+            allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows));
+            allAppsNumCols = (availableWidthPx) /
+                    (allAppsCellWidthPx + allAppsCellPaddingPx);
+            allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols));
+        }
     }
 
     void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx,
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 109a771..ffce116 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -22,6 +22,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
 import android.app.Activity;
@@ -82,6 +83,7 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnLongClickListener;
+import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -90,6 +92,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Advanceable;
 import android.widget.FrameLayout;
@@ -2061,14 +2064,25 @@
             sourceBounds = mSearchDropTargetBar.getSearchBarBounds();
         }
 
-        startSearch(initialQuery, selectInitialQuery,
+        boolean clearTextImmediately = startSearch(initialQuery, selectInitialQuery,
                 appSearchData, sourceBounds);
+        if (clearTextImmediately) {
+            clearTypedText();
+        }
     }
 
-    public void startSearch(String initialQuery,
+    /**
+     * Start a text search.
+     *
+     * @return {@code true} if the search will start immediately, so any further keypresses
+     * will be handled directly by the search UI. {@code false} if {@link Launcher} should continue
+     * to buffer keypresses.
+     */
+    public boolean startSearch(String initialQuery,
             boolean selectInitialQuery, Bundle appSearchData, Rect sourceBounds) {
         startGlobalSearch(initialQuery, selectInitialQuery,
                 appSearchData, sourceBounds);
+        return false;
     }
 
     /**
@@ -3202,10 +3216,12 @@
         final View fromView = mWorkspace;
         final AppsCustomizeTabHost toView = mAppsCustomizeTabHost;
 
+        final ArrayList<View> layerViews = new ArrayList<View>();
+
         Workspace.State workspaceState = contentType == AppsCustomizePagedView.ContentType.Widgets ?
                 Workspace.State.OVERVIEW_HIDDEN : Workspace.State.NORMAL_HIDDEN;
         Animator workspaceAnim =
-                mWorkspace.getChangeStateAnimation(workspaceState, animated);
+                mWorkspace.getChangeStateAnimation(workspaceState, animated, layerViews);
         if (!LauncherAppState.isDisableAllApps()
                 || contentType == AppsCustomizePagedView.ContentType.Widgets) {
             // Set the content type for the all apps/widgets space
@@ -3214,7 +3230,6 @@
 
         if (animated) {
             mStateAnimation = LauncherAnimUtils.createAnimatorSet();
-
             final AppsCustomizePagedView content = (AppsCustomizePagedView)
                     toView.findViewById(R.id.apps_customize_pane_content);
 
@@ -3231,32 +3246,46 @@
             }
 
             // Hide the real page background, and swap in the fake one
-            revealView.setVisibility(View.VISIBLE);
             content.setPageBackgroundsVisible(false);
+            revealView.setVisibility(View.VISIBLE);
+            // We need to hide this view as the animation start will be posted.
+            revealView.setAlpha(0);
 
             int width = revealView.getMeasuredWidth();
             int height = revealView.getMeasuredHeight();
-
             float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
+
             revealView.setTranslationY(0);
             revealView.setTranslationX(0);
 
             // Get the y delta between the center of the page and the center of the all apps button
             int[] allAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
                     getAllAppsButton(), null);
-            float yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
-            float xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
 
-            float initAlpha = isWidgetTray ? 0.3f : 1f;
+            float alpha = 0;
+            float xDrift = 0;
+            float yDrift = 0;
+            if (material) {
+                alpha = isWidgetTray ? 0.3f : 1f;
+                yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
+                xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
+            } else {
+                yDrift = 2 * height / 3;
+                xDrift = 0;
+            }
+            final float initAlpha = alpha;
+
             revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            layerViews.add(revealView);
             PropertyValuesHolder panelAlpha = PropertyValuesHolder.ofFloat("alpha", initAlpha, 1f);
             PropertyValuesHolder panelDriftY =
                     PropertyValuesHolder.ofFloat("translationY", yDrift, 0);
             PropertyValuesHolder panelDriftX =
                     PropertyValuesHolder.ofFloat("translationX", xDrift, 0);
 
-            ObjectAnimator panelAlphaAndDrift =
-                    LauncherAnimUtils.ofPropertyValuesHolder(revealView, panelAlpha, panelDriftY, panelDriftX);
+            ObjectAnimator panelAlphaAndDrift = ObjectAnimator.ofPropertyValuesHolder(revealView,
+                    panelAlpha, panelDriftY, panelDriftX);
+
             panelAlphaAndDrift.setDuration(revealDuration);
             panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
 
@@ -3265,15 +3294,17 @@
             if (page != null) {
                 page.setVisibility(View.VISIBLE);
                 page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                layerViews.add(page);
 
-                ObjectAnimator pageDrift = LauncherAnimUtils.ofFloat(page, "translationY", yDrift, 0);
+                ObjectAnimator pageDrift = ObjectAnimator.ofFloat(page, "translationY", yDrift, 0);
+                page.setTranslationY(yDrift);
                 pageDrift.setDuration(revealDuration);
                 pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
                 pageDrift.setStartDelay(itemsAlphaStagger);
                 mStateAnimation.play(pageDrift);
 
                 page.setAlpha(0f);
-                ObjectAnimator itemsAlpha = LauncherAnimUtils.ofFloat(page, "alpha", 0f, 1f);
+                ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(page, "alpha", 0f, 1f);
                 itemsAlpha.setDuration(revealDuration);
                 itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
                 itemsAlpha.setStartDelay(itemsAlphaStagger);
@@ -3283,7 +3314,7 @@
             View pageIndicators = toView.findViewById(R.id.apps_customize_page_indicator);
             pageIndicators.setAlpha(0.01f);
             ObjectAnimator indicatorsAlpha =
-                    LauncherAnimUtils.ofFloat(pageIndicators, "alpha", 1f);
+                    ObjectAnimator.ofFloat(pageIndicators, "alpha", 1f);
             indicatorsAlpha.setDuration(revealDuration);
             mStateAnimation.play(indicatorsAlpha);
 
@@ -3292,7 +3323,7 @@
                 int allAppsButtonSize = LauncherAppState.getInstance().
                         getDynamicGrid().getDeviceProfile().allAppsButtonVisualSize;
                 float startRadius = isWidgetTray ? 0 : allAppsButtonSize / 2;
-                Animator reveal = LauncherAnimUtils.createCircularReveal(revealView, width / 2,
+                Animator reveal = ViewAnimationUtils.createCircularReveal(revealView, width / 2,
                                 height / 2, startRadius, revealRadius);
                 reveal.setDuration(revealDuration);
                 reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
@@ -3309,7 +3340,6 @@
                         }
                     }
                 });
-
                 mStateAnimation.play(reveal);
             }
 
@@ -3332,54 +3362,40 @@
                     }
                 }
 
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    // Prepare the position
-                    toView.bringToFront();
-                    toView.setVisibility(View.VISIBLE);
-                }
             });
 
-            boolean delayAnim = false;
             if (workspaceAnim != null) {
                 mStateAnimation.play(workspaceAnim);
             }
+
             dispatchOnLauncherTransitionPrepare(fromView, animated, false);
             dispatchOnLauncherTransitionPrepare(toView, animated, false);
-
-            // If any of the objects being animated haven't been measured/laid out
-            // yet, delay the animation until we get a layout pass
-            if ((((LauncherTransitionable) toView).getContent().getMeasuredWidth() == 0) ||
-                    (mWorkspace.getMeasuredWidth() == 0) ||
-                    (toView.getMeasuredWidth() == 0)) {
-                delayAnim = true;
-            }
-
             final AnimatorSet stateAnimation = mStateAnimation;
             final Runnable startAnimRunnable = new Runnable() {
                 public void run() {
+                    if (!toView.isAttachedToWindow()) {
+                        return;
+                    }
                     // Check that mStateAnimation hasn't changed while
                     // we waited for a layout/draw pass
                     if (mStateAnimation != stateAnimation)
                         return;
                     dispatchOnLauncherTransitionStart(fromView, animated, false);
                     dispatchOnLauncherTransitionStart(toView, animated, false);
-                    LauncherAnimUtils.startAnimationAfterNextDraw(mStateAnimation, toView);
+
+                    revealView.setAlpha(initAlpha);
+                    if (Utilities.isLmp()) {
+                        for (int i = 0; i < layerViews.size(); i++) {
+                            View v = layerViews.get(i);
+                            if (v != null) v.buildLayer();
+                        }
+                    }
+                    mStateAnimation.start();
                 }
             };
-            if (delayAnim) {
-                toView.bringToFront();
-                toView.setVisibility(View.VISIBLE);
-                final ViewTreeObserver observer = toView.getViewTreeObserver();
-                observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
-                        public void onGlobalLayout() {
-                            startAnimRunnable.run();
-                            toView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                        }
-                    });
-            } else {
-                startAnimRunnable.run();
-            }
+            toView.bringToFront();
+            toView.setVisibility(View.VISIBLE);
+            toView.post(startAnimRunnable);
         } else {
             toView.setTranslationX(0.0f);
             toView.setTranslationY(0.0f);
@@ -3431,18 +3447,22 @@
         final View fromView = mAppsCustomizeTabHost;
         final View toView = mWorkspace;
         Animator workspaceAnim = null;
+        final ArrayList<View> layerViews = new ArrayList<View>();
+
         if (toState == Workspace.State.NORMAL) {
             workspaceAnim = mWorkspace.getChangeStateAnimation(
-                    toState, animated);
+                    toState, animated, layerViews);
         } else if (toState == Workspace.State.SPRING_LOADED ||
                 toState == Workspace.State.OVERVIEW) {
             workspaceAnim = mWorkspace.getChangeStateAnimation(
-                    toState, animated);
+                    toState, animated, layerViews);
         }
 
-        showHotseat(animated);
         if (animated) {
             mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+            if (workspaceAnim != null) {
+                mStateAnimation.play(workspaceAnim);
+            }
 
             final AppsCustomizePagedView content = (AppsCustomizePagedView)
                     fromView.findViewById(R.id.apps_customize_pane_content);
@@ -3450,113 +3470,133 @@
             final View page = content.getPageAt(content.getNextPage());
             final View revealView = fromView.findViewById(R.id.fake_page);
 
-            AppsCustomizePagedView.ContentType contentType = content.getContentType();
-            final boolean isWidgetTray = contentType == AppsCustomizePagedView.ContentType.Widgets;
+            // hideAppsCustomizeHelper is called in some cases when it is already hidden
+            // don't perform all these no-op animations. In particularly, this was causing
+            // the all-apps button to pop in and out.
+            if (fromView.getVisibility() == View.VISIBLE) {
+                AppsCustomizePagedView.ContentType contentType = content.getContentType();
+                final boolean isWidgetTray =
+                        contentType == AppsCustomizePagedView.ContentType.Widgets;
 
-            if (isWidgetTray) {
-                revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
-            } else {
-                revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
-            }
-
-            int width = revealView.getMeasuredWidth();
-            int height = revealView.getMeasuredHeight();
-            float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
-
-            // Hide the real page background, and swap in the fake one
-            revealView.setVisibility(View.VISIBLE);
-            content.setPageBackgroundsVisible(false);
-
-            final View allAppsButton = getAllAppsButton();
-            revealView.setTranslationY(0);
-            int[] allAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
-                    allAppsButton, null);
-            float yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
-            float xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
-
-            revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-
-            // The vertical motion of the apps panel should be delayed by one frame
-            // from the conceal animation in order to give the right feel. We correpsondingly
-            // shorten the duration so that the slide and conceal end at the same time.
-            ObjectAnimator panelDriftY = LauncherAnimUtils.ofFloat(revealView, "translationY", 0, yDrift);
-            panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
-            panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
-            panelDriftY.setInterpolator(new LogDecelerateInterpolator(100, 0));
-            mStateAnimation.play(panelDriftY);
-
-            ObjectAnimator panelDriftX = LauncherAnimUtils.ofFloat(revealView, "translationX", 0, xDrift);
-            panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
-            panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
-            panelDriftX.setInterpolator(new LogDecelerateInterpolator(100, 0));
-            mStateAnimation.play(panelDriftX);
-
-            if (isWidgetTray) {
-                ObjectAnimator panelAlpha = LauncherAnimUtils.ofFloat(revealView, "alpha", 1f, 0.4f);
-                panelAlpha.setDuration(revealDuration);
-                panelAlpha.setInterpolator(new LogDecelerateInterpolator(100, 0));
-                mStateAnimation.play(panelAlpha);
-            }
-
-            if (page != null) {
-                page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-
-                ObjectAnimator pageDrift = LauncherAnimUtils.ofFloat(page, "translationY",
-                        0, yDrift);
-                pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
-                pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0));
-                pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
-                mStateAnimation.play(pageDrift);
-
-                page.setAlpha(1f);
-                ObjectAnimator itemsAlpha = LauncherAnimUtils.ofFloat(page, "alpha", 1f, 0f);
-                itemsAlpha.setDuration(100);
-                itemsAlpha.setInterpolator(new LogDecelerateInterpolator(100, 0));
-                mStateAnimation.play(itemsAlpha);
-            }
-
-            View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator);
-            pageIndicators.setAlpha(1f);
-            ObjectAnimator indicatorsAlpha =
-                    LauncherAnimUtils.ofFloat(pageIndicators, "alpha", 0f);
-            indicatorsAlpha.setDuration(revealDuration);
-            indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f));
-            mStateAnimation.play(indicatorsAlpha);
-
-            width = revealView.getMeasuredWidth();
-
-            if (material) {
-                if (!isWidgetTray) {
-                    allAppsButton.setVisibility(View.INVISIBLE);
+                if (isWidgetTray) {
+                    revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark));
+                } else {
+                    revealView.setBackground(res.getDrawable(R.drawable.quantum_panel));
                 }
-                int allAppsButtonSize = LauncherAppState.getInstance().
-                        getDynamicGrid().getDeviceProfile().allAppsButtonVisualSize;
-                float finalRadius = isWidgetTray ? 0 : allAppsButtonSize / 2;
-                Animator reveal =
-                        LauncherAnimUtils.createCircularReveal(revealView, width / 2,
-                                height / 2, revealRadius, finalRadius);
-                reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
-                reveal.setDuration(revealDuration);
-                reveal.setStartDelay(itemsAlphaStagger);
 
-                reveal.addListener(new AnimatorListenerAdapter() {
-                    public void onAnimationEnd(Animator animation) {
-                        revealView.setVisibility(View.INVISIBLE);
-                        if (!isWidgetTray) {
-                            allAppsButton.setVisibility(View.VISIBLE);
-                        }
+                int width = revealView.getMeasuredWidth();
+                int height = revealView.getMeasuredHeight();
+                float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4);
+
+                // Hide the real page background, and swap in the fake one
+                revealView.setVisibility(View.VISIBLE);
+                content.setPageBackgroundsVisible(false);
+
+                final View allAppsButton = getAllAppsButton();
+                revealView.setTranslationY(0);
+                int[] allAppsToPanelDelta = Utilities.getCenterDeltaInScreenSpace(revealView,
+                        allAppsButton, null);
+
+                float xDrift = 0;
+                float yDrift = 0;
+                if (material) {
+                    yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
+                    xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
+                } else {
+                    yDrift = 5 * height / 4;
+                    xDrift = 0;
+                }
+
+                revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                TimeInterpolator decelerateInterpolator = material ?
+                        new LogDecelerateInterpolator(100, 0) :
+                        new LogDecelerateInterpolator(30, 0);
+
+                // The vertical motion of the apps panel should be delayed by one frame
+                // from the conceal animation in order to give the right feel. We correpsondingly
+                // shorten the duration so that the slide and conceal end at the same time.
+                ObjectAnimator panelDriftY = LauncherAnimUtils.ofFloat(revealView, "translationY",
+                        0, yDrift);
+                panelDriftY.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+                panelDriftY.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+                panelDriftY.setInterpolator(decelerateInterpolator);
+                mStateAnimation.play(panelDriftY);
+
+                ObjectAnimator panelDriftX = LauncherAnimUtils.ofFloat(revealView, "translationX",
+                        0, xDrift);
+                panelDriftX.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+                panelDriftX.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+                panelDriftX.setInterpolator(decelerateInterpolator);
+                mStateAnimation.play(panelDriftX);
+
+                if (isWidgetTray || !material) {
+                    float finalAlpha = material ? 0.4f : 0f;
+                    revealView.setAlpha(1f);
+                    ObjectAnimator panelAlpha = LauncherAnimUtils.ofFloat(revealView, "alpha",
+                            1f, finalAlpha);
+                    panelAlpha.setDuration(revealDuration);
+                    panelAlpha.setInterpolator(material ? decelerateInterpolator :
+                        new AccelerateInterpolator(1.5f));
+                    mStateAnimation.play(panelAlpha);
+                }
+
+                if (page != null) {
+                    page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+                    ObjectAnimator pageDrift = LauncherAnimUtils.ofFloat(page, "translationY",
+                            0, yDrift);
+                    page.setTranslationY(0);
+                    pageDrift.setDuration(revealDuration - SINGLE_FRAME_DELAY);
+                    pageDrift.setInterpolator(decelerateInterpolator);
+                    pageDrift.setStartDelay(itemsAlphaStagger + SINGLE_FRAME_DELAY);
+                    mStateAnimation.play(pageDrift);
+
+                    page.setAlpha(1f);
+                    ObjectAnimator itemsAlpha = LauncherAnimUtils.ofFloat(page, "alpha", 1f, 0f);
+                    itemsAlpha.setDuration(100);
+                    itemsAlpha.setInterpolator(decelerateInterpolator);
+                    mStateAnimation.play(itemsAlpha);
+                }
+
+                View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator);
+                pageIndicators.setAlpha(1f);
+                ObjectAnimator indicatorsAlpha =
+                        LauncherAnimUtils.ofFloat(pageIndicators, "alpha", 0f);
+                indicatorsAlpha.setDuration(revealDuration);
+                indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f));
+                mStateAnimation.play(indicatorsAlpha);
+
+                width = revealView.getMeasuredWidth();
+
+                if (material) {
+                    if (!isWidgetTray) {
+                        allAppsButton.setVisibility(View.INVISIBLE);
                     }
-                });
+                    int allAppsButtonSize = LauncherAppState.getInstance().
+                            getDynamicGrid().getDeviceProfile().allAppsButtonVisualSize;
+                    float finalRadius = isWidgetTray ? 0 : allAppsButtonSize / 2;
+                    Animator reveal =
+                            LauncherAnimUtils.createCircularReveal(revealView, width / 2,
+                                    height / 2, revealRadius, finalRadius);
+                    reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
+                    reveal.setDuration(revealDuration);
+                    reveal.setStartDelay(itemsAlphaStagger);
 
-                mStateAnimation.play(reveal);
-            }
+                    reveal.addListener(new AnimatorListenerAdapter() {
+                        public void onAnimationEnd(Animator animation) {
+                            revealView.setVisibility(View.INVISIBLE);
+                            if (!isWidgetTray) {
+                                allAppsButton.setVisibility(View.VISIBLE);
+                            }
+                        }
+                    });
 
-            dispatchOnLauncherTransitionPrepare(fromView, animated, true);
-            dispatchOnLauncherTransitionPrepare(toView, animated, true);
-            mAppsCustomizeContent.stopScrolling();
+                    mStateAnimation.play(reveal);
+                }
 
-            if (workspaceAnim != null) {
-                mStateAnimation.play(workspaceAnim);
+                dispatchOnLauncherTransitionPrepare(fromView, animated, true);
+                dispatchOnLauncherTransitionPrepare(toView, animated, true);
+                mAppsCustomizeContent.stopScrolling();
             }
 
             mStateAnimation.addListener(new AnimatorListenerAdapter() {
@@ -3578,9 +3618,29 @@
                 }
             });
 
-            dispatchOnLauncherTransitionStart(fromView, animated, true);
-            dispatchOnLauncherTransitionStart(toView, animated, true);
-            LauncherAnimUtils.startAnimationAfterNextDraw(mStateAnimation, toView);
+            final AnimatorSet stateAnimation = mStateAnimation;
+            final Runnable startAnimRunnable = new Runnable() {
+                public void run() {
+                    if (!fromView.isAttachedToWindow()) {
+                        return;
+                    }
+                    // Check that mStateAnimation hasn't changed while
+                    // we waited for a layout/draw pass
+                    if (mStateAnimation != stateAnimation)
+                        return;
+                    dispatchOnLauncherTransitionStart(fromView, animated, false);
+                    dispatchOnLauncherTransitionStart(toView, animated, false);
+
+                    if (Utilities.isLmp()) {
+                        for (int i = 0; i < layerViews.size(); i++) {
+                            View v = layerViews.get(i);
+                            if (v != null) v.buildLayer();
+                        }
+                    }
+                    mStateAnimation.start();
+                }
+            };
+            fromView.post(startAnimRunnable);
         } else {
             fromView.setVisibility(View.GONE);
             dispatchOnLauncherTransitionPrepare(fromView, animated, true);
@@ -3725,25 +3785,6 @@
     }
 
     /**
-     * Shows the hotseat area.
-     */
-    void showHotseat(boolean animated) {
-        if (!LauncherAppState.getInstance().isScreenLarge()) {
-            if (animated) {
-                if (mHotseat.getAlpha() != 1f) {
-                    int duration = 0;
-                    if (mSearchDropTargetBar != null) {
-                        duration = mSearchDropTargetBar.getTransitionInDuration();
-                    }
-                    mHotseat.animate().alpha(1f).setDuration(duration);
-                }
-            } else {
-                mHotseat.setAlpha(1f);
-            }
-        }
-    }
-
-    /**
      * Hides the hotseat area.
      */
     void hideHotseat(boolean animated) {
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 842e0b0..30086ad 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -327,7 +327,7 @@
                 final Partner partner = Partner.get(getContext().getPackageManager());
                 if (partner != null && partner.hasDefaultLayout()) {
                     final Resources partnerRes = partner.getResources();
-                    int workspaceResId = partnerRes.getIdentifier(Partner.RESOURCE_DEFAULT_LAYOUT,
+                    int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT,
                             "xml", partner.getPackageName());
                     if (workspaceResId != 0) {
                         loader = new SimpleWorkspaceLoader(mOpenHelper, partnerRes, workspaceResId);
@@ -1509,7 +1509,7 @@
                         final Partner partner = Partner.get(mPackageManager);
                         if (partner != null) {
                             final Resources partnerRes = partner.getResources();
-                            final int resId = partnerRes.getIdentifier(Partner.RESOURCE_FOLDER,
+                            final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER,
                                     "xml", partner.getPackageName());
                             if (resId != 0) {
                                 final XmlResourceParser partnerParser = partnerRes.getXml(resId);
diff --git a/src/com/android/launcher3/Partner.java b/src/com/android/launcher3/Partner.java
new file mode 100644
index 0000000..e191319
--- /dev/null
+++ b/src/com/android/launcher3/Partner.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.File;
+
+/**
+ * Utilities to discover and interact with partner customizations. There can
+ * only be one set of customizations on a device, and it must be bundled with
+ * the system.
+ */
+public class Partner {
+
+    static final String TAG = "Launcher.Partner";
+
+    /** Marker action used to discover partner */
+    private static final String
+            ACTION_PARTNER_CUSTOMIZATION = "com.android.launcher3.action.PARTNER_CUSTOMIZATION";
+
+    public static final String RES_FOLDER = "partner_folder";
+    public static final String RES_WALLPAPERS = "partner_wallpapers";
+    public static final String RES_DEFAULT_LAYOUT = "partner_default_layout";
+
+    public static final String RES_DEFAULT_WALLPAPER_HIDDEN = "default_wallpapper_hidden";
+    public static final String RES_SYSTEM_WALLPAPER_DIR = "system_wallpaper_directory";
+
+    public static final String RES_REQUIRE_FIRST_RUN_FLOW = "requires_first_run_flow";
+
+    /** These resources are used to override the device profile  */
+    public static final String RES_GRID_AA_SHORT_EDGE_COUNT = "grid_aa_short_edge_count";
+    public static final String RES_GRID_AA_LONG_EDGE_COUNT = "grid_aa_long_edge_count";
+    public static final String RES_GRID_NUM_ROWS = "grid_num_rows";
+    public static final String RES_GRID_NUM_COLUMNS = "grid_num_columns";
+    public static final String RES_GRID_ICON_SIZE_DP = "grid_icon_size_dp";
+
+    private static boolean sSearched = false;
+    private static Partner sPartner;
+
+    /**
+     * Find and return partner details, or {@code null} if none exists.
+     */
+    public static synchronized Partner get(PackageManager pm) {
+        if (!sSearched) {
+            Pair<String, Resources> apkInfo = Utilities.findSystemApk(ACTION_PARTNER_CUSTOMIZATION, pm);
+            if (apkInfo != null) {
+                sPartner = new Partner(apkInfo.first, apkInfo.second);
+            }
+            sSearched = true;
+        }
+        return sPartner;
+    }
+
+    private final String mPackageName;
+    private final Resources mResources;
+
+    private Partner(String packageName, Resources res) {
+        mPackageName = packageName;
+        mResources = res;
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public Resources getResources() {
+        return mResources;
+    }
+
+    public boolean hasDefaultLayout() {
+        int defaultLayout = getResources().getIdentifier(Partner.RES_DEFAULT_LAYOUT,
+                "xml", getPackageName());
+        return defaultLayout != 0;
+    }
+
+    public boolean hasFolder() {
+        int folder = getResources().getIdentifier(Partner.RES_FOLDER,
+                "xml", getPackageName());
+        return folder != 0;
+    }
+
+    public boolean hideDefaultWallpaper() {
+        int resId = getResources().getIdentifier(RES_DEFAULT_WALLPAPER_HIDDEN, "bool",
+                getPackageName());
+        return resId != 0 && getResources().getBoolean(resId);
+    }
+
+    public File getWallpaperDirectory() {
+        int resId = getResources().getIdentifier(RES_SYSTEM_WALLPAPER_DIR, "string",
+                getPackageName());
+        return (resId != 0) ? new File(getResources().getString(resId)) : null;
+    }
+
+    public boolean requiresFirstRunFlow() {
+        int resId = getResources().getIdentifier(RES_REQUIRE_FIRST_RUN_FLOW, "bool",
+                getPackageName());
+        return resId != 0 && getResources().getBoolean(resId);
+    }
+
+    public DeviceProfile getDeviceProfileOverride(DisplayMetrics dm) {
+        boolean containsProfileOverrides = false;
+
+        DeviceProfile dp = new DeviceProfile();
+
+        // We initialize customizable fields to be invalid
+        dp.numRows = -1;
+        dp.numColumns = -1;
+        dp.allAppsShortEdgeCount = -1;
+        dp.allAppsLongEdgeCount = -1;
+
+        try {
+            int resId = getResources().getIdentifier(RES_GRID_NUM_ROWS,
+                    "integer", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                dp.numRows = getResources().getInteger(resId);
+            }
+
+            resId = getResources().getIdentifier(RES_GRID_NUM_COLUMNS,
+                    "integer", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                dp.numColumns = getResources().getInteger(resId);
+            }
+
+            resId = getResources().getIdentifier(RES_GRID_AA_SHORT_EDGE_COUNT,
+                    "integer", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                dp.allAppsShortEdgeCount = getResources().getInteger(resId);
+            }
+
+            resId = getResources().getIdentifier(RES_GRID_AA_LONG_EDGE_COUNT,
+                    "integer", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                dp.allAppsLongEdgeCount = getResources().getInteger(resId);
+            }
+
+            resId = getResources().getIdentifier(RES_GRID_ICON_SIZE_DP,
+                    "dimen", getPackageName());
+            if (resId > 0) {
+                containsProfileOverrides = true;
+                int px = getResources().getDimensionPixelSize(resId);
+                dp.iconSize = DynamicGrid.dpiFromPx(px, dm);
+            }
+        } catch (Resources.NotFoundException ex) {
+            Log.e(TAG, "Invalid Partner grid resource!", ex);
+        }
+        return containsProfileOverrides ? dp : null;
+    }
+}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index f19cad5..2e966de 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1212,14 +1212,6 @@
                 enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
             }
         }
-
-        // If we are not fading in adjacent screens, we still need to restore the alpha in case the
-        // user scrolls while we are transitioning (should not affect dispatchDraw optimizations)
-        if (!mWorkspaceFadeInAdjacentScreens) {
-            for (int i = 0; i < getChildCount(); ++i) {
-                ((CellLayout) getPageAt(i)).setShortcutAndWidgetAlpha(1f);
-            }
-        }
     }
 
     protected void onPageEndMoving() {
@@ -2051,8 +2043,9 @@
         mNewAlphas = new float[childCount];
     }
 
-    Animator getChangeStateAnimation(final State state, boolean animated) {
-        return getChangeStateAnimation(state, animated, 0, -1);
+    Animator getChangeStateAnimation(final State state, boolean animated,
+            ArrayList<View> layerViews) {
+        return getChangeStateAnimation(state, animated, 0, -1, layerViews);
     }
 
     @Override
@@ -2188,6 +2181,11 @@
     private static final int HIDE_WORKSPACE_DURATION = 100;
 
     Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage) {
+        return getChangeStateAnimation(state, animated, delay, snapPage, null);
+    }
+
+    Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage,
+            ArrayList<View> layerViews) {
         if (mState == state) {
             return null;
         }
@@ -2309,6 +2307,9 @@
                     cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
                     cl.setShortcutAndWidgetAlpha(mNewAlphas[i]);
                 } else {
+                    if (layerViews != null) {
+                        layerViews.add(cl);
+                    }
                     if (mOldAlphas[i] != mNewAlphas[i] || currentAlpha != mNewAlphas[i]) {
                         LauncherViewPropertyAnimator alphaAnim =
                             new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
@@ -2356,6 +2357,17 @@
                 .alpha(finalOverviewPanelAlpha).withLayer();
             overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
 
+            // For animation optimations, we may need to provide the Launcher transition
+            // with a set of views on which to force build layers in certain scenarios.
+            hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            if (layerViews != null) {
+                layerViews.add(hotseat);
+                layerViews.add(searchBar);
+                layerViews.add(overviewPanel);
+            }
+
             if (workspaceToOverview) {
                 pageIndicatorAlpha.setInterpolator(new DecelerateInterpolator(2));
                 hotseatAlpha.setInterpolator(new DecelerateInterpolator(2));
@@ -2501,21 +2513,6 @@
     private void onTransitionEnd() {
         mIsSwitchingState = false;
         updateChildrenLayersEnabled(false);
-        // The code in getChangeStateAnimation to determine initialAlpha and finalAlpha will ensure
-        // ensure that only the current page is visible during (and subsequently, after) the
-        // transition animation.  If fade adjacent pages is disabled, then re-enable the page
-        // visibility after the transition animation.
-        if (!mWorkspaceFadeInAdjacentScreens) {
-            for (int i = 0; i < getChildCount(); i++) {
-                final CellLayout cl = (CellLayout) getChildAt(i);
-                cl.setShortcutAndWidgetAlpha(1f);
-            }
-        } else {
-            for (int i = 0; i < numCustomPages(); i++) {
-                final CellLayout cl = (CellLayout) getChildAt(i);
-                cl.setShortcutAndWidgetAlpha(1f);
-            }
-        }
         showCustomContentIfNecessary();
     }
 
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index 0f8444b..de8c669 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -48,7 +48,7 @@
 
     public static LauncherAppsCompat getInstance(Context context) {
         synchronized (sInstanceLock) {
-            // TODO change this to use api version once L gets an API number.
+            // STOPSHIP(kennyguy) change this to use api version once L gets an API number.
             if (sInstance == null) {
                 if ("L".equals(Build.VERSION.CODENAME)) {
                     sInstance = new LauncherAppsCompatVL(context);
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index e7de99c..6422551 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -70,11 +70,11 @@
 
     public void startActivityForProfile(ComponentName component, UserHandleCompat user,
             Rect sourceBounds, Bundle opts) {
-        mLauncherApps.startActivityForProfile(component, user.getUser(), sourceBounds, opts);
+        mLauncherApps.startMainActivity(component, user.getUser(), sourceBounds, opts);
     }
 
     public void showAppDetailsForProfile(ComponentName component, UserHandleCompat user) {
-        mLauncherApps.showAppDetailsForProfile(component, user.getUser(), null, null);
+        mLauncherApps.startAppDetailsActivity(component, user.getUser(), null, null);
     }
 
     public void addOnAppsChangedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {
@@ -82,7 +82,7 @@
         synchronized (mCallbacks) {
             mCallbacks.put(callback, wrappedCallback);
         }
-        mLauncherApps.addOnAppsChangedCallback(wrappedCallback);
+        mLauncherApps.addCallback(wrappedCallback);
     }
 
     public void removeOnAppsChangedCallback(
@@ -92,19 +92,19 @@
             wrappedCallback = mCallbacks.remove(callback);
         }
         if (wrappedCallback != null) {
-            mLauncherApps.removeOnAppsChangedCallback(wrappedCallback);
+            mLauncherApps.removeCallback(wrappedCallback);
         }
     }
 
     public boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user) {
-        return mLauncherApps.isPackageEnabledForProfile(packageName, user.getUser());
+        return mLauncherApps.isPackageEnabled(packageName, user.getUser());
     }
 
     public boolean isActivityEnabledForProfile(ComponentName component, UserHandleCompat user) {
-        return mLauncherApps.isActivityEnabledForProfile(component, user.getUser());
+        return mLauncherApps.isActivityEnabled(component, user.getUser());
     }
 
-    private static class WrappedCallback extends LauncherApps.OnAppsChangedCallback {
+    private static class WrappedCallback extends LauncherApps.Callback {
         private LauncherAppsCompat.OnAppsChangedCallbackCompat mCallback;
 
         public WrappedCallback(LauncherAppsCompat.OnAppsChangedCallbackCompat callback) {