Merge "Implementing new API : takeScreenshot()"

This commit is contained in:
Jacky Kao
2020-01-15 08:29:49 +00:00
committed by Android (Google) Code Review
19 changed files with 251 additions and 50 deletions

View File

@@ -386,6 +386,7 @@ package android {
field public static final int canRequestFingerprintGestures = 16844109; // 0x101054d
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int canTakeScreenshot = 16844304; // 0x1010610
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
field public static final int cantSaveState = 16844142; // 0x101056e
field @Deprecated public static final int capitalize = 16843113; // 0x1010169
@@ -2864,6 +2865,7 @@ package android.accessibilityservice {
method protected void onServiceConnected();
method public final boolean performGlobalAction(int);
method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
method public boolean takeScreenshot(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.graphics.Bitmap>);
field public static final int GESTURE_SWIPE_DOWN = 2; // 0x2
field public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 15; // 0xf
field public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16; // 0x10
@@ -2960,6 +2962,7 @@ package android.accessibilityservice {
field public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 64; // 0x40
field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
field public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1; // 0x1
field public static final int CAPABILITY_CAN_TAKE_SCREENSHOT = 128; // 0x80
field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.AccessibilityServiceInfo> CREATOR;
field public static final int DEFAULT = 1; // 0x1
field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff

View File

@@ -17,6 +17,7 @@
package android.accessibilityservice;
import android.accessibilityservice.GestureDescription.MotionEventGenerator;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,12 +27,15 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.graphics.Bitmap;
import android.graphics.Region;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
@@ -48,10 +52,13 @@ import android.view.accessibility.AccessibilityWindowInfo;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* Accessibility services should only be used to assist users with disabilities in using
@@ -483,6 +490,9 @@ public abstract class AccessibilityService extends Service {
private FingerprintGestureController mFingerprintGestureController;
/** @hide */
public static final String KEY_ACCESSIBILITY_SCREENSHOT = "screenshot";
/**
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
*
@@ -1760,6 +1770,51 @@ public abstract class AccessibilityService extends Service {
return super.getSystemService(name);
}
/**
* Takes a screenshot of the specified display and returns it by {@link Bitmap.Config#HARDWARE}
* format.
* <p>
* <strong>Note:</strong> In order to take screenshot your service has
* to declare the capability to take screenshot by setting the
* {@link android.R.styleable#AccessibilityService_canTakeScreenshot}
* property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
* Besides, This API is only supported for default display now
* {@link Display#DEFAULT_DISPLAY}.
* </p>
*
* @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.
*
* @return {@code true} if the taking screenshot accepted, {@code false} if not.
*/
public boolean takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<Bitmap> callback) {
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
mConnectionId);
if (connection == null) {
return false;
}
try {
connection.takeScreenshotWithCallback(displayId, new RemoteCallback((result) -> {
final Bitmap screenshot = result.getParcelable(KEY_ACCESSIBILITY_SCREENSHOT);
final long identity = Binder.clearCallingIdentity();
try {
executor.execute(() -> callback.accept(screenshot));
} finally {
Binder.restoreCallingIdentity(identity);
}
}));
} catch (RemoteException re) {
throw new RuntimeException(re);
}
return true;
}
/**
* Implement to return the implementation of the internal accessibility
* service interface.

View File

@@ -86,6 +86,7 @@ import java.util.List;
* @attr ref android.R.styleable#AccessibilityService_settingsActivity
* @attr ref android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
* @attr ref android.R.styleable#AccessibilityService_interactiveUiTimeout
* @attr ref android.R.styleable#AccessibilityService_canTakeScreenshot
* @see AccessibilityService
* @see android.view.accessibility.AccessibilityEvent
* @see android.view.accessibility.AccessibilityManager
@@ -136,6 +137,12 @@ public class AccessibilityServiceInfo implements Parcelable {
*/
public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 0x00000040;
/**
* Capability: This accessibility service can take screenshot.
* @see android.R.styleable#AccessibilityService_canTakeScreenshot
*/
public static final int CAPABILITY_CAN_TAKE_SCREENSHOT = 0x00000080;
private static SparseArray<CapabilityInfo> sAvailableCapabilityInfos;
/**
@@ -625,6 +632,10 @@ public class AccessibilityServiceInfo implements Parcelable {
.AccessibilityService_canRequestFingerprintGestures, false)) {
mCapabilities |= CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES;
}
if (asAttributes.getBoolean(com.android.internal.R.styleable
.AccessibilityService_canTakeScreenshot, false)) {
mCapabilities |= CAPABILITY_CAN_TAKE_SCREENSHOT;
}
TypedValue peekedValue = asAttributes.peekValue(
com.android.internal.R.styleable.AccessibilityService_description);
if (peekedValue != null) {
@@ -794,6 +805,7 @@ public class AccessibilityServiceInfo implements Parcelable {
* @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
* @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
* @see #CAPABILITY_CAN_PERFORM_GESTURES
* @see #CAPABILITY_CAN_TAKE_SCREENSHOT
*/
public int getCapabilities() {
return mCapabilities;
@@ -810,6 +822,7 @@ public class AccessibilityServiceInfo implements Parcelable {
* @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
* @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
* @see #CAPABILITY_CAN_PERFORM_GESTURES
* @see #CAPABILITY_CAN_TAKE_SCREENSHOT
*
* @hide
*/
@@ -1253,6 +1266,8 @@ public class AccessibilityServiceInfo implements Parcelable {
return "CAPABILITY_CAN_PERFORM_GESTURES";
case CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES:
return "CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES";
case CAPABILITY_CAN_TAKE_SCREENSHOT:
return "CAPABILITY_CAN_TAKE_SCREENSHOT";
default:
return "UNKNOWN";
}
@@ -1314,6 +1329,10 @@ public class AccessibilityServiceInfo implements Parcelable {
new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES,
R.string.capability_title_canPerformGestures,
R.string.capability_desc_canPerformGestures));
sAvailableCapabilityInfos.put(CAPABILITY_CAN_TAKE_SCREENSHOT,
new CapabilityInfo(CAPABILITY_CAN_TAKE_SCREENSHOT,
R.string.capability_title_canTakeScreenshot,
R.string.capability_desc_canTakeScreenshot));
if ((context == null) || fingerprintAvailable(context)) {
sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES,
new CapabilityInfo(CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES,

View File

@@ -18,8 +18,10 @@ package android.accessibilityservice;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.pm.ParceledListSlice;
import android.graphics.Bitmap;
import android.graphics.Region;
import android.os.Bundle;
import android.os.RemoteCallback;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -104,4 +106,8 @@ interface IAccessibilityServiceConnection {
IBinder getOverlayWindowToken(int displayid);
int getWindowIdForLeashToken(IBinder token);
Bitmap takeScreenshot(int displayId);
void takeScreenshotWithCallback(int displayId, in RemoteCallback callback);
}

View File

@@ -39,7 +39,6 @@ interface IUiAutomationConnection {
boolean injectInputEvent(in InputEvent event, boolean sync);
void syncInputTransactions();
boolean setRotation(int rotation);
Bitmap takeScreenshot(in Rect crop, int rotation);
boolean clearWindowContentFrameStats(int windowId);
WindowContentFrameStats getWindowContentFrameStats(int windowId);
void clearWindowAnimationFrameStats();

View File

@@ -27,10 +27,7 @@ import android.annotation.Nullable;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
@@ -831,39 +828,20 @@ public final class UiAutomation {
}
/**
* Takes a screenshot.
* Takes a screenshot of the default display and returns it by {@link Bitmap.Config#HARDWARE}
* format.
*
* @return The screenshot bitmap on success, null otherwise.
*/
public Bitmap takeScreenshot() {
final int connectionId;
synchronized (mLock) {
throwIfNotConnectedLocked();
connectionId = mConnectionId;
}
Display display = DisplayManagerGlobal.getInstance()
.getRealDisplay(Display.DEFAULT_DISPLAY);
Point displaySize = new Point();
display.getRealSize(displaySize);
int rotation = display.getRotation();
// Take the screenshot
Bitmap screenShot = null;
try {
// Calling out without a lock held.
screenShot = mUiAutomationConnection.takeScreenshot(
new Rect(0, 0, displaySize.x, displaySize.y), rotation);
if (screenShot == null) {
return null;
}
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while taking screnshot!", re);
return null;
}
// Optimization
screenShot.setHasAlpha(false);
return screenShot;
// Calling out without a lock held.
return AccessibilityInteractionClient.getInstance()
.takeScreenshot(connectionId, Display.DEFAULT_DISPLAY);
}
/**

View File

@@ -21,8 +21,6 @@ import android.accessibilityservice.IAccessibilityServiceClient;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Binder;
import android.os.IBinder;
@@ -179,23 +177,6 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
return false;
}
@Override
public Bitmap takeScreenshot(Rect crop, int rotation) {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
throwIfShutdownLocked();
throwIfNotConnectedLocked();
}
final long identity = Binder.clearCallingIdentity();
try {
int width = crop.width();
int height = crop.height();
return SurfaceControl.screenshot(crop, width, height, rotation);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public boolean clearWindowContentFrameStats(int windowId) throws RemoteException {
synchronized (mLock) {
@@ -449,7 +430,8 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS);
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
| AccessibilityServiceInfo.CAPABILITY_CAN_TAKE_SCREENSHOT);
try {
// Calling out with a lock held is fine since if the system
// process is gone the client calling in will be killed.

View File

@@ -20,6 +20,7 @@ import android.accessibilityservice.IAccessibilityServiceConnection;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -827,6 +828,31 @@ public final class AccessibilityInteractionClient
}
}
/**
* Takes the screenshot of the specified display and returns it by bitmap format.
*
* @param connectionId The id of a connection for interacting with the system.
* @param displayId The logic display id, use {@link Display#DEFAULT_DISPLAY} for
* default display.
* @return The screenshot bitmap on success, null otherwise.
*/
public Bitmap takeScreenshot(int connectionId, int displayId) {
Bitmap screenShot = null;
try {
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
screenShot = connection.takeScreenshot(displayId);
} else {
if (DEBUG) {
Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
}
}
} catch (RemoteException re) {
Log.w(LOG_TAG, "Error while calling remote takeScreenshot", re);
}
return screenShot;
}
/**
* Clears the result state.
*/

View File

@@ -3752,6 +3752,8 @@
</p>
-->
<attr name="canRequestFingerprintGestures" format="boolean" />
<!-- Attribute whether the accessibility service wants to be able to take screenshot. -->
<attr name="canTakeScreenshot" format="boolean" />
<!-- Animated image of the accessibility service purpose or behavior, to help users
understand how the service can help them.-->

View File

@@ -3007,6 +3007,7 @@
<public name="featureId" />
<public name="supportsInlineSuggestions" />
<public name="crossProfile" />
<public name="canTakeScreenshot"/>
</public-group>
<public-group type="drawable" first-id="0x010800b5">

View File

@@ -794,6 +794,11 @@
<string name="capability_desc_canCaptureFingerprintGestures">Can capture gestures performed on
the device\'s fingerprint sensor.</string>
<!-- Title for the capability of an accessibility service to take screenshot. [CHAR LIMIT=32] -->
<string name="capability_title_canTakeScreenshot">Take screenshot</string>
<!-- Description for the capability of an accessibility service to take screenshot. [CHAR LIMIT=NONE] -->
<string name="capability_desc_canTakeScreenshot">Can take a screenshot of the display.</string>
<!-- Permissions -->
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->

View File

@@ -3811,4 +3811,9 @@
<java-symbol type="dimen" name="waterfall_display_top_edge_size" />
<java-symbol type="dimen" name="waterfall_display_right_edge_size" />
<java-symbol type="dimen" name="waterfall_display_bottom_edge_size" />
<!-- Accessibility take screenshot -->
<java-symbol type="string" name="capability_desc_canTakeScreenshot" />
<java-symbol type="string" name="capability_title_canTakeScreenshot" />
</resources>

View File

@@ -19,9 +19,11 @@ package android.view.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.content.pm.ParceledListSlice;
import android.graphics.Bitmap;
import android.graphics.Region;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteCallback;
/**
* Stub implementation of IAccessibilityServiceConnection so each test doesn't need to implement
@@ -147,4 +149,10 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon
public int getWindowIdForLeashToken(IBinder token) {
return -1;
}
public Bitmap takeScreenshot(int displayId) {
return null;
}
public void takeScreenshotWithCallback(int displayId, RemoteCallback callback) {}
}

View File

@@ -36,8 +36,12 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -54,6 +58,7 @@ import android.util.SparseArray;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowInfo;
import android.view.accessibility.AccessibilityCache;
@@ -90,6 +95,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
private static final String LOG_TAG = "AbstractAccessibilityServiceConnection";
private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;
protected static final String TAKE_SCREENSHOT = "takeScreenshot";
protected final Context mContext;
protected final SystemSupport mSystemSupport;
protected final WindowManagerInternal mWindowManagerService;
@@ -934,6 +940,54 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
}
@Nullable
@Override
public Bitmap takeScreenshot(int displayId) {
synchronized (mLock) {
if (!hasRightsToCurrentUserLocked()) {
return null;
}
if (!mSecurityPolicy.canTakeScreenshotLocked(this)) {
return null;
}
}
if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
return null;
}
final Display display = DisplayManagerGlobal.getInstance()
.getRealDisplay(displayId);
if (display == null) {
return null;
}
final Point displaySize = new Point();
display.getRealSize(displaySize);
final int rotation = display.getRotation();
Bitmap screenShot = null;
final long identity = Binder.clearCallingIdentity();
try {
final Rect crop = new Rect(0, 0, displaySize.x, displaySize.y);
// TODO (b/145893483): calling new API with the display as a parameter
// when surface control supported.
screenShot = SurfaceControl.screenshot(crop, displaySize.x, displaySize.y,
rotation);
if (screenShot != null) {
// Optimization for telling the bitmap that all of the pixels are known to be
// opaque (false). This is meant as a drawing hint, as in some cases a bitmap
// that is known to be opaque can take a faster drawing case than one that may
// have non-opaque per-pixel alpha values.
screenShot.setHasAlpha(false);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
return screenShot;
}
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;

View File

@@ -325,6 +325,19 @@ public class AccessibilitySecurityPolicy {
& AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES) != 0;
}
/**
* Checks if a service can take screenshot.
*
* @param service The service requesting access
*
* @return Whether ot not the service may take screenshot
*/
public boolean canTakeScreenshotLocked(
@NonNull AbstractAccessibilityServiceConnection service) {
return (service.getCapabilities()
& AccessibilityServiceInfo.CAPABILITY_CAN_TAKE_SCREENSHOT) != 0;
}
/**
* Returns the parent userId of the profile according to the specified userId.
*

View File

@@ -16,6 +16,8 @@
package com.android.server.accessibility;
import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import android.Manifest;
@@ -25,16 +27,20 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.graphics.Bitmap;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.view.Display;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -387,4 +393,15 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
}
}
}
@Override
public void takeScreenshotWithCallback(int displayId, RemoteCallback callback) {
mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
final Bitmap screenshot = super.takeScreenshot(displayId);
// Send back the result.
final Bundle payload = new Bundle();
payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT, screenshot);
callback.sendResult(payload);
}, null).recycleOnUse());
}
}

View File

@@ -25,6 +25,7 @@ import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.util.Slog;
import android.view.Display;
@@ -325,5 +326,8 @@ class UiAutomationManager {
@Override
public void onFingerprintGesture(int gesture) {}
@Override
public void takeScreenshotWithCallback(int displayId, RemoteCallback callback) {}
}
}

View File

@@ -75,6 +75,7 @@ import android.os.IBinder;
import android.os.IPowerManager;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.testing.DexmakerShareClassLoaderRule;
import android.view.Display;
@@ -693,6 +694,18 @@ public class AbstractAccessibilityServiceConnectionTest {
assertThat(result, is(false));
}
@Test
public void takeScreenshot_returnNull() {
// no canTakeScreenshot, should return null.
when(mMockSecurityPolicy.canTakeScreenshotLocked(mServiceConnection)).thenReturn(false);
assertThat(mServiceConnection.takeScreenshot(Display.DEFAULT_DISPLAY), is(nullValue()));
// no checkAccessibilityAccess, should return null.
when(mMockSecurityPolicy.canTakeScreenshotLocked(mServiceConnection)).thenReturn(true);
when(mMockSecurityPolicy.checkAccessibilityAccess(mServiceConnection)).thenReturn(false);
assertThat(mServiceConnection.takeScreenshot(Display.DEFAULT_DISPLAY), is(nullValue()));
}
private void updateServiceInfo(AccessibilityServiceInfo serviceInfo, int eventType,
int feedbackType, int flags, String[] packageNames, int notificationTimeout) {
serviceInfo.eventTypes = eventType;
@@ -832,5 +845,8 @@ public class AbstractAccessibilityServiceConnectionTest {
@Override
public void onFingerprintGesture(int gesture) {}
@Override
public void takeScreenshotWithCallback(int displayId, RemoteCallback callback) {}
}
}

View File

@@ -345,6 +345,14 @@ public class AccessibilitySecurityPolicyTest {
assertTrue(mA11ySecurityPolicy.canCaptureFingerprintGestures(mMockA11yServiceConnection));
}
@Test
public void canTakeScreenshot_hasCapability_returnTrue() {
when(mMockA11yServiceConnection.getCapabilities())
.thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_TAKE_SCREENSHOT);
assertTrue(mA11ySecurityPolicy.canTakeScreenshotLocked(mMockA11yServiceConnection));
}
@Test
public void resolveProfileParent_userIdIsCurrentUser_returnCurrentUser() {
final int currentUserId = 10;