summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java11
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java35
5 files changed, 63 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 89b46bc4eba4..84ee942e84d9 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -248,6 +248,7 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.sEnableShellTransitions;
import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
+import static com.android.window.flags.Flags.enablePresentationForConnectedDisplays;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -6224,6 +6225,16 @@ final class ActivityRecord extends WindowToken {
return false;
}
+ // Hide all activities on the presenting display so that malicious apps can't do tap
+ // jacking (b/391466268).
+ // For now, this should only be applied to external displays because presentations can only
+ // be shown on them.
+ // TODO(b/390481621): Disallow a presentation from covering its controlling activity so that
+ // the presentation won't stop its controlling activity.
+ if (enablePresentationForConnectedDisplays() && mDisplayContent.mIsPresenting) {
+ return false;
+ }
+
// Check if the activity is on a sleeping display and keyguard is not going away (to
// align with TaskFragment#shouldSleepActivities), canTurnScreenOn will also check keyguard
// visibility
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a0d2d260b39e..1847be2b7c09 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -547,6 +547,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// TODO(multi-display): remove some of the usages.
boolean isDefaultDisplay;
+ /** Indicates whether any presentation is shown on this display. */
+ boolean mIsPresenting;
+
/** Save allocating when calculating rects */
private final Rect mTmpRect = new Rect();
private final Region mTmpRegion = new Region();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3a1d652f82d4..6bfb9468a381 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -157,6 +157,7 @@ import static com.android.server.wm.WindowManagerServiceDumpProto.POLICY;
import static com.android.server.wm.WindowManagerServiceDumpProto.ROOT_WINDOW_CONTAINER;
import static com.android.server.wm.WindowManagerServiceDumpProto.WINDOW_FRAMES_VALID;
import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions;
+import static com.android.window.flags.Flags.enablePresentationForConnectedDisplays;
import static com.android.window.flags.Flags.multiCrop;
import static com.android.window.flags.Flags.setScPropertiesInClient;
@@ -1924,6 +1925,12 @@ public class WindowManagerService extends IWindowManager.Stub
if (res >= ADD_OKAY
&& (type == TYPE_PRESENTATION || type == TYPE_PRIVATE_PRESENTATION)) {
+ displayContent.mIsPresenting = true;
+ if (enablePresentationForConnectedDisplays()) {
+ // A presentation hides all activities behind on the same display.
+ displayContent.ensureActivitiesVisible(/*starting=*/ null,
+ /*notifyClients=*/ true);
+ }
mDisplayManagerInternal.onPresentation(displayContent.getDisplay().getDisplayId(),
/*isShown=*/ true);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a8f22eaeabb8..84d8f840d849 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -182,6 +182,7 @@ import static com.android.server.wm.WindowStateProto.UNRESTRICTED_KEEP_CLEAR_ARE
import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
+import static com.android.window.flags.Flags.enablePresentationForConnectedDisplays;
import static com.android.window.flags.Flags.surfaceTrustedOverlay;
import android.annotation.CallSuper;
@@ -2317,6 +2318,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final int type = mAttrs.type;
if (type == TYPE_PRESENTATION || type == TYPE_PRIVATE_PRESENTATION) {
+ // TODO(b/393945496): Make sure that there's one presentation at most per display.
+ dc.mIsPresenting = false;
+ if (enablePresentationForConnectedDisplays()) {
+ // A presentation hides all activities behind on the same display.
+ dc.ensureActivitiesVisible(/*starting=*/ null, /*notifyClients=*/ true);
+ }
mWmService.mDisplayManagerInternal.onPresentation(dc.getDisplay().getDisplayId(),
/*isShown=*/ false);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index be79160c3a09..7bc2c477f144 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -26,6 +26,7 @@ import static android.permission.flags.Flags.FLAG_SENSITIVE_CONTENT_RECENTS_SCRE
import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_OWN_FOCUS;
+import static android.view.Display.FLAG_PRESENTATION;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
@@ -53,6 +54,7 @@ import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_WALLPAPER;
+import static com.android.window.flags.Flags.FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS;
import static com.google.common.truth.Truth.assertThat;
@@ -99,6 +101,7 @@ import android.provider.Settings;
import android.util.ArraySet;
import android.util.MergedConfiguration;
import android.view.ContentRecordingSession;
+import android.view.DisplayInfo;
import android.view.IWindow;
import android.view.InputChannel;
import android.view.InputDevice;
@@ -1405,6 +1408,38 @@ public class WindowManagerServiceTests extends WindowTestsBase {
assertEquals(activityWindowInfo2, activityWindowInfo3);
}
+ @EnableFlags(FLAG_ENABLE_PRESENTATION_FOR_CONNECTED_DISPLAYS)
+ @Test
+ public void testPresentationHidesActivitiesBehind() {
+ DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.copyFrom(mDisplayInfo);
+ displayInfo.flags = FLAG_PRESENTATION;
+ DisplayContent dc = createNewDisplay(displayInfo);
+ int displayId = dc.getDisplayId();
+ doReturn(dc).when(mWm.mRoot).getDisplayContentOrCreate(displayId);
+ ActivityRecord activity = createActivityRecord(createTask(dc));
+ assertTrue(activity.isVisible());
+
+ doReturn(true).when(() -> UserManager.isVisibleBackgroundUsersEnabled());
+ int uid = 100000; // uid for non-system user
+ Session session = createTestSession(mAtm, 1234 /* pid */, uid);
+ int userId = UserHandle.getUserId(uid);
+ doReturn(false).when(mWm.mUmInternal).isUserVisible(eq(userId), eq(displayId));
+ WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ LayoutParams.TYPE_PRESENTATION);
+
+ final IWindow clientWindow = new TestIWindow();
+ int result = mWm.addWindow(session, clientWindow, params, View.VISIBLE, displayId,
+ userId, WindowInsets.Type.defaultVisible(), null, new InsetsState(),
+ new InsetsSourceControl.Array(), new Rect(), new float[1]);
+ assertTrue(result >= WindowManagerGlobal.ADD_OKAY);
+ assertFalse(activity.isVisible());
+
+ final WindowState window = mWm.windowForClientLocked(session, clientWindow, false);
+ window.removeImmediately();
+ assertTrue(activity.isVisible());
+ }
+
@Test
public void testAddOverlayWindowToUnassignedDisplay_notAllowed_ForVisibleBackgroundUsers() {
doReturn(true).when(() -> UserManager.isVisibleBackgroundUsersEnabled());