From f0a60a9c60d9973e10a859dd8c31b8f18adb5a0e Mon Sep 17 00:00:00 2001 From: Wale Ogunwale Date: Thu, 19 Jan 2017 09:44:40 -0800 Subject: [PATCH] Workaround for leaked dim layer. Tasks are some how leaking their dim layer. The root cause of Task not properly cleaning-up its dim layer in Task.removeImmediately() hasn't being identified, but the CL will prevent user devices from getting into a bad state until we figure-out the cause for the leak. Note that when this occurs the task has been completely removed from the system and the only reference left to it is for the dim layer... Bug: 34395537 Test: This is a workaround until the real problem is identified. Change-Id: Id8d45edb3b6858be82e4f057ae3da480da4f4b59 --- .../java/com/android/server/wm/DimLayer.java | 2 ++ .../android/server/wm/DimLayerController.java | 17 +++++++++++++++-- .../server/wm/DockedStackDividerController.java | 5 +++++ .../core/java/com/android/server/wm/Task.java | 7 ++++++- .../com/android/server/wm/TaskPositioner.java | 5 +++++ .../java/com/android/server/wm/TaskStack.java | 5 +++++ 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java index b99dda15b22e6..015c084667080 100644 --- a/services/core/java/com/android/server/wm/DimLayer.java +++ b/services/core/java/com/android/server/wm/DimLayer.java @@ -77,6 +77,8 @@ public class DimLayer { boolean dimFullscreen(); /** Returns the display info. of the dim layer user. */ DisplayInfo getDisplayInfo(); + /** Returns true if the dim layer user is currently attached to a display */ + boolean isAttachedToDisplay(); /** Gets the bounds of the dim layer user. */ void getDimBounds(Rect outBounds); String toShortString(); diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java index 04ae72f97e935..2ec2dba888889 100644 --- a/services/core/java/com/android/server/wm/DimLayerController.java +++ b/services/core/java/com/android/server/wm/DimLayerController.java @@ -191,8 +191,21 @@ class DimLayerController { boolean result = false; for (int i = mState.size() - 1; i >= 0; i--) { - DimLayer.DimLayerUser user = mState.keyAt(i); - DimLayerState state = mState.valueAt(i); + final DimLayer.DimLayerUser user = mState.keyAt(i); + final DimLayerState state = mState.valueAt(i); + + if (!user.isAttachedToDisplay()) { + // Leaked dim user that is no longer attached to the display. Go ahead and clean it + // clean-up and log what happened. + // TODO: This is a work around for b/34395537 as the dim user should have cleaned-up + // it self when it was detached from the display. Need to investigate how the dim + // user is leaking... + Slog.wtfStack(TAG_WM, "Leaked dim user=" + user.toShortString() + + " state=" + state); + removeDimLayerUser(user); + continue; + } + // We have to check that we are actually the shared fullscreen layer // for this path. If we began as non fullscreen and became fullscreen // (e.g. Docked stack closing), then we may not be the shared layer diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index e6bc7f44ab0cd..ed1e2d998d63c 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -834,6 +834,11 @@ public class DockedStackDividerController implements DimLayerUser { return mDisplayContent.getDisplayInfo(); } + @Override + public boolean isAttachedToDisplay() { + return mDisplayContent != null; + } + @Override public void getDimBounds(Rect outBounds) { // This dim layer user doesn't need this. diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 824d4606dfe94..680d0f2881a6b 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -628,7 +628,12 @@ class Task extends WindowContainer implements DimLayer.DimLayerU @Override public DisplayInfo getDisplayInfo() { - return mStack.getDisplayContent().getDisplayInfo(); + return getDisplayContent().getDisplayInfo(); + } + + @Override + public boolean isAttachedToDisplay() { + return getDisplayContent() != null; } void forceWindowsScaleable(boolean force) { diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 267566bfd6f7d..7bc577eae468b 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -692,6 +692,11 @@ class TaskPositioner implements DimLayer.DimLayerUser { return mTask.mStack.getDisplayInfo(); } + @Override + public boolean isAttachedToDisplay() { + return mTask != null && mTask.getDisplayContent() != null; + } + @Override public void getDimBounds(Rect out) { // This dim layer user doesn't need this. diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index eeea532858f13..bebc745443725 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -1208,6 +1208,11 @@ public class TaskStack extends WindowContainer implements DimLayer.DimLaye return mDisplayContent.getDisplayInfo(); } + @Override + public boolean isAttachedToDisplay() { + return mDisplayContent != null; + } + @Override public String toString() { return "{stackId=" + mStackId + " tasks=" + mChildren + "}";