Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa993a65 authored by Phil Weaver's avatar Phil Weaver Committed by Android (Google) Code Review
Browse files

Merge "Add a11y action to take screenshot"

parents f7157470 d0429743
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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";
+5 −0
Original line number Diff line number Diff line
@@ -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";

    /**
+12 −1
Original line number Diff line number Diff line
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;
+27 −0
Original line number Diff line number Diff line
@@ -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;
    }
}
+17 −1
Original line number Diff line number Diff line
@@ -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));
    }
}