Fixed a few memory leaks in SystemUI

Fist of all we made the statemap a weak hashmap in order never
to leak any views anymore.

Another leak could occur because predrawlisteners were added twice
but removal only removes one. A view was then leaked in case it was detached
before predraw.

Also fixed a leak when transforming the header because a state wasn't
nulled.

Change-Id: I2573a506c307196ef60c905dc823ea8a95e91a16
Fixes: 28945863
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 32b61cd..06863ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -359,7 +359,9 @@
 
     private void setVisible(final boolean isVisible) {
         if (isVisible) {
-
+            // This call can happen multiple times, but removing only removes a single one.
+            // We therefore need to remove the old one.
+            getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
             // We only animate if we are drawn at least once, otherwise the view might animate when
             // it's shown the first time
             getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
index b66e9f3..8463e06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
@@ -109,9 +109,6 @@
     @Override
     public void recycle() {
         super.recycle();
-        if (mWorkProfileState != null) {
-            mWorkProfileState.recycle();
-        }
         sInstancePool.release(this);
     }
 
@@ -120,6 +117,10 @@
         super.reset();
         mExpandButton = null;
         mWorkProfileState = null;
+        if (mWorkProfileState != null) {
+            mWorkProfileState.recycle();
+            mWorkProfileState = null;
+        }
     }
 
     public void setVisible(boolean visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index d6c5506..8f0cd8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -26,9 +26,8 @@
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
 
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
+import java.util.WeakHashMap;
 
 /**
  * A state of a {@link com.android.systemui.statusbar.stack.NotificationStackScrollLayout} which
@@ -39,12 +38,12 @@
     private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
 
     private final ViewGroup mHostView;
-    private Map<ExpandableView, StackViewState> mStateMap;
+    private WeakHashMap<ExpandableView, StackViewState> mStateMap;
     private final int mClearAllTopPadding;
 
     public StackScrollState(ViewGroup hostView) {
         mHostView = hostView;
-        mStateMap = new HashMap<ExpandableView, StackViewState>();
+        mStateMap = new WeakHashMap<>();
         mClearAllTopPadding = hostView.getContext().getResources().getDimensionPixelSize(
                 R.dimen.clear_all_padding_top);
     }