Merge "Send core-created snapshots to transition player" into tm-qpr-dev
This commit is contained in:
@@ -397,6 +397,8 @@ public final class TransitionInfo implements Parcelable {
|
|||||||
private @Surface.Rotation int mEndFixedRotation = ROTATION_UNDEFINED;
|
private @Surface.Rotation int mEndFixedRotation = ROTATION_UNDEFINED;
|
||||||
private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
|
private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
|
||||||
private @ColorInt int mBackgroundColor;
|
private @ColorInt int mBackgroundColor;
|
||||||
|
private SurfaceControl mSnapshot = null;
|
||||||
|
private float mSnapshotLuma;
|
||||||
|
|
||||||
public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
|
public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) {
|
||||||
mContainer = container;
|
mContainer = container;
|
||||||
@@ -420,6 +422,8 @@ public final class TransitionInfo implements Parcelable {
|
|||||||
mEndFixedRotation = in.readInt();
|
mEndFixedRotation = in.readInt();
|
||||||
mRotationAnimation = in.readInt();
|
mRotationAnimation = in.readInt();
|
||||||
mBackgroundColor = 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. */
|
/** 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;
|
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) */
|
/** @return the container that is changing. May be null if non-remotable (eg. activity) */
|
||||||
@Nullable
|
@Nullable
|
||||||
public WindowContainerToken getContainer() {
|
public WindowContainerToken getContainer() {
|
||||||
@@ -587,6 +597,17 @@ public final class TransitionInfo implements Parcelable {
|
|||||||
return mBackgroundColor;
|
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 */
|
/** @hide */
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||||
@@ -605,6 +626,8 @@ public final class TransitionInfo implements Parcelable {
|
|||||||
dest.writeInt(mEndFixedRotation);
|
dest.writeInt(mEndFixedRotation);
|
||||||
dest.writeInt(mRotationAnimation);
|
dest.writeInt(mRotationAnimation);
|
||||||
dest.writeInt(mBackgroundColor);
|
dest.writeInt(mBackgroundColor);
|
||||||
|
dest.writeTypedObject(mSnapshot, flags);
|
||||||
|
dest.writeFloat(mSnapshotLuma);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -629,11 +652,13 @@ public final class TransitionInfo implements Parcelable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{" + mContainer + "(" + mParent + ") leash=" + mLeash
|
String out = "{" + mContainer + "(" + mParent + ") leash=" + mLeash
|
||||||
+ " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb="
|
+ " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb="
|
||||||
+ mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r="
|
+ mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r="
|
||||||
+ mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation
|
+ mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation
|
||||||
+ " endFixedRotation=" + mEndFixedRotation + "}";
|
+ " endFixedRotation=" + mEndFixedRotation;
|
||||||
|
if (mSnapshot != null) out += " snapshot=" + mSnapshot;
|
||||||
|
return out + "}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,11 @@ class ScreenRotationAnimation {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (change.getSnapshot() != null) {
|
||||||
|
mScreenshotLayer = change.getSnapshot();
|
||||||
|
t.reparent(mScreenshotLayer, mAnimLeash);
|
||||||
|
mStartLuma = change.getSnapshotLuma();
|
||||||
|
} else {
|
||||||
SurfaceControl.LayerCaptureArgs args =
|
SurfaceControl.LayerCaptureArgs args =
|
||||||
new SurfaceControl.LayerCaptureArgs.Builder(mSurfaceControl)
|
new SurfaceControl.LayerCaptureArgs.Builder(mSurfaceControl)
|
||||||
.setCaptureSecureLayers(true)
|
.setCaptureSecureLayers(true)
|
||||||
@@ -161,16 +166,20 @@ class ScreenRotationAnimation {
|
|||||||
.setName("RotationLayer")
|
.setName("RotationLayer")
|
||||||
.build();
|
.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 ColorSpace colorSpace = screenshotBuffer.getColorSpace();
|
||||||
final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
|
final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
|
||||||
t.setDataSpace(mScreenshotLayer, colorSpace.getDataSpace());
|
t.setDataSpace(mScreenshotLayer, colorSpace.getDataSpace());
|
||||||
t.setBuffer(mScreenshotLayer, hardwareBuffer);
|
t.setBuffer(mScreenshotLayer, hardwareBuffer);
|
||||||
t.show(mScreenshotLayer);
|
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()) {
|
if (!isCustomRotate()) {
|
||||||
mBackColorSurface = new SurfaceControl.Builder(session)
|
mBackColorSurface = new SurfaceControl.Builder(session)
|
||||||
@@ -181,8 +190,6 @@ class ScreenRotationAnimation {
|
|||||||
.setName("BackColorSurface")
|
.setName("BackColorSurface")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
mStartLuma = getMedianBorderLuma(hardwareBuffer, colorSpace);
|
|
||||||
|
|
||||||
t.setLayer(mBackColorSurface, -1);
|
t.setLayer(mBackColorSurface, -1);
|
||||||
t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma});
|
t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma});
|
||||||
t.show(mBackColorSurface);
|
t.show(mBackColorSurface);
|
||||||
|
|||||||
@@ -93,11 +93,13 @@ import com.android.internal.protolog.ProtoLogGroup;
|
|||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
import com.android.internal.util.function.pooled.PooledLambda;
|
import com.android.internal.util.function.pooled.PooledLambda;
|
||||||
import com.android.server.inputmethod.InputMethodManagerInternal;
|
import com.android.server.inputmethod.InputMethodManagerInternal;
|
||||||
|
import com.android.server.wm.utils.RotationAnimationUtils;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,9 +291,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
|||||||
if (mContainerFreezer == null) {
|
if (mContainerFreezer == null) {
|
||||||
mContainerFreezer = new ScreenshotFreezer();
|
mContainerFreezer = new ScreenshotFreezer();
|
||||||
}
|
}
|
||||||
mIsSeamlessRotation = true;
|
|
||||||
final WindowState top = dc.getDisplayPolicy().getTopFullscreenOpaqueWindow();
|
final WindowState top = dc.getDisplayPolicy().getTopFullscreenOpaqueWindow();
|
||||||
if (top != null) {
|
if (top != null) {
|
||||||
|
mIsSeamlessRotation = true;
|
||||||
top.mSyncMethodOverride = BLASTSyncEngine.METHOD_BLAST;
|
top.mSyncMethodOverride = BLASTSyncEngine.METHOD_BLAST;
|
||||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Override sync-method for %s "
|
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Override sync-method for %s "
|
||||||
+ "because seamless rotating", top.getName());
|
+ "because seamless rotating", top.getName());
|
||||||
@@ -1635,6 +1637,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
|||||||
change.setEndAbsBounds(bounds);
|
change.setEndAbsBounds(bounds);
|
||||||
}
|
}
|
||||||
change.setRotation(info.mRotation, endRotation);
|
change.setRotation(info.mRotation, endRotation);
|
||||||
|
if (info.mSnapshot != null) {
|
||||||
|
change.setSnapshot(info.mSnapshot, info.mSnapshotLuma);
|
||||||
|
}
|
||||||
|
|
||||||
out.addChange(change);
|
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. */
|
/** These are just extra info. They aren't used for change-detection. */
|
||||||
@Flag int mFlags = FLAG_NONE;
|
@Flag int mFlags = FLAG_NONE;
|
||||||
|
|
||||||
|
/** Snapshot surface and luma, if relevant. */
|
||||||
|
SurfaceControl mSnapshot;
|
||||||
|
float mSnapshotLuma;
|
||||||
|
|
||||||
ChangeInfo(@NonNull WindowContainer origState) {
|
ChangeInfo(@NonNull WindowContainer origState) {
|
||||||
mVisible = origState.isVisibleRequested();
|
mVisible = origState.isVisibleRequested();
|
||||||
mWindowingMode = origState.getWindowingMode();
|
mWindowingMode = origState.getWindowingMode();
|
||||||
@@ -2098,8 +2107,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
private class ScreenshotFreezer implements IContainerFreezer {
|
private class ScreenshotFreezer implements IContainerFreezer {
|
||||||
/** Values are the screenshot "surfaces" or null if it was frozen via BLAST override. */
|
/** Keeps track of which windows are frozen. Not all frozen windows have snapshots. */
|
||||||
private final ArrayMap<WindowContainer, SurfaceControl> mSnapshots = new ArrayMap<>();
|
private final ArraySet<WindowContainer> mFrozen = new ArraySet<>();
|
||||||
|
|
||||||
/** Takes a screenshot and puts it at the top of the container's surface. */
|
/** Takes a screenshot and puts it at the top of the container's surface. */
|
||||||
@Override
|
@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
|
// Check if any parents have already been "frozen". If so, `wc` is already part of that
|
||||||
// snapshot, so just skip it.
|
// snapshot, so just skip it.
|
||||||
for (WindowContainer p = wc; p != null; p = p.getParent()) {
|
for (WindowContainer p = wc; p != null; p = p.getParent()) {
|
||||||
if (mSnapshots.containsKey(p)) return false;
|
if (mFrozen.contains(p)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsSeamlessRotation) {
|
if (mIsSeamlessRotation) {
|
||||||
@@ -2118,7 +2127,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
|||||||
if (top != null && (top == wc || top.isDescendantOf(wc))) {
|
if (top != null && (top == wc || top.isDescendantOf(wc))) {
|
||||||
// Don't use screenshots for seamless windows: these will use BLAST even if not
|
// Don't use screenshots for seamless windows: these will use BLAST even if not
|
||||||
// BLAST mode.
|
// BLAST mode.
|
||||||
mSnapshots.put(wc, null);
|
mFrozen.add(wc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2151,7 +2160,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
|||||||
.setCallsite("Transition.ScreenshotSync")
|
.setCallsite("Transition.ScreenshotSync")
|
||||||
.setBLASTLayer()
|
.setBLASTLayer()
|
||||||
.build();
|
.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();
|
SurfaceControl.Transaction t = wc.mWmService.mTransactionFactory.get();
|
||||||
|
|
||||||
t.setBuffer(snapshotSurface, buffer);
|
t.setBuffer(snapshotSurface, buffer);
|
||||||
@@ -2172,11 +2189,12 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cleanUp(SurfaceControl.Transaction t) {
|
public void cleanUp(SurfaceControl.Transaction t) {
|
||||||
for (int i = 0; i < mSnapshots.size(); ++i) {
|
for (int i = 0; i < mFrozen.size(); ++i) {
|
||||||
SurfaceControl snap = mSnapshots.valueAt(i);
|
SurfaceControl snap =
|
||||||
|
Objects.requireNonNull(mChanges.get(mFrozen.valueAt(i))).mSnapshot;
|
||||||
// May be null if it was frozen via BLAST override.
|
// May be null if it was frozen via BLAST override.
|
||||||
if (snap == null) continue;
|
if (snap == null) continue;
|
||||||
t.remove(snap);
|
t.reparent(snap, null /* newParent */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_NAVIGATION_BAR_PANEL;
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
|
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
|
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_CLOSE;
|
||||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||||
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
||||||
@@ -82,6 +83,7 @@ import org.mockito.ArgumentCaptor;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -1167,6 +1169,42 @@ public class TransitionTests extends WindowTestsBase {
|
|||||||
assertTrue(mSyncEngine.isReady(transition.getSyncId()));
|
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) {
|
private static void makeTaskOrganized(Task... tasks) {
|
||||||
final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
|
final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
|
||||||
for (Task t : tasks) {
|
for (Task t : tasks) {
|
||||||
|
|||||||
Reference in New Issue
Block a user