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

Commit da06944a authored by Evan Rosky's avatar Evan Rosky Committed by Android (Google) Code Review
Browse files

Merge "Send core-created snapshots to transition player" into tm-qpr-dev

parents 6fae7ad3 c8b3fc0a
Loading
Loading
Loading
Loading
+27 −2
Original line number Diff line number Diff line
@@ -397,6 +397,8 @@ public final class TransitionInfo implements Parcelable {
        private @Surface.Rotation int mEndFixedRotation = ROTATION_UNDEFINED;
        private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
        private @ColorInt int mBackgroundColor;
        private SurfaceControl mSnapshot = null;
        private float mSnapshotLuma;

        public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
            mContainer = container;
@@ -420,6 +422,8 @@ public final class TransitionInfo implements Parcelable {
            mEndFixedRotation = in.readInt();
            mRotationAnimation = in.readInt();
            mBackgroundColor = in.readInt();
            mSnapshot = in.readTypedObject(SurfaceControl.CREATOR);
            mSnapshotLuma = in.readFloat();
        }

        /** Sets the parent of this change's container. The parent must be a participant or null. */
@@ -489,6 +493,12 @@ public final class TransitionInfo implements Parcelable {
            mBackgroundColor = backgroundColor;
        }

        /** Sets a snapshot surface for the "start" state of the container. */
        public void setSnapshot(@Nullable SurfaceControl snapshot, float luma) {
            mSnapshot = snapshot;
            mSnapshotLuma = luma;
        }

        /** @return the container that is changing. May be null if non-remotable (eg. activity) */
        @Nullable
        public WindowContainerToken getContainer() {
@@ -587,6 +597,17 @@ public final class TransitionInfo implements Parcelable {
            return mBackgroundColor;
        }

        /** @return a snapshot surface (if applicable). */
        @Nullable
        public SurfaceControl getSnapshot() {
            return mSnapshot;
        }

        /** @return the luma calculated for the snapshot surface (if applicable). */
        public float getSnapshotLuma() {
            return mSnapshotLuma;
        }

        /** @hide */
        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -605,6 +626,8 @@ public final class TransitionInfo implements Parcelable {
            dest.writeInt(mEndFixedRotation);
            dest.writeInt(mRotationAnimation);
            dest.writeInt(mBackgroundColor);
            dest.writeTypedObject(mSnapshot, flags);
            dest.writeFloat(mSnapshotLuma);
        }

        @NonNull
@@ -629,11 +652,13 @@ public final class TransitionInfo implements Parcelable {

        @Override
        public String toString() {
            return "{" + mContainer + "(" + mParent + ") leash=" + mLeash
            String out = "{" + mContainer + "(" + mParent + ") leash=" + mLeash
                    + " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb="
                    + mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r="
                    + mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation
                    + " endFixedRotation=" + mEndFixedRotation + "}";
                    + " endFixedRotation=" + mEndFixedRotation;
            if (mSnapshot != null) out += " snapshot=" + mSnapshot;
            return out + "}";
        }
    }

+35 −28
Original line number Diff line number Diff line
@@ -139,6 +139,11 @@ class ScreenRotationAnimation {
                .build();

        try {
            if (change.getSnapshot() != null) {
                mScreenshotLayer = change.getSnapshot();
                t.reparent(mScreenshotLayer, mAnimLeash);
                mStartLuma = change.getSnapshotLuma();
            } else {
                SurfaceControl.LayerCaptureArgs args =
                        new SurfaceControl.LayerCaptureArgs.Builder(mSurfaceControl)
                                .setCaptureSecureLayers(true)
@@ -161,16 +166,20 @@ class ScreenRotationAnimation {
                        .setName("RotationLayer")
                        .build();

            t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE);
            t.show(mAnimLeash);
            // Crop the real content in case it contains a larger child layer, e.g. wallpaper.
            t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight));

                final ColorSpace colorSpace = screenshotBuffer.getColorSpace();
                final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
                t.setDataSpace(mScreenshotLayer, colorSpace.getDataSpace());
                t.setBuffer(mScreenshotLayer, hardwareBuffer);
                t.show(mScreenshotLayer);
                if (!isCustomRotate()) {
                    mStartLuma = getMedianBorderLuma(hardwareBuffer, colorSpace);
                }
            }

            t.setLayer(mAnimLeash, SCREEN_FREEZE_LAYER_BASE);
            t.show(mAnimLeash);
            // Crop the real content in case it contains a larger child layer, e.g. wallpaper.
            t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight));

            if (!isCustomRotate()) {
                mBackColorSurface = new SurfaceControl.Builder(session)
@@ -181,8 +190,6 @@ class ScreenRotationAnimation {
                        .setName("BackColorSurface")
                        .build();

                mStartLuma = getMedianBorderLuma(hardwareBuffer, colorSpace);

                t.setLayer(mBackColorSurface, -1);
                t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma});
                t.show(mBackColorSurface);
+27 −9
Original line number Diff line number Diff line
@@ -93,11 +93,13 @@ import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.wm.utils.RotationAnimationUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;

