Add API to disable snapshotting of activities
Test: runtest frameworks-services -c
com.android.server.wm.TaskSnapshotControllerTest
Test: Launch DisableScreenshotsActivity, go to recents, make sure
content is white.
Bug: 31339431
Change-Id: I329925d2fca389e561da3389a67fe888b5bb1033
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 18befef..2821446 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -128,7 +128,6 @@
import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS;
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
-import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
@@ -149,8 +148,6 @@
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
-import static java.lang.Integer.MAX_VALUE;
-
import android.Manifest;
import android.Manifest.permission;
import android.annotation.NonNull;
@@ -10826,6 +10823,25 @@
}
}
+ @Override
+ public void setDisablePreviewScreenshots(IBinder token, boolean disable)
+ throws RemoteException {
+ synchronized (this) {
+ final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ Slog.w(TAG, "setDisablePreviewScreenshots: Unable to find activity for token="
+ + token);
+ return;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ r.setDisablePreviewScreenshots(disable);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
// =========================================================
// CONTENT PROVIDERS
// =========================================================
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 7868fdf..ecaa751 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1973,6 +1973,10 @@
task.taskId, requestedOrientation);
}
+ void setDisablePreviewScreenshots(boolean disable) {
+ mWindowContainerController.setDisablePreviewScreenshots(disable);
+ }
+
/**
* Set the last reported global configuration to the client. Should be called whenever a new
* global configuration is sent to the client for this activity.
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index bd38be4..ef3d87c 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -35,7 +35,6 @@
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Trace;
import android.util.Slog;
import android.view.IApplicationToken;
@@ -228,7 +227,7 @@
boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
boolean alwaysFocusable, AppWindowContainerController controller) {
- return new AppWindowToken(service, token, voiceInteraction, dc,
+ return new AppWindowToken(service, token, voiceInteraction, dc,
inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
controller);
@@ -298,6 +297,17 @@
}
}
+ public void setDisablePreviewScreenshots(boolean disable) {
+ synchronized (mWindowMap) {
+ if (mContainer == null) {
+ Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
+ + " token: " + mToken);
+ return;
+ }
+ mContainer.setDisablePreviewSnapshots(disable);
+ }
+ }
+
public void setVisibility(boolean visible) {
synchronized(mWindowMap) {
if (mContainer == null) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index c20ee97..27e9dea 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -166,6 +166,8 @@
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
+ private boolean mDisbalePreviewScreenshots;
+
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
@@ -1433,6 +1435,14 @@
return candidate;
}
+ void setDisablePreviewSnapshots(boolean disable) {
+ mDisbalePreviewScreenshots = disable;
+ }
+
+ boolean shouldDisablePreviewScreenshots() {
+ return mDisbalePreviewScreenshots;
+ }
+
@Override
int getAnimLayerAdjustment() {
return mAppAnimator.animLayerAdjustment;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 469a8a7..4ae6dbe 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -152,8 +152,13 @@
}
}
- private boolean canSnapshotTask(Task task) {
- return !StackId.isHomeOrRecentsStack(task.mStack.mStackId);
+ @VisibleForTesting
+ boolean canSnapshotTask(Task task) {
+ // TODO: Figure out what happens when snapshots are disabled. Can we draw a splash screen
+ // instead?
+ final AppWindowToken topChild = task.getTopChild();
+ return !StackId.isHomeOrRecentsStack(task.mStack.mStackId)
+ && topChild != null && !topChild.shouldDisablePreviewScreenshots();
}
/**
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 58d277b..45a7999 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -19,6 +19,8 @@
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
@@ -68,4 +70,15 @@
sWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks);
assertEquals(0, closingTasks.size());
}
+
+ @Test
+ public void testSnapshotsDisabled() throws Exception {
+ final WindowState disabledWindow = createWindow(null,
+ FIRST_APPLICATION_WINDOW, sDisplayContent, "disabledWindow");
+ disabledWindow.mAppToken.setDisablePreviewSnapshots(true);
+ assertFalse(sWm.mTaskSnapshotController.canSnapshotTask(disabledWindow.getTask()));
+ final WindowState normalWindow = createWindow(null,
+ FIRST_APPLICATION_WINDOW, sDisplayContent, "normalWindow");
+ assertTrue(sWm.mTaskSnapshotController.canSnapshotTask(normalWindow.getTask()));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 65efd9c..96481dd 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -42,6 +42,7 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.EMPTY;
+import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;