OSDN Git Service

Reset docked divider to the middle of the screen if sys-ui dies
authorWale Ogunwale <ogunwale@google.com>
Fri, 5 Feb 2016 02:04:39 +0000 (18:04 -0800)
committerWale Ogunwale <ogunwale@google.com>
Fri, 5 Feb 2016 02:51:48 +0000 (18:51 -0800)
It is possible for the docked divider to be in an unstable location
when sys-ui dies. E.g sys-ui animating the divider from behind the
nav bar. When this occurs we reset the divider to the middle of the
screen so that the system remains in a useable state. Otherwise, the
docked stack can be fullscreen always preventing the user from going
into any other application.

Bug: 26965731
Change-Id: Icd254fffe69da4ee3f2efb4ff1d210a778703f64

services/core/java/com/android/server/wm/TaskStack.java
services/core/java/com/android/server/wm/WindowState.java

index 5b93979..40ca1c5 100644 (file)
@@ -585,7 +585,8 @@ public class TaskStack implements DimLayer.DimLayerUser,
     }
 
     void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
-        if (!StackId.isResizeableByDockedStack(mStackId) || mDisplayContent == null) {
+        if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
+                || mDisplayContent == null) {
             outBounds.set(mBounds);
             return;
         }
@@ -614,8 +615,7 @@ public class TaskStack implements DimLayer.DimLayerUser,
 
         mDisplayContent.getLogicalDisplayRect(mTmpRect);
         dockedStack.getRawBounds(mTmpRect2);
-        final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP
-                || dockedSide == DOCKED_LEFT;
+        final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
         getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2,
                 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
 
@@ -720,6 +720,19 @@ public class TaskStack implements DimLayer.DimLayerUser,
         }
     }
 
+    void resetDockedStackToMiddle() {
+        if (mStackId != DOCKED_STACK_ID) {
+            throw new IllegalStateException("Not a docked stack=" + this);
+        }
+
+        mService.mDockedStackCreateBounds = null;
+
+        final Rect bounds = new Rect();
+        getStackDockedModeBoundsLocked(bounds, true /*ignoreVisibility*/);
+        mService.mH.obtainMessage(RESIZE_STACK, DOCKED_STACK_ID,
+                1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
+    }
+
     void detachDisplay() {
         EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
 
index 1f7b810..2f916d9 100644 (file)
@@ -57,6 +57,7 @@ import java.io.PrintWriter;
 import java.util.ArrayList;
 
 import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
@@ -1608,6 +1609,14 @@ final class WindowState implements WindowManagerPolicy.WindowState {
                             win.mAppToken.appDied = true;
                         }
                         mService.removeWindowLocked(win);
+                        if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
+                            // The owner of the docked divider died :( We reset the docked stack,
+                            // just in case they have the divider at an unstable position.
+                            final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
+                            if (stack != null) {
+                                stack.resetDockedStackToMiddle();
+                            }
+                        }
                     } else if (mHasSurface) {
                         Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
                         mService.removeWindowLocked(WindowState.this);