Merge "Make activities in untrusted embedding mode invisible behind overlay" into tm-dev am: c0ccf9b0ec
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16947300 Change-Id: Ie220624f2fca6ff10b825b518452c6a80ba8a2cd
This commit is contained in:
@@ -278,6 +278,7 @@ import android.graphics.PixelFormat;
|
|||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.gui.DropInputMode;
|
||||||
import android.hardware.HardwareBuffer;
|
import android.hardware.HardwareBuffer;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
@@ -782,6 +783,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
boolean startingDisplayed;
|
boolean startingDisplayed;
|
||||||
boolean startingMoved;
|
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
|
* If it is non-null, it requires all activities who have the same starting data to be drawn
|
||||||
* to remove the starting window.
|
* to remove the starting window.
|
||||||
@@ -1548,6 +1553,60 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
rootTask.setHasBeenVisible(true);
|
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() {
|
void updateAnimatingActivityRegistry() {
|
||||||
@@ -5443,6 +5502,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
return false;
|
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
|
// Check if the activity is on a sleeping display, canTurnScreenOn will also check
|
||||||
// keyguard visibility
|
// keyguard visibility
|
||||||
if (mDisplayContent.isSleeping()) {
|
if (mDisplayContent.isSleeping()) {
|
||||||
@@ -5452,6 +5516,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) {
|
void updateVisibilityIgnoringKeyguard(boolean behindFullscreenActivity) {
|
||||||
visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
|
visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
|
||||||
&& showToCurrentUser();
|
&& showToCurrentUser();
|
||||||
|
|||||||
@@ -516,12 +516,13 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
|||||||
* @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord)
|
* @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord)
|
||||||
*/
|
*/
|
||||||
boolean isAllowedToEmbedActivity(@NonNull ActivityRecord a) {
|
boolean isAllowedToEmbedActivity(@NonNull ActivityRecord a) {
|
||||||
if ((a.info.flags & FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING)
|
return isAllowedToEmbedActivityInUntrustedMode(a)
|
||||||
== FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING) {
|
|| isAllowedToEmbedActivityInTrustedMode(a);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
* <li>the activity has declared the organizer host as trusted explicitly via known
|
||||||
* certificate.</li>
|
* certificate.</li>
|
||||||
*/
|
*/
|
||||||
private boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a) {
|
boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a) {
|
||||||
if (UserHandle.getAppId(mTaskFragmentOrganizerUid) == SYSTEM_UID) {
|
if (UserHandle.getAppId(mTaskFragmentOrganizerUid) == SYSTEM_UID) {
|
||||||
// The system is trusted to embed other apps securely and for all users.
|
// The system is trusted to embed other apps securely and for all users.
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -701,6 +701,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
|||||||
sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(),
|
sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(),
|
||||||
errorCallbackToken,
|
errorCallbackToken,
|
||||||
convertStartFailureToThrowable(result, activityIntent));
|
convertStartFailureToThrowable(result, activityIntent));
|
||||||
|
} else {
|
||||||
|
effects |= TRANSACT_EFFECTS_LIFECYCLE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import static android.view.WindowManager.TRANSIT_OPEN;
|
|||||||
|
|
||||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
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.doNothing;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
@@ -422,6 +423,7 @@ public class AppTransitionTests extends WindowTestsBase {
|
|||||||
public void testActivityRecordReparentToTaskFragment() {
|
public void testActivityRecordReparentToTaskFragment() {
|
||||||
final ActivityRecord activity = createActivityRecord(mDc);
|
final ActivityRecord activity = createActivityRecord(mDc);
|
||||||
final SurfaceControl activityLeash = mock(SurfaceControl.class);
|
final SurfaceControl activityLeash = mock(SurfaceControl.class);
|
||||||
|
doNothing().when(activity).setDropInputMode(anyInt());
|
||||||
activity.setVisibility(true);
|
activity.setVisibility(true);
|
||||||
activity.setSurfaceControl(activityLeash);
|
activity.setSurfaceControl(activityLeash);
|
||||||
final Task task = activity.getTask();
|
final Task task = activity.getTask();
|
||||||
|
|||||||
Reference in New Issue
Block a user