Merge "Decoupling launcher/workspace package cleanup from the application list (Bug 6602756)"
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 7daccd0..4750ae2 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -42,9 +42,6 @@
     <integer name="apps_customize_maxCellCountY">-1</integer>
     <dimen name="all_apps_button_vertical_padding">4dip</dimen>
 
-    <!-- roughly a status bar (for determining how many rows of icons are in home) -->
-    <dimen name="status_bar_height">48dip</dimen>
-
     <!-- dimensions for the wallpaper picker wallpaper thumbnail width -->
     <dimen name="wallpaper_chooser_grid_width">196dp</dimen>
     <dimen name="wallpaper_chooser_grid_height">140dp</dimen>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index d9ce915..58fd9d0 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -63,7 +63,7 @@
     <string name="accessibility_delete_button" msgid="3628162007991023603">"Kaldır"</string>
     <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Güncelleme kaldırılsın mı?"</string>
     <string name="menu_add" msgid="3065046628354640854">"Ekle"</string>
-    <string name="menu_manage_apps" msgid="2308685199463588895">"Uyglm yönet"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Uygulamaları yönet"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Duvar Kağıdı"</string>
     <string name="menu_search" msgid="4826514464423239041">"Ara"</string>
     <string name="menu_notifications" msgid="6424587053194766192">"Bildirimler"</string>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f15d3d8..fb96c0d 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -86,10 +86,6 @@
     <!-- Drag padding to add to the bottom of drop targets -->
     <dimen name="drop_target_drag_padding">14dp</dimen>
 
-    <!-- roughly a status bar (for vertically centering the all apps
-         home icon in landscape) -->
-    <dimen name="status_bar_height">25dip</dimen>
-
 <!-- Dragging -->
     <!-- the area at the edge of the screen that makes the workspace go left
          or right while you're dragging. -->
diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java
index 8824686..e8b1dc0 100644
--- a/src/com/android/launcher2/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher2/AppWidgetResizeFrame.java
@@ -403,17 +403,17 @@
                     newHeight);
             PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", lp.x, newX);
             PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", lp.y, newY);
-            ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
-            ObjectAnimator leftOa = ObjectAnimator.ofFloat(mLeftHandle, "alpha", 1.0f);
-            ObjectAnimator rightOa = ObjectAnimator.ofFloat(mRightHandle, "alpha", 1.0f);
-            ObjectAnimator topOa = ObjectAnimator.ofFloat(mTopHandle, "alpha", 1.0f);
-            ObjectAnimator bottomOa = ObjectAnimator.ofFloat(mBottomHandle, "alpha", 1.0f);
+            ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(lp, width, height, x, y);
+            ObjectAnimator leftOa = LauncherAnimUtils.ofFloat(mLeftHandle, "alpha", 1.0f);
+            ObjectAnimator rightOa = LauncherAnimUtils.ofFloat(mRightHandle, "alpha", 1.0f);
+            ObjectAnimator topOa = LauncherAnimUtils.ofFloat(mTopHandle, "alpha", 1.0f);
+            ObjectAnimator bottomOa = LauncherAnimUtils.ofFloat(mBottomHandle, "alpha", 1.0f);
             oa.addUpdateListener(new AnimatorUpdateListener() {
                 public void onAnimationUpdate(ValueAnimator animation) {
                     requestLayout();
                 }
             });
-            AnimatorSet set = new AnimatorSet();
+            AnimatorSet set = LauncherAnimUtils.createAnimatorSet();
             if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
                 set.playTogether(oa, topOa, bottomOa);
             } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 11ae8f2..d7bb438 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -17,7 +17,6 @@
 package com.android.launcher2;
 
 import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
@@ -586,10 +585,10 @@
             // Create a little animation to show that the widget can move
             float offsetY = getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
             final ImageView p = (ImageView) v.findViewById(R.id.widget_preview);
-            AnimatorSet bounce = new AnimatorSet();
-            ValueAnimator tyuAnim = ObjectAnimator.ofFloat(p, "translationY", offsetY);
+            AnimatorSet bounce = LauncherAnimUtils.createAnimatorSet();
+            ValueAnimator tyuAnim = LauncherAnimUtils.ofFloat(p, "translationY", offsetY);
             tyuAnim.setDuration(125);
