Fix weirdness when home task forces rotation

- Make sure to retain the state when divider goes through a configuration
change in order to avoid that nothing happens when entering multi-window.
Save the state in DividerState and use a handler that's independant of the
attached state.
- Don't allow home task to dictate orientation unless the docked stack is
minimized. This caused a lot of weird bugs because when docking a task,
home stack gets moved to front, and if home task is front of stack, it
temporarily might dictate the rotation but later not anymore so this
causes two rapid configuration changes which may cause a lot of weirdness.

Change-Id: I6a2308af893cd8413ee8801e5b964f6ddc0abd51
Fixes: 28943853
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index e89c136..a0bae20 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -39,6 +39,7 @@
 public class Divider extends SystemUI {
     private DividerWindowManager mWindowManager;
     private DividerView mView;
+    private final DividerState mDividerState = new DividerState();
     private DockDividerVisibilityListener mDockDividerVisibilityListener;
     private boolean mVisible = false;
     private boolean mMinimized = false;
@@ -76,7 +77,7 @@
         final int width = landscape ? size : MATCH_PARENT;
         final int height = landscape ? MATCH_PARENT : size;
         mWindowManager.add(mView, width, height);
-        mView.setWindowManager(mWindowManager);
+        mView.injectDependencies(mWindowManager, mDividerState);
     }
 
     private void removeDivider() {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
new file mode 100644
index 0000000..353a974
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.stackdivider;
+
+/**
+ * Class to hold state of divider that needs to persist across configuration changes.
+ */
+public class DividerState {
+    public boolean animateAfterRecentsDrawn;
+    public boolean growAfterRecentsDrawn;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index f728aa4..d09587b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -30,12 +30,12 @@
 import android.graphics.Region.Op;
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
+import android.os.Handler;
 import android.util.AttributeSet;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.GestureDetector;
 import android.view.GestureDetector.SimpleOnGestureListener;
-import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.VelocityTracker;
@@ -141,8 +141,6 @@
     private DividerSnapAlgorithm mSnapAlgorithm;
     private final Rect mStableInsets = new Rect();
 
-    private boolean mAnimateAfterRecentsDrawn;
-    private boolean mGrowAfterRecentsDrawn;
     private boolean mGrowRecents;
     private ValueAnimator mCurrentAnimator;
     private boolean mEntranceAnimationRunning;
@@ -151,6 +149,8 @@
     private GestureDetector mGestureDetector;
     private boolean mDockedStackMinimized;
     private boolean mAdjustedForIme;
+    private DividerState mState;
+    private final Handler mHandler = new Handler();
 
     private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
         @Override
@@ -335,8 +335,9 @@
         }
     }
 
-    public void setWindowManager(DividerWindowManager windowManager) {
+    public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState) {
         mWindowManager = windowManager;
+        mState = dividerState;
     }
 
     public WindowManagerProxy getWindowManagerProxy() {
@@ -558,7 +559,7 @@
                 if (endDelay == 0 || mCancelled) {
                     endAction.run();
                 } else {
-                    postDelayed(endAction, endDelay);
+                    mHandler.postDelayed(endAction, endDelay);
                 }
             }
         });
@@ -1048,15 +1049,15 @@
     public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
         if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP
                 && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
-            mGrowAfterRecentsDrawn = true;
+            mState.growAfterRecentsDrawn = true;
             startDragging(false /* animate */, false /* touching */);
         }
     }
 
     public final void onBusEvent(DockedTopTaskEvent event) {
         if (event.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) {
-            mGrowAfterRecentsDrawn = false;
-            mAnimateAfterRecentsDrawn = true;
+            mState.growAfterRecentsDrawn = false;
+            mState.animateAfterRecentsDrawn = true;
             startDragging(false /* animate */, false /* touching */);
         }
         updateDockSide();
@@ -1068,11 +1069,11 @@
     }
 
     public final void onBusEvent(RecentsDrawnEvent drawnEvent) {
-        if (mAnimateAfterRecentsDrawn) {
-            mAnimateAfterRecentsDrawn = false;
+        if (mState.animateAfterRecentsDrawn) {
+            mState.animateAfterRecentsDrawn = false;
             updateDockSide();
 
-            post(() -> {
+            mHandler.post(() -> {
                 // Delay switching resizing mode because this might cause jank in recents animation
                 // that's longer than this animation.
                 stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(),
@@ -1080,8 +1081,8 @@
                         200 /* endDelay */);
             });
         }
-        if (mGrowAfterRecentsDrawn) {
-            mGrowAfterRecentsDrawn = false;
+        if (mState.growAfterRecentsDrawn) {
+            mState.growAfterRecentsDrawn = false;
             updateDockSide();
             EventBus.getDefault().send(new RecentsGrowingEvent());
             stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 336,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 08256e6..3f4c1d5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3569,6 +3569,8 @@
         final ArrayList<Task> tasks = displayContent.getTasks();
         final boolean inMultiWindow = isStackVisibleLocked(DOCKED_STACK_ID)
                 || isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID);
+        final boolean dockMinimized =
+                getDefaultDisplayContentLocked().mDividerControllerLocked.isMinimizedDock();
         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
             final int firstToken = tokens.size() - 1;
@@ -3603,8 +3605,10 @@
                     continue;
                 }
 
-                // No app except the home app may specify the screen orientation in multi-window.
-                if (inMultiWindow && !atoken.mTask.isHomeTask()) {
+                // No app except the home app may specify the screen orientation in multi-window,
+                // and only if the docked stack is minimized to avoid weirdness when home task
+                // temporarily gets moved to the front.
+                if (inMultiWindow && (!atoken.mTask.isHomeTask() || !dockMinimized)) {
                     continue;
                 }