diff options
5 files changed, 62 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt index 86f1a3b52583..65bcec7bf233 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2796,6 +2796,7 @@ package android.accessibilityservice { field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6 field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5 field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3 + field public static final int GLOBAL_ACTION_TAKE_SCREENSHOT = 9; // 0x9 field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7 field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService"; field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice"; diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 97dcb90bbb99..0a4541ba4777 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -363,6 +363,11 @@ public abstract class AccessibilityService extends Service { */ public static final int GLOBAL_ACTION_LOCK_SCREEN = 8; + /** + * Action to take a screenshot + */ + public static final int GLOBAL_ACTION_TAKE_SCREENSHOT = 9; + private static final String LOG_TAG = "AccessibilityService"; /** diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java index f7ea7875c8df..7fd94c6859fb 100644 --- a/core/java/com/android/internal/util/ScreenshotHelper.java +++ b/core/java/com/android/internal/util/ScreenshotHelper.java @@ -1,5 +1,6 @@ package com.android.internal.util; +import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -32,8 +33,18 @@ public class ScreenshotHelper { mContext = context; } + /** + * Request a screenshot be taken. + * + * @param screenshotType The type of screenshot, for example either + * {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN} + * or {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION} + * @param hasStatus {@code true} if the status bar is currently showing. {@code false} if not. + * @param hasNav {@code true} if the navigation bar is currently showing. {@code false} if not. + * @param handler A handler used in case the screenshot times out + */ public void takeScreenshot(final int screenshotType, final boolean hasStatus, - final boolean hasNav, Handler handler) { + final boolean hasNav, @NonNull Handler handler) { synchronized (mScreenshotLock) { if (mScreenshotConnection != null) { return; diff --git a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java index 3b8d4bca0598..672518cc17ed 100644 --- a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java +++ b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java @@ -21,6 +21,8 @@ import android.app.StatusBarManager; import android.content.Context; import android.hardware.input.InputManager; import android.os.Binder; +import android.os.Handler; +import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; @@ -30,20 +32,34 @@ import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ScreenshotHelper; import com.android.server.LocalServices; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.wm.WindowManagerInternal; +import java.util.function.Supplier; + /** * Handle the back-end of AccessibilityService#performGlobalAction */ public class GlobalActionPerformer { private final WindowManagerInternal mWindowManagerService; private final Context mContext; + private Supplier<ScreenshotHelper> mScreenshotHelperSupplier; public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal) { mContext = context; mWindowManagerService = windowManagerInternal; + mScreenshotHelperSupplier = null; + } + + // Used to mock ScreenshotHelper + @VisibleForTesting + public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal, + Supplier<ScreenshotHelper> screenshotHelperSupplier) { + this(context, windowManagerInternal); + mScreenshotHelperSupplier = screenshotHelperSupplier; } public boolean performGlobalAction(int action) { @@ -79,6 +95,9 @@ public class GlobalActionPerformer { case AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN: { return lockScreen(); } + case AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT: { + return takeScreenshot(); + } } return false; } finally { @@ -167,4 +186,12 @@ public class GlobalActionPerformer { mWindowManagerService.lockNow(); return true; } + + private boolean takeScreenshot() { + ScreenshotHelper screenshotHelper = (mScreenshotHelperSupplier != null) + ? mScreenshotHelperSupplier.get() : new ScreenshotHelper(mContext); + screenshotHelper.takeScreenshot(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN, + true, true, new Handler(Looper.getMainLooper())); + return true; + } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java index 1213e814b3fa..e72e4601bbe8 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java @@ -16,13 +16,18 @@ package com.android.server.accessibility; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.accessibilityservice.AccessibilityService; import android.app.StatusBarManager; import android.content.Context; +import android.os.Handler; +import com.android.internal.util.ScreenshotHelper; import com.android.server.wm.WindowManagerInternal; import org.junit.Before; @@ -39,6 +44,7 @@ public class GlobalActionPerformerTest { @Mock Context mMockContext; @Mock WindowManagerInternal mMockWindowManagerInternal; @Mock StatusBarManager mMockStatusBarManager; + @Mock ScreenshotHelper mMockScreenshotHelper; @Before public void setup() { @@ -48,7 +54,8 @@ public class GlobalActionPerformerTest { .thenReturn(mMockStatusBarManager); mGlobalActionPerformer = - new GlobalActionPerformer(mMockContext, mMockWindowManagerInternal); + new GlobalActionPerformer(mMockContext, mMockWindowManagerInternal, + () -> mMockScreenshotHelper); } @Test @@ -70,4 +77,13 @@ public class GlobalActionPerformerTest { mGlobalActionPerformer.performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG); verify(mMockWindowManagerInternal).showGlobalActions(); } + + @Test + public void testScreenshot_requestsFromScreenshotHelper() { + mGlobalActionPerformer.performGlobalAction( + AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT); + verify(mMockScreenshotHelper).takeScreenshot( + eq(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN), anyBoolean(), + anyBoolean(), any(Handler.class)); + } } |