Merge "Fix talkback unable to select pip window buttons"
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 5723afd..c452f64 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -90,7 +90,7 @@
     public static final int MESSAGE_UPDATE_ACTIONS = 4;
     public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;
     public static final int MESSAGE_ANIMATION_ENDED = 6;
-    public static final int MESSAGE_TOUCH_EVENT = 7;
+    public static final int MESSAGE_POINTER_EVENT = 7;
 
     private static final int INITIAL_DISMISS_DELAY = 3500;
     private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
@@ -165,9 +165,9 @@
                     break;
                 }
 
-                case MESSAGE_TOUCH_EVENT: {
+                case MESSAGE_POINTER_EVENT: {
                     final MotionEvent ev = (MotionEvent) msg.obj;
-                    dispatchTouchEvent(ev);
+                    dispatchPointerEvent(ev);
                     break;
                 }
             }
@@ -219,6 +219,9 @@
         updateFromIntent(getIntent());
         setTitle(R.string.pip_menu_title);
         setDisablePreviewScreenshots(true);
+
+        // Hide without an animation.
+        getWindow().setExitTransition(null);
     }
 
     @Override
@@ -269,6 +272,17 @@
         }
     }
 
+    /**
+     * Dispatch a pointer event from {@link PipTouchHandler}.
+     */
+    private void dispatchPointerEvent(MotionEvent event) {
+        if (event.isTouchEvent()) {
+            dispatchTouchEvent(event);
+        } else {
+            dispatchGenericMotionEvent(event);
+        }
+    }
+
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         if (!mAllowTouches) {
@@ -288,8 +302,6 @@
     public void finish() {
         notifyActivityCallback(null);
         super.finish();
-        // Hide without an animation (the menu should already be invisible at this point)
-        overridePendingTransition(0, 0);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 62c59e5..b8e0b81 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -508,12 +508,12 @@
     }
 
     /**
-     * Handles touch event sent from pip input consumer.
+     * Handles a pointer event sent from pip input consumer.
      */
-    void handleTouchEvent(MotionEvent ev) {
+    void handlePointerEvent(MotionEvent ev) {
         if (mToActivityMessenger != null) {
             Message m = Message.obtain();
-            m.what = PipMenuActivity.MESSAGE_TOUCH_EVENT;
+            m.what = PipMenuActivity.MESSAGE_POINTER_EVENT;
             m.obj = ev;
             try {
                 mToActivityMessenger.send(m);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 1f36d97..f59b372 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -132,6 +132,7 @@
     private boolean mSendingHoverAccessibilityEvents;
     private boolean mMovementWithinMinimize;
     private boolean mMovementWithinDismiss;
+    private PipAccessibilityInteractionConnection mConnection;
 
     // Touch state
     private final PipTouchState mTouchState;
@@ -213,9 +214,10 @@
         // Register the listener for input consumer touch events
         inputConsumerController.setInputListener(this::handleTouchEvent);
         inputConsumerController.setRegistrationListener(this::onRegistrationChanged);
-        onRegistrationChanged(inputConsumerController.isRegistered());
 
         mPipBoundsHandler = pipBoundsHandler;
+        mConnection = new PipAccessibilityInteractionConnection(mMotionHelper,
+                this::onAccessibilityShowMenu, mHandler);
     }
 
     public void setTouchEnabled(boolean enabled) {
@@ -339,9 +341,7 @@
 
     private void onRegistrationChanged(boolean isRegistered) {
         mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
-                ? new PipAccessibilityInteractionConnection(mMotionHelper,
-                        this::onAccessibilityShowMenu, mHandler) : null);
-
+                ? mConnection : null);
         if (!isRegistered && mTouchState.isUserInteracting()) {
             // If the input consumer is unregistered while the user is interacting, then we may not
             // get the final TOUCH_UP event, so clean up the dismiss target as well
@@ -409,27 +409,15 @@
             }
             case MotionEvent.ACTION_HOVER_ENTER:
             case MotionEvent.ACTION_HOVER_MOVE: {
-                if (mAccessibilityManager.isEnabled() && !mSendingHoverAccessibilityEvents) {
-                    AccessibilityEvent event = AccessibilityEvent.obtain(
-                            AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
-                    event.setImportantForAccessibility(true);
-                    event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
-                    event.setWindowId(
-                            AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
-                    mAccessibilityManager.sendAccessibilityEvent(event);
+                if (!shouldDeliverToMenu && !mSendingHoverAccessibilityEvents) {
+                    sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
                     mSendingHoverAccessibilityEvents = true;
                 }
                 break;
             }
             case MotionEvent.ACTION_HOVER_EXIT: {
-                if (mAccessibilityManager.isEnabled() && mSendingHoverAccessibilityEvents) {
-                    AccessibilityEvent event = AccessibilityEvent.obtain(
-                            AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
-                    event.setImportantForAccessibility(true);
-                    event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
-                    event.setWindowId(
-                            AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
-                    mAccessibilityManager.sendAccessibilityEvent(event);
+                if (!shouldDeliverToMenu && mSendingHoverAccessibilityEvents) {
+                    sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
                     mSendingHoverAccessibilityEvents = false;
                 }
                 break;
@@ -445,12 +433,25 @@
                 mMenuController.pokeMenu();
             }
 
-            mMenuController.handleTouchEvent(cloneEvent);
+            mMenuController.handlePointerEvent(cloneEvent);
         }
 
         return true;
     }
 
+    private void sendAccessibilityHoverEvent(int type) {
+        if (!mAccessibilityManager.isEnabled()) {
+            return;
+        }
+
+        AccessibilityEvent event = AccessibilityEvent.obtain(type);
+        event.setImportantForAccessibility(true);
+        event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
+        event.setWindowId(
+                AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
+        mAccessibilityManager.sendAccessibilityEvent(event);
+    }
+
     /**
      * Updates the appearance of the menu and scrim on top of the PiP while dismissing.
      */
@@ -523,6 +524,10 @@
      * Sets the menu visibility.
      */
     private void setMenuState(int menuState, boolean resize) {
+        if (mMenuState == menuState && !resize) {
+            return;
+        }
+
         if (menuState == MENU_STATE_FULL && mMenuState != MENU_STATE_FULL) {
             // Save the current snap fraction and if we do not drag or move the PiP, then
             // we store back to this snap fraction.  Otherwise, we'll reset the snap
@@ -571,6 +576,9 @@
         }
         mMenuState = menuState;
         updateMovementBounds(menuState);
+        // If pip menu has dismissed, we should register the A11y ActionReplacingConnection for pip
+        // as well, or it can't handle a11y focus and pip menu can't perform any action.
+        onRegistrationChanged(menuState == MENU_STATE_NONE);
         if (menuState != MENU_STATE_CLOSE) {
             MetricsLoggerWrapper.logPictureInPictureMenuVisible(mContext, menuState == MENU_STATE_FULL);
         }