DessertCase memory improvements

  - reuse intermediate bitmaps when loading resources
  - only use hardware layers on views that are animating

Bug: 11269977
Change-Id: I39ad7aff16468632da47448404416404f3b54cc4
diff --git a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
index 90de65e..6fce732 100644
--- a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
@@ -17,6 +17,7 @@
 package com.android.systemui;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
@@ -166,15 +167,19 @@
         if (mCellSize < 512) { // assuming 512x512 images
             opts.inSampleSize = 2;
         }
+        opts.inMutable = true;
+        Bitmap loaded = null;
         for (int[] list : new int[][] { PASTRIES, RARE_PASTRIES, XRARE_PASTRIES, XXRARE_PASTRIES }) {
             for (int resid : list) {
-                final BitmapDrawable d = new BitmapDrawable(res,
-                        convertToAlphaMask(BitmapFactory.decodeResource(res, resid, opts)));
+                opts.inBitmap = loaded;
+                loaded = BitmapFactory.decodeResource(res, resid, opts);
+                final BitmapDrawable d = new BitmapDrawable(res, convertToAlphaMask(loaded));
                 d.setColorFilter(new ColorMatrixColorFilter(ALPHA_MASK));
                 d.setBounds(0, 0, mCellSize, mCellSize);
                 mDrawables.append(resid, d);
             }
         }
+        loaded = null;
         if (DEBUG) setWillNotDraw(false);
     }
 
@@ -304,8 +309,6 @@
                 v.getOverlay().add(d);
             }
 
-            v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-
             lp.width = lp.height = mCellSize;
             addView(v, lp);
             place(v, pt, false);
@@ -314,7 +317,7 @@
                 v.setScaleX(0.5f * s);
                 v.setScaleY(0.5f * s);
                 v.setAlpha(0f);
-                v.animate().scaleX(s).scaleY(s).alpha(1f).setDuration(animationLen);
+                v.animate().withLayer().scaleX(s).scaleY(s).alpha(1f).setDuration(animationLen);
             }
         }
     }
@@ -323,6 +326,21 @@
         place(v, new Point(irand(0, mColumns), irand(0, mRows)), animate);
     }
 
+    // we don't have .withLayer() on general Animators
+    private final Animator.AnimatorListener makeHardwareLayerListener(final View v) {
+        return new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animator) {
+                v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                v.buildLayer();
+            }
+            @Override
+            public void onAnimationEnd(Animator animator) {
+                v.setLayerType(View.LAYER_TYPE_NONE, null);
+            }
+        };
+    }
+
     private final HashSet<View> tmpSet = new HashSet<View>();
     public synchronized void place(View v, Point pt, boolean animate) {
         final int i = pt.x;
@@ -370,7 +388,8 @@
             if (squatter != v) {
                 squatter.setTag(TAG_POS, null);
                 if (animate) {
-                    squatter.animate().scaleX(0.5f).scaleY(0.5f).alpha(0)
+                    squatter.animate().withLayer()
+                            .scaleX(0.5f).scaleY(0.5f).alpha(0)
                             .setDuration(DURATION)
                             .setInterpolator(new AccelerateInterpolator())
                             .setListener(new Animator.AnimatorListener() {
@@ -397,6 +416,7 @@
 
         if (animate) {
             v.bringToFront();
+
             AnimatorSet set1 = new AnimatorSet();
             set1.playTogether(
                     ObjectAnimator.ofFloat(v, View.SCALE_X, (float) scale),
@@ -404,7 +424,6 @@
             );
             set1.setInterpolator(new AnticipateOvershootInterpolator());
             set1.setDuration(DURATION);
-            set1.start();
 
             AnimatorSet set2 = new AnimatorSet();
             set2.playTogether(
@@ -414,6 +433,10 @@
             );
             set2.setInterpolator(new DecelerateInterpolator());
             set2.setDuration(DURATION);
+
+            set1.addListener(makeHardwareLayerListener(v));
+
+            set1.start();
             set2.start();
         } else {
             v.setX(i * mCellSize + (scale-1) * mCellSize /2);