summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java83
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java2
4 files changed, 94 insertions, 6 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e66f309d2ccc..e9fb4d40ed0d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -278,6 +278,7 @@ import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.gui.DropInputMode;
import android.hardware.HardwareBuffer;
import android.net.Uri;
import android.os.Binder;
@@ -782,6 +783,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean startingDisplayed;
boolean startingMoved;
+ /** The last set {@link DropInputMode} for this activity surface. */
+ @DropInputMode
+ private int mLastDropInputMode = DropInputMode.NONE;
+
/**
* If it is non-null, it requires all activities who have the same starting data to be drawn
* to remove the starting window.
@@ -1548,6 +1553,60 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
rootTask.setHasBeenVisible(true);
}
}
+
+ // Update the input mode if the embedded mode is changed.
+ updateUntrustedEmbeddingInputProtection();
+ }
+
+ @Override
+ void setSurfaceControl(SurfaceControl sc) {
+ super.setSurfaceControl(sc);
+ if (sc != null) {
+ mLastDropInputMode = DropInputMode.NONE;
+ updateUntrustedEmbeddingInputProtection();
+ }
+ }
+
+ /**
+ * Sets to drop input when obscured to activity if it is embedded in untrusted mode.
+ *
+ * Although the untrusted embedded activity should be invisible when behind other overlay,
+ * theoretically even if this activity is the top most, app can still move surface of activity
+ * below it to the top. As a result, we want to update the input mode to drop when obscured for
+ * all untrusted activities.
+ */
+ private void updateUntrustedEmbeddingInputProtection() {
+ final SurfaceControl sc = getSurfaceControl();
+ if (sc == null) {
+ return;
+ }
+ if (isEmbeddedInUntrustedMode()) {
+ // Set drop input to OBSCURED when untrusted embedded.
+ setDropInputMode(DropInputMode.OBSCURED);
+ } else {
+ // Reset drop input mode when this activity is not embedded in untrusted mode.
+ setDropInputMode(DropInputMode.NONE);
+ }
+ }
+
+ @VisibleForTesting
+ void setDropInputMode(@DropInputMode int mode) {
+ if (mLastDropInputMode != mode && getSurfaceControl() != null) {
+ mLastDropInputMode = mode;
+ mWmService.mTransactionFactory.get()
+ .setDropInputMode(getSurfaceControl(), mode)
+ .apply();
+ }
+ }
+
+ private boolean isEmbeddedInUntrustedMode() {
+ final TaskFragment organizedTaskFragment = getOrganizedTaskFragment();
+ if (organizedTaskFragment == null) {
+ // Not embedded.
+ return false;
+ }
+ // Check if trusted.
+ return !organizedTaskFragment.isAllowedToEmbedActivityInTrustedMode(this);
}
void updateAnimatingActivityRegistry() {
@@ -5428,6 +5487,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return false;
}
+ // Untrusted embedded activity can be visible only if there is no other overlay window.
+ if (hasOverlayOverUntrustedModeEmbedded()) {
+ return false;
+ }
+
// Check if the activity is on a sleeping display, canTurnScreenOn will also check
// keyguard visibility
if (mDisplayContent.isSleeping()) {
@@ -5437,6 +5501,25 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
+ /**
+ * Checks if there are any activities or other containers that belong to the same task on top of
+ * this activity when embedded in untrusted mode.
+ */
+ boolean hasOverlayOverUntrustedModeEmbedded() {
+ if (!isEmbeddedInUntrustedMode() || getRootTask() == null) {
+ // The activity is not embedded in untrusted mode.
+ return false;
+ }
+
+ // Check if there are any activities with different UID over the activity that is embedded
+ // in untrusted mode. Traverse bottom to top with boundary so that it will only check
+ // activities above this activity.
+ final ActivityRecord differentUidOverlayActivity = getRootTask().getActivity(
+ a -> a.getUid() != getUid(), this /* boundary */, false /* includeBoundary */,
+ false /* traverseTopToBottom */);
+ return differentUidOverlayActivity != null;
+ }
+
void updateVisibilityIgnoringKeyguard(boolean behindFullscreenActivity) {
visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
&& showToCurrentUser();
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index afc3087f4ee9..3411104dbff0 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -516,12 +516,13 @@ class TaskFragment extends WindowContainer<WindowContainer> {
* @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord)
*/
boolean isAllowedToEmbedActivity(@NonNull ActivityRecord a) {
- if ((a.info.flags & FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING)
- == FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING) {
- return true;
- }
+ return isAllowedToEmbedActivityInUntrustedMode(a)
+ || isAllowedToEmbedActivityInTrustedMode(a);
+ }
- return isAllowedToEmbedActivityInTrustedMode(a);
+ boolean isAllowedToEmbedActivityInUntrustedMode(@NonNull ActivityRecord a) {
+ return (a.info.flags & FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING)
+ == FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING;
}
/**
@@ -531,7 +532,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
* <li>the activity has declared the organizer host as trusted explicitly via known
* certificate.</li>
*/
- private boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a) {
+ boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a) {
if (UserHandle.getAppId(mTaskFragmentOrganizerUid) == SYSTEM_UID) {
// The system is trusted to embed other apps securely and for all users.
return true;
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index ce27d739e1b1..81344ac31108 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -701,6 +701,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(),
errorCallbackToken,
convertStartFailureToThrowable(result, activityIntent));
+ } else {
+ effects |= TRANSACT_EFFECTS_LIFECYCLE;
}
break;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 2ea7fdaf6348..eb6395b46120 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -36,6 +36,7 @@ import static android.view.WindowManager.TRANSIT_OPEN;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -422,6 +423,7 @@ public class AppTransitionTests extends WindowTestsBase {
public void testActivityRecordReparentToTaskFragment() {
final ActivityRecord activity = createActivityRecord(mDc);
final SurfaceControl activityLeash = mock(SurfaceControl.class);
+ doNothing().when(activity).setDropInputMode(anyInt());
activity.setVisibility(true);
activity.setSurfaceControl(activityLeash);
final Task task = activity.getTask();