Merge "Add passthrough functionality for touch exploration and gesture detection."
This commit is contained in:
@@ -2871,7 +2871,9 @@ package android.accessibilityservice {
|
||||
method protected void onServiceConnected();
|
||||
method public void onSystemActionsChanged();
|
||||
method public final boolean performGlobalAction(int);
|
||||
method public void setGestureDetectionPassthroughRegion(int, @NonNull android.graphics.Region);
|
||||
method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
|
||||
method public void setTouchExplorationPassthroughRegion(int, @NonNull android.graphics.Region);
|
||||
method public boolean takeScreenshot(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.accessibilityservice.AccessibilityService.ScreenshotResult>);
|
||||
field public static final int GESTURE_2_FINGER_DOUBLE_TAP = 20; // 0x14
|
||||
field public static final int GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD = 40; // 0x28
|
||||
|
||||
@@ -2414,4 +2414,55 @@ public abstract class AccessibilityService extends Service {
|
||||
return mTimestamp;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, this
|
||||
* function requests that touch interactions starting in the specified region of the screen
|
||||
* bypass the gesture detector. There can only be one gesture detection passthrough region per
|
||||
* display. Requesting a new gesture detection passthrough region clears the existing one. To
|
||||
* disable this passthrough and return to the original behavior, pass in an empty region. When
|
||||
* {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this
|
||||
* function has no effect.
|
||||
*
|
||||
* @param displayId The display on which to set this region.
|
||||
* @param region the region of the screen.
|
||||
*/
|
||||
public void setGestureDetectionPassthroughRegion(int displayId, @NonNull Region region) {
|
||||
Preconditions.checkNotNull(region, "region cannot be null");
|
||||
final IAccessibilityServiceConnection connection =
|
||||
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.setGestureDetectionPassthroughRegion(displayId, region);
|
||||
} catch (RemoteException re) {
|
||||
throw new RuntimeException(re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, this
|
||||
* function requests that touch interactions starting in the specified region of the screen
|
||||
* bypass the touch explorer and go straight to the view hierarchy. There can only be one touch
|
||||
* exploration passthrough region per display. Requesting a new touch explorationpassthrough
|
||||
* region clears the existing one. To disable this passthrough and return to the original
|
||||
* behavior, pass in an empty region. When {@link
|
||||
* AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this function has
|
||||
* no effect.
|
||||
*
|
||||
* @param displayId The display on which to set this region.
|
||||
* @param region the region of the screen .
|
||||
*/
|
||||
public void setTouchExplorationPassthroughRegion(int displayId, @NonNull Region region) {
|
||||
Preconditions.checkNotNull(region, "region cannot be null");
|
||||
final IAccessibilityServiceConnection connection =
|
||||
AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.setTouchExplorationPassthroughRegion(displayId, region);
|
||||
} catch (RemoteException re) {
|
||||
throw new RuntimeException(re);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,4 +111,8 @@ interface IAccessibilityServiceConnection {
|
||||
int getWindowIdForLeashToken(IBinder token);
|
||||
|
||||
void takeScreenshot(int displayId, in RemoteCallback callback);
|
||||
|
||||
void setGestureDetectionPassthroughRegion(int displayId, in Region region);
|
||||
|
||||
void setTouchExplorationPassthroughRegion(int displayId, in Region region);
|
||||
}
|
||||
|
||||
@@ -157,4 +157,8 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
|
||||
}
|
||||
|
||||
public void takeScreenshot(int displayId, RemoteCallback callback) {}
|
||||
|
||||
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {}
|
||||
|
||||
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {}
|
||||
}
|
||||
|
||||
@@ -230,6 +230,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
/* This is exactly PendingIntent.getActivity, separated out for testability */
|
||||
PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent,
|
||||
int flags);
|
||||
|
||||
void setGestureDetectionPassthroughRegion(int displayId, Region region);
|
||||
|
||||
void setTouchExplorationPassthroughRegion(int displayId, Region region);
|
||||
}
|
||||
|
||||
public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
|
||||
@@ -1736,4 +1740,14 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
||||
public boolean isMultiFingerGesturesEnabled() {
|
||||
return mRequestMultiFingerGestures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
|
||||
mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
|
||||
mSystemSupport.setTouchExplorationPassthroughRegion(displayId, region);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Region;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
@@ -726,4 +727,16 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
|
||||
return shouldProcess;
|
||||
}
|
||||
}
|
||||
|
||||
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
|
||||
if (region != null && mTouchExplorer.contains(displayId)) {
|
||||
mTouchExplorer.get(displayId).setGestureDetectionPassthroughRegion(region);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
|
||||
if (region != null && mTouchExplorer.contains(displayId)) {
|
||||
mTouchExplorer.get(displayId).setTouchExplorationPassthroughRegion(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3058,4 +3058,40 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
|
||||
mMainHandler.sendMessage(
|
||||
obtainMessage(
|
||||
AccessibilityManagerService::setGestureDetectionPassthroughRegionInternal,
|
||||
this,
|
||||
displayId,
|
||||
region));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
|
||||
mMainHandler.sendMessage(
|
||||
obtainMessage(
|
||||
AccessibilityManagerService::setTouchExplorationPassthroughRegionInternal,
|
||||
this,
|
||||
displayId,
|
||||
region));
|
||||
}
|
||||
|
||||
private void setTouchExplorationPassthroughRegionInternal(int displayId, Region region) {
|
||||
synchronized (mLock) {
|
||||
if (mHasInputFilter && mInputFilter != null) {
|
||||
mInputFilter.setTouchExplorationPassthroughRegion(displayId, region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setGestureDetectionPassthroughRegionInternal(int displayId, Region region) {
|
||||
synchronized (mLock) {
|
||||
if (mHasInputFilter && mInputFilter != null) {
|
||||
mInputFilter.setGestureDetectionPassthroughRegion(displayId, region);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static com.android.server.accessibility.gestures.TouchState.ALL_POINTER_I
|
||||
import android.accessibilityservice.AccessibilityGestureEvent;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Region;
|
||||
import android.os.Handler;
|
||||
import android.util.Slog;
|
||||
import android.view.InputDevice;
|
||||
@@ -120,6 +121,8 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
// Context in which this explorer operates.
|
||||
private final Context mContext;
|
||||
|
||||
private Region mGestureDetectionPassthroughRegion;
|
||||
private Region mTouchExplorationPassthroughRegion;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
@@ -165,6 +168,8 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
} else {
|
||||
mGestureDetector = detector;
|
||||
}
|
||||
mGestureDetectionPassthroughRegion = new Region();
|
||||
mTouchExplorationPassthroughRegion = new Region();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -230,10 +235,11 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
}
|
||||
|
||||
mState.onReceivedMotionEvent(rawEvent);
|
||||
|
||||
if (mGestureDetector.onMotionEvent(event, rawEvent, policyFlags)) {
|
||||
// Event was handled by the gesture detector.
|
||||
return;
|
||||
if (shouldPerformGestureDetection(event)) {
|
||||
if (mGestureDetector.onMotionEvent(event, rawEvent, policyFlags)) {
|
||||
// Event was handled by the gesture detector.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
|
||||
@@ -418,6 +424,21 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
mSendTouchExplorationEndDelayed.forceSendAndRemove();
|
||||
mSendTouchInteractionEndDelayed.forceSendAndRemove();
|
||||
mDispatcher.sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
|
||||
if (mTouchExplorationPassthroughRegion.contains(
|
||||
(int) event.getX(), (int) event.getY())) {
|
||||
// The touch exploration passthrough overrides the gesture detection passthrough in
|
||||
// the event they overlap.
|
||||
// Pass this entire gesture through to the system as-is.
|
||||
mState.startDelegating();
|
||||
event = MotionEvent.obtainNoHistory(event);
|
||||
mDispatcher.sendMotionEvent(
|
||||
event, event.getAction(), rawEvent, ALL_POINTER_ID_BITS, policyFlags);
|
||||
mSendHoverEnterAndMoveDelayed.cancel();
|
||||
} else if (mGestureDetectionPassthroughRegion.contains(
|
||||
(int) event.getX(), (int) event.getY())) {
|
||||
// Jump straight to touch exploration.
|
||||
mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
|
||||
}
|
||||
} else {
|
||||
// Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double tap.
|
||||
mSendTouchInteractionEndDelayed.cancel();
|
||||
@@ -909,6 +930,29 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
mGestureDetector.setMultiFingerGesturesEnabled(enabled);
|
||||
}
|
||||
|
||||
public void setGestureDetectionPassthroughRegion(Region region) {
|
||||
mGestureDetectionPassthroughRegion = region;
|
||||
}
|
||||
|
||||
public void setTouchExplorationPassthroughRegion(Region region) {
|
||||
mTouchExplorationPassthroughRegion = region;
|
||||
}
|
||||
|
||||
private boolean shouldPerformGestureDetection(MotionEvent event) {
|
||||
if (mState.isDelegating()) {
|
||||
return false;
|
||||
}
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
final int x = (int) event.getX();
|
||||
final int y = (int) event.getY();
|
||||
if (mTouchExplorationPassthroughRegion.contains(x, y)
|
||||
|| mGestureDetectionPassthroughRegion.contains(x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for delayed exiting from gesture detecting mode.
|
||||
*/
|
||||
@@ -1135,5 +1179,4 @@ public class TouchExplorer extends BaseEventStreamTransformation
|
||||
+ ", mTempPoint: " + mTempPoint
|
||||
+ " }";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user