OSDN Git Service

Fixing crash when ActivityManager does not have a proper thumbnail
authorWinson Chung <winsonc@google.com>
Sat, 15 Mar 2014 00:52:47 +0000 (17:52 -0700)
committerWinson Chung <winsonc@google.com>
Sat, 15 Mar 2014 00:52:47 +0000 (17:52 -0700)
- Fixing issue with hw layers ref count not properly being incremented and decremented
- Preventing message handler from keeping a strong ref to the RecentsService

packages/SystemUI/src/com/android/systemui/recents/Constants.java
packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java

index 34dd726..62da17e 100644 (file)
@@ -31,7 +31,7 @@ public class Constants {
             // This disables the bitmap and icon caches to
             public static final boolean DisableBackgroundCache = false;
 
-            public static final boolean TaskDataLoader = true;
+            public static final boolean TaskDataLoader = false;
             public static final boolean SystemUIHandshake = false;
             public static final boolean TimeSystemCalls = false;
             public static final boolean Memory = false;
@@ -43,7 +43,7 @@ public class Constants {
             public static final boolean TouchEvents = false;
             public static final boolean MeasureAndLayout = false;
             public static final boolean Clipping = false;
-            public static final boolean HwLayers = true;
+            public static final boolean HwLayers = false;
         }
 
         public static class TaskStack {
index 13a3424..46ff841 100644 (file)
@@ -30,18 +30,31 @@ import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.TaskStackView;
 import com.android.systemui.recents.views.TaskViewTransform;
 
+import java.lang.ref.WeakReference;
+
 
 /* Service */
 public class RecentsService extends Service {
     // XXX: This should be getting the message from recents definition
     final static int MSG_UPDATE_RECENTS_FOR_CONFIGURATION = 0;
 
-    class MessageHandler extends Handler {
+    /** This Handler should be static to prevent holding onto a reference to the service. */
+    static class MessageHandler extends Handler {
+        WeakReference<Context> mContext;
+
+        MessageHandler(Context context) {
+            // Keep a weak ref to the context instead of a strong ref
+            mContext = new WeakReference<Context>(context);
+        }
+
         @Override
         public void handleMessage(Message msg) {
-            Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsService|handleMessage]", msg);
+            Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                    "[RecentsService|handleMessage]", msg);
             if (msg.what == MSG_UPDATE_RECENTS_FOR_CONFIGURATION) {
-                Context context = RecentsService.this;
+                Context context = mContext.get();
+                if (context == null) return;
+
                 RecentsTaskLoader.initialize(context);
                 RecentsConfiguration.reinitialize(context);
 
@@ -70,7 +83,7 @@ public class RecentsService extends Service {
         }
     }
 
-    Messenger mMessenger = new Messenger(new MessageHandler());
+    Messenger mMessenger = new Messenger(new MessageHandler(this));
 
     @Override
     public void onCreate() {
index c8576b2..253b8e3 100644 (file)
@@ -162,11 +162,13 @@ class TaskResourceLoader implements Runnable {
                                     PackageManager.GET_META_DATA);
                             Drawable icon = info.loadIcon(pm);
                             if (!mCancelled) {
-                                Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                                        "    [TaskResourceLoader|loadIcon]",
-                                        icon);
-                                loadIcon = icon;
-                                mIconCache.put(t.key, icon);
+                                if (icon != null) {
+                                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                                            "    [TaskResourceLoader|loadIcon]",
+                                            icon);
+                                    loadIcon = icon;
+                                    mIconCache.put(t.key, icon);
+                                }
                             }
                         }
                         // Load the thumbnail
@@ -387,7 +389,11 @@ public class RecentsTaskLoader {
                     }
                     if (task.icon == null) {
                         task.icon = info.loadIcon(pm);
-                        mIconCache.put(task.key, task.icon);
+                        if (task.icon != null) {
+                            mIconCache.put(task.key, task.icon);
+                        } else {
+                            task.icon = mDefaultIcon;
+                        }
                     }
 
                     // Load the thumbnail (if possible and not the foremost task, from the cache)
@@ -398,7 +404,11 @@ public class RecentsTaskLoader {
                         Console.log(Constants.DebugFlags.App.TaskDataLoader,
                                 "[RecentsTaskLoader|loadingTaskThumbnail]");
                         task.thumbnail = am.getTaskTopThumbnail(t.id);
-                        mThumbnailCache.put(task.key, task.thumbnail);
+                        if (task.thumbnail != null) {
+                            mThumbnailCache.put(task.key, task.thumbnail);
+                        } else {
+                            task.thumbnail = mDefaultThumbnail;
+                        }
                     }
 
                     // Create as many tasks a we want to multiply by
index 32110cf..c85c14b 100644 (file)
@@ -90,7 +90,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
         int width = MeasureSpec.getSize(widthMeasureSpec);
         int height = MeasureSpec.getSize(heightMeasureSpec);
         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[RecentsView|measure]", "width: " + width + " height: " + height, Console.AnsiGreen);
+        Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[RecentsView|measure]",
+                "width: " + width + " height: " + height, Console.AnsiGreen);
 
         // We measure our stack views sans the status bar.  It will handle the nav bar itself.
         RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -111,7 +112,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[RecentsView|layout]", new Rect(left, top, right, bottom) + " changed: " + changed, Console.AnsiGreen);
+        Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[RecentsView|layout]",
+                new Rect(left, top, right, bottom) + " changed: " + changed, Console.AnsiGreen);
         // We offset our stack views by the status bar height.  It will handle the nav bar itself.
         RecentsConfiguration config = RecentsConfiguration.getInstance();
         top += config.systemInsets.top;
