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

Commit 44cc1e27 authored by Miranda Kephart's avatar Miranda Kephart Committed by Android (Google) Code Review
Browse files

Merge "Add screenshots logging" into rvc-dev

parents aac0276a 7b2c313d
Loading
Loading
Loading
Loading
+16 −25
Original line number Diff line number Diff line
@@ -514,33 +514,24 @@ public interface WindowManager extends ViewManager {
    int TAKE_SCREENSHOT_PROVIDED_IMAGE = 3;

    /**
     * Parcel key for the screen shot bitmap sent with messages of type
     * {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}, type {@link android.graphics.Bitmap}
     * @hide
     */
    String PARCEL_KEY_SCREENSHOT_BITMAP = "screenshot_screen_bitmap";

    /**
     * Parcel key for the screen bounds of the image sent with messages of type
     * [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type {@link Rect} in screen coordinates.
     * @hide
     */
    String PARCEL_KEY_SCREENSHOT_BOUNDS = "screenshot_screen_bounds";

    /**
     * Parcel key for the task id of the task that the screen shot was taken of, sent with messages
     * of type [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type int.
     * @hide
     */
    String PARCEL_KEY_SCREENSHOT_TASK_ID = "screenshot_task_id";

    /**
     * Parcel key for the visible insets of the image sent with messages of type
     * [@link {@link #TAKE_SCREENSHOT_PROVIDED_IMAGE}], type {@link android.graphics.Insets} in
     * screen coordinates.
     * Enum listing the possible sources from which a screenshot was originated. Used for logging.
     *
     * @hide
     */
    String PARCEL_KEY_SCREENSHOT_INSETS = "screenshot_insets";
    @IntDef({ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS,
            ScreenshotSource.SCREENSHOT_KEY_CHORD,
            ScreenshotSource.SCREENSHOT_KEY_OTHER,
            ScreenshotSource.SCREENSHOT_OVERVIEW,
            ScreenshotSource.SCREENSHOT_ACCESSIBILITY_ACTIONS,
            ScreenshotSource.SCREENSHOT_OTHER})
    @interface ScreenshotSource {
        int SCREENSHOT_GLOBAL_ACTIONS = 0;
        int SCREENSHOT_KEY_CHORD = 1;
        int SCREENSHOT_KEY_OTHER = 2;
        int SCREENSHOT_OVERVIEW = 3;
        int SCREENSHOT_ACCESSIBILITY_ACTIONS = 4;
        int SCREENSHOT_OTHER = 5;
    }

    /**
     * @hide
+149 −28
Original line number Diff line number Diff line
package com.android.internal.util;

import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
@@ -10,11 +12,12 @@ import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
@@ -23,6 +26,109 @@ import android.view.WindowManager;
import java.util.function.Consumer;

public class ScreenshotHelper {

    /**
     * Describes a screenshot request (to make it easier to pass data through to the handler).
     */
    public static class ScreenshotRequest implements Parcelable {
        private int mSource;
        private boolean mHasStatusBar;
        private boolean mHasNavBar;
        private Bitmap mBitmap;
        private Rect mBoundsInScreen;
        private Insets mInsets;
        private int mTaskId;

        ScreenshotRequest(int source, boolean hasStatus, boolean hasNav) {
            mSource = source;
            mHasStatusBar = hasStatus;
            mHasNavBar = hasNav;
        }

        ScreenshotRequest(
                int source, Bitmap bitmap, Rect boundsInScreen, Insets insets, int taskId) {
            mSource = source;
            mBitmap = bitmap;
            mBoundsInScreen = boundsInScreen;
            mInsets = insets;
            mTaskId = taskId;
        }

        ScreenshotRequest(Parcel in) {
            mSource = in.readInt();
            mHasStatusBar = in.readBoolean();
            mHasNavBar = in.readBoolean();
            if (in.readInt() == 1) {
                mBitmap = in.readParcelable(Bitmap.class.getClassLoader());
                mBoundsInScreen = in.readParcelable(Rect.class.getClassLoader());
                mInsets = in.readParcelable(Insets.class.getClassLoader());
                mTaskId = in.readInt();
            }
        }

        public int getSource() {
            return mSource;
        }

        public boolean getHasStatusBar() {
            return mHasStatusBar;
        }

        public boolean getHasNavBar() {
            return mHasNavBar;
        }

        public Bitmap getBitmap() {
            return mBitmap;
        }

        public Rect getBoundsInScreen() {
            return mBoundsInScreen;
        }

        public Insets getInsets() {
            return mInsets;
        }

        public int getTaskId() {
            return mTaskId;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mSource);
            dest.writeBoolean(mHasStatusBar);
            dest.writeBoolean(mHasNavBar);
            if (mBitmap == null) {
                dest.writeInt(0);
            } else {
                dest.writeInt(1);
                dest.writeParcelable(mBitmap, 0);
                dest.writeParcelable(mBoundsInScreen, 0);
                dest.writeParcelable(mInsets, 0);
                dest.writeInt(mTaskId);
            }
        }

        public static final @NonNull Parcelable.Creator<ScreenshotRequest> CREATOR =
                new Parcelable.Creator<ScreenshotRequest>() {

                    @Override
                    public ScreenshotRequest createFromParcel(Parcel source) {
                        return new ScreenshotRequest(source);
                    }

                    @Override
                    public ScreenshotRequest[] newArray(int size) {
                        return new ScreenshotRequest[size];
                    }
                };
    }
    private static final String TAG = "ScreenshotHelper";

    // Time until we give up on the screenshot & show an error instead.
