Fix talkback unable to select pip window buttons
While talkback enabled, single touch would be translated to hover events, and all touch events would first sent to pip input consumer then dispatch them to pip menu activity. So we should dispatch these hover events to dispatchGenericMotionEvent of menu activity to make sure them would be handled correctly. - It should unregister PictureInPictureActionReplacingConnection when menu activity shown to make sure a11y action can be performed by default. - Move overridePendingTransition to onCreate to ensure a11y window infos can be updated after first time finish. Bug: 142268623 Test: Enable talkback and launch pip, click buttons on pip window Test: atest AbstractAccessibilityServiceConnectionTest Change-Id: I886106d3d36c54e4540e25056c79dad5c82405e8
This commit is contained in:
@@ -90,7 +90,7 @@ public class PipMenuActivity extends Activity {
|
||||
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 @@ public class PipMenuActivity extends Activity {
|
||||
break;
|
||||
}
|
||||
|
||||
case MESSAGE_TOUCH_EVENT: {
|
||||
case MESSAGE_POINTER_EVENT: {
|
||||
final MotionEvent ev = (MotionEvent) msg.obj;
|
||||
dispatchTouchEvent(ev);
|
||||
dispatchPointerEvent(ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -219,6 +219,9 @@ public class PipMenuActivity extends Activity {
|
||||
updateFromIntent(getIntent());
|
||||
setTitle(R.string.pip_menu_title);
|
||||
setDisablePreviewScreenshots(true);
|
||||
|
||||
// Hide without an animation.
|
||||
getWindow().setExitTransition(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -269,6 +272,17 @@ public class PipMenuActivity extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class PipMenuActivity extends Activity {
|
||||
public void finish() {
|
||||
notifyActivityCallback(null);
|
||||
super.finish();
|
||||
// Hide without an animation (the menu should already be invisible at this point)
|
||||
overridePendingTransition(0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -508,12 +508,12 @@ public class PipMenuActivityController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
@@ -132,6 +132,7 @@ public class PipTouchHandler {
|
||||
private boolean mSendingHoverAccessibilityEvents;
|
||||
private boolean mMovementWithinMinimize;
|
||||
private boolean mMovementWithinDismiss;
|
||||
private PipAccessibilityInteractionConnection mConnection;
|
||||
|
||||
// Touch state
|
||||
private final PipTouchState mTouchState;
|
||||
@@ -213,9 +214,10 @@ public class PipTouchHandler {
|
||||
// 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 @@ public class PipTouchHandler {
|
||||
|
||||
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 @@ public class PipTouchHandler {
|
||||
}
|
||||
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 @@ public class PipTouchHandler {
|
||||
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 @@ public class PipTouchHandler {
|
||||
* 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 @@ public class PipTouchHandler {
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user