index a3ed535..17660d8 100644 (file)
@@ -243,10 +243,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
         int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
         if (newScroll != curScroll) {
             // Enable hw layers on the stack
-            addHwLayersRefCount();
+            addHwLayersRefCount("animateBoundScroll");
 
             // Abort any current animations
-            mScroller.abortAnimation();
+            abortScroller();
             if (mScrollAnimator != null) {
                 mScrollAnimator.cancel();
                 mScrollAnimator.removeAllListeners();
@@ -265,7 +265,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     // Disable hw layers on the stack
-                    decHwLayersRefCount();
+                    decHwLayersRefCount("animateBoundScroll");
                 }
             });
             mScrollAnimator.start();
@@ -280,6 +280,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
         }
     }
 
+    void abortScroller() {
+        if (!mScroller.isFinished()) {
+            // Abort the scroller
+            mScroller.abortAnimation();
+            // And disable hw layers on the stack
+            decHwLayersRefCount("flingScroll");
+        }
+    }
+
     /** Bounds the current scroll if necessary */
     public boolean boundScroll() {
         int curScroll = getStackScroll();
@@ -319,10 +328,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
     }
 
     /** Enables the hw layers and increments the hw layer requirement ref count */
-    void addHwLayersRefCount() {
+    void addHwLayersRefCount(String reason) {
         Console.log(Constants.DebugFlags.UI.HwLayers,
                 "[TaskStackView|addHwLayersRefCount] refCount: " +
-                        mHwLayersRefCount + "->" + (mHwLayersRefCount + 1));
+                        mHwLayersRefCount + "->" + (mHwLayersRefCount + 1) + " " + reason);
         if (mHwLayersRefCount == 0) {
             // Enable hw layers on each of the children
             int childCount = getChildCount();
@@ -336,10 +345,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
 
     /** Decrements the hw layer requirement ref count and disables the hw layers when we don't
         need them anymore. */
-    void decHwLayersRefCount() {
+    void decHwLayersRefCount(String reason) {
         Console.log(Constants.DebugFlags.UI.HwLayers,
                 "[TaskStackView|decHwLayersRefCount] refCount: " +
-                        mHwLayersRefCount + "->" + (mHwLayersRefCount - 1));
+                        mHwLayersRefCount + "->" + (mHwLayersRefCount - 1) + " " + reason);
         mHwLayersRefCount--;
         if (mHwLayersRefCount == 0) {
             // Disable hw layers on each of the children
@@ -362,7 +371,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
 
             // If we just finished scrolling, then disable the hw layers
             if (mScroller.isFinished()) {
-                decHwLayersRefCount();
+                decHwLayersRefCount("finishedFlingScroll");
             }
         }
     }
@@ -775,15 +784,13 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                 mActivePointerId = ev.getPointerId(0);
                 mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
                 // Stop the current scroll if it is still flinging
-                mSv.mScroller.abortAnimation();
+                mSv.abortScroller();
                 mSv.abortBoundScrollAnimation();
                 // Initialize the velocity tracker
                 initOrResetVelocityTracker();
                 mVelocityTracker.addMovement(ev);
                 // Check if the scroller is finished yet
                 mIsScrolling = !mSv.mScroller.isFinished();
-                // Enable HW layers
-                mSv.addHwLayersRefCount();
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
@@ -803,6 +810,8 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                     if (parent != null) {
                         parent.requestDisallowInterceptTouchEvent(true);
                     }
+                    // Enable HW layers
+                    mSv.addHwLayersRefCount("stackScroll");
                 }
 
                 mLastMotionX = x;
@@ -813,14 +822,16 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
             case MotionEvent.ACTION_UP: {
                 // Animate the scroll back if we've cancelled
                 mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+                // Disable HW layers
+                if (mIsScrolling) {
+                    mSv.decHwLayersRefCount("stackScroll");
+                }
                 // Reset the drag state and the velocity tracker
                 mIsScrolling = false;
                 mActivePointerId = INACTIVE_POINTER_ID;
                 mActiveTaskView = null;
                 mTotalScrollMotion = 0;
                 recycleVelocityTracker();
-                // Disable HW layers
-                mSv.decHwLayersRefCount();
                 break;
             }
         }
