Merge "Add Accessibility Resize support." into rvc-dev

This commit is contained in:
Ben Lin
2020-06-18 18:54:46 +00:00
committed by Android (Google) Code Review
4 changed files with 111 additions and 34 deletions

View File

@@ -174,5 +174,8 @@
<item type="id" name="accessibility_action_controls_move_before" /> <item type="id" name="accessibility_action_controls_move_before" />
<item type="id" name="accessibility_action_controls_move_after" /> <item type="id" name="accessibility_action_controls_move_after" />
<!-- Accessibility actions for PIP -->
<item type="id" name="action_pip_resize" />
</resources> </resources>

View File

@@ -2392,6 +2392,9 @@
<!-- Button to skip to the prev media on picture-in-picture (PIP) [CHAR LIMIT=30] --> <!-- Button to skip to the prev media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
<string name="pip_skip_to_prev">Skip to previous</string> <string name="pip_skip_to_prev">Skip to previous</string>
<!-- Accessibility action for resizing PIP [CHAR LIMIT=NONE] -->
<string name="accessibility_action_pip_resize">Resize</string>
<!-- Tuner string --> <!-- Tuner string -->
<string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string> <string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string>
<!-- Tuner string --> <!-- Tuner string -->

View File

@@ -15,6 +15,7 @@
*/ */
package com.android.systemui.pip.phone; package com.android.systemui.pip.phone;
import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Region; import android.graphics.Region;
import android.os.Bundle; import android.os.Bundle;
@@ -26,6 +27,10 @@ import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnection; import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback; import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import com.android.systemui.R;
import com.android.systemui.pip.PipSnapAlgorithm;
import com.android.systemui.pip.PipTaskOrganizer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -43,16 +48,30 @@ public class PipAccessibilityInteractionConnection
private static final long ACCESSIBILITY_NODE_ID = 1; private static final long ACCESSIBILITY_NODE_ID = 1;
private List<AccessibilityNodeInfo> mAccessibilityNodeInfoList; private List<AccessibilityNodeInfo> mAccessibilityNodeInfoList;
private Context mContext;
private Handler mHandler; private Handler mHandler;
private PipMotionHelper mMotionHelper; private PipMotionHelper mMotionHelper;
private PipTaskOrganizer mTaskOrganizer;
private PipSnapAlgorithm mSnapAlgorithm;
private Runnable mUpdateMovementBoundCallback;
private AccessibilityCallbacks mCallbacks; private AccessibilityCallbacks mCallbacks;
private final Rect mNormalBounds = new Rect();
private final Rect mExpandedBounds = new Rect();
private final Rect mNormalMovementBounds = new Rect();
private final Rect mExpandedMovementBounds = new Rect();
private Rect mTmpBounds = new Rect(); private Rect mTmpBounds = new Rect();
public PipAccessibilityInteractionConnection(PipMotionHelper motionHelper, public PipAccessibilityInteractionConnection(Context context, PipMotionHelper motionHelper,
AccessibilityCallbacks callbacks, Handler handler) { PipTaskOrganizer taskOrganizer, PipSnapAlgorithm snapAlgorithm,
AccessibilityCallbacks callbacks, Runnable updateMovementBoundCallback,
Handler handler) {
mContext = context;
mHandler = handler; mHandler = handler;
mMotionHelper = motionHelper; mMotionHelper = motionHelper;
mTaskOrganizer = taskOrganizer;
mSnapAlgorithm = snapAlgorithm;
mUpdateMovementBoundCallback = updateMovementBoundCallback;
mCallbacks = callbacks; mCallbacks = callbacks;
} }
@@ -78,34 +97,46 @@ public class PipAccessibilityInteractionConnection
// We only support one view. A request for anything else is invalid // We only support one view. A request for anything else is invalid
boolean result = false; boolean result = false;
if (accessibilityNodeId == AccessibilityNodeInfo.ROOT_NODE_ID) { if (accessibilityNodeId == AccessibilityNodeInfo.ROOT_NODE_ID) {
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK: // R constants are not final so this cannot be put in the switch-case.
mHandler.post(() -> { if (action == R.id.action_pip_resize) {
mCallbacks.onAccessibilityShowMenu(); if (mMotionHelper.getBounds().width() == mNormalBounds.width()
}); && mMotionHelper.getBounds().height() == mNormalBounds.height()) {
result = true; setToExpandedBounds();
break; } else {
case AccessibilityNodeInfo.ACTION_DISMISS: setToNormalBounds();
mMotionHelper.dismissPip(); }
result = true; result = true;
break; } else {
case com.android.internal.R.id.accessibilityActionMoveWindow: switch (action) {
int newX = arguments.getInt( case AccessibilityNodeInfo.ACTION_CLICK:
AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_X); mHandler.post(() -> {
int newY = arguments.getInt( mCallbacks.onAccessibilityShowMenu();
AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_Y); });
Rect pipBounds = new Rect(); result = true;
pipBounds.set(mMotionHelper.getBounds()); break;
mTmpBounds.offsetTo(newX, newY); case AccessibilityNodeInfo.ACTION_DISMISS:
mMotionHelper.movePip(mTmpBounds); mMotionHelper.dismissPip();
result = true; result = true;
break; break;
case AccessibilityNodeInfo.ACTION_EXPAND: case com.android.internal.R.id.accessibilityActionMoveWindow:
mMotionHelper.expandPipToFullscreen(); int newX = arguments.getInt(
result = true; AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_X);
break; int newY = arguments.getInt(
default: AccessibilityNodeInfo.ACTION_ARGUMENT_MOVE_WINDOW_Y);
// Leave result as false Rect pipBounds = new Rect();
pipBounds.set(mMotionHelper.getBounds());
mTmpBounds.offsetTo(newX, newY);
mMotionHelper.movePip(mTmpBounds);
result = true;
break;
case AccessibilityNodeInfo.ACTION_EXPAND:
mMotionHelper.expandPipToFullscreen();
result = true;
break;
default:
// Leave result as false
}
} }
} }
try { try {
@@ -115,6 +146,27 @@ public class PipAccessibilityInteractionConnection
} }
} }
private void setToExpandedBounds() {
float savedSnapFraction = mSnapAlgorithm.getSnapFraction(
new Rect(mTaskOrganizer.getLastReportedBounds()), mNormalMovementBounds);
mSnapAlgorithm.applySnapFraction(mExpandedBounds, mExpandedMovementBounds,
savedSnapFraction);
mTaskOrganizer.scheduleFinishResizePip(mExpandedBounds, (Rect bounds) -> {
mMotionHelper.synchronizePinnedStackBounds();
mUpdateMovementBoundCallback.run();
});
}
private void setToNormalBounds() {
float savedSnapFraction = mSnapAlgorithm.getSnapFraction(
new Rect(mTaskOrganizer.getLastReportedBounds()), mExpandedMovementBounds);
mSnapAlgorithm.applySnapFraction(mNormalBounds, mNormalMovementBounds, savedSnapFraction);
mTaskOrganizer.scheduleFinishResizePip(mNormalBounds, (Rect bounds) -> {
mMotionHelper.synchronizePinnedStackBounds();
mUpdateMovementBoundCallback.run();
});
}
@Override @Override
public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
String viewId, Region interactiveRegion, int interactionId, String viewId, Region interactiveRegion, int interactionId,
@@ -175,7 +227,21 @@ public class PipAccessibilityInteractionConnection
// Do nothing. // Do nothing.
} }
public static AccessibilityNodeInfo obtainRootAccessibilityNodeInfo() { /**
* Update the normal and expanded bounds so they can be used for Resize.
*/
void onMovementBoundsChanged(Rect normalBounds, Rect expandedBounds, Rect normalMovementBounds,
Rect expandedMovementBounds) {
mNormalBounds.set(normalBounds);
mExpandedBounds.set(expandedBounds);
mNormalMovementBounds.set(normalMovementBounds);
mExpandedMovementBounds.set(expandedMovementBounds);
}
/**
* Update the Root node with PIP Accessibility action items.
*/
public static AccessibilityNodeInfo obtainRootAccessibilityNodeInfo(Context context) {
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
info.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID, info.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID); AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
@@ -183,6 +249,8 @@ public class PipAccessibilityInteractionConnection
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS); info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_MOVE_WINDOW); info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_MOVE_WINDOW);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND); info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.action_pip_resize,
context.getString(R.string.accessibility_action_pip_resize)));
info.setImportantForAccessibility(true); info.setImportantForAccessibility(true);
info.setClickable(true); info.setClickable(true);
info.setVisibleToUser(true); info.setVisibleToUser(true);
@@ -193,7 +261,7 @@ public class PipAccessibilityInteractionConnection
if (mAccessibilityNodeInfoList == null) { if (mAccessibilityNodeInfoList == null) {
mAccessibilityNodeInfoList = new ArrayList<>(1); mAccessibilityNodeInfoList = new ArrayList<>(1);
} }
AccessibilityNodeInfo info = obtainRootAccessibilityNodeInfo(); AccessibilityNodeInfo info = obtainRootAccessibilityNodeInfo(mContext);
mAccessibilityNodeInfoList.clear(); mAccessibilityNodeInfoList.clear();
mAccessibilityNodeInfoList.add(info); mAccessibilityNodeInfoList.add(info);
return mAccessibilityNodeInfoList; return mAccessibilityNodeInfoList;

