Merge "Add a rate limitation of takeScreenshot() API" into rvc-dev
This commit is contained in:
@@ -48,6 +48,10 @@ package android.accessibilityservice {
|
|||||||
ctor public AccessibilityGestureEvent(int, int);
|
ctor public AccessibilityGestureEvent(int, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract class AccessibilityService extends android.app.Service {
|
||||||
|
field public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 1000; // 0x3e8
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
package android.animation {
|
package android.animation {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.annotation.IntDef;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
|
import android.annotation.TestApi;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -572,6 +573,26 @@ public abstract class AccessibilityService extends Service {
|
|||||||
*/
|
*/
|
||||||
public static final int SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN = 0x40000000;
|
public static final int SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN = 0x40000000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interval time of calling
|
||||||
|
* {@link AccessibilityService#takeScreenshot(int, Executor, Consumer)} API.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@TestApi
|
||||||
|
public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 1000;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public static final String KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER =
|
||||||
|
"screenshot_hardwareBuffer";
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public static final String KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE =
|
||||||
|
"screenshot_colorSpace";
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public static final String KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP =
|
||||||
|
"screenshot_timestamp";
|
||||||
|
|
||||||
private int mConnectionId = AccessibilityInteractionClient.NO_ID;
|
private int mConnectionId = AccessibilityInteractionClient.NO_ID;
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
@@ -597,17 +618,6 @@ public abstract class AccessibilityService extends Service {
|
|||||||
|
|
||||||
private FingerprintGestureController mFingerprintGestureController;
|
private FingerprintGestureController mFingerprintGestureController;
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
public static final String KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER =
|
|
||||||
"screenshot_hardwareBuffer";
|
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
public static final String KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE =
|
|
||||||
"screenshot_colorSpace";
|
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
public static final String KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP =
|
|
||||||
"screenshot_timestamp";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
|
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
|
||||||
@@ -1926,10 +1936,9 @@ public abstract class AccessibilityService extends Service {
|
|||||||
* default display.
|
* default display.
|
||||||
* @param executor Executor on which to run the callback.
|
* @param executor Executor on which to run the callback.
|
||||||
* @param callback The callback invoked when the taking screenshot is done.
|
* @param callback The callback invoked when the taking screenshot is done.
|
||||||
* The {@link AccessibilityService.ScreenshotResult} will be null for an
|
|
||||||
* invalid display.
|
|
||||||
*
|
*
|
||||||
* @return {@code true} if the taking screenshot accepted, {@code false} if not.
|
* @return {@code true} if the taking screenshot accepted, {@code false} if too little time
|
||||||
|
* has elapsed since the last screenshot, invalid display or internal errors.
|
||||||
*/
|
*/
|
||||||
public boolean takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor,
|
public boolean takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor,
|
||||||
@NonNull Consumer<ScreenshotResult> callback) {
|
@NonNull Consumer<ScreenshotResult> callback) {
|
||||||
@@ -1942,11 +1951,7 @@ public abstract class AccessibilityService extends Service {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
connection.takeScreenshot(displayId, new RemoteCallback((result) -> {
|
return connection.takeScreenshot(displayId, new RemoteCallback((result) -> {
|
||||||
if (result == null) {
|
|
||||||
sendScreenshotResult(executor, callback, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final HardwareBuffer hardwareBuffer =
|
final HardwareBuffer hardwareBuffer =
|
||||||
result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER);
|
result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER);
|
||||||
final ParcelableColorSpace colorSpace =
|
final ParcelableColorSpace colorSpace =
|
||||||
@@ -1959,7 +1964,6 @@ public abstract class AccessibilityService extends Service {
|
|||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
throw new RuntimeException(re);
|
throw new RuntimeException(re);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ interface IAccessibilityServiceConnection {
|
|||||||
|
|
||||||
int getWindowIdForLeashToken(IBinder token);
|
int getWindowIdForLeashToken(IBinder token);
|
||||||
|
|
||||||
void takeScreenshot(int displayId, in RemoteCallback callback);
|
boolean takeScreenshot(int displayId, in RemoteCallback callback);
|
||||||
|
|
||||||
void setGestureDetectionPassthroughRegion(int displayId, in Region region);
|
void setGestureDetectionPassthroughRegion(int displayId, in Region region);
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,9 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void takeScreenshot(int displayId, RemoteCallback callback) {}
|
public boolean takeScreenshot(int displayId, RemoteCallback callback) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {}
|
public void setTouchExplorationPassthroughRegion(int displayId, Region region) {}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
|
|||||||
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
|
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
|
||||||
|
|
||||||
import android.accessibilityservice.AccessibilityGestureEvent;
|
import android.accessibilityservice.AccessibilityGestureEvent;
|
||||||
|
import android.accessibilityservice.AccessibilityService;
|
||||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||||
import android.accessibilityservice.IAccessibilityServiceClient;
|
import android.accessibilityservice.IAccessibilityServiceClient;
|
||||||
import android.accessibilityservice.IAccessibilityServiceConnection;
|
import android.accessibilityservice.IAccessibilityServiceConnection;
|
||||||
@@ -177,6 +178,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
|||||||
|
|
||||||
final SparseArray<IBinder> mOverlayWindowTokens = new SparseArray();
|
final SparseArray<IBinder> mOverlayWindowTokens = new SparseArray();
|
||||||
|
|
||||||
|
/** The timestamp of requesting to take screenshot in milliseconds */
|
||||||
|
private long mRequestTakeScreenshotTimestampMs;
|
||||||
|
|
||||||
public interface SystemSupport {
|
public interface SystemSupport {
|
||||||
/**
|
/**
|
||||||
@@ -974,44 +977,39 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void takeScreenshot(int displayId, RemoteCallback callback) {
|
public boolean takeScreenshot(int displayId, RemoteCallback callback) {
|
||||||
|
final long currentTimestamp = SystemClock.uptimeMillis();
|
||||||
|
if (mRequestTakeScreenshotTimestampMs != 0
|
||||||
|
&& (currentTimestamp - mRequestTakeScreenshotTimestampMs)
|
||||||
|
<= AccessibilityService.ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mRequestTakeScreenshotTimestampMs = currentTimestamp;
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (!hasRightsToCurrentUserLocked()) {
|
if (!hasRightsToCurrentUserLocked()) {
|
||||||
sendScreenshotResult(true, null, callback);
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSecurityPolicy.canTakeScreenshotLocked(this)) {
|
if (!mSecurityPolicy.canTakeScreenshotLocked(this)) {
|
||||||
sendScreenshotResult(true, null, callback);
|
|
||||||
throw new SecurityException("Services don't have the capability of taking"
|
throw new SecurityException("Services don't have the capability of taking"
|
||||||
+ " the screenshot.");
|
+ " the screenshot.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
|
if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
|
||||||
sendScreenshotResult(true, null, callback);
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final Display display = DisplayManagerGlobal.getInstance()
|
final Display display = DisplayManagerGlobal.getInstance()
|
||||||
.getRealDisplay(displayId);
|
.getRealDisplay(displayId);
|
||||||
if (display == null) {
|
if (display == null) {
|
||||||
sendScreenshotResult(true, null, callback);
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendScreenshotResult(false, display, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendScreenshotResult(boolean noResult, Display display, RemoteCallback callback) {
|
|
||||||
final boolean noScreenshot = noResult;
|
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
|
mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
|
||||||
if (noScreenshot) {
|
|
||||||
callback.sendResult(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final Point displaySize = new Point();
|
final Point displaySize = new Point();
|
||||||
// TODO (b/145893483): calling new API with the display as a parameter
|
// TODO (b/145893483): calling new API with the display as a parameter
|
||||||
// when surface control supported.
|
// when surface control supported.
|
||||||
@@ -1041,6 +1039,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
|
|||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -328,6 +328,8 @@ class UiAutomationManager {
|
|||||||
public void onFingerprintGesture(int gesture) {}
|
public void onFingerprintGesture(int gesture) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void takeScreenshot(int displayId, RemoteCallback callback) {}
|
public boolean takeScreenshot(int displayId, RemoteCallback callback) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user