Allow virtual displays to launch activities if trusted

This CL updates ActivityStackSupervisor to allow virtual displays to
launch Activities if they are trusted displays. Trusted virtual displays
can only be created if the ADD_TRUSTED_DISPLAY permission is held.

Bug: 162255799
Bug: 162042798
Test: atest WmTests:ActivityStackSupervisorTests
Change-Id: I0ec3ef91e7ee2cbea34183d2607b31a4b0dd0fc3
This commit is contained in:
Sean Stout
2020-07-30 21:34:44 -07:00
parent bbdf17a432
commit 7beb378783
3 changed files with 58 additions and 4 deletions

View File

@@ -130,6 +130,7 @@ import android.util.MergedConfiguration;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.Display;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -1090,9 +1091,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// Check if caller is already present on display
final boolean uidPresentOnDisplay = displayContent.isUidPresent(callingUid);
final int displayOwnerUid = displayContent.mDisplay.getOwnerUid();
if (displayContent.mDisplay.getType() == TYPE_VIRTUAL && displayOwnerUid != SYSTEM_UID) {
// Limit launching on virtual displays, because their contents can be read from Surface
final Display display = displayContent.mDisplay;
if (!display.isTrusted()) {
// Limit launching on untrusted displays because their contents can be read from Surface
// by apps that created them.
if ((aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
@@ -1116,7 +1117,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
// Check if the caller is the owner of the display.
if (displayOwnerUid == callingUid) {
if (display.getOwnerUid() == callingUid) {
if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
+ " allow launch for owner of the display");
return true;

View File

@@ -38,6 +38,7 @@
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.STATUS_BAR" />
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
<application android:debuggable="true"

View File

@@ -38,7 +38,13 @@ import static org.mockito.ArgumentMatchers.eq;
import android.app.WaitResult;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.ImageReader;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.view.DisplayInfo;
import androidx.test.filters.MediumTest;
@@ -173,4 +179,50 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
verify(taskChangeNotifier).notifyTaskFocusChanged(eq(taskB.mTaskId) /* taskId */,
eq(true) /* focused */);
}
@Test
/** Ensures that a trusted virtual display can launch arbitrary activities. */
public void testTrustedVirtualDisplayCanLaunchActivities() {
final DisplayContent newDisplay = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
final Task stack = new StackBuilder(mRootWindowContainer)
.setDisplay(newDisplay).build();
final ActivityRecord unresizableActivity = stack.getTopNonFinishingActivity();
VirtualDisplay virtualDisplay = createVirtualDisplay(true);
final boolean allowed = mSupervisor.isCallerAllowedToLaunchOnDisplay(1234, 1234,
virtualDisplay.getDisplay().getDisplayId(), unresizableActivity.info);
assertThat(allowed).isTrue();
}
@Test
/** Ensures that an untrusted virtual display cannot launch arbitrary activities. */
public void testUntrustedVirtualDisplayCannotLaunchActivities() {
final DisplayContent newDisplay = addNewDisplayContentAt(DisplayContent.POSITION_TOP);
final Task stack = new StackBuilder(mRootWindowContainer)
.setDisplay(newDisplay).build();
final ActivityRecord unresizableActivity = stack.getTopNonFinishingActivity();
VirtualDisplay virtualDisplay = createVirtualDisplay(false);
final boolean allowed = mSupervisor.isCallerAllowedToLaunchOnDisplay(1234, 1234,
virtualDisplay.getDisplay().getDisplayId(), unresizableActivity.info);
assertThat(allowed).isFalse();
}
private VirtualDisplay createVirtualDisplay(boolean trusted) {
final DisplayManager dm = mContext.getSystemService(DisplayManager.class);
final DisplayInfo displayInfo = new DisplayInfo();
final Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
defaultDisplay.getDisplayInfo(displayInfo);
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
if (trusted) {
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
}
final ImageReader imageReader = ImageReader.newInstance(
displayInfo.logicalWidth, displayInfo.logicalHeight, PixelFormat.RGBA_8888, 2);
return dm.createVirtualDisplay("virtualDisplay", displayInfo.logicalWidth,
displayInfo.logicalHeight,
displayInfo.logicalDensityDpi, imageReader.getSurface(), flags);
}
}