Also factor the floating rotation button into the active touch region

- The floating rotation button sits in the gesture region and touches
  over the button should not start the recents animation. Add a
  visibility callback to the floating rotation button in addition to
  the existing contextual button listener and update when needed.

Bug: 162775448
Bug: 161921293
Test: Repeatedly rotate with floating button
Test: atest SystemUITests:NavigationBarRotationContextTest

Change-Id: I798370b41041e4f02bb82f5aeb20b9ccc1d2a4e8
Merged-In: I798370b41041e4f02bb82f5aeb20b9ccc1d2a4e8
(cherry picked from commit 3e64e959ea6cf13c27b8ba3b583d25f0f9bb9ea8)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index 16b5a23..78742f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -33,6 +33,8 @@
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 import com.android.systemui.statusbar.policy.KeyButtonView;
 
+import java.util.function.Consumer;
+
 /** Containing logic for the rotation button on the physical left bottom corner of the screen. */
 public class FloatingRotationButton implements RotationButton {
 
@@ -48,6 +50,7 @@
     private boolean mCanShow = true;
 
     private RotationButtonController mRotationButtonController;
+    private Consumer<Boolean> mVisibilityChangedCallback;
 
     FloatingRotationButton(Context context) {
         mContext = context;
@@ -68,6 +71,11 @@
     }
 
     @Override
+    public void setVisibilityChangedCallback(Consumer<Boolean> visibilityChangedCallback) {
+        mVisibilityChangedCallback = visibilityChangedCallback;
+    }
+
+    @Override
     public View getCurrentView() {
         return mKeyButtonView;
     }
@@ -107,6 +115,16 @@
             mKeyButtonDrawable.resetAnimation();
             mKeyButtonDrawable.startAnimation();
         }
+        mKeyButtonView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5,
+                    int i6, int i7) {
+                if (mIsShowing && mVisibilityChangedCallback != null) {
+                    mVisibilityChangedCallback.accept(true);
+                }
+                mKeyButtonView.removeOnLayoutChangeListener(this);
+            }
+        });
         return true;
     }
 
@@ -117,6 +135,9 @@
         }
         mWindowManager.removeViewImmediate(mKeyButtonView);
         mIsShowing = false;
+        if (mVisibilityChangedCallback != null) {
+            mVisibilityChangedCallback.accept(false);
+        }
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index f3c4d05..e60293c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -354,15 +354,6 @@
                 }
             };
 
-    private final ContextButtonListener mRotationButtonListener = (button, visible) -> {
-        if (visible) {
-            // If the button will actually become visible and the navbar is about to hide,
-            // tell the statusbar to keep it around for longer
-            mAutoHideController.touchAutoHide();
-            mNavigationBarView.notifyActiveTouchRegions();
-        }
-    };
-
     private final Runnable mAutoDim = () -> getBarTransitions().setAutoDim(true);
 
     private final ContentObserver mAssistContentObserver = new ContentObserver(
@@ -522,8 +513,6 @@
 
         // Currently there is no accelerometer sensor on non-default display.
         if (mIsOnDefaultDisplay) {
-            mNavigationBarView.getRotateSuggestionButton().setListener(mRotationButtonListener);
-
             final RotationButtonController rotationButtonController =
                     mNavigationBarView.getRotationButtonController();
             rotationButtonController.addRotationCallback(mRotationWatcher);
@@ -1316,6 +1305,7 @@
         if (mAutoHideController != null) {
             mAutoHideController.setNavigationBar(mAutoHideUiElement);
         }
+        mNavigationBarView.setAutoHideController(autoHideController);
     }
 
     private boolean isTransientShown() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 9d95c30..93d4a5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -126,6 +126,7 @@
     private boolean mDeadZoneConsuming = false;
     private final NavigationBarTransitions mBarTransitions;
     private final OverviewProxyService mOverviewProxyService;
+    private AutoHideController mAutoHideController;
 
     // performs manual animation in sync with layout transitions
     private final NavTransitionListener mTransitionListener = new NavTransitionListener();
@@ -271,6 +272,15 @@
         info.touchableRegion.setEmpty();
     };
 
+    private final Consumer<Boolean> mRotationButtonListener = (visible) -> {
+        if (visible) {
+            // If the button will actually become visible and the navbar is about to hide,
+            // tell the statusbar to keep it around for longer
+            mAutoHideController.touchAutoHide();
+        }
+        notifyActiveTouchRegions();
+    };
+
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -301,7 +311,8 @@
         mFloatingRotationButton = new FloatingRotationButton(context);
         mRotationButtonController = new RotationButtonController(context,
                 R.style.RotateButtonCCWStart90,
-                isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton);
+                isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton,
+                mRotationButtonListener);
 
         mConfiguration = new Configuration();
         mTmpLastConfiguration = new Configuration();