-            ValueAnimator tydAnim = ObjectAnimator.ofFloat(p, "translationY", 0f);
+            ValueAnimator tydAnim = LauncherAnimUtils.ofFloat(p, "translationY", 0f);
             tydAnim.setDuration(100);
             bounce.play(tyuAnim).before(tydAnim);
             bounce.setInterpolator(new AccelerateInterpolator());
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index a2cab53..409affe 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -23,7 +23,6 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -266,7 +265,7 @@
                 onTabChangedEnd(type);
 
                 // Animate the transition
-                ObjectAnimator outAnim = ObjectAnimator.ofFloat(mAnimationBuffer, "alpha", 0f);
+                ObjectAnimator outAnim = LauncherAnimUtils.ofFloat(mAnimationBuffer, "alpha", 0f);
                 outAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
@@ -279,14 +278,14 @@
                         mAnimationBuffer.removeAllViews();
                     }
                 });
-                ObjectAnimator inAnim = ObjectAnimator.ofFloat(mAppsCustomizePane, "alpha", 1f);
+                ObjectAnimator inAnim = LauncherAnimUtils.ofFloat(mAppsCustomizePane, "alpha", 1f);
                 inAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
                         reloadCurrentPage();
                     }
                 });
-                AnimatorSet animSet = new AnimatorSet();
+                AnimatorSet animSet = LauncherAnimUtils.createAnimatorSet();
                 animSet.playTogether(outAnim, inAnim);
                 animSet.setDuration(duration);
                 animSet.start();
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index c028ff1..8319cb7 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -17,9 +17,9 @@
 package com.android.launcher2;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -1082,7 +1082,7 @@
                 return true;
             }
 
-            ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+            ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1f);
             va.setDuration(duration);
             mReorderAnimators.put(lp, va);
 
@@ -2064,7 +2064,7 @@
             if (finalDeltaX == 0 && finalDeltaY == 0) {
                 return;
             }
-            ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+            ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1f);
             a = va;
             va.setRepeatMode(ValueAnimator.REVERSE);
             va.setRepeatCount(ValueAnimator.INFINITE);
@@ -2106,13 +2106,13 @@
                 a.cancel();
             }
 
-            AnimatorSet s = new AnimatorSet();
+            AnimatorSet s = LauncherAnimUtils.createAnimatorSet();
             a = s;
             s.playTogether(
-                ObjectAnimator.ofFloat(child, "scaleX", 1f),
-                ObjectAnimator.ofFloat(child, "scaleY", 1f),
-                ObjectAnimator.ofFloat(child, "translationX", 0f),
-                ObjectAnimator.ofFloat(child, "translationY", 0f)
+                LauncherAnimUtils.ofFloat(child, "scaleX", 1f),
+                LauncherAnimUtils.ofFloat(child, "scaleY", 1f),
+                LauncherAnimUtils.ofFloat(child, "translationX", 0f),
+                LauncherAnimUtils.ofFloat(child, "translationY", 0f)
             );
             s.setDuration(REORDER_ANIMATION_DURATION);
             s.setInterpolator(new android.view.animation.DecelerateInterpolator(1.5f));
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index b6645e1..d7ac97d 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -76,7 +76,7 @@
         final float scale = (width + scaleDps) / width;
 
         // Animate the view into the correct position
