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

Commit e3605c63 authored by wilsonshih's avatar wilsonshih
Browse files

Prepare to deprecate getHardwareBuffer from TaskSnapshot.(2/N)

To more easily track and manage memory usage of TaskSnapshot object in
a client-side process.

Flag: com.android.window.flags.reduce_task_snapshot_memory_usage
Bug: 238206323
Test: presubmit

Change-Id: I8d7879d9a232aadab97c4953c3b733b81559b6cc
parent a770e5d7
Loading
Loading
Loading
Loading
+34 −15
Original line number Diff line number Diff line
@@ -118,9 +118,14 @@ public class SnapshotDrawerUtils {
            mRootSurface = rootSurface;
            mSnapshot = snapshot;
            mTitle = title;
            if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) {
                mSnapshotH = snapshot.getHardwareBufferHeight();
                mSnapshotW = snapshot.getHardwareBufferWidth();
            } else {
                final HardwareBuffer hwBuffer = snapshot.getHardwareBuffer();
                mSnapshotW = hwBuffer.getWidth();
                mSnapshotH = hwBuffer.getHeight();
            }
            mContainerW = windowBounds.width();
            mContainerH = windowBounds.height();
        }
@@ -140,31 +145,41 @@ public class SnapshotDrawerUtils {
            }

            // In case window manager leaks us, make sure we don't retain the snapshot.
            if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) {
                mSnapshot.closeBuffer();
            } else {
                if (mSnapshot.getHardwareBuffer() != null) {
                    mSnapshot.getHardwareBuffer().close();
                }
            }
            if (releaseAfterDraw) {
                mRootSurface.release();
            }
        }

        private void drawSizeMatchSnapshot() {
            mTransaction.setBuffer(mRootSurface, mSnapshot.getHardwareBuffer())
                    .setColorSpace(mRootSurface, mSnapshot.getColorSpace())
                    .apply();
            if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) {
                mSnapshot.setBufferToSurface(mTransaction, mRootSurface);
            } else {
                mTransaction.setBuffer(mRootSurface, mSnapshot.getHardwareBuffer());
            }
            mTransaction.setColorSpace(mRootSurface, mSnapshot.getColorSpace()).apply();
        }

        private void drawSizeMismatchSnapshot() {
            final HardwareBuffer buffer = mSnapshot.getHardwareBuffer();

            // Keep a reference to it such that it doesn't get destroyed when finalized.
            SurfaceControl childSurfaceControl = new SurfaceControl.Builder()
            final SurfaceControl.Builder builder = new SurfaceControl.Builder()
                    .setName(mTitle + " - task-snapshot-surface")
                    .setBLASTLayer()
                    .setFormat(buffer.getFormat())
                    .setParent(mRootSurface)
                    .setCallsite("TaskSnapshotWindow.drawSizeMismatchSnapshot")
                    .build();
                    .setCallsite("TaskSnapshotWindow.drawSizeMismatchSnapshot");
            if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) {
                builder.setFormat(mSnapshot.getHardwareBufferFormat());
            } else {
                final HardwareBuffer buffer = mSnapshot.getHardwareBuffer();
                builder.setFormat(buffer.getFormat());
            }
            SurfaceControl childSurfaceControl = builder.build();

            final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
            float offsetX = letterboxInsets.left;
@@ -184,7 +199,11 @@ public class SnapshotDrawerUtils {
            final float scaleY = (float) mContainerH / mSnapshotH;
            mTransaction.setScale(childSurfaceControl, scaleX, scaleY);
            mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace());
            if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) {
                mSnapshot.setBufferToSurface(mTransaction, childSurfaceControl);
            } else {
                mTransaction.setBuffer(childSurfaceControl, mSnapshot.getHardwareBuffer());
            }
            mTransaction.apply();
            childSurfaceControl.release();
        }