@@ -858,7 +869,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                 mActivePointerId = ev.getPointerId(0);
                 mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
                 // Stop the current scroll if it is still flinging
-                mSv.mScroller.abortAnimation();
+                mSv.abortScroller();
                 mSv.abortBoundScrollAnimation();
                 // Initialize the velocity tracker
                 initOrResetVelocityTracker();
@@ -889,7 +900,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                             parent.requestDisallowInterceptTouchEvent(true);
                         }
                         // Enable HW layers
-                        mSv.addHwLayersRefCount();
+                        mSv.addHwLayersRefCount("stackScroll");
                     }
                 }
                 if (mIsScrolling) {
@@ -914,7 +925,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                         "scroll: " + mSv.getStackScroll() + " velocity: " + velocity,
                             Console.AnsiGreen);
                     // Enable HW layers on the stack
-                    mSv.addHwLayersRefCount();
+                    mSv.addHwLayersRefCount("flingScroll");
                     // Fling scroll
                     mSv.mScroller.fling(0, mSv.getStackScroll(),
                             0, -velocity,
@@ -929,27 +940,30 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                     mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
                 }
 
+                if (mIsScrolling) {
+                    // Disable HW layers
+                    mSv.decHwLayersRefCount("stackScroll");
+                }
                 mActivePointerId = INACTIVE_POINTER_ID;
                 mIsScrolling = false;
                 mTotalScrollMotion = 0;
                 recycleVelocityTracker();
-                // Disable HW layers
-                mSv.decHwLayersRefCount();
                 break;
             }
             case MotionEvent.ACTION_CANCEL: {
+                if (mIsScrolling) {
+                    // Disable HW layers
+                    mSv.decHwLayersRefCount("stackScroll");
+                }
                 if (mSv.isScrollOutOfBounds()) {
                     // Animate the scroll back into bounds
                     // XXX: Make this animation a function of the velocity OR distance
                     mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
                 }
-
                 mActivePointerId = INACTIVE_POINTER_ID;
                 mIsScrolling = false;
                 mTotalScrollMotion = 0;
                 recycleVelocityTracker();
-                // Disable HW layers
-                mSv.decHwLayersRefCount();
                 break;
             }
         }
@@ -971,7 +985,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
     @Override
     public void onBeginDrag(View v) {
         // Enable HW layers
-        mSv.addHwLayersRefCount();
+        mSv.addHwLayersRefCount("swipeBegin");
         // Disallow parents from intercepting touch events
         final ViewParent parent = mSv.getParent();
         if (parent != null) {
@@ -1010,7 +1024,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
         }
 
         // Disable HW layers
-        mSv.decHwLayersRefCount();
+        mSv.decHwLayersRefCount("swipeComplete");
     }
 
     @Override
@@ -1021,6 +1035,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
     @Override
     public void onDragCancelled(View v) {
         // Disable HW layers
-        mSv.decHwLayersRefCount();
+        mSv.decHwLayersRefCount("swipeCancelled");
     }
 }