@@ -349,6 +360,10 @@
                 });
     }
 
+    public void setAutoHideController(AutoHideController autoHideController) {
+        mAutoHideController = autoHideController;
+    }
+
     public NavigationBarTransitions getBarTransitions() {
         return mBarTransitions;
     }
@@ -936,7 +951,15 @@
         updateButtonLocation(getBackButton());
         updateButtonLocation(getHomeButton());
         updateButtonLocation(getRecentsButton());
-        updateButtonLocation(getRotateSuggestionButton());
+        updateButtonLocation(getImeSwitchButton());
+        updateButtonLocation(getAccessibilityButton());
+        if (mFloatingRotationButton.isVisible()) {
+            View floatingRotationView = mFloatingRotationButton.getCurrentView();
+            floatingRotationView.getBoundsOnScreen(mTmpBounds);
+            mActiveRegion.op(mTmpBounds, Op.UNION);
+        } else {
+            updateButtonLocation(getRotateSuggestionButton());
+        }
         mOverviewProxyService.onActiveNavBarRegionChanges(mActiveRegion);
     }
 
@@ -1208,6 +1231,7 @@
         dumpButton(pw, "rcnt", getRecentsButton());
         dumpButton(pw, "rota", getRotateSuggestionButton());
         dumpButton(pw, "a11y", getAccessibilityButton());
+        dumpButton(pw, "ime", getImeSwitchButton());
 
         pw.println("    }");
         pw.println("    mScreenOn: " + mScreenOn);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java
index 2580c0e..281207b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButton.java
@@ -20,9 +20,12 @@
 
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
+import java.util.function.Consumer;
+
 /** Interface of a rotation button that interacts {@link RotationButtonController}. */
 interface RotationButton {
     void setRotationButtonController(RotationButtonController rotationButtonController);
+    void setVisibilityChangedCallback(Consumer<Boolean> visibilityChangedCallback);
     View getCurrentView();
     boolean show();
     boolean hide();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
index 59b10e4..dbf5aa7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
@@ -117,7 +117,8 @@
         return (disable2Flags & StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS) != 0;
     }
 
-    RotationButtonController(Context context, @StyleRes int style, RotationButton rotationButton) {
+    RotationButtonController(Context context, @StyleRes int style, RotationButton rotationButton,
+            Consumer<Boolean> visibilityChangedCallback) {
         mContext = context;
         mRotationButton = rotationButton;
         mRotationButton.setRotationButtonController(this);
@@ -131,6 +132,7 @@
         mTaskStackListener = new TaskStackListenerImpl();
         mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
         mRotationButton.setOnHoverListener(this::onRotateSuggestionHover);
+        mRotationButton.setVisibilityChangedCallback(visibilityChangedCallback);
     }
 
     void registerListeners() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index bd96752..687c223 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -26,6 +26,8 @@
 
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
+import java.util.function.Consumer;
+
 /** Containing logic for the rotation button in nav bar. */
 public class RotationContextButton extends ContextualButton implements
         NavigationModeController.ModeChangedListener, RotationButton {
@@ -44,6 +46,18 @@
     }
 
     @Override
+    public void setVisibilityChangedCallback(Consumer<Boolean> visibilityChangedCallback) {
+        setListener(new ContextButtonListener() {
+            @Override
+            public void onVisibilityChanged(ContextualButton button, boolean visible) {
+                if (visibilityChangedCallback != null) {
+                    visibilityChangedCallback.accept(visible);
+                }
+            }
+        });
+    }
+
+    @Override
     public void setVisibility(int visibility) {
         super.setVisibility(visibility);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java
index d6b38ff..1b1ea31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java
@@ -60,7 +60,8 @@
         final View view = new View(mContext);
         mRotationButton = mock(RotationButton.class);
         mRotationButtonController = spy(
-                new RotationButtonController(mContext, RES_UNDEF, mRotationButton));
+                new RotationButtonController(mContext, RES_UNDEF, mRotationButton,
+                        (visibility) -> {}));
         final KeyButtonDrawable kbd = mock(KeyButtonDrawable.class);
         doReturn(view).when(mRotationButton).getCurrentView();
         doReturn(true).when(mRotationButton).acceptRotationProposal();