+109 −0
Original line number Diff line number Diff line
@@ -19,9 +19,11 @@ package android.window;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Point;
@@ -33,8 +35,12 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowInsetsController;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.TransitionAnimation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.function.Consumer;
@@ -185,19 +191,122 @@ public class TaskSnapshot implements Parcelable {
     *
     * Note: Prefer {@link #getHardwareBuffer}, which returns the internal object. This version
     * creates a new object.
     *
     * @deprecated Do not access hardware buffer directly.
     */
    @UnsupportedAppUsage
    @Deprecated
    public GraphicBuffer getSnapshot() {
        return GraphicBuffer.createFromHardwareBuffer(mSnapshot);
    }

    /**
     * @return The hardware buffer representing the screenshot.
     * @deprecated Do not access hardware buffer directly.
     */
    @Deprecated
    public HardwareBuffer getHardwareBuffer() {
        return mSnapshot;
    }

    /**
     * Returns the width from the hardware buffer.
     */
    public int getHardwareBufferWidth() {
        return mSnapshot.getWidth();
    }

    /**
     * Returns the height from the hardware buffer.
     */
    public int getHardwareBufferHeight() {
        return mSnapshot.getHeight();
    }

    /**
     * Returns the format from the hardware buffer.
     */
    public @HardwareBuffer.Format int getHardwareBufferFormat() {
        return mSnapshot.getFormat();
    }

    /**
     * Sets hardware buffer to a SurfaceControl.
     */
    public void setBufferToSurface(SurfaceControl.Transaction t,
            SurfaceControl surface) {
        if (!isBufferValid()) {
            return;
        }
        t.setBuffer(surface, mSnapshot);
    }

    /**
     * Creates a bitmap from the hardware buffer, this can return null if the hardware buffer is
     * closed or not exists.
     */
    public Bitmap wrapToBitmap() {
        if (!isBufferValid()) {
            return null;
        }
        return Bitmap.wrapHardwareBuffer(mSnapshot, mColorSpace);
    }

    /**
     * Creates a bitmap from the hardware buffer with specific ColorSpace. This can return null if
     * the hardware buffer is closed or not exists.
     */
    public Bitmap wrapToBitmap(@Nullable ColorSpace colorSpace) {
        if (!isBufferValid()) {
            return null;
        }
        return Bitmap.wrapHardwareBuffer(mSnapshot, colorSpace);
    }

    /**
     * Actively close hardware buffer.
     */
    public void closeBuffer() {
        if (isBufferValid()) {
            mSnapshot.close();
        }
    }

    /**
     * Returns whether the hardware buffer is valid.
     */
    public boolean isBufferValid() {
        return mSnapshot != null && !mSnapshot.isClosed();
    }

    /**
     * Returns whether the hardware buffer has protected content.
     */
    public boolean hasProtectedContent() {
        if (!isBufferValid()) {
            return false;
        }
        return TransitionAnimation.hasProtectedContent(mSnapshot);
    }

    /**
     * Attach the hardware buffer and color space to a Surface.
     */
    public void attachAndQueueBufferWithColorSpace(@NonNull Surface surface) {
        if (!isBufferValid()) {
            return;
        }
        surface.attachAndQueueBufferWithColorSpace(mSnapshot, mColorSpace);
    }

    /**
     * Test only
     */
    @VisibleForTesting
    public boolean isSameHardwareBuffer(@NonNull HardwareBuffer buffer) {
        return buffer == mSnapshot;
    }

    /**
     * @return The color space of hardware buffer representing the screenshot.
     */
+3 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.window;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.app.ActivityTaskManager;
import android.os.RemoteException;
import android.util.Singleton;
@@ -139,6 +140,8 @@ public class TaskSnapshotManager {

    private static final Singleton<ITaskSnapshotManager> ISnapshotManagerSingleton =
            new Singleton<ITaskSnapshotManager>() {
                @RequiresPermission(allOf = {android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
                        android.Manifest.permission.READ_FRAME_BUFFER})
                @Override
                protected ITaskSnapshotManager create() {
                    try {
+17 −5
Original line number Diff line number Diff line
@@ -143,13 +143,25 @@ public abstract class PipContentOverlay {

        @Override
        public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) {
            final float taskSnapshotScaleX = (float) mSnapshot.getTaskSize().x
                    / mSnapshot.getHardwareBuffer().getWidth();
            final float taskSnapshotScaleY = (float) mSnapshot.getTaskSize().y
                    / mSnapshot.getHardwareBuffer().getHeight();
            final float taskSnapshotScaleX;
            final float taskSnapshotScaleY;
            if (com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()) {
                taskSnapshotScaleX = (float) mSnapshot.getTaskSize().x
                        / mSnapshot.getHardwareBufferWidth();
                taskSnapshotScaleY = (float) mSnapshot.getTaskSize().y
                        / mSnapshot.getHardwareBufferHeight();
                mSnapshot.setBufferToSurface(tx, mLeash);
            } else {
                final HardwareBuffer hw = mSnapshot.getHardwareBuffer();
                taskSnapshotScaleX = (float) mSnapshot.getTaskSize().x
                        / hw.getWidth();
                taskSnapshotScaleY = (float) mSnapshot.getTaskSize().y
                        / hw.getHeight();
                tx.setBuffer(mLeash, hw);
            }

            tx.show(mLeash);
            tx.setLayer(mLeash, Integer.MAX_VALUE);
            tx.setBuffer(mLeash, mSnapshot.getHardwareBuffer());
            // Relocate the content to parentLeash's coordinates.
            tx.setPosition(mLeash, -mSourceRectHint.left, -mSourceRectHint.top);
            tx.setScale(mLeash, taskSnapshotScaleX, taskSnapshotScaleY);
+4 −1
Original line number Diff line number Diff line
@@ -86,9 +86,12 @@ public class TaskSnapshotWindow {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
                "create taskSnapshot surface for task: %d", taskId);

        final int format = com.android.window.flags.Flags.reduceTaskSnapshotMemoryUsage()
                ? snapshot.getHardwareBufferFormat()
                : snapshot.getHardwareBuffer().getFormat();
        final WindowManager.LayoutParams layoutParams = SnapshotDrawerUtils.createLayoutParameters(
                info, TITLE_FORMAT + taskId, TYPE_APPLICATION_STARTING,
                snapshot.getHardwareBuffer().getFormat(), appToken);
                format, appToken);
        if (layoutParams == null) {
            Slog.e(TAG, "TaskSnapshotWindow no layoutParams");
            return null;
Loading