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
This commit is contained in:
@ -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 @@ import java.io.PrintWriter;
|
||||
*/
|
||||
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 @@ class TaskSnapshotController {
|
||||
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 @@ class TaskSnapshotController {
|
||||
}
|
||||
|
||||
@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 */);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ package com.android.server.wm;
|
||||
|
||||
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 @@ public class TaskSnapshotControllerTest extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@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()));
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,8 @@
|
||||
<receiver android:name="TrackTimeReceiver" />
|
||||
<receiver android:name="AlarmSpamReceiver" />
|
||||
<activity android:name="DisableScreenshotsActivity"
|
||||
android:label="DisableScreenshots">
|
||||
android:label="DisableScreenshots"
|
||||
android:theme="@style/DisableScreenshots">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
18
tests/ActivityTests/res/values/colors.xml
Normal file
18
tests/ActivityTests/res/values/colors.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<color name="blue">#0000ff</color>
|
||||
</resources>
|
@ -22,4 +22,8 @@
|
||||
<item name="android:windowEnterAnimation">@anim/slow_enter</item>
|
||||
<item name="android:windowExitAnimation">@anim/slow_exit</item>
|
||||
</style>
|
||||
<style name="DisableScreenshots" parent="@android:style/Theme.Material">
|
||||
<item name="android:colorBackground">@color/blue</item>
|
||||
<item name="android:windowBackground">@color/blue</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
@ -20,6 +20,7 @@ import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
|
||||
/**
|
||||
* Activity for which screenshotting is disabled.
|
||||
@ -32,4 +33,13 @@ public class DisableScreenshotsActivity extends Activity {
|
||||
setDisablePreviewScreenshots(true);
|
||||
getWindow().getDecorView().setBackgroundColor(Color.RED);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// This is to simulate slowness over resuming the app, such that we have plenty of time to
|
||||
// see the starting window.
|
||||
SystemClock.sleep(500);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user