Loading services/core/java/com/android/server/wm/ActivityStackSupervisor.java +5 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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:" Loading @@ -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; Loading services/tests/wmtests/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -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" Loading services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java +52 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -173,4 +179,50 @@ public class ActivityStackSupervisorTests extends WindowTestsBase { 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); } } Loading
services/core/java/com/android/server/wm/ActivityStackSupervisor.java +5 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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:" Loading @@ -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; Loading
services/tests/wmtests/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -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" Loading
services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java +52 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -173,4 +179,50 @@ public class ActivityStackSupervisorTests extends WindowTestsBase { 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); } }