View File

@@ -250,8 +250,9 @@ public class PipTouchHandler {
mPipBoundsHandler = pipBoundsHandler; mPipBoundsHandler = pipBoundsHandler;
mFloatingContentCoordinator = floatingContentCoordinator; mFloatingContentCoordinator = floatingContentCoordinator;
mConnection = new PipAccessibilityInteractionConnection(mMotionHelper, mConnection = new PipAccessibilityInteractionConnection(mContext, mMotionHelper,
this::onAccessibilityShowMenu, mHandler); pipTaskOrganizer, pipSnapAlgorithm, this::onAccessibilityShowMenu,
this::updateMovementBounds, mHandler);
mTargetView = new DismissCircleView(context); mTargetView = new DismissCircleView(context);
mTargetViewContainer = new FrameLayout(context); mTargetViewContainer = new FrameLayout(context);
@@ -499,6 +500,8 @@ public class PipTouchHandler {
mInsetBounds.set(insetBounds); mInsetBounds.set(insetBounds);
updateMovementBounds(); updateMovementBounds();
mMovementBoundsExtraOffsets = extraOffset; mMovementBoundsExtraOffsets = extraOffset;
mConnection.onMovementBoundsChanged(mNormalBounds, mExpandedBounds, mNormalMovementBounds,
mExpandedMovementBounds);
// If we have a deferred resize, apply it now // If we have a deferred resize, apply it now
if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) { if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) {