Loading api/current.txt +10 −1 Original line number Diff line number Diff line Loading @@ -2879,7 +2879,11 @@ package android.accessibilityservice { 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>); method public void takeScreenshot(int, @NonNull java.util.concurrent.Executor, @NonNull android.accessibilityservice.AccessibilityService.TakeScreenshotCallback); field public static final int ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR = 1; // 0x1 field public static final int ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT = 3; // 0x3 field public static final int ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY = 4; // 0x4 field public static final int ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS = 2; // 0x2 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 field public static final int GESTURE_2_FINGER_SINGLE_TAP = 19; // 0x13 Loading Loading @@ -2980,6 +2984,11 @@ package android.accessibilityservice { method public void onShowModeChanged(@NonNull android.accessibilityservice.AccessibilityService.SoftKeyboardController, int); } public static interface AccessibilityService.TakeScreenshotCallback { method public void onFailure(int); method public void onSuccess(@NonNull android.accessibilityservice.AccessibilityService.ScreenshotResult); } public class AccessibilityServiceInfo implements android.os.Parcelable { ctor public AccessibilityServiceInfo(); method public static String capabilityToString(int); core/java/android/accessibilityservice/AccessibilityService.java +84 −19 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ import android.graphics.ColorSpace; import android.graphics.ParcelableColorSpace; import android.graphics.Region; import android.hardware.HardwareBuffer; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -575,6 +574,46 @@ public abstract class AccessibilityService extends Service { */ public static final int SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN = 0x40000000; /** * Annotations for error codes of taking screenshot. * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "TAKE_SCREENSHOT_" }, value = { ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS, ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY }) public @interface ScreenshotErrorCode {} /** * The status of taking screenshot is success. * @hide */ public static final int TAKE_SCREENSHOT_SUCCESS = 0; /** * The status of taking screenshot is failure and the reason is internal error. */ public static final int ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR = 1; /** * The status of taking screenshot is failure and the reason is no accessibility access. */ public static final int ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS = 2; /** * The status of taking screenshot is failure and the reason is that too little time has * elapsed since the last screenshot. */ public static final int ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT = 3; /** * The status of taking screenshot is failure and the reason is invalid display Id. */ public static final int ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY = 4; /** * The interval time of calling * {@link AccessibilityService#takeScreenshot(int, Executor, Consumer)} API. Loading @@ -583,6 +622,10 @@ public abstract class AccessibilityService extends Service { @TestApi public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 1000; /** @hide */ public static final String KEY_ACCESSIBILITY_SCREENSHOT_STATUS = "screenshot_status"; /** @hide */ public static final String KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER = "screenshot_hardwareBuffer"; Loading Loading @@ -1945,14 +1988,13 @@ public abstract class AccessibilityService extends Service { * @param displayId The logic display id, must be {@link Display#DEFAULT_DISPLAY} for * default display. * @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 taking screenshot has succeeded or failed. * See {@link TakeScreenshotCallback} for details. * * @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. * @throws IllegalArgumentException if displayId is not {@link Display#DEFAULT_DISPLAY}. */ public boolean takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<ScreenshotResult> callback) { public void takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor, @NonNull TakeScreenshotCallback callback) { Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); Loading @@ -1964,18 +2006,24 @@ public abstract class AccessibilityService extends Service { AccessibilityInteractionClient.getInstance().getConnection( mConnectionId); if (connection == null) { return false; sendScreenshotFailure(ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, executor, callback); return; } try { return connection.takeScreenshot(displayId, new RemoteCallback((result) -> { connection.takeScreenshot(displayId, new RemoteCallback((result) -> { final int status = result.getInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS); if (status != TAKE_SCREENSHOT_SUCCESS) { sendScreenshotFailure(status, executor, callback); return; } final HardwareBuffer hardwareBuffer = result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER); final ParcelableColorSpace colorSpace = result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE); ScreenshotResult screenshot = new ScreenshotResult(hardwareBuffer, final ScreenshotResult screenshot = new ScreenshotResult(hardwareBuffer, colorSpace.getColorSpace(), result.getLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP)); sendScreenshotResult(executor, callback, screenshot); sendScreenshotSuccess(screenshot, executor, callback); })); } catch (RemoteException re) { throw new RuntimeException(re); Loading Loading @@ -2374,15 +2422,32 @@ public abstract class AccessibilityService extends Service { } } private void sendScreenshotResult(Executor executor, Consumer<ScreenshotResult> callback, ScreenshotResult screenshot) { final ScreenshotResult result = screenshot; final long identity = Binder.clearCallingIdentity(); try { executor.execute(() -> callback.accept(result)); } finally { Binder.restoreCallingIdentity(identity); private void sendScreenshotSuccess(ScreenshotResult screenshot, Executor executor, TakeScreenshotCallback callback) { executor.execute(() -> callback.onSuccess(screenshot)); } private void sendScreenshotFailure(@ScreenshotErrorCode int errorCode, Executor executor, TakeScreenshotCallback callback) { executor.execute(() -> callback.onFailure(errorCode)); } /** * Interface used to report status of taking screenshot. */ public interface TakeScreenshotCallback { /** Called when taking screenshot has completed successfully. * * @param screenshot The content of screenshot. */ void onSuccess(@NonNull ScreenshotResult screenshot); /** Called when taking screenshot has failed. {@code errorCode} will identify the * reason of failure. * * @param errorCode The error code of this operation. */ void onFailure(@ScreenshotErrorCode int errorCode); } /** Loading core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -110,7 +110,7 @@ interface IAccessibilityServiceConnection { int getWindowIdForLeashToken(IBinder token); boolean takeScreenshot(int displayId, in RemoteCallback callback); void takeScreenshot(int displayId, in RemoteCallback callback); void setGestureDetectionPassthroughRegion(int displayId, in Region region); Loading core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java +1 −3 Original line number Diff line number Diff line Loading @@ -156,9 +156,7 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon return -1; } public boolean takeScreenshot(int displayId, RemoteCallback callback) { return false; } public void takeScreenshot(int displayId, RemoteCallback callback) {} public void setTouchExplorationPassthroughRegion(int displayId, Region region) {} Loading services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +48 −20 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.accessibility; import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE; import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER; import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_STATUS; import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP; import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; Loading Loading @@ -66,6 +67,7 @@ import android.view.Display; import android.view.KeyEvent; import android.view.MagnificationSpec; import android.view.SurfaceControl; import android.view.SurfaceControl.ScreenshotGraphicBuffer; import android.view.View; import android.view.WindowInfo; import android.view.accessibility.AccessibilityCache; Loading Loading @@ -977,18 +979,22 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } @Override public boolean takeScreenshot(int displayId, RemoteCallback callback) { public void 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; sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, callback); return; } mRequestTakeScreenshotTimestampMs = currentTimestamp; synchronized (mLock) { if (!hasRightsToCurrentUserLocked()) { return false; sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, callback); return; } if (!mSecurityPolicy.canTakeScreenshotLocked(this)) { Loading @@ -998,18 +1004,24 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } if (!mSecurityPolicy.checkAccessibilityAccess(this)) { return false; sendScreenshotFailure( AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS, callback); return; } final Display display = DisplayManagerGlobal.getInstance() .getRealDisplay(displayId); if (display == null) { return false; sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback); return; } final long identity = Binder.clearCallingIdentity(); try { mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { sendScreenshotSuccess(display, callback); } private ScreenshotGraphicBuffer takeScreenshotBuffer(Display display) { final Point displaySize = new Point(); // TODO (b/145893483): calling new API with the display as a parameter // when surface control supported. Loading @@ -1018,23 +1030,31 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ final int rotation = display.getRotation(); display.getRealSize(displaySize); final SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer = SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, crop, displaySize.x, displaySize.y, false, rotation); return SurfaceControl.screenshotToBuffer(token, crop, displaySize.x, displaySize.y, false, rotation); } private void sendScreenshotSuccess(Display display, RemoteCallback callback) { final long identity = Binder.clearCallingIdentity(); try { mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { final ScreenshotGraphicBuffer screenshotBuffer = takeScreenshotBuffer(display); final GraphicBuffer graphicBuffer = screenshotBuffer.getGraphicBuffer(); try (HardwareBuffer hardwareBuffer = HardwareBuffer.createFromGraphicBuffer(graphicBuffer)) { final ParcelableColorSpace colorSpace = new ParcelableColorSpace(screenshotBuffer.getColorSpace()); // Send back the result. final Bundle payload = new Bundle(); payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, AccessibilityService.TAKE_SCREENSHOT_SUCCESS); payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER, hardwareBuffer); payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace); payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP, SystemClock.uptimeMillis()); // Send back the result. callback.sendResult(payload); hardwareBuffer.close(); } Loading @@ -1042,8 +1062,16 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } finally { Binder.restoreCallingIdentity(identity); } } return true; private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode, RemoteCallback callback) { mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { final Bundle payload = new Bundle(); payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, errorCode); // Send back the result. callback.sendResult(payload); }, null).recycleOnUse()); } @Override Loading Loading
api/current.txt +10 −1 Original line number Diff line number Diff line Loading @@ -2879,7 +2879,11 @@ package android.accessibilityservice { 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>); method public void takeScreenshot(int, @NonNull java.util.concurrent.Executor, @NonNull android.accessibilityservice.AccessibilityService.TakeScreenshotCallback); field public static final int ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR = 1; // 0x1 field public static final int ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT = 3; // 0x3 field public static final int ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY = 4; // 0x4 field public static final int ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS = 2; // 0x2 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 field public static final int GESTURE_2_FINGER_SINGLE_TAP = 19; // 0x13 Loading Loading @@ -2980,6 +2984,11 @@ package android.accessibilityservice { method public void onShowModeChanged(@NonNull android.accessibilityservice.AccessibilityService.SoftKeyboardController, int); } public static interface AccessibilityService.TakeScreenshotCallback { method public void onFailure(int); method public void onSuccess(@NonNull android.accessibilityservice.AccessibilityService.ScreenshotResult); } public class AccessibilityServiceInfo implements android.os.Parcelable { ctor public AccessibilityServiceInfo(); method public static String capabilityToString(int);
core/java/android/accessibilityservice/AccessibilityService.java +84 −19 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ import android.graphics.ColorSpace; import android.graphics.ParcelableColorSpace; import android.graphics.Region; import android.hardware.HardwareBuffer; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -575,6 +574,46 @@ public abstract class AccessibilityService extends Service { */ public static final int SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN = 0x40000000; /** * Annotations for error codes of taking screenshot. * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "TAKE_SCREENSHOT_" }, value = { ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS, ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY }) public @interface ScreenshotErrorCode {} /** * The status of taking screenshot is success. * @hide */ public static final int TAKE_SCREENSHOT_SUCCESS = 0; /** * The status of taking screenshot is failure and the reason is internal error. */ public static final int ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR = 1; /** * The status of taking screenshot is failure and the reason is no accessibility access. */ public static final int ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS = 2; /** * The status of taking screenshot is failure and the reason is that too little time has * elapsed since the last screenshot. */ public static final int ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT = 3; /** * The status of taking screenshot is failure and the reason is invalid display Id. */ public static final int ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY = 4; /** * The interval time of calling * {@link AccessibilityService#takeScreenshot(int, Executor, Consumer)} API. Loading @@ -583,6 +622,10 @@ public abstract class AccessibilityService extends Service { @TestApi public static final int ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS = 1000; /** @hide */ public static final String KEY_ACCESSIBILITY_SCREENSHOT_STATUS = "screenshot_status"; /** @hide */ public static final String KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER = "screenshot_hardwareBuffer"; Loading Loading @@ -1945,14 +1988,13 @@ public abstract class AccessibilityService extends Service { * @param displayId The logic display id, must be {@link Display#DEFAULT_DISPLAY} for * default display. * @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 taking screenshot has succeeded or failed. * See {@link TakeScreenshotCallback} for details. * * @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. * @throws IllegalArgumentException if displayId is not {@link Display#DEFAULT_DISPLAY}. */ public boolean takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<ScreenshotResult> callback) { public void takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor, @NonNull TakeScreenshotCallback callback) { Preconditions.checkNotNull(executor, "executor cannot be null"); Preconditions.checkNotNull(callback, "callback cannot be null"); Loading @@ -1964,18 +2006,24 @@ public abstract class AccessibilityService extends Service { AccessibilityInteractionClient.getInstance().getConnection( mConnectionId); if (connection == null) { return false; sendScreenshotFailure(ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, executor, callback); return; } try { return connection.takeScreenshot(displayId, new RemoteCallback((result) -> { connection.takeScreenshot(displayId, new RemoteCallback((result) -> { final int status = result.getInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS); if (status != TAKE_SCREENSHOT_SUCCESS) { sendScreenshotFailure(status, executor, callback); return; } final HardwareBuffer hardwareBuffer = result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER); final ParcelableColorSpace colorSpace = result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE); ScreenshotResult screenshot = new ScreenshotResult(hardwareBuffer, final ScreenshotResult screenshot = new ScreenshotResult(hardwareBuffer, colorSpace.getColorSpace(), result.getLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP)); sendScreenshotResult(executor, callback, screenshot); sendScreenshotSuccess(screenshot, executor, callback); })); } catch (RemoteException re) { throw new RuntimeException(re); Loading Loading @@ -2374,15 +2422,32 @@ public abstract class AccessibilityService extends Service { } } private void sendScreenshotResult(Executor executor, Consumer<ScreenshotResult> callback, ScreenshotResult screenshot) { final ScreenshotResult result = screenshot; final long identity = Binder.clearCallingIdentity(); try { executor.execute(() -> callback.accept(result)); } finally { Binder.restoreCallingIdentity(identity); private void sendScreenshotSuccess(ScreenshotResult screenshot, Executor executor, TakeScreenshotCallback callback) { executor.execute(() -> callback.onSuccess(screenshot)); } private void sendScreenshotFailure(@ScreenshotErrorCode int errorCode, Executor executor, TakeScreenshotCallback callback) { executor.execute(() -> callback.onFailure(errorCode)); } /** * Interface used to report status of taking screenshot. */ public interface TakeScreenshotCallback { /** Called when taking screenshot has completed successfully. * * @param screenshot The content of screenshot. */ void onSuccess(@NonNull ScreenshotResult screenshot); /** Called when taking screenshot has failed. {@code errorCode} will identify the * reason of failure. * * @param errorCode The error code of this operation. */ void onFailure(@ScreenshotErrorCode int errorCode); } /** Loading
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -110,7 +110,7 @@ interface IAccessibilityServiceConnection { int getWindowIdForLeashToken(IBinder token); boolean takeScreenshot(int displayId, in RemoteCallback callback); void takeScreenshot(int displayId, in RemoteCallback callback); void setGestureDetectionPassthroughRegion(int displayId, in Region region); Loading
core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java +1 −3 Original line number Diff line number Diff line Loading @@ -156,9 +156,7 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon return -1; } public boolean takeScreenshot(int displayId, RemoteCallback callback) { return false; } public void takeScreenshot(int displayId, RemoteCallback callback) {} public void setTouchExplorationPassthroughRegion(int displayId, Region region) {} Loading
services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +48 −20 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.accessibility; import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE; import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER; import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_STATUS; import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP; import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; Loading Loading @@ -66,6 +67,7 @@ import android.view.Display; import android.view.KeyEvent; import android.view.MagnificationSpec; import android.view.SurfaceControl; import android.view.SurfaceControl.ScreenshotGraphicBuffer; import android.view.View; import android.view.WindowInfo; import android.view.accessibility.AccessibilityCache; Loading Loading @@ -977,18 +979,22 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } @Override public boolean takeScreenshot(int displayId, RemoteCallback callback) { public void 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; sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, callback); return; } mRequestTakeScreenshotTimestampMs = currentTimestamp; synchronized (mLock) { if (!hasRightsToCurrentUserLocked()) { return false; sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, callback); return; } if (!mSecurityPolicy.canTakeScreenshotLocked(this)) { Loading @@ -998,18 +1004,24 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } if (!mSecurityPolicy.checkAccessibilityAccess(this)) { return false; sendScreenshotFailure( AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS, callback); return; } final Display display = DisplayManagerGlobal.getInstance() .getRealDisplay(displayId); if (display == null) { return false; sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback); return; } final long identity = Binder.clearCallingIdentity(); try { mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { sendScreenshotSuccess(display, callback); } private ScreenshotGraphicBuffer takeScreenshotBuffer(Display display) { final Point displaySize = new Point(); // TODO (b/145893483): calling new API with the display as a parameter // when surface control supported. Loading @@ -1018,23 +1030,31 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ final int rotation = display.getRotation(); display.getRealSize(displaySize); final SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer = SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, crop, displaySize.x, displaySize.y, false, rotation); return SurfaceControl.screenshotToBuffer(token, crop, displaySize.x, displaySize.y, false, rotation); } private void sendScreenshotSuccess(Display display, RemoteCallback callback) { final long identity = Binder.clearCallingIdentity(); try { mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { final ScreenshotGraphicBuffer screenshotBuffer = takeScreenshotBuffer(display); final GraphicBuffer graphicBuffer = screenshotBuffer.getGraphicBuffer(); try (HardwareBuffer hardwareBuffer = HardwareBuffer.createFromGraphicBuffer(graphicBuffer)) { final ParcelableColorSpace colorSpace = new ParcelableColorSpace(screenshotBuffer.getColorSpace()); // Send back the result. final Bundle payload = new Bundle(); payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, AccessibilityService.TAKE_SCREENSHOT_SUCCESS); payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER, hardwareBuffer); payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace); payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP, SystemClock.uptimeMillis()); // Send back the result. callback.sendResult(payload); hardwareBuffer.close(); } Loading @@ -1042,8 +1062,16 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } finally { Binder.restoreCallingIdentity(identity); } } return true; private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode, RemoteCallback callback) { mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> { final Bundle payload = new Bundle(); payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, errorCode); // Send back the result. callback.sendResult(payload); }, null).recycleOnUse()); } @Override Loading