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

Commit 37d8f86b authored by Vladimir Komsiyski's avatar Vladimir Komsiyski Committed by Android (Google) Code Review
Browse files

Merge "Allow for cross-device clipboard." into main

parents 57f63527 6325a3bc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3253,6 +3253,7 @@ package android.companion.virtual {
    field @Deprecated public static final int NAVIGATION_POLICY_DEFAULT_BLOCKED = 1; // 0x1
    field @FlaggedApi("android.companion.virtual.flags.dynamic_policy") public static final int POLICY_TYPE_ACTIVITY = 3; // 0x3
    field public static final int POLICY_TYPE_AUDIO = 1; // 0x1
    field @FlaggedApi("android.companion.virtual.flags.cross_device_clipboard") public static final int POLICY_TYPE_CLIPBOARD = 4; // 0x4
    field public static final int POLICY_TYPE_RECENTS = 2; // 0x2
    field public static final int POLICY_TYPE_SENSORS = 0; // 0x0
  }
+20 −1
Original line number Diff line number Diff line
@@ -169,7 +169,8 @@ public final class VirtualDeviceParams implements Parcelable {
     * @see VirtualDeviceManager.VirtualDevice#setDevicePolicy
     * @hide
     */
    @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY})
    @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY,
            POLICY_TYPE_CLIPBOARD})
    @Retention(RetentionPolicy.SOURCE)
    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
    public @interface DynamicPolicyType {}
@@ -230,6 +231,20 @@ public final class VirtualDeviceParams implements Parcelable {
    @FlaggedApi(Flags.FLAG_DYNAMIC_POLICY)
    public static final int POLICY_TYPE_ACTIVITY = 3;

    /**
     * Tells the clipboard manager whether this device's clipboard should be shared or not.
     *
     * <ul>
     *     <li>{@link #DEVICE_POLICY_DEFAULT}: By default the device's clipboard is its own and is
     *     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.
     * </ul>
     */
    @FlaggedApi(Flags.FLAG_CROSS_DEVICE_CLIPBOARD)
    public static final int POLICY_TYPE_CLIPBOARD = 4;

    private final int mLockState;
    @NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
    @NavigationPolicy
@@ -1086,6 +1101,10 @@ public final class VirtualDeviceParams implements Parcelable {
                }
            }

            if (!Flags.crossDeviceClipboard()) {
                mDevicePolicies.delete(POLICY_TYPE_CLIPBOARD);
            }

            if ((mAudioPlaybackSessionId != AUDIO_SESSION_ID_GENERATE
                    || mAudioRecordingSessionId != AUDIO_SESSION_ID_GENERATE)
                    && mDevicePolicies.get(POLICY_TYPE_AUDIO, DEVICE_POLICY_DEFAULT)
+7 −0
Original line number Diff line number Diff line
@@ -15,6 +15,13 @@ flag {
  bug: "298401780"
}

flag {
  name: "cross_device_clipboard"
  namespace: "virtual_devices"
  description: "Enable cross-device clipboard API"
  bug: "306622082"
}

flag {
  name: "vdm_custom_home"
  namespace: "virtual_devices"
+8 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.companion.virtual.VirtualDeviceParams.ACTIVITY_POLICY_DEFA
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;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
@@ -665,6 +666,13 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                    }
                }
                break;
            case POLICY_TYPE_CLIPBOARD:
                if (Flags.crossDeviceClipboard()) {
                    synchronized (mVirtualDeviceLock) {
                        mDevicePolicies.put(policyType, devicePolicy);
                    }
                }
                break;
            default:
                throw new IllegalArgumentException("Device policy " + policyType
                        + " cannot be changed at runtime. ");
+37 −16
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.server.clipboard;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED;
import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.content.Context.DEVICE_ID_INVALID;

@@ -409,7 +411,7 @@ public class ClipboardService extends SystemService {

    /**
     * Determines which deviceId to use for selecting a Clipboard, depending on where a given app
     * is running.
     * is running and the device's clipboard policy.
     *
     * @param requestedDeviceId the requested deviceId passed in from the client side
     * @param uid the intended app uid
@@ -431,28 +433,47 @@ public class ClipboardService extends SystemService {
            }
        }

        if (requestedDeviceId != DEVICE_ID_DEFAULT) {
            // Privileged apps that own the VirtualDevices, or regular apps running on it, can
            // request it by id.
            if (mVdmInternal.getDeviceOwnerUid(requestedDeviceId) == uid
                    || virtualDeviceIds.contains(requestedDeviceId)) {
                return requestedDeviceId;
        // If an app is running on any VirtualDevice, it isn't clear which clipboard they
        // should use, unless all of the devices share the default device's clipboard.
        boolean allDevicesHaveDefaultClipboard = true;
        for (int deviceId : virtualDeviceIds) {
            if (!deviceUsesDefaultClipboard(deviceId)) {
                allDevicesHaveDefaultClipboard = false;
                break;
            }
            return DEVICE_ID_INVALID;
        }

        // The common case is apps running normally (not on a VirtualDevice).
        if (virtualDeviceIds.isEmpty()) {
            return DEVICE_ID_DEFAULT;
        // Apps running on a virtual device may get the default clipboard if all the devices the app
        // runs on share that clipboard. Otherwise it's not clear which clipboard to use.
        if (requestedDeviceId == DEVICE_ID_DEFAULT) {
            return allDevicesHaveDefaultClipboard ? DEVICE_ID_DEFAULT : DEVICE_ID_INVALID;
        }

        // If an app is running on more than one VirtualDevice, it isn't clear which clipboard they
        // should use.
        if (virtualDeviceIds.size() > 1) {
            return DEVICE_ID_INVALID;
        // At this point the app wants to access a virtual device clipboard. It may do so if:
        //  1. The app owns the VirtualDevice
        //  2. The app is present on the VirtualDevice
        //  3. The VirtualDevice shares the default device clipboard and all virtual devices that
        //     the app is running on do the same.
        int clipboardDeviceId = deviceUsesDefaultClipboard(requestedDeviceId)
                ? DEVICE_ID_DEFAULT
                : requestedDeviceId;

        if (mVdmInternal.getDeviceOwnerUid(requestedDeviceId) == uid
                || virtualDeviceIds.contains(requestedDeviceId)
                || (clipboardDeviceId == DEVICE_ID_DEFAULT && allDevicesHaveDefaultClipboard)) {
            return clipboardDeviceId;
        }

        // Fallback to the device where the app is running, unless it uses the default clipboard.
        int fallbackDeviceId = virtualDeviceIds.valueAt(0);
        return deviceUsesDefaultClipboard(fallbackDeviceId) ? DEVICE_ID_DEFAULT : fallbackDeviceId;
    }

        return virtualDeviceIds.valueAt(0);
    private boolean deviceUsesDefaultClipboard(int deviceId) {
        if (deviceId == DEVICE_ID_DEFAULT || mVdm == null) {
            return true;
        }
        return mVdm.getDevicePolicy(deviceId, POLICY_TYPE_CLIPBOARD) == DEVICE_POLICY_CUSTOM;
    }

    /**