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

Commit a607768e authored by Raymond Chiu's avatar Raymond Chiu Committed by Android (Google) Code Review
Browse files

Merge "Add feature to capture layer" into sc-dev

parents 76b68a37 e4cde9c8
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.window.TaskOrganizer;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
import com.android.wm.shell.startingsurface.StartingWindowController;
@@ -55,6 +56,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * Unified task organizer for all components in the shell.
@@ -342,6 +344,19 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        notifySizeCompatUI(info.getTaskInfo(), listener);
    }

    /**
     * Take a screenshot of a task.
     */
    public void screenshotTask(RunningTaskInfo taskInfo, Rect crop,
            Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
        final TaskAppearedInfo info = mTasks.get(taskInfo.taskId);
        if (info == null) {
            return;
        }
        ScreenshotUtils.captureLayer(info.getLeash(), crop, consumer);
    }


    @Override
    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
        synchronized (mLock) {
+55 −23
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.view.SurfaceControl;

import java.util.function.Consumer;

/**
 * Helpers for working with screenshots.
 */
@@ -29,28 +31,41 @@ public class ScreenshotUtils {
    /**
     * Take a screenshot of the specified SurfaceControl.
     *
     * @param t the transaction used to set changes on the resulting screenshot.
     * @param sc the SurfaceControl to take a screenshot of
     * @param crop the crop to use when capturing the screenshot
     * @param layer the layer to place the screenshot
     *
     * @return A SurfaceControl where the screenshot will be attached, or null if failed.
     * @param consumer Consumer for the captured buffer
     */
    public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
            Rect crop, int layer) {
        final SurfaceControl.ScreenshotHardwareBuffer buffer = SurfaceControl.captureLayers(
    public static void captureLayer(SurfaceControl sc, Rect crop,
            Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
        consumer.accept(SurfaceControl.captureLayers(
                new SurfaceControl.LayerCaptureArgs.Builder(sc)
                    .setSourceCrop(crop)
                    .setCaptureSecureLayers(true)
                    .setAllowProtected(true)
                        .build()
        );
                    .build()));
    }

    private static class BufferConsumer implements
            Consumer<SurfaceControl.ScreenshotHardwareBuffer> {
        SurfaceControl mScreenshot = null;
        SurfaceControl.Transaction mTransaction;
        SurfaceControl mSurfaceControl;
        int mLayer;

        BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, int layer) {
            mTransaction = t;
            mSurfaceControl = sc;
            mLayer = layer;
        }

        @Override
        public void accept(SurfaceControl.ScreenshotHardwareBuffer buffer) {
            if (buffer == null || buffer.getHardwareBuffer() == null) {
            return null;
                return;
            }
            final GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
                buffer.getHardwareBuffer());
        final SurfaceControl screenshot = new SurfaceControl.Builder()
            mScreenshot = new SurfaceControl.Builder()
                .setName("ScreenshotUtils screenshot")
                .setFormat(PixelFormat.TRANSLUCENT)
                .setSecure(buffer.containsSecureLayers())
@@ -58,12 +73,29 @@ public class ScreenshotUtils {
                .setBLASTLayer()
                .build();

        t.setBuffer(screenshot, graphicBuffer);
        t.setColorSpace(screenshot, buffer.getColorSpace());
        t.reparent(screenshot, sc);
        t.setLayer(screenshot, layer);
        t.show(screenshot);
        t.apply();
        return screenshot;
            mTransaction.setBuffer(mScreenshot, graphicBuffer);
            mTransaction.setColorSpace(mScreenshot, buffer.getColorSpace());
            mTransaction.reparent(mScreenshot, mSurfaceControl);
            mTransaction.setLayer(mScreenshot, mLayer);
            mTransaction.show(mScreenshot);
            mTransaction.apply();
        }
    }

    /**
     * Take a screenshot of the specified SurfaceControl.
     *
     * @param t the transaction used to set changes on the resulting screenshot.
     * @param sc the SurfaceControl to take a screenshot of
     * @param crop the crop to use when capturing the screenshot
     * @param layer the layer to place the screenshot
     *
     * @return A SurfaceControl where the screenshot will be attached, or null if failed.
     */
    public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
            Rect crop, int layer) {
        BufferConsumer consumer = new BufferConsumer(t, sc, layer);
        captureLayer(sc, crop, consumer);
        return consumer.mScreenshot;
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,13 @@

package com.android.wm.shell.tasksurfacehelper;

import android.app.ActivityManager.RunningTaskInfo;
import android.graphics.Rect;
import android.view.SurfaceControl;

import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * Interface to communicate with a Task's SurfaceControl.
 */
@@ -23,4 +30,8 @@ public interface TaskSurfaceHelper {

    /** Sets the METADATA_GAME_MODE for the layer corresponding to the task **/
    default void setGameModeForTask(int taskId, int gameMode) {}

    /** Takes a screenshot for a task **/
    default void screenshotTask(RunningTaskInfo taskInfo, Rect crop, Executor executor,
            Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {}
}
+22 −0
Original line number Diff line number Diff line
@@ -16,11 +16,16 @@

package com.android.wm.shell.tasksurfacehelper;

import android.app.ActivityManager.RunningTaskInfo;
import android.graphics.Rect;
import android.view.SurfaceControl;

import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;

import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * Intermediary controller that communicates with {@link ShellTaskOrganizer} to send commands
 * to SurfaceControl.
@@ -49,6 +54,14 @@ public class TaskSurfaceHelperController {
        mTaskOrganizer.setSurfaceMetadata(taskId, SurfaceControl.METADATA_GAME_MODE, gameMode);
    }

    /**
     * Take screenshot of the specified task.
     */
    public void screenshotTask(RunningTaskInfo taskInfo, Rect crop,
            Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
        mTaskOrganizer.screenshotTask(taskInfo, crop, consumer);
    }

    private class TaskSurfaceHelperImpl implements TaskSurfaceHelper {
        @Override
        public void setGameModeForTask(int taskId, int gameMode) {
@@ -56,5 +69,14 @@ public class TaskSurfaceHelperController {
                TaskSurfaceHelperController.this.setGameModeForTask(taskId, gameMode);
            });
        }

        @Override
        public void screenshotTask(RunningTaskInfo taskInfo, Rect crop, Executor executor,
                Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
            mMainExecutor.execute(() -> {
                TaskSurfaceHelperController.this.screenshotTask(taskInfo, crop,
                        (t) -> executor.execute(() -> consumer.accept(t)));
            });
        }
    }
}