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

Commit bdd0d83e authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "VDM limitations for untrusted displays" into main

parents aa20dc8e 24c03513
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1135,8 +1135,11 @@ public final class VirtualDeviceManager {
        /**
         * Sets the visibility of the pointer icon for this VirtualDevice's associated displays.
         *
         * <p>Only applicable to trusted displays.</p>
         *
         * @param showPointerIcon True if the pointer should be shown; false otherwise. The default
         *   visibility is true.
         * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED
         */
        @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
        public void setShowPointerIcon(boolean showPointerIcon) {
+14 −6
Original line number Diff line number Diff line
@@ -159,7 +159,7 @@ public final class VirtualDeviceParams implements Parcelable {
     * @hide
     */
    @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO,
            POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY, POLICY_TYPE_CAMERA,
            POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY, POLICY_TYPE_CLIPBOARD, POLICY_TYPE_CAMERA,
            POLICY_TYPE_BLOCKED_ACTIVITY})
    @Retention(RetentionPolicy.SOURCE)
    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
@@ -220,11 +220,16 @@ public final class VirtualDeviceParams implements Parcelable {
     * Tells the activity manager how to handle recents entries for activities run on this device.
     *
     * <ul>
     *     <li>{@link #DEVICE_POLICY_DEFAULT}: Activities launched on VirtualDisplays owned by this
     *     <li>{@link #DEVICE_POLICY_DEFAULT}: Activities launched on trusted displays owned by this
     *     device will appear in the host device recents.
     *     <li>{@link #DEVICE_POLICY_CUSTOM}: Activities launched on VirtualDisplays owned by this
     *     <li>{@link #DEVICE_POLICY_CUSTOM}: Activities launched on trusted displays owned by this
     *     device will not appear in recents.
     * </ul>
     *
     * <p>Activities launched on untrusted displays will always show in the host device recents,
     * regardless of the policy.</p>
     *
     * @see android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED
     */
    public static final int POLICY_TYPE_RECENTS = 2;

@@ -254,8 +259,10 @@ public final class VirtualDeviceParams implements Parcelable {
     *     not shared with other devices' clipboards, including the clipboard of the default device.
     *     <li>{@link #DEVICE_POLICY_CUSTOM}: The device's clipboard is shared with the default
     *     device's clipboard. Any clipboard operation on the virtual device is as if it was done on
     *     the default device.
     *     the default device. Requires all displays of the virtual device to be trusted.
     * </ul>
     *
     * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED
     */
    @FlaggedApi(Flags.FLAG_CROSS_DEVICE_CLIPBOARD)
    public static final int POLICY_TYPE_CLIPBOARD = 4;
@@ -821,8 +828,8 @@ public final class VirtualDeviceParams implements Parcelable {
        }

        /**
         * Specifies a component to be used as input method on all displays owned by this virtual
         * device.
         * Specifies a component to be used as input method on all trusted displays owned by this
         * virtual device.
         *
         * @param inputMethodComponent The component name to be used as input method. Must comply to
         *   all general input method requirements described in the guide to
@@ -831,6 +838,7 @@ public final class VirtualDeviceParams implements Parcelable {
         *   may interact with the virtual device, then there will effectively be no IME on this
         *   device's displays for that user.
         *
         * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED
         * @see android.inputmethodservice.InputMethodService
         * @attr ref android.R.styleable#InputMethod_isVirtualDeviceOnly
         * @attr ref android.R.styleable#InputMethod_showInInputMethodPicker
+4 −1
Original line number Diff line number Diff line
@@ -163,7 +163,6 @@ public abstract class VirtualInputDeviceConfig {
            return self();
        }


        /**
         * Sets the product id of the device, uniquely identifying the device within the address
         * space of a given vendor, identified by the device's vendor id.
@@ -179,6 +178,10 @@ public abstract class VirtualInputDeviceConfig {
         *
         * <p>The input device is restricted to the display with the given ID and may not send
         * events to any other display.</p>
         * <p>The corresponding display must be trusted or mirror display.</p>
         *
         * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED
         * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
         */
        @NonNull
        public T setAssociatedDisplayId(int displayId) {
+78 −22
Original line number Diff line number Diff line
@@ -16,10 +16,13 @@

package com.android.server.companion.virtual;

import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY;
import static android.Manifest.permission.ADD_TRUSTED_DISPLAY;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_ENABLED;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
import static android.companion.virtual.VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_ACTIVITY;
@@ -425,6 +428,27 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        mDisplayManager = displayManager;
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
        mPowerManager = context.getSystemService(PowerManager.class);

        if (mDevicePolicies.get(POLICY_TYPE_CLIPBOARD, DEVICE_POLICY_DEFAULT)
                != DEVICE_POLICY_DEFAULT) {
            if (mContext.checkCallingOrSelfPermission(ADD_TRUSTED_DISPLAY)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
                        + "set a custom clipboard policy.");
            }
        }

        int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
        if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
            if (mContext.checkCallingOrSelfPermission(ADD_ALWAYS_UNLOCKED_DISPLAY)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException("Requires ADD_ALWAYS_UNLOCKED_DISPLAY permission to "
                        + "create an always unlocked virtual device.");
            }
            flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
        }
        mBaseVirtualDisplayFlags = flags;

        if (inputController == null) {
            mInputController = new InputController(
                    context.getMainThreadHandler(),
@@ -467,12 +491,6 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                            : mParams.getAllowedActivities();
        }

        int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
        if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
            flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
        }
        mBaseVirtualDisplayFlags = flags;

        if (Flags.vdmCustomIme() && mParams.getInputMethodComponent() != null) {
            final String imeId = mParams.getInputMethodComponent().flattenToShortString();
            Slog.d(TAG, "Setting custom input method " + imeId + " as default for virtual device "
@@ -884,8 +902,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                synchronized (mVirtualDeviceLock) {
                    mDevicePolicies.put(policyType, devicePolicy);
                    for (int i = 0; i < mVirtualDisplays.size(); i++) {
                        mVirtualDisplays.valueAt(i).getWindowPolicyController()
                                .setShowInHostDeviceRecents(devicePolicy == DEVICE_POLICY_DEFAULT);
                        VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
                        if (wrapper.isTrusted()) {
                            wrapper.getWindowPolicyController()
                                    .setShowInHostDeviceRecents(
                                            devicePolicy == DEVICE_POLICY_DEFAULT);
                        }
                    }
                }
                break;
@@ -905,7 +927,20 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                break;
            case POLICY_TYPE_CLIPBOARD:
                if (Flags.crossDeviceClipboard()) {
                    if (policyType == DEVICE_POLICY_CUSTOM
                            && mContext.checkCallingOrSelfPermission(ADD_TRUSTED_DISPLAY)
                            != PackageManager.PERMISSION_GRANTED) {
                        throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
                                + "set a custom clipboard policy.");
                    }
                    synchronized (mVirtualDeviceLock) {
                        for (int i = 0; i < mVirtualDisplays.size(); i++) {
                            VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
                            if (!wrapper.isTrusted() && !wrapper.isMirror()) {
                                throw new SecurityException("All displays must be trusted for "
                                        + "devices with custom clipboard policy.");
                            }
                        }
                        mDevicePolicies.put(policyType, devicePolicy);
                    }
                }
@@ -936,8 +971,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            checkDisplayOwnedByVirtualDeviceLocked(displayId);
            switch (policyType) {
                case POLICY_TYPE_RECENTS:
                    mVirtualDisplays.get(displayId).getWindowPolicyController()
                    VirtualDisplayWrapper wrapper = mVirtualDisplays.get(displayId);
                    if (wrapper.isTrusted()) {
                        wrapper.getWindowPolicyController()
                                .setShowInHostDeviceRecents(devicePolicy == DEVICE_POLICY_DEFAULT);
                    }
                    break;
                case POLICY_TYPE_ACTIVITY:
                    mVirtualDisplays.get(displayId).getWindowPolicyController()
@@ -1247,10 +1285,13 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        try {
            synchronized (mVirtualDeviceLock) {
                mDefaultShowPointerIcon = showPointerIcon;
                for (int i = 0; i < mVirtualDisplays.size(); i++) {
                    VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
                    if (wrapper.isTrusted() || wrapper.isMirror()) {
                        mInputController.setShowPointerIcon(
                                mDefaultShowPointerIcon, mVirtualDisplays.keyAt(i));
                    }
                }
            final int[] displayIds = getDisplayIds();
            for (int i = 0; i < displayIds.length; ++i) {
                mInputController.setShowPointerIcon(showPointerIcon, displayIds[i]);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
@@ -1491,6 +1532,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        boolean isTrustedDisplay =
                (mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED)
                        == Display.FLAG_TRUSTED;
        if (!isTrustedDisplay) {
            if (getDevicePolicy(POLICY_TYPE_CLIPBOARD) != DEVICE_POLICY_DEFAULT) {
                throw new SecurityException("All displays must be trusted for devices with custom"
                        + "clipboard policy.");
            }
        }

        boolean showPointer;
        synchronized (mVirtualDeviceLock) {
@@ -1500,7 +1547,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                        "Virtual device already has a virtual display with ID " + displayId);
            }

            PowerManager.WakeLock wakeLock = createAndAcquireWakeLockForDisplay(displayId);
            PowerManager.WakeLock wakeLock =
                    isTrustedDisplay ? createAndAcquireWakeLockForDisplay(displayId) : null;
            mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock,
                    isTrustedDisplay, isMirrorDisplay));
            showPointer = mDefaultShowPointerIcon;
@@ -1508,14 +1556,15 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub

        final long token = Binder.clearCallingIdentity();
        try {
            mInputController.setShowPointerIcon(showPointer, displayId);
            mInputController.setMousePointerAccelerationEnabled(false, displayId);
            mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false,
                    displayId);
            // WM throws a SecurityException if the display is untrusted.
            if (isTrustedDisplay) {
                mInputController.setShowPointerIcon(showPointer, displayId);
                mInputController.setDisplayImePolicy(displayId,
                        WindowManager.DISPLAY_IME_POLICY_LOCAL);
            } else {
                gwpc.setShowInHostDeviceRecents(true);
            }
        } finally {
            Binder.restoreCallingIdentity(token);
@@ -1616,6 +1665,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                    != PackageManager.PERMISSION_GRANTED) {
            synchronized (mVirtualDeviceLock) {
                checkDisplayOwnedByVirtualDeviceLocked(displayId);
                VirtualDisplayWrapper wrapper = mVirtualDisplays.get(displayId);
                if (!wrapper.isTrusted() && !wrapper.isMirror()) {
                    throw new SecurityException(
                            "Cannot create input device associated with an untrusted display");
                }
            }
        }
    }
@@ -1665,7 +1719,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
     * @param virtualDisplayWrapper - VirtualDisplayWrapper to release resources for.
     */
    private void releaseOwnedVirtualDisplayResources(VirtualDisplayWrapper virtualDisplayWrapper) {
        virtualDisplayWrapper.getWakeLock().release();
        virtualDisplayWrapper.releaseWakeLock();
        virtualDisplayWrapper.getWindowPolicyController().unregisterRunningAppsChangedListener(
                this);
    }
@@ -1833,10 +1887,10 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub

        VirtualDisplayWrapper(@NonNull IVirtualDisplayCallback token,
                @NonNull GenericWindowPolicyController windowPolicyController,
                @NonNull PowerManager.WakeLock wakeLock, boolean isTrusted, boolean isMirror) {
                @Nullable PowerManager.WakeLock wakeLock, boolean isTrusted, boolean isMirror) {
            mToken = Objects.requireNonNull(token);
            mWindowPolicyController = Objects.requireNonNull(windowPolicyController);
            mWakeLock = Objects.requireNonNull(wakeLock);
            mWakeLock = wakeLock;
            mIsTrusted = isTrusted;
            mIsMirror = isMirror;
        }
@@ -1845,8 +1899,10 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            return mWindowPolicyController;
        }

        PowerManager.WakeLock getWakeLock() {
            return mWakeLock;
        void releaseWakeLock() {
            if (mWakeLock != null && mWakeLock.isHeld()) {
                mWakeLock.release();
            }
        }

        boolean isTrusted() {
+4 −5
Original line number Diff line number Diff line
@@ -1769,10 +1769,11 @@ public final class DisplayManagerService extends SystemService {
            flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
        }
        // Put the display in the virtual device's display group only if it's not a mirror display,
        // and if it doesn't need its own display group. So effectively, mirror displays go into the
        // default display group.
        // it is a trusted display, and it doesn't need its own display group. So effectively,
        // mirror and untrusted displays go into the default display group.
        if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) == 0
                && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) == 0
                && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == VIRTUAL_DISPLAY_FLAG_TRUSTED
                && virtualDevice != null) {
            flags |= VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP;
        }
@@ -1848,9 +1849,7 @@ public final class DisplayManagerService extends SystemService {

        if (callingUid != Process.SYSTEM_UID
                && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
            // The virtualDevice instance has been validated above using isValidVirtualDevice
            if (virtualDevice == null
                    && !checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
            if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
                throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
                        + "create a virtual display which is not in the default DisplayGroup.");
            }
Loading