-        mAnim = ValueAnimator.ofFloat(0.0f, 1.0f);
+        mAnim = LauncherAnimUtils.ofFloat(0.0f, 1.0f);
         mAnim.setDuration(150);
         mAnim.addUpdateListener(new AnimatorUpdateListener() {
             @Override
@@ -199,7 +199,7 @@
     }
 
     public void crossFade(int duration) {
-        ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+        ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1f);
         va.setDuration(duration);
         va.setInterpolator(new DecelerateInterpolator(1.5f));
         va.addUpdateListener(new AnimatorUpdateListener() {
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 53c3046..84c815e 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -421,7 +421,7 @@
         PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
         PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
         final ObjectAnimator oa = mOpenCloseAnimator =
-            ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+            LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
 
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
@@ -479,7 +479,7 @@
         PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
         PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
         final ObjectAnimator oa = mOpenCloseAnimator =
-                ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+                LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
 
         oa.addListener(new AnimatorListenerAdapter() {
             @Override
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index 76f3114..af3eea9 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -199,7 +199,7 @@
             if (mNeutralAnimator != null) {
                 mNeutralAnimator.cancel();
             }
-            mAcceptAnimator = ValueAnimator.ofFloat(0f, 1f);
+            mAcceptAnimator = LauncherAnimUtils.ofFloat(0f, 1f);
             mAcceptAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
 
             final int previewSize = sPreviewSize;
@@ -228,7 +228,7 @@
             if (mAcceptAnimator != null) {
                 mAcceptAnimator.cancel();
             }
-            mNeutralAnimator = ValueAnimator.ofFloat(0f, 1f);
+            mNeutralAnimator = LauncherAnimUtils.ofFloat(0f, 1f);
             mNeutralAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
 
             final int previewSize = sPreviewSize;
@@ -574,7 +574,7 @@
         final float transY0 = (mAvailableSpaceInPreview - d.getIntrinsicHeight()) / 2;
         mAnimParams.drawable = d;
 
-        ValueAnimator va = ValueAnimator.ofFloat(0f, 1.0f);
+        ValueAnimator va = LauncherAnimUtils.ofFloat(0f, 1.0f);
         va.addUpdateListener(new AnimatorUpdateListener(){
             public void onAnimationUpdate(ValueAnimator animation) {
                 float progress = (Float) animation.getAnimatedValue();
diff --git a/src/com/android/launcher2/InterruptibleInOutAnimator.java b/src/com/android/launcher2/InterruptibleInOutAnimator.java
index 135fa39..9831ba3 100644
--- a/src/com/android/launcher2/InterruptibleInOutAnimator.java
+++ b/src/com/android/launcher2/InterruptibleInOutAnimator.java
@@ -45,7 +45,7 @@
     private int mDirection = STOPPED;
 
     public InterruptibleInOutAnimator(long duration, float fromValue, float toValue) {
-        mAnimator = ValueAnimator.ofFloat(fromValue, toValue).setDuration(duration);
+        mAnimator = LauncherAnimUtils.ofFloat(fromValue, toValue).setDuration(duration);
         mOriginalDuration = duration;
         mOriginalFromValue = fromValue;
         mOriginalToValue = toValue;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 1231558..3e8c7aa 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -65,6 +65,7 @@
 import android.speech.RecognizerIntent;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
 import android.text.method.TextKeyListener;
 import android.util.Log;
 import android.view.Display;
@@ -1465,7 +1466,7 @@
         mWorkspace = null;
         mDragController = null;
 
-        ValueAnimator.clearAllAnimations();
+        LauncherAnimUtils.onDestroyActivity();
     }
 
     public DragController getDragController() {
@@ -1498,10 +1499,48 @@
         }
         Rect sourceBounds = mSearchDropTargetBar.getSearchBarBounds();
 
+        startGlobalSearch(initialQuery, selectInitialQuery,
+            appSearchData, sourceBounds);
+    }
+
+    /**
+     * Starts the global search activity. This code is a copied from SearchManager
+     */
+    public void startGlobalSearch(String initialQuery,
+            boolean selectInitialQuery, Bundle appSearchData, Rect sourceBounds) {
         final SearchManager searchManager =
-                (SearchManager) getSystemService(Context.SEARCH_SERVICE);
-        searchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(),
-            appSearchData, globalSearch, sourceBounds);
+            (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+        ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity();
+        if (globalSearchActivity == null) {
+            Log.w(TAG, "No global search activity found.");
+            return;
+        }
+        Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setComponent(globalSearchActivity);
+        // Make sure that we have a Bundle to put source in
+        if (appSearchData == null) {
+            appSearchData = new Bundle();
+        } else {
+            appSearchData = new Bundle(appSearchData);
+        }
+        // Set source to package name of app that starts global search, if not set already.
+        if (!appSearchData.containsKey("source")) {
+            appSearchData.putString("source", getPackageName());
+        }
+        intent.putExtra(SearchManager.APP_DATA, appSearchData);
+        if (!TextUtils.isEmpty(initialQuery)) {
+            intent.putExtra(SearchManager.QUERY, initialQuery);
+        }
+        if (selectInitialQuery) {
+            intent.putExtra(SearchManager.EXTRA_SELECT_QUERY, selectInitialQuery);
+        }
+        intent.setSourceBounds(sourceBounds);
+        try {
+            startActivity(intent);
+        } catch (ActivityNotFoundException ex) {
+            Log.e(TAG, "Global search activity not found: " + globalSearchActivity);
+        }
     }
 
     @Override
@@ -2102,7 +2141,7 @@
         copyFolderIconToImage(fi);
         fi.setVisibility(View.INVISIBLE);
 
-        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(mFolderIconImageView, alpha,
+        ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(mFolderIconImageView, alpha,
                 scaleX, scaleY);
         oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
         oa.start();
@@ -2119,7 +2158,7 @@
         // We remove and re-draw the FolderIcon in-case it has changed
         mDragLayer.removeView(mFolderIconImageView);
         copyFolderIconToImage(fi);
-        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(mFolderIconImageView, alpha,
+        ObjectAnimator oa = LauncherAnimUtils.ofPropertyValuesHolder(mFolderIconImageView, alpha,
                 scaleX, scaleY);
         oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
         oa.addListener(new AnimatorListenerAdapter() {
@@ -2413,7 +2452,7 @@
 
             // toView should appear right at the end of the workspace shrink
             // animation
-            mStateAnimation = new AnimatorSet();
+            mStateAnimation = LauncherAnimUtils.createAnimatorSet();
             mStateAnimation.play(scaleAnim).after(startDelay);
             mStateAnimation.play(alphaAnim).after(startDelay);
 
@@ -2588,7 +2627,7 @@
                 }
             });
 
-            mStateAnimation = new AnimatorSet();
+            mStateAnimation = LauncherAnimUtils.createAnimatorSet();
 
             dispatchOnLauncherTransitionPrepare(fromView, animated, true);
             dispatchOnLauncherTransitionPrepare(toView, animated, true);
@@ -2772,9 +2811,9 @@
                 mDividerAnimator = null;
             }
             if (animated) {
-                mDividerAnimator = new AnimatorSet();
-                mDividerAnimator.playTogether(ObjectAnimator.ofFloat(mQsbDivider, "alpha", 1f),
-                        ObjectAnimator.ofFloat(mDockDivider, "alpha", 1f));
+                mDividerAnimator = LauncherAnimUtils.createAnimatorSet();
+                mDividerAnimator.playTogether(LauncherAnimUtils.ofFloat(mQsbDivider, "alpha", 1f),
+                        LauncherAnimUtils.ofFloat(mDockDivider, "alpha", 1f));
                 mDividerAnimator.setDuration(mSearchDropTargetBar.getTransitionInDuration());
                 mDividerAnimator.start();
             }
@@ -3352,7 +3391,7 @@
      * @param immediate whether to run the animation or show the results immediately
      */
     private void runNewAppsAnimation(boolean immediate) {
-        AnimatorSet anim = new AnimatorSet();
+        AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
         Collection<Animator> bounceAnims = new ArrayList<Animator>();
 
         // Order these new views spatially so that they animate in order
@@ -3376,7 +3415,7 @@
         } else {
             for (int i = 0; i < mNewShortcutAnimateViews.size(); ++i) {
                 View v = mNewShortcutAnimateViews.get(i);
-                ValueAnimator bounceAnim = ObjectAnimator.ofPropertyValuesHolder(v,
+                ValueAnimator bounceAnim = LauncherAnimUtils.ofPropertyValuesHolder(v,
                         PropertyValuesHolder.ofFloat("alpha", 1f),
                         PropertyValuesHolder.ofFloat("scaleX", 1f),
                         PropertyValuesHolder.ofFloat("scaleY", 1f));
@@ -3584,7 +3623,7 @@
     }
     private void dismissCling(final Cling cling, final String flag, int duration) {
         if (cling != null) {
-            ObjectAnimator anim = ObjectAnimator.ofFloat(cling, "alpha", 0f);
+            ObjectAnimator anim = LauncherAnimUtils.ofFloat(cling, "alpha", 0f);
             anim.setDuration(duration);
             anim.addListener(new AnimatorListenerAdapter() {
                 public void onAnimationEnd(Animator animation) {
diff --git a/src/com/android/launcher2/LauncherAnimUtils.java b/src/com/android/launcher2/LauncherAnimUtils.java
new file mode 100644
index 0000000..182adf5
--- /dev/null
+++ b/src/com/android/launcher2/LauncherAnimUtils.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 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.launcher2;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+
+import java.util.HashSet;
+
+public class LauncherAnimUtils {
+    static HashSet<Animator> sAnimators = new HashSet<Animator>();
+    Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() {
+        public void onAnimationStart(Animator animation) {
+        }
+
+        public void onAnimationRepeat(Animator animation) {
+        }
+
+        public void onAnimationEnd(Animator animation) {
+            sAnimators.remove(animation);
+        }
+
+        public void onAnimationCancel(Animator animation) {
+            sAnimators.remove(animation);
+        }
+    };
+
+    public static void cancelOnDestroyActivity(Animator a) {
+        sAnimators.add(a);
+    }
+
+    public static void onDestroyActivity() {
+        for (Animator a : sAnimators) {
+            if (a.isRunning()) {
+                a.cancel();
+            }
+        }
+    }
+
+    public static AnimatorSet createAnimatorSet() {
+        AnimatorSet anim = new AnimatorSet();
+        cancelOnDestroyActivity(anim);
+        return anim;
+    }
+
+    public static ValueAnimator ofFloat(float... values) {
+        ValueAnimator anim = new ValueAnimator();
+        anim.setFloatValues(values);
+        cancelOnDestroyActivity(anim);
+        return anim;
+    }
+
+    public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
+        ObjectAnimator anim = new ObjectAnimator();
+        anim.setTarget(target);
+        anim.setPropertyName(propertyName);
+        anim.setFloatValues(values);
+        cancelOnDestroyActivity(anim);
+        return anim;
+    }
+
+    public static ObjectAnimator ofPropertyValuesHolder(Object target,
+            PropertyValuesHolder... values) {
+        ObjectAnimator anim = new ObjectAnimator();
+        anim.setTarget(target);
+        anim.setValues(values);
+        cancelOnDestroyActivity(anim);
+        return anim;
+    }
+}
diff --git a/src/com/android/launcher2/LauncherAppWidgetHost.java b/src/com/android/launcher2/LauncherAppWidgetHost.java
index 35c60a0..45c1d23 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHost.java
@@ -47,7 +47,6 @@
         clearViews();
     }
 
-    @Override
     protected void onProvidersChanged() {
         // Once we get the message that widget packages are updated, we need to rebind items
         // in AppsCustomize accordingly.
diff --git a/src/com/android/launcher2/LauncherViewPropertyAnimator.java b/src/com/android/launcher2/LauncherViewPropertyAnimator.java
index 88b4cb4..3ffc418 100644
--- a/src/com/android/launcher2/LauncherViewPropertyAnimator.java
+++ b/src/com/android/launcher2/LauncherViewPropertyAnimator.java
@@ -215,6 +215,7 @@
         }
         mViewPropertyAnimator.setListener(this);
         mViewPropertyAnimator.start();
+        LauncherAnimUtils.cancelOnDestroyActivity(this);
     }
 
     public LauncherViewPropertyAnimator translationX(float value) {
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index ad0baf4..4765dae 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -18,7 +18,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -791,20 +790,11 @@
                 canvas.clipRect(getScrollX(), getScrollY(), getScrollX() + getRight() - getLeft(),
                         getScrollY() + getBottom() - getTop());
 
-                // On certain graphics drivers, if you draw to a off-screen buffer that's not
-                // used, it can lead to poor performance. We were running into this when
-                // setChildrenLayersEnabled was called on a CellLayout; that triggered a re-draw
-                // of that CellLayout's hardware layer, even if that CellLayout wasn't visible.
-                // As a fix, below we set pages that aren't going to be rendered are to be
-                // View.INVISIBLE, preventing re-drawing of their hardware layer
                 for (int i = getChildCount() - 1; i >= 0; i--) {
                     final View v = getPageAt(i);
                     if (mForceDrawAllChildrenNextFrame ||
                                (leftScreen <= i && i <= rightScreen && shouldDrawChild(v))) {
-                        v.setVisibility(VISIBLE);
                         drawChild(canvas, v, drawingTime);
-                    } else {
-                        v.setVisibility(INVISIBLE);
                     }
                 }
                 mForceDrawAllChildrenNextFrame = false;
@@ -1756,7 +1746,7 @@
             if (immediately) {
                 mScrollIndicator.setAlpha(1f);
             } else {
-                mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 1f);
+                mScrollIndicatorAnimator = LauncherAnimUtils.ofFloat(mScrollIndicator, "alpha", 1f);
                 mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeInDuration);
                 mScrollIndicatorAnimator.start();
             }
@@ -1782,7 +1772,7 @@
                 mScrollIndicator.setVisibility(View.INVISIBLE);
                 mScrollIndicator.setAlpha(0f);
             } else {
-                mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 0f);
+                mScrollIndicatorAnimator = LauncherAnimUtils.ofFloat(mScrollIndicator, "alpha", 0f);
                 mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeOutDuration);
                 mScrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() {
                     private boolean cancelled = false;
diff --git a/src/com/android/launcher2/RocketLauncher.java b/src/com/android/launcher2/RocketLauncher.java
index 268769d..6eefedd 100644
--- a/src/com/android/launcher2/RocketLauncher.java
+++ b/src/com/android/launcher2/RocketLauncher.java
@@ -21,7 +21,6 @@
 package com.android.launcher2;
 
 import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
 import android.animation.TimeAnimator;
 import android.content.ComponentName;
 import android.content.Context;
@@ -150,11 +149,11 @@
                                 }
                             }, LAUNCH_ZOOM_TIME);
                             endscale = 0;
-                            AnimatorSet s = new AnimatorSet();
+                            AnimatorSet s = LauncherAnimUtils.createAnimatorSet();
                             s.playTogether(
-                                ObjectAnimator.ofFloat(this, "scaleX", 15f),
-                                ObjectAnimator.ofFloat(this, "scaleY", 15f),
-                                ObjectAnimator.ofFloat(this, "alpha", 0f)
+                                LauncherAnimUtils.ofFloat(this, "scaleX", 15f),
+                                LauncherAnimUtils.ofFloat(this, "scaleY", 15f),
+                                LauncherAnimUtils.ofFloat(this, "alpha", 0f)
                             );
 
                             // make sure things are still moving until the very last instant the
diff --git a/src/com/android/launcher2/SearchDropTargetBar.java b/src/com/android/launcher2/SearchDropTargetBar.java
index a1d36cd..fada48a 100644
--- a/src/com/android/launcher2/SearchDropTargetBar.java
+++ b/src/com/android/launcher2/SearchDropTargetBar.java
@@ -111,14 +111,14 @@
         // Create the various fade animations
         if (mEnableDropDownDropTargets) {
             mDropTargetBar.setTranslationY(-mBarHeight);
-            mDropTargetBarAnim = ObjectAnimator.ofFloat(mDropTargetBar, "translationY",
+            mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "translationY",
                     -mBarHeight, 0f);
-            mQSBSearchBarAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "translationY", 0,
+            mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
                     -mBarHeight);
         } else {
             mDropTargetBar.setAlpha(0f);
-            mDropTargetBarAnim = ObjectAnimator.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
-            mQSBSearchBarAnim = ObjectAnimator.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
+            mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
+            mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
         }
         setupAnimation(mDropTargetBarAnim, mDropTargetBar);
         setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
@@ -224,16 +224,14 @@
 
     public Rect getSearchBarBounds() {
         if (mQSBSearchBar != null) {
-            final float appScale = mQSBSearchBar.getContext().getResources()
-                    .getCompatibilityInfo().applicationScale;
             final int[] pos = new int[2];
             mQSBSearchBar.getLocationOnScreen(pos);
 
             final Rect rect = new Rect();
-            rect.left = (int) (pos[0] * appScale + 0.5f);
-            rect.top = (int) (pos[1] * appScale + 0.5f);
-            rect.right = (int) ((pos[0] + mQSBSearchBar.getWidth()) * appScale + 0.5f);
-            rect.bottom = (int) ((pos[1] + mQSBSearchBar.getHeight()) * appScale + 0.5f);
+            rect.left = pos[0];
+            rect.top = pos[1];
+            rect.right = pos[0] + mQSBSearchBar.getWidth();
+            rect.bottom = pos[1] + mQSBSearchBar.getHeight();
             return rect;
         } else {
             return null;
diff --git a/src/com/android/launcher2/Utilities.java b/src/com/android/launcher2/Utilities.java
index b27f7bb..d3e4516 100644
--- a/src/com/android/launcher2/Utilities.java
+++ b/src/com/android/launcher2/Utilities.java
@@ -29,7 +29,6 @@
 import android.graphics.PaintFlagsDrawFilter;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
-import android.graphics.TableMaskFilter;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.PaintDrawable;
@@ -243,9 +242,7 @@
 
         sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
         sGlowColorPressedPaint.setColor(0xffffc300);
-        sGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
         sGlowColorFocusedPaint.setColor(0xffff8e00);
-        sGlowColorFocusedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
 
         ColorMatrix cm = new ColorMatrix();
         cm.setSaturation(0.2f);
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 5a4a523..83b0329 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -273,6 +273,7 @@
         // With workspace, data is available straight from the get-go
         setDataIsReady();
 
+        mLauncher = (Launcher) context;
         final Resources res = getResources();
         mWorkspaceFadeInAdjacentScreens = res.getBoolean(R.bool.config_workspaceFadeAdjacentScreens);
         mFadeInAdjacentScreens = false;
@@ -291,20 +292,20 @@
             // landscape
             TypedArray actionBarSizeTypedArray =
                 context.obtainStyledAttributes(new int[] { android.R.attr.actionBarSize });
-            DisplayMetrics displayMetrics = res.getDisplayMetrics();
             final float actionBarHeight = actionBarSizeTypedArray.getDimension(0, 0f);
-            final float systemBarHeight = res.getDimension(R.dimen.status_bar_height);
-            final float smallestScreenDim = res.getConfiguration().smallestScreenWidthDp *
-                    displayMetrics.density;
+
+            Point minDims = new Point();
+            Point maxDims = new Point();
+            mLauncher.getWindowManager().getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
 
             cellCountX = 1;
-            while (CellLayout.widthInPortrait(res, cellCountX + 1) <= smallestScreenDim) {
+            while (CellLayout.widthInPortrait(res, cellCountX + 1) <= minDims.x) {
                 cellCountX++;
             }
 
             cellCountY = 1;
             while (actionBarHeight + CellLayout.heightInLandscape(res, cellCountY + 1)
-                <= smallestScreenDim - systemBarHeight) {
+                <= minDims.y) {
                 cellCountY++;
             }
         }
@@ -326,7 +327,6 @@
         LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
         setHapticFeedbackEnabled(false);
 
-        mLauncher = (Launcher) context;
         initWorkspace();
 
         // Disable multitouch across the workspace/all apps/customize tray
@@ -366,19 +366,9 @@
         return r;
     }
 
-    public void buildPageHardwareLayers() {
-        if (getWindowToken() != null) {
-            final int childCount = getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                CellLayout cl = (CellLayout) getChildAt(i);
-                cl.getShortcutsAndWidgets().buildLayer();
-            }
-        }
-    }
-
     public void onDragStart(DragSource source, Object info, int dragAction) {
         mIsDragOccuring = true;
-        updateChildrenLayersEnabled();
+        updateChildrenLayersEnabled(false);
         mLauncher.lockScreenOrientation();
         setChildrenBackgroundAlphaMultipliers(1f);
         // Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
@@ -388,7 +378,7 @@
 
     public void onDragEnd() {
         mIsDragOccuring = false;
-        updateChildrenLayersEnabled();
+        updateChildrenLayersEnabled(false);
         mLauncher.unlockScreenOrientation(false);
 
         // Re-enable any Un/InstallShortcutReceiver and now process any queued items
@@ -730,7 +720,7 @@
         super.onPageBeginMoving();
 
         if (isHardwareAccelerated()) {
-            updateChildrenLayersEnabled();
+            updateChildrenLayersEnabled(false);
         } else {
             if (mNextPage != INVALID_PAGE) {
                 // we're snapping to a particular screen
@@ -764,7 +754,7 @@
         super.onPageEndMoving();
 
         if (isHardwareAccelerated()) {
-            updateChildrenLayersEnabled();
+            updateChildrenLayersEnabled(false);
         } else {
             clearChildrenCache();
         }
@@ -839,10 +829,12 @@
     }
 
     protected void setWallpaperDimension() {
-        DisplayMetrics displayMetrics = new DisplayMetrics();
-        mLauncher.getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
-        final int maxDim = Math.max(displayMetrics.widthPixels, displayMetrics.heightPixels);
-        final int minDim = Math.min(displayMetrics.widthPixels, displayMetrics.heightPixels);
+        Point minDims = new Point();
+        Point maxDims = new Point();
+        mLauncher.getWindowManager().getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
+
+        final int maxDim = Math.max(maxDims.x, maxDims.y);
+        final int minDim = Math.min(minDims.x, minDims.y);
 
         // We need to ensure that there is enough extra space in the wallpaper for the intended
         // parallax effects
@@ -1090,7 +1082,7 @@
         if (!isSmall() && !mIsSwitchingState) {
             if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
             if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
-            mChildrenOutlineFadeInAnimation = ObjectAnimator.ofFloat(this, "childrenOutlineAlpha", 1.0f);
+            mChildrenOutlineFadeInAnimation = LauncherAnimUtils.ofFloat(this, "childrenOutlineAlpha", 1.0f);
             mChildrenOutlineFadeInAnimation.setDuration(CHILDREN_OUTLINE_FADE_IN_DURATION);
             mChildrenOutlineFadeInAnimation.start();
         }
@@ -1100,7 +1092,7 @@
         if (!isSmall() && !mIsSwitchingState) {
             if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
             if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
-            mChildrenOutlineFadeOutAnimation = ObjectAnimator.ofFloat(this, "childrenOutlineAlpha", 0.0f);
+            mChildrenOutlineFadeOutAnimation = LauncherAnimUtils.ofFloat(this, "childrenOutlineAlpha", 0.0f);
             mChildrenOutlineFadeOutAnimation.setDuration(CHILDREN_OUTLINE_FADE_OUT_DURATION);
             mChildrenOutlineFadeOutAnimation.setStartDelay(CHILDREN_OUTLINE_FADE_OUT_DELAY);
             mChildrenOutlineFadeOutAnimation.start();
@@ -1145,7 +1137,7 @@
         float startAlpha = getBackgroundAlpha();
         if (finalAlpha != startAlpha) {
             if (animated) {
-                mBackgroundFadeOutAnimation = ValueAnimator.ofFloat(startAlpha, finalAlpha);
+                mBackgroundFadeOutAnimation = LauncherAnimUtils.ofFloat(startAlpha, finalAlpha);
                 mBackgroundFadeOutAnimation.addUpdateListener(new AnimatorUpdateListener() {
                     public void onAnimationUpdate(ValueAnimator animation) {
                         setBackgroundAlpha(((Float) animation.getAnimatedValue()).floatValue());
@@ -1370,18 +1362,34 @@
         }
     }
 
-    private void updateChildrenLayersEnabled() {
+
+    private void updateChildrenLayersEnabled(boolean force) {
         boolean small = mState == State.SMALL || mIsSwitchingState;
-        boolean enableChildrenLayers = small || mAnimatingViewIntoPlace || isPageMoving();
+        boolean enableChildrenLayers = force || small || mAnimatingViewIntoPlace || isPageMoving();
 
         if (enableChildrenLayers != mChildrenLayersEnabled) {
             mChildrenLayersEnabled = enableChildrenLayers;
             for (int i = 0; i < getPageCount(); i++) {
-                ((ViewGroup)getChildAt(i)).setChildrenLayersEnabled(mChildrenLayersEnabled);
+                CellLayout cl = (CellLayout) getChildAt(i);
+                cl.getShortcutsAndWidgets().setLayerType(
+                        mChildrenLayersEnabled ? LAYER_TYPE_HARDWARE : LAYER_TYPE_NONE, null);
             }
         }
     }
 
+    public void buildPageHardwareLayers() {
+        // force layers to be enabled just for the call to buildLayer
+        updateChildrenLayersEnabled(true);
+        if (getWindowToken() != null) {
+            final int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                CellLayout cl = (CellLayout) getChildAt(i);
+                cl.getShortcutsAndWidgets().buildLayer();
+            }
+        }
+        updateChildrenLayersEnabled(false);
+    }
+
     protected void onWallpaperTap(MotionEvent ev) {
         final int[] position = mTempCell;
         getLocationOnScreen(position);
@@ -1515,7 +1523,7 @@
         // Initialize animation arrays for the first time if necessary
         initAnimationArrays();
 
-        AnimatorSet anim = animated ? new AnimatorSet() : null;
+        AnimatorSet anim = animated ? LauncherAnimUtils.createAnimatorSet() : null;
 
         // Stop any scrolling, move to the current page right away
         setCurrentPage(getNextPage());
@@ -1540,7 +1548,7 @@
             if (oldStateIsNormal && stateIsSmall) {
                 zoomIn = false;
                 setLayoutScale(finalScaleFactor);
-                updateChildrenLayersEnabled();
+                updateChildrenLayersEnabled(false);
             } else {
                 finalBackgroundAlpha = 1.0f;
                 setLayoutScale(finalScaleFactor);
@@ -1631,7 +1639,7 @@
                     }
                     if (mOldBackgroundAlphas[i] != 0 ||
                         mNewBackgroundAlphas[i] != 0) {
-                        ValueAnimator bgAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
+                        ValueAnimator bgAnim = LauncherAnimUtils.ofFloat(0f, 1f).setDuration(duration);
                         bgAnim.setInterpolator(mZoomInInterpolator);
                         bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
                                 public void onAnimationUpdate(float a, float b) {
@@ -1680,7 +1688,7 @@
     public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
         mIsSwitchingState = false;
         mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
-        updateChildrenLayersEnabled();
+        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
@@ -2262,7 +2270,7 @@
                 @Override
                 public void run() {
                     mAnimatingViewIntoPlace = false;
-                    updateChildrenLayersEnabled();
+                    updateChildrenLayersEnabled(false);
                     if (finalResizeRunnable != null) {
                         finalResizeRunnable.run();
                     }
@@ -3291,7 +3299,7 @@
 
         // hardware layers on children are enabled on startup, but should be disabled until
         // needed
-        updateChildrenLayersEnabled();
+        updateChildrenLayersEnabled(false);
         setWallpaperDimension();
     }