/**
@@ -289,9 +291,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
        if (mContainerFreezer == null) {
            mContainerFreezer = new ScreenshotFreezer();
        }
        mIsSeamlessRotation = true;
        final WindowState top = dc.getDisplayPolicy().getTopFullscreenOpaqueWindow();
        if (top != null) {
            mIsSeamlessRotation = true;
            top.mSyncMethodOverride = BLASTSyncEngine.METHOD_BLAST;
            ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Override sync-method for %s "
                    + "because seamless rotating", top.getName());
@@ -1635,6 +1637,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
                change.setEndAbsBounds(bounds);
            }
            change.setRotation(info.mRotation, endRotation);
            if (info.mSnapshot != null) {
                change.setSnapshot(info.mSnapshot, info.mSnapshotLuma);
            }

            out.addChange(change);
        }
@@ -1790,6 +1795,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
        /** These are just extra info. They aren't used for change-detection. */
        @Flag int mFlags = FLAG_NONE;

        /** Snapshot surface and luma, if relevant. */
        SurfaceControl mSnapshot;
        float mSnapshotLuma;

        ChangeInfo(@NonNull WindowContainer origState) {
            mVisible = origState.isVisibleRequested();
            mWindowingMode = origState.getWindowingMode();
@@ -2098,8 +2107,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
     */
    @VisibleForTesting
    private class ScreenshotFreezer implements IContainerFreezer {
        /** Values are the screenshot "surfaces" or null if it was frozen via BLAST override. */
        private final ArrayMap<WindowContainer, SurfaceControl> mSnapshots = new ArrayMap<>();
        /** Keeps track of which windows are frozen. Not all frozen windows have snapshots. */
        private final ArraySet<WindowContainer> mFrozen = new ArraySet<>();

        /** Takes a screenshot and puts it at the top of the container's surface. */
        @Override
@@ -2109,7 +2118,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
            // Check if any parents have already been "frozen". If so, `wc` is already part of that
            // snapshot, so just skip it.
            for (WindowContainer p = wc; p != null; p = p.getParent()) {
                if (mSnapshots.containsKey(p)) return false;
                if (mFrozen.contains(p)) return false;
            }

            if (mIsSeamlessRotation) {
@@ -2118,7 +2127,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
                if (top != null && (top == wc || top.isDescendantOf(wc))) {
                    // Don't use screenshots for seamless windows: these will use BLAST even if not
                    // BLAST mode.
                    mSnapshots.put(wc, null);
                    mFrozen.add(wc);
                    return true;
                }
            }
@@ -2151,7 +2160,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
                    .setCallsite("Transition.ScreenshotSync")
                    .setBLASTLayer()
                    .build();
            mSnapshots.put(wc, snapshotSurface);
            mFrozen.add(wc);
            final ChangeInfo changeInfo = Objects.requireNonNull(mChanges.get(wc));
            changeInfo.mSnapshot = snapshotSurface;
            if (wc.asDisplayContent() != null) {
                // This isn't cheap, so only do it for rotations: assume display-level is rotate
                // since most of the time it is.
                changeInfo.mSnapshotLuma = RotationAnimationUtils.getMedianBorderLuma(
                        screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace());
            }
            SurfaceControl.Transaction t = wc.mWmService.mTransactionFactory.get();

            t.setBuffer(snapshotSurface, buffer);
@@ -2172,11 +2189,12 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe

        @Override
        public void cleanUp(SurfaceControl.Transaction t) {
            for (int i = 0; i < mSnapshots.size(); ++i) {
                SurfaceControl snap = mSnapshots.valueAt(i);
            for (int i = 0; i < mFrozen.size(); ++i) {
                SurfaceControl snap =
                        Objects.requireNonNull(mChanges.get(mFrozen.valueAt(i))).mSnapshot;
                // May be null if it was frozen via BLAST override.
                if (snap == null) continue;
                t.remove(snap);
                t.reparent(snap, null /* newParent */);
            }
        }
    }
+38 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -82,6 +83,7 @@ import org.mockito.ArgumentCaptor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@@ -1167,6 +1169,42 @@ public class TransitionTests extends WindowTestsBase {
        assertTrue(mSyncEngine.isReady(transition.getSyncId()));
    }

    @Test
    public void testVisibleChange_snapshot() {
        registerTestTransitionPlayer();
        final ActivityRecord app = createActivityRecord(mDisplayContent);
        final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */,
                app.mTransitionController, mWm.mSyncEngine);
        app.mTransitionController.moveToCollecting(transition, BLASTSyncEngine.METHOD_NONE);
        final SurfaceControl mockSnapshot = mock(SurfaceControl.class);
        transition.setContainerFreezer(new Transition.IContainerFreezer() {
            @Override
            public boolean freeze(@NonNull WindowContainer wc, @NonNull Rect bounds) {
                Objects.requireNonNull(transition.mChanges.get(wc)).mSnapshot = mockSnapshot;
                return true;
            }

            @Override
            public void cleanUp(SurfaceControl.Transaction t) {
            }
        });
        final Task task = app.getTask();
        transition.collect(task);
        final Rect bounds = new Rect(task.getBounds());
        Configuration c = new Configuration(task.getRequestedOverrideConfiguration());
        bounds.inset(10, 10);
        c.windowConfiguration.setBounds(bounds);
        task.onRequestedOverrideConfigurationChanged(c);

        ArrayList<WindowContainer> targets = Transition.calculateTargets(
                transition.mParticipants, transition.mChanges);
        TransitionInfo info = Transition.calculateTransitionInfo(
                TRANSIT_CHANGE, 0, targets, transition.mChanges, mMockT);
        assertEquals(mockSnapshot,
                info.getChange(task.mRemoteToken.toWindowContainerToken()).getSnapshot());
        transition.abort();
    }

    private static void makeTaskOrganized(Task... tasks) {
        final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
        for (Task t : tasks) {