Expose the system ui visibility flags and translucent state with snapshot
- Allow SystemUI/Launcher to determine whether the snapshot is of a translucent activity (to reduce overdraw by skipping drawing task background) and also the sysui visibility flags are (to determine how to update the nav bar while animating before the app is started. - Fixing issue where the recents animation was reporting task fillsparent state instead of the app's fillsparent state (as we do in normal remote animations) Bug: 79228291 Bug: 77984778 Bug: 78659249 Test: atest FrameworksServicesTests:TaskSnapshotPersisterLoaderTest Change-Id: I19bdf7f780e7d94014d6a115bf84fa614b1dffa0
This commit is contained in:
@@ -2110,9 +2110,12 @@ public class ActivityManager {
|
||||
private final boolean mIsRealSnapshot;
|
||||
private final int mWindowingMode;
|
||||
private final float mScale;
|
||||
private final int mSystemUiVisibility;
|
||||
private final boolean mIsTranslucent;
|
||||
|
||||
public TaskSnapshot(GraphicBuffer snapshot, int orientation, Rect contentInsets,
|
||||
boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode) {
|
||||
boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode,
|
||||
int systemUiVisibility, boolean isTranslucent) {
|
||||
mSnapshot = snapshot;
|
||||
mOrientation = orientation;
|
||||
mContentInsets = new Rect(contentInsets);
|
||||
@@ -2120,6 +2123,8 @@ public class ActivityManager {
|
||||
mScale = scale;
|
||||
mIsRealSnapshot = isRealSnapshot;
|
||||
mWindowingMode = windowingMode;
|
||||
mSystemUiVisibility = systemUiVisibility;
|
||||
mIsTranslucent = isTranslucent;
|
||||
}
|
||||
|
||||
private TaskSnapshot(Parcel source) {
|
||||
@@ -2130,6 +2135,8 @@ public class ActivityManager {
|
||||
mScale = source.readFloat();
|
||||
mIsRealSnapshot = source.readBoolean();
|
||||
mWindowingMode = source.readInt();
|
||||
mSystemUiVisibility = source.readInt();
|
||||
mIsTranslucent = source.readBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2169,6 +2176,13 @@ public class ActivityManager {
|
||||
return mIsRealSnapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether or not the snapshot is of a translucent app window.
|
||||
*/
|
||||
public boolean isTranslucent() {
|
||||
return mIsTranslucent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The windowing mode of the task when this snapshot was taken.
|
||||
*/
|
||||
@@ -2176,6 +2190,14 @@ public class ActivityManager {
|
||||
return mWindowingMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The system ui visibility flags for the top most visible fullscreen window at the
|
||||
* time that the snapshot was taken.
|
||||
*/
|
||||
public int getSystemUiVisibility() {
|
||||
return mSystemUiVisibility;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The scale this snapshot was taken in.
|
||||
*/
|
||||
@@ -2197,6 +2219,8 @@ public class ActivityManager {
|
||||
dest.writeFloat(mScale);
|
||||
dest.writeBoolean(mIsRealSnapshot);
|
||||
dest.writeInt(mWindowingMode);
|
||||
dest.writeInt(mSystemUiVisibility);
|
||||
dest.writeBoolean(mIsTranslucent);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2207,7 +2231,9 @@ public class ActivityManager {
|
||||
+ " mOrientation=" + mOrientation
|
||||
+ " mContentInsets=" + mContentInsets.toShortString()
|
||||
+ " mReducedResolution=" + mReducedResolution + " mScale=" + mScale
|
||||
+ " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode;
|
||||
+ " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode
|
||||
+ " mSystemUiVisibility=" + mSystemUiVisibility
|
||||
+ " mIsTranslucent=" + mIsTranslucent;
|
||||
}
|
||||
|
||||
public static final Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() {
|
||||
|
||||
@@ -33,7 +33,9 @@ public class ThumbnailData {
|
||||
public Rect insets;
|
||||
public boolean reducedResolution;
|
||||
public boolean isRealSnapshot;
|
||||
public boolean isTranslucent;
|
||||
public int windowingMode;
|
||||
public int systemUiVisibility;
|
||||
public float scale;
|
||||
|
||||
public ThumbnailData() {
|
||||
@@ -43,7 +45,9 @@ public class ThumbnailData {
|
||||
reducedResolution = false;
|
||||
scale = 1f;
|
||||
isRealSnapshot = true;
|
||||
isTranslucent = false;
|
||||
windowingMode = WINDOWING_MODE_UNDEFINED;
|
||||
systemUiVisibility = 0;
|
||||
}
|
||||
|
||||
public ThumbnailData(TaskSnapshot snapshot) {
|
||||
@@ -53,6 +57,8 @@ public class ThumbnailData {
|
||||
reducedResolution = snapshot.isReducedResolution();
|
||||
scale = snapshot.getScale();
|
||||
isRealSnapshot = snapshot.isRealSnapshot();
|
||||
isTranslucent = snapshot.isTranslucent();
|
||||
windowingMode = snapshot.getWindowingMode();
|
||||
systemUiVisibility = snapshot.getSystemUiVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,6 @@
|
||||
int32 inset_bottom = 5;
|
||||
bool is_real_snapshot = 6;
|
||||
int32 windowing_mode = 7;
|
||||
int32 system_ui_visibility = 8;
|
||||
bool is_translucent = 9;
|
||||
}
|
||||
@@ -558,14 +558,17 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
}
|
||||
|
||||
RemoteAnimationTarget createRemoteAnimationApp() {
|
||||
final WindowState mainWindow = mTask.getTopVisibleAppMainWindow();
|
||||
final AppWindowToken topApp = mTask.getTopVisibleAppToken();
|
||||
final WindowState mainWindow = topApp != null
|
||||
? topApp.findMainWindow()
|
||||
: null;
|
||||
if (mainWindow == null) {
|
||||
return null;
|
||||
}
|
||||
final Rect insets = new Rect(mainWindow.mContentInsets);
|
||||
InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
|
||||
mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
|
||||
!mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
|
||||
!topApp.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
|
||||
insets, mTask.getPrefixOrderIndex(), mPosition, mBounds,
|
||||
mTask.getWindowConfiguration(), mIsRecentTaskInvisible);
|
||||
return mTarget;
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.view.DisplayListCanvas;
|
||||
import android.view.RenderNode;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.ThreadedRenderer;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -274,7 +275,8 @@ class TaskSnapshotController {
|
||||
}
|
||||
return new TaskSnapshot(buffer, top.getConfiguration().orientation,
|
||||
getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
|
||||
true /* isRealSnapshot */, task.getWindowingMode());
|
||||
true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
|
||||
!top.fillsParent());
|
||||
}
|
||||
|
||||
private boolean shouldDisableSnapshots() {
|
||||
@@ -364,7 +366,8 @@ class TaskSnapshotController {
|
||||
return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
|
||||
topChild.getConfiguration().orientation, mainWindow.mStableInsets,
|
||||
ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */,
|
||||
false /* isRealSnapshot */, task.getWindowingMode());
|
||||
false /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
|
||||
!topChild.fillsParent());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -429,6 +432,21 @@ class TaskSnapshotController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The SystemUI visibility flags for the top fullscreen window in the given
|
||||
* {@param task}.
|
||||
*/
|
||||
private int getSystemUiVisibility(Task task) {
|
||||
final AppWindowToken topFullscreenToken = task.getTopFullscreenAppToken();
|
||||
final WindowState topFullscreenWindow = topFullscreenToken != null
|
||||
? topFullscreenToken.getTopFullscreenWindow()
|
||||
: null;
|
||||
if (topFullscreenWindow != null) {
|
||||
return topFullscreenWindow.getSystemUiVisibility();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump(PrintWriter pw, String prefix) {
|
||||
mCache.dump(pw, prefix);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ class TaskSnapshotLoader {
|
||||
return new TaskSnapshot(buffer, proto.orientation,
|
||||
new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
|
||||
reducedResolution, reducedResolution ? REDUCED_SCALE : 1f,
|
||||
proto.isRealSnapshot, proto.windowingMode);
|
||||
proto.isRealSnapshot, proto.windowingMode, proto.systemUiVisibility,
|
||||
proto.isTranslucent);
|
||||
} catch (IOException e) {
|
||||
Slog.w(TAG, "Unable to load task snapshot data for taskId=" + taskId);
|
||||
return null;
|
||||
|
||||
@@ -317,6 +317,8 @@ class TaskSnapshotPersister {
|
||||
proto.insetBottom = mSnapshot.getContentInsets().bottom;
|
||||
proto.isRealSnapshot = mSnapshot.isRealSnapshot();
|
||||
proto.windowingMode = mSnapshot.getWindowingMode();
|
||||
proto.systemUiVisibility = mSnapshot.getSystemUiVisibility();
|
||||
proto.isTranslucent = mSnapshot.isTranslucent();
|
||||
final byte[] bytes = TaskSnapshotProto.toByteArray(proto);
|
||||
final File file = getProtoFile(mTaskId, mUserId);
|
||||
final AtomicFile atomicFile = new AtomicFile(file);
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.support.test.filters.MediumTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import android.view.View;
|
||||
import com.android.server.wm.TaskSnapshotPersister.RemoveObsoleteFilesQueueItem;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -166,10 +167,12 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
|
||||
|
||||
@Test
|
||||
public void testIsRealSnapshotPersistAndLoadSnapshot() {
|
||||
TaskSnapshot a = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
TaskSnapshot b = createSnapshot(1f /* scale */, false /* isRealSnapshot */,
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
TaskSnapshot a = new TaskSnapshotBuilder()
|
||||
.setIsRealSnapshot(true)
|
||||
.build();
|
||||
TaskSnapshot b = new TaskSnapshotBuilder()
|
||||
.setIsRealSnapshot(false)
|
||||
.build();
|
||||
assertTrue(a.isRealSnapshot());
|
||||
assertFalse(b.isRealSnapshot());
|
||||
mPersister.persistSnapshot(1, mTestUserId, a);
|
||||
@@ -185,10 +188,12 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
|
||||
|
||||
@Test
|
||||
public void testWindowingModePersistAndLoadSnapshot() {
|
||||
TaskSnapshot a = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
TaskSnapshot b = createSnapshot(1f /* scale */, true /* isRealSnapshot */,
|
||||
WINDOWING_MODE_PINNED);
|
||||
TaskSnapshot a = new TaskSnapshotBuilder()
|
||||
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
|
||||
.build();
|
||||
TaskSnapshot b = new TaskSnapshotBuilder()
|
||||
.setWindowingMode(WINDOWING_MODE_PINNED)
|
||||
.build();
|
||||
assertTrue(a.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
|
||||
assertTrue(b.getWindowingMode() == WINDOWING_MODE_PINNED);
|
||||
mPersister.persistSnapshot(1, mTestUserId, a);
|
||||
@@ -202,6 +207,50 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
|
||||
assertTrue(snapshotB.getWindowingMode() == WINDOWING_MODE_PINNED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsTranslucentPersistAndLoadSnapshot() {
|
||||
TaskSnapshot a = new TaskSnapshotBuilder()
|
||||
.setIsTranslucent(true)
|
||||
.build();
|
||||
TaskSnapshot b = new TaskSnapshotBuilder()
|
||||
.setIsTranslucent(false)
|
||||
.build();
|
||||
assertTrue(a.isTranslucent());
|
||||
assertFalse(b.isTranslucent());
|
||||
mPersister.persistSnapshot(1, mTestUserId, a);
|
||||
mPersister.persistSnapshot(2, mTestUserId, b);
|
||||
mPersister.waitForQueueEmpty();
|
||||
final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
|
||||
final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
|
||||
assertNotNull(snapshotA);
|
||||
assertNotNull(snapshotB);
|
||||
assertTrue(snapshotA.isTranslucent());
|
||||
assertFalse(snapshotB.isTranslucent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemUiVisibilityPersistAndLoadSnapshot() {
|
||||
final int lightBarFlags = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
| View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
|
||||
TaskSnapshot a = new TaskSnapshotBuilder()
|
||||
.setSystemUiVisibility(0)
|
||||
.build();
|
||||
TaskSnapshot b = new TaskSnapshotBuilder()
|
||||
.setSystemUiVisibility(lightBarFlags)
|
||||
.build();
|
||||
assertTrue(a.getSystemUiVisibility() == 0);
|
||||
assertTrue(b.getSystemUiVisibility() == lightBarFlags);
|
||||
mPersister.persistSnapshot(1, mTestUserId, a);
|
||||
mPersister.persistSnapshot(2, mTestUserId, b);
|
||||
mPersister.waitForQueueEmpty();
|
||||
final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
|
||||
final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
|
||||
assertNotNull(snapshotA);
|
||||
assertNotNull(snapshotB);
|
||||
assertTrue(snapshotA.getSystemUiVisibility() == 0);
|
||||
assertTrue(snapshotB.getSystemUiVisibility() == lightBarFlags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveObsoleteFiles() {
|
||||
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
|
||||
|
||||
@@ -85,16 +85,57 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
|
||||
}
|
||||
|
||||
TaskSnapshot createSnapshot(float scale) {
|
||||
return createSnapshot(scale, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN);
|
||||
return new TaskSnapshotBuilder()
|
||||
.setScale(scale)
|
||||
.build();
|
||||
}
|
||||
|
||||
TaskSnapshot createSnapshot(float scale, boolean isRealSnapshot, int windowingMode) {
|
||||
final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
|
||||
USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
|
||||
Canvas c = buffer.lockCanvas();
|
||||
c.drawColor(Color.RED);
|
||||
buffer.unlockCanvasAndPost(c);
|
||||
return new TaskSnapshot(buffer, ORIENTATION_PORTRAIT, TEST_INSETS,
|
||||
scale < 1f /* reducedResolution */, scale, isRealSnapshot, windowingMode);
|
||||
/**
|
||||
* Builds a TaskSnapshot.
|
||||
*/
|
||||
class TaskSnapshotBuilder {
|
||||
|
||||
private float mScale = 1f;
|
||||
private boolean mIsRealSnapshot = true;
|
||||
private boolean mIsTranslucent = false;
|
||||
private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
|
||||
private int mSystemUiVisibility = 0;
|
||||
|
||||
public TaskSnapshotBuilder setScale(float scale) {
|
||||
mScale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskSnapshotBuilder setIsRealSnapshot(boolean isRealSnapshot) {
|
||||
mIsRealSnapshot = isRealSnapshot;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskSnapshotBuilder setIsTranslucent(boolean isTranslucent) {
|
||||
mIsTranslucent = isTranslucent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskSnapshotBuilder setWindowingMode(int windowingMode) {
|
||||
mWindowingMode = windowingMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskSnapshotBuilder setSystemUiVisibility(int systemUiVisibility) {
|
||||
mSystemUiVisibility = systemUiVisibility;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskSnapshot build() {
|
||||
final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
|
||||
USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
|
||||
Canvas c = buffer.lockCanvas();
|
||||
c.drawColor(Color.RED);
|
||||
buffer.unlockCanvasAndPost(c);
|
||||
return new TaskSnapshot(buffer, ORIENTATION_PORTRAIT, TEST_INSETS,
|
||||
mScale < 1f /* reducedResolution */, mScale, mIsRealSnapshot, mWindowingMode,
|
||||
mSystemUiVisibility, mIsTranslucent);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
||||
GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
|
||||
final TaskSnapshot snapshot = new TaskSnapshot(buffer,
|
||||
ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */,
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */);
|
||||
mSurface = new TaskSnapshotSurface(sWm, new Window(), new Surface(), snapshot, "Test",
|
||||
Color.WHITE, Color.RED, Color.BLUE, sysuiVis, windowFlags, 0, taskBounds,
|
||||
ORIENTATION_PORTRAIT);
|
||||
|
||||
Reference in New Issue
Block a user