Merge "Add Accessibility Resize support." into rvc-dev
This commit is contained in:
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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 -->
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user