When snapshots are disabled, fill it with single color.
Test: Launch DisableScreenshotsActivity, go to recents, make sure
content is blue. Reopen activity from home, make sure starting
window is blue.
Bug: 31339431
Change-Id: I29689774c3cdcb784d8f5bfa4f947a6f35b91e01
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 4ae6dbe..b8d0b8c 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -17,11 +17,16 @@
package com.android.server.wm;
import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
+import static android.graphics.GraphicBuffer.USAGE_HW_TEXTURE;
+import static android.graphics.GraphicBuffer.USAGE_SW_READ_NEVER;
+import static android.graphics.GraphicBuffer.USAGE_SW_WRITE_RARELY;
+import static android.graphics.PixelFormat.RGBA_8888;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskSnapshot;
+import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
import android.os.Environment;
import android.util.ArraySet;
@@ -48,6 +53,26 @@
*/
class TaskSnapshotController {
+ /**
+ * Return value for {@link #getSnapshotMode}: We are allowed to take a real screenshot to be
+ * used as the snapshot.
+ */
+ @VisibleForTesting
+ static final int SNAPSHOT_MODE_REAL = 0;
+
+ /**
+ * Return value for {@link #getSnapshotMode}: We are not allowed to take a real screenshot but
+ * we should try to use the app theme to create a dummy representation of the app.
+ */
+ @VisibleForTesting
+ static final int SNAPSHOT_MODE_APP_THEME = 1;
+
+ /**
+ * Return value for {@link #getSnapshotMode}: We aren't allowed to take any snapshot.
+ */
+ @VisibleForTesting
+ static final int SNAPSHOT_MODE_NONE = 2;
+
private final WindowManagerService mService;
private final TaskSnapshotCache mCache;
@@ -88,10 +113,21 @@
getClosingTasks(closingApps, mTmpTasks);
for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
final Task task = mTmpTasks.valueAt(i);
- if (!canSnapshotTask(task)) {
- continue;
+ final int mode = getSnapshotMode(task);
+ final TaskSnapshot snapshot;
+ switch (mode) {
+ case SNAPSHOT_MODE_NONE:
+ continue;
+ case SNAPSHOT_MODE_APP_THEME:
+ snapshot = drawAppThemeSnapshot(task);
+ break;
+ case SNAPSHOT_MODE_REAL:
+ snapshot = snapshotTask(task);
+ break;
+ default:
+ snapshot = null;
+ break;
}
- final TaskSnapshot snapshot = snapshotTask(task);
if (snapshot != null) {
mCache.putSnapshot(task, snapshot);
mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
@@ -153,12 +189,42 @@
}
@VisibleForTesting
- boolean canSnapshotTask(Task task) {
- // TODO: Figure out what happens when snapshots are disabled. Can we draw a splash screen
- // instead?
+ int getSnapshotMode(Task task) {
final AppWindowToken topChild = task.getTopChild();
- return !StackId.isHomeOrRecentsStack(task.mStack.mStackId)
- && topChild != null && !topChild.shouldDisablePreviewScreenshots();
+ if (StackId.isHomeOrRecentsStack(task.mStack.mStackId)) {
+ return SNAPSHOT_MODE_NONE;
+ } else if (topChild != null && topChild.shouldDisablePreviewScreenshots()) {
+ return SNAPSHOT_MODE_APP_THEME;
+ } else {
+ return SNAPSHOT_MODE_REAL;
+ }
+ }
+
+ /**
+ * If we are not allowed to take a real screenshot, this attempts to represent the app as best
+ * as possible by using the theme's window background.
+ */
+ private TaskSnapshot drawAppThemeSnapshot(Task task) {
+ final AppWindowToken topChild = task.getTopChild();
+ if (topChild == null) {
+ return null;
+ }
+ final WindowState mainWindow = topChild.findMainWindow();
+ if (mainWindow == null) {
+ return null;
+ }
+ final int color = task.getTaskDescription().getBackgroundColor();
+ final GraphicBuffer buffer = GraphicBuffer.create(mainWindow.getFrameLw().width(),
+ mainWindow.getFrameLw().height(),
+ RGBA_8888, USAGE_HW_TEXTURE | USAGE_SW_WRITE_RARELY | USAGE_SW_READ_NEVER);
+ if (buffer == null) {
+ return null;
+ }
+ final Canvas c = buffer.lockCanvas();
+ c.drawColor(color);
+ buffer.unlockCanvasAndPost(c);
+ return new TaskSnapshot(buffer, topChild.getConfiguration().orientation,
+ mainWindow.mStableInsets, false /* reduced */, 1.0f /* scale */);
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 45a7999..2752340 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -18,6 +18,7 @@
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static com.android.server.wm.TaskSnapshotController.*;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -72,13 +73,15 @@
}
@Test
- public void testSnapshotsDisabled() throws Exception {
+ public void testGetSnapshotMode() throws Exception {
final WindowState disabledWindow = createWindow(null,
FIRST_APPLICATION_WINDOW, sDisplayContent, "disabledWindow");
disabledWindow.mAppToken.setDisablePreviewSnapshots(true);
- assertFalse(sWm.mTaskSnapshotController.canSnapshotTask(disabledWindow.getTask()));
+ assertEquals(SNAPSHOT_MODE_APP_THEME,
+ sWm.mTaskSnapshotController.getSnapshotMode(disabledWindow.getTask()));
final WindowState normalWindow = createWindow(null,
FIRST_APPLICATION_WINDOW, sDisplayContent, "normalWindow");
- assertTrue(sWm.mTaskSnapshotController.canSnapshotTask(normalWindow.getTask()));
+ assertEquals(SNAPSHOT_MODE_REAL,
+ sWm.mTaskSnapshotController.getSnapshotMode(normalWindow.getTask()));
}
}