@@ -36,8 +142,10 @@ public class ScreenshotHelper {
        mContext = context;
    }



    /**
     * Request a screenshot be taken with a specific timeout.
     * Request a screenshot be taken.
     *
     * Added to support reducing unit test duration; the method variant without a timeout argument
     * is recommended for general use.
@@ -47,6 +155,32 @@ public class ScreenshotHelper {
     *                           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 source             The source of the screenshot request. One of
     *                           {SCREENSHOT_GLOBAL_ACTIONS, SCREENSHOT_KEY_CHORD,
     *                           SCREENSHOT_OVERVIEW, SCREENSHOT_OTHER}
     * @param handler            A handler used in case the screenshot times out
     * @param completionConsumer Consumes `false` if a screenshot was not taken, and `true` if the
     *                           screenshot was taken.
     */
    public void takeScreenshot(final int screenshotType, final boolean hasStatus,
            final boolean hasNav, int source, @NonNull Handler handler,
            @Nullable Consumer<Uri> completionConsumer) {
        ScreenshotRequest screenshotRequest = new ScreenshotRequest(source, hasStatus, hasNav);
        takeScreenshot(screenshotType, SCREENSHOT_TIMEOUT_MS, handler, screenshotRequest,
                completionConsumer);
    }

    /**
     * Request a screenshot be taken, with provided reason.
     *
     * @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
@@ -64,7 +198,7 @@ public class ScreenshotHelper {
    }

    /**
     * Request a screenshot be taken.
     * Request a screenshot be taken with a specific timeout.
     *
     * Added to support reducing unit test duration; the method variant without a timeout argument
     * is recommended for general use.
@@ -89,9 +223,9 @@ public class ScreenshotHelper {
    public void takeScreenshot(final int screenshotType, final boolean hasStatus,
            final boolean hasNav, long timeoutMs, @NonNull Handler handler,
            @Nullable Consumer<Uri> completionConsumer) {
        takeScreenshot(screenshotType, hasStatus, hasNav, timeoutMs, handler, null,
                completionConsumer
        );
        ScreenshotRequest screenshotRequest = new ScreenshotRequest(SCREENSHOT_OTHER, hasStatus,
                hasNav);
        takeScreenshot(screenshotType, timeoutMs, handler, screenshotRequest, completionConsumer);
    }

    /**
@@ -106,23 +240,16 @@ public class ScreenshotHelper {
     *                           screenshot was taken.
     */
    public void provideScreenshot(@NonNull Bitmap screenshot, @NonNull Rect boundsInScreen,
            @NonNull Insets insets, int taskId, @NonNull Handler handler,
            @Nullable Consumer<Uri> completionConsumer) {
        Bundle imageBundle = new Bundle();
        imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_BITMAP, screenshot);
        imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_BOUNDS, boundsInScreen);
        imageBundle.putParcelable(WindowManager.PARCEL_KEY_SCREENSHOT_INSETS, insets);
        imageBundle.putInt(WindowManager.PARCEL_KEY_SCREENSHOT_TASK_ID, taskId);

        takeScreenshot(
                WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE,
                false, false, // ignored when image bundle is set
                SCREENSHOT_TIMEOUT_MS, handler, imageBundle, completionConsumer);
            @NonNull Insets insets, int taskId, int source,
            @NonNull Handler handler, @Nullable Consumer<Uri> completionConsumer) {
        ScreenshotRequest screenshotRequest =
                new ScreenshotRequest(source, screenshot, boundsInScreen, insets, taskId);
        takeScreenshot(WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_TIMEOUT_MS,
                handler, screenshotRequest, completionConsumer);
    }

    private void takeScreenshot(final int screenshotType, final boolean hasStatus,
            final boolean hasNav, long timeoutMs, @NonNull Handler handler,
            @Nullable Bundle providedImage, @Nullable Consumer<Uri> completionConsumer) {
    private void takeScreenshot(final int screenshotType, long timeoutMs, @NonNull Handler handler,
            ScreenshotRequest screenshotRequest, @Nullable Consumer<Uri> completionConsumer) {
        synchronized (mScreenshotLock) {
            if (mScreenshotConnection != null) {
                return;
@@ -157,7 +284,7 @@ public class ScreenshotHelper {
                            return;
                        }
                        Messenger messenger = new Messenger(service);
                        Message msg = Message.obtain(null, screenshotType);
                        Message msg = Message.obtain(null, screenshotType, screenshotRequest);
                        final ServiceConnection myConn = this;
                        Handler h = new Handler(handler.getLooper()) {
                            @Override
@@ -175,12 +302,6 @@ public class ScreenshotHelper {
                            }
                        };
                        msg.replyTo = new Messenger(h);
                        msg.arg1 = hasStatus ? 1 : 0;
                        msg.arg2 = hasNav ? 1 : 0;

                        if (screenshotType == WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE) {
                            msg.setData(providedImage);
                        }

                        try {
                            messenger.send(msg);
+3 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.view.WindowManager;

import androidx.test.runner.AndroidJUnit4;

@@ -91,7 +92,8 @@ public final class ScreenshotHelperTest {
    public void testProvidedImageScreenshot() {
        mScreenshotHelper.provideScreenshot(
                Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888), new Rect(),
                Insets.of(0, 0, 0, 0), 1, mHandler, null);
                Insets.of(0, 0, 0, 0), 1,
                WindowManager.ScreenshotSource.SCREENSHOT_OTHER, mHandler, null);
    }

    @Test
+4 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.accessibility;

import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS;

import android.accessibilityservice.AccessibilityService;
import android.app.PendingIntent;
import android.app.RemoteAction;
@@ -282,8 +284,8 @@ public class SystemActions extends SystemUI {

    private void handleTakeScreenshot() {
        ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
        screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
                true, true, new Handler(Looper.getMainLooper()), null);
        screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN, true, true,
                SCREENSHOT_GLOBAL_ACTIONS, new Handler(Looper.getMainLooper()), null);
    }

    private void handleAccessibilityMenu() {
+4 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@ package com.android.systemui.globalactions;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS;
import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;

import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
@@ -830,7 +832,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScreenshotHelper.takeScreenshot(1, true, true, mHandler, null);
                    mScreenshotHelper.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN, true, true,
                            SCREENSHOT_GLOBAL_ACTIONS, mHandler, null);
                    mMetricsLogger.action(MetricsEvent.ACTION_SCREENSHOT_POWER_MENU);
                    mUiEventLogger.log(GlobalActionsEvent.GA_SCREENSHOT_PRESS);
                }
Loading