Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd3f81ff authored by Sean Stout's avatar Sean Stout Committed by Android (Google) Code Review
Browse files

Merge "Allow virtual displays to launch activities if trusted"

parents 26da5e34 7beb3787
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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"
+52 −0
Original line number Diff line number Diff line
@@ -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 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);
    }
}