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

Commit 25ab95cb authored by Vladimir Komsiyski's avatar Vladimir Komsiyski
Browse files

Replace CDM association ID with VDM device ID.

Whenever the association ID is used as a map key in VDM. This allows
for multiple virtual devices for the same association and loosens the
coupling between CDM and VDM.

Bug: 262240190
Test: atest VirtualDeviceManagerServiceTest

Change-Id: Id232251377e68daaee02fe90c4f8f10d3dc45c81
parent b78d7e46
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -776,11 +776,11 @@ public final class VirtualDeviceManager {

        private String getVirtualDisplayName() {
            try {
                // Currently this just use the association ID, which means all of the virtual
                // displays created using the same virtual device will have the same name. The name
                // should only be used for informational purposes, and not for identifying the
                // display in code.
                return "VirtualDevice_" + mVirtualDevice.getAssociationId();
                // Currently this just use the device ID, which means all of the virtual displays
                // created using the same virtual device will have the same name. The name should
                // only be used for informational purposes, and not for identifying the display in
                // code.
                return "VirtualDevice_" + mVirtualDevice.getDeviceId();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
+8 −7
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
    private VirtualAudioController mVirtualAudioController;
    @VisibleForTesting
    final Set<Integer> mVirtualDisplayIds = new ArraySet<>();
    private final OnDeviceCloseListener mListener;
    private final OnDeviceCloseListener mOnDeviceCloseListener;
    private final IBinder mAppToken;
    private final VirtualDeviceParams mParams;
    private final Map<Integer, PowerManager.WakeLock> mPerDisplayWakelocks = new ArrayMap<>();
@@ -155,7 +155,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            IBinder token,
            int ownerUid,
            int deviceId,
            OnDeviceCloseListener listener,
            OnDeviceCloseListener onDeviceCloseListener,
            PendingTrampolineCallback pendingTrampolineCallback,
            IVirtualDeviceActivityListener activityListener,
            Consumer<ArraySet<Integer>> runningAppsChangedCallback,
@@ -168,7 +168,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                deviceId,
                /* inputController= */ null,
                /* sensorController= */ null,
                listener,
                onDeviceCloseListener,
                pendingTrampolineCallback,
                activityListener,
                runningAppsChangedCallback,
@@ -184,7 +184,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
            int deviceId,
            InputController inputController,
            SensorController sensorController,
            OnDeviceCloseListener listener,
            OnDeviceCloseListener onDeviceCloseListener,
            PendingTrampolineCallback pendingTrampolineCallback,
            IVirtualDeviceActivityListener activityListener,
            Consumer<ArraySet<Integer>> runningAppsChangedCallback,
@@ -212,7 +212,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
        } else {
            mSensorController = sensorController;
        }
        mListener = listener;
        mOnDeviceCloseListener = onDeviceCloseListener;
        try {
            token.linkToDeath(this, 0);
        } catch (RemoteException e) {
@@ -330,7 +330,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
                mVirtualAudioController = null;
            }
        }
        mListener.onClose(mAssociationInfo.getId());
        mOnDeviceCloseListener.onClose(mDeviceId);
        mAppToken.unlinkToDeath(this, 0);

        final long ident = Binder.clearCallingIdentity();
@@ -650,6 +650,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
    @Override
    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
        fout.println("  VirtualDevice: ");
        fout.println("    mDeviceId: " + mDeviceId);
        fout.println("    mAssociationId: " + mAssociationInfo.getId());
        fout.println("    mParams: " + mParams);
        fout.println("    mVirtualDisplayIds: ");
@@ -839,7 +840,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
    }

    interface OnDeviceCloseListener {
        void onClose(int associationId);
        void onClose(int deviceId);
    }

    interface PendingTrampolineCallback {
+44 −50
Original line number Diff line number Diff line
@@ -90,14 +90,20 @@ public class VirtualDeviceManagerService extends SystemService {
            new SparseArray<>();

    /**
     * Mapping from CDM association IDs to virtual devices. Only one virtual device is allowed for
     * each CDM associated device.
     * Mapping from device IDs to CameraAccessControllers.
     */
    @GuardedBy("mVirtualDeviceManagerLock")
    private final SparseArray<CameraAccessController> mCameraAccessControllersByDeviceId =
            new SparseArray<>();

    /**
     * Mapping from device IDs to virtual devices.
     */
    @GuardedBy("mVirtualDeviceManagerLock")
    private final SparseArray<VirtualDeviceImpl> mVirtualDevices = new SparseArray<>();

    /**
     * Mapping from CDM association IDs to app UIDs running on the corresponding virtual device.
     * Mapping from device IDs to app UIDs running on the corresponding virtual device.
     */
    @GuardedBy("mVirtualDeviceManagerLock")
    private final SparseArray<ArraySet<Integer>> mAppsOnVirtualDevices = new SparseArray<>();
@@ -160,7 +166,7 @@ public class VirtualDeviceManagerService extends SystemService {
    @GuardedBy("mVirtualDeviceManagerLock")
    private boolean isValidVirtualDeviceLocked(IVirtualDevice virtualDevice) {
        try {
            return mVirtualDevices.contains(virtualDevice.getAssociationId());
            return mVirtualDevices.contains(virtualDevice.getDeviceId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -230,9 +236,9 @@ public class VirtualDeviceManagerService extends SystemService {
    }

    @VisibleForTesting
    void notifyRunningAppsChanged(int associationId, ArraySet<Integer> uids) {
    void notifyRunningAppsChanged(int deviceId, ArraySet<Integer> uids) {
        synchronized (mVirtualDeviceManagerLock) {
            mAppsOnVirtualDevices.put(associationId, uids);
            mAppsOnVirtualDevices.put(deviceId, uids);
        }
        mLocalService.onAppsOnVirtualDeviceChanged();
    }
@@ -240,7 +246,7 @@ public class VirtualDeviceManagerService extends SystemService {
    @VisibleForTesting
    void addVirtualDevice(VirtualDeviceImpl virtualDevice) {
        synchronized (mVirtualDeviceManagerLock) {
            mVirtualDevices.put(virtualDevice.getAssociationId(), virtualDevice);
            mVirtualDevices.put(virtualDevice.getDeviceId(), virtualDevice);
        }
    }

@@ -268,60 +274,26 @@ public class VirtualDeviceManagerService extends SystemService {
                throw new IllegalArgumentException("No association with ID " + associationId);
            }
            synchronized (mVirtualDeviceManagerLock) {
                if (mVirtualDevices.contains(associationId)) {
                    throw new IllegalStateException(
                            "Virtual device for association ID " + associationId
                                    + " already exists");
                }
                final int userId = UserHandle.getUserId(callingUid);
                final CameraAccessController cameraAccessController =
                        mCameraAccessControllers.get(userId);
                final int uniqueId = sNextUniqueIndex.getAndIncrement();

                final int deviceId = sNextUniqueIndex.getAndIncrement();
                VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl(getContext(),
                        associationInfo, token, callingUid, uniqueId,
                        new VirtualDeviceImpl.OnDeviceCloseListener() {
                            @Override
                            public void onClose(int associationId) {
                                synchronized (mVirtualDeviceManagerLock) {
                                    VirtualDeviceImpl removedDevice =
                                            mVirtualDevices.removeReturnOld(associationId);
                                    if (removedDevice != null) {
                                        Intent i = new Intent(
                                                VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED);
                                        i.putExtra(
                                                VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID,
                                                removedDevice.getDeviceId());
                                        i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                                        final long identity = Binder.clearCallingIdentity();
                                        try {
                                            getContext().sendBroadcastAsUser(i, UserHandle.ALL);
                                        } finally {
                                            Binder.restoreCallingIdentity(identity);
                                        }
                                    }
                                    mAppsOnVirtualDevices.remove(associationId);
                                    if (cameraAccessController != null) {
                                        cameraAccessController.stopObservingIfNeeded();
                                    } else {
                                        Slog.w(TAG, "cameraAccessController not found for user "
                                                + userId);
                                    }
                                }
                            }
                        },
                        associationInfo, token, callingUid, deviceId,
                        /* onDeviceCloseListener= */ this::onDeviceClosed,
                        this, activityListener,
                        runningUids -> {
                            cameraAccessController.blockCameraAccessIfNeeded(runningUids);
                            notifyRunningAppsChanged(associationInfo.getId(), runningUids);
                            notifyRunningAppsChanged(deviceId, runningUids);
                        },
                        params);
                if (cameraAccessController != null) {
                    cameraAccessController.startObservingIfNeeded();
                    mCameraAccessControllersByDeviceId.put(deviceId, cameraAccessController);
                } else {
                    Slog.w(TAG, "cameraAccessController not found for user " + userId);
                }
                mVirtualDevices.put(associationInfo.getId(), virtualDevice);
                mVirtualDevices.put(deviceId, virtualDevice);
                return virtualDevice;
            }
        }
@@ -338,7 +310,7 @@ public class VirtualDeviceManagerService extends SystemService {
            }
            VirtualDeviceImpl virtualDeviceImpl;
            synchronized (mVirtualDeviceManagerLock) {
                virtualDeviceImpl = mVirtualDevices.get(virtualDevice.getAssociationId());
                virtualDeviceImpl = mVirtualDevices.get(virtualDevice.getDeviceId());
                if (virtualDeviceImpl == null) {
                    throw new SecurityException("Invalid VirtualDevice");
                }
@@ -419,8 +391,7 @@ public class VirtualDeviceManagerService extends SystemService {
        @Nullable
        private AssociationInfo getAssociationInfo(String packageName, int associationId) {
            final int callingUserId = getCallingUserHandle().getIdentifier();
            final List<AssociationInfo> associations =
                    mAllAssociations.get(callingUserId);
            final List<AssociationInfo> associations = mAllAssociations.get(callingUserId);
            if (associations != null) {
                final int associationSize = associations.size();
                for (int i = 0; i < associationSize; i++) {
@@ -436,6 +407,29 @@ public class VirtualDeviceManagerService extends SystemService {
            return null;
        }

        private void onDeviceClosed(int deviceId) {
            synchronized (mVirtualDeviceManagerLock) {
                mVirtualDevices.remove(deviceId);
                Intent i = new Intent(VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED);
                i.putExtra(VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID, deviceId);
                i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                final long identity = Binder.clearCallingIdentity();
                try {
                    getContext().sendBroadcastAsUser(i, UserHandle.ALL);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
                mAppsOnVirtualDevices.remove(deviceId);
                final CameraAccessController cameraAccessController =
                        mCameraAccessControllersByDeviceId.removeReturnOld(deviceId);
                if (cameraAccessController != null) {
                    cameraAccessController.stopObservingIfNeeded();
                } else {
                    Slog.w(TAG, "cameraAccessController not found for device Id " + deviceId);
                }
            }
        }

        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                throws RemoteException {
+16 −24
Original line number Diff line number Diff line
@@ -134,8 +134,6 @@ public class VirtualDeviceManagerServiceTest {
    private static final int UID_2 = 10;
    private static final int UID_3 = 10000;
    private static final int UID_4 = 10001;
    private static final int ASSOCIATION_ID_1 = 1;
    private static final int ASSOCIATION_ID_2 = 2;
    private static final int PRODUCT_ID = 10;
    private static final int VENDOR_ID = 5;
    private static final String UNIQUE_ID = "uniqueid";
@@ -307,13 +305,13 @@ public class VirtualDeviceManagerServiceTest {
                mContext.getSystemService(WindowManager.class), threadVerifier);
        mSensorController = new SensorController(new Object(), VIRTUAL_DEVICE_ID);

        mAssociationInfo = new AssociationInfo(ASSOCIATION_ID_1, 0, null,
        mAssociationInfo = new AssociationInfo(/* associationId= */ 1, 0, null,
                MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0);

        mVdms = new VirtualDeviceManagerService(mContext);
        mLocalService = mVdms.getLocalServiceInstance();
        mVdm = mVdms.new VirtualDeviceManagerImpl();
        mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID, DEVICE_OWNER_UID_1, mAssociationInfo);
        mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID, DEVICE_OWNER_UID_1);
    }

    @Test
@@ -377,7 +375,8 @@ public class VirtualDeviceManagerServiceTest {
                .build();
        mDeviceImpl = new VirtualDeviceImpl(mContext,
                mAssociationInfo, new Binder(), /* ownerUid */ 0, VIRTUAL_DEVICE_ID,
                mInputController, mSensorController, (int associationId) -> {},
                mInputController, mSensorController,
                /* onDeviceCloseListener= */ (int deviceId) -> {},
                mPendingTrampolineCallback, mActivityListener, mRunningAppsChangedCallback, params);
        mVdms.addVirtualDevice(mDeviceImpl);

@@ -396,9 +395,7 @@ public class VirtualDeviceManagerServiceTest {
        int firstDeviceId = mDeviceImpl.getDeviceId();
        int secondDeviceId = VIRTUAL_DEVICE_ID + 1;

        createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2,
                new AssociationInfo(ASSOCIATION_ID_2, 0, null,
                        MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0));
        createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2);

        int secondDeviceOwner = mLocalService.getDeviceOwnerUid(secondDeviceId);
        assertThat(secondDeviceOwner).isEqualTo(DEVICE_OWNER_UID_2);
@@ -457,9 +454,7 @@ public class VirtualDeviceManagerServiceTest {
    public void getDeviceIdsForUid_twoDevicesUidOnOne_returnsCorrectId() {
        int secondDeviceId = VIRTUAL_DEVICE_ID + 1;

        VirtualDeviceImpl secondDevice = createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2,
                new AssociationInfo(ASSOCIATION_ID_2, 0, null,
                        MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0));
        VirtualDeviceImpl secondDevice = createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2);

        GenericWindowPolicyController gwpc =
                secondDevice.createWindowPolicyController(new ArrayList<>());
@@ -474,9 +469,7 @@ public class VirtualDeviceManagerServiceTest {
    public void getDeviceIdsForUid_twoDevicesUidOnBoth_returnsCorrectId() {
        int secondDeviceId = VIRTUAL_DEVICE_ID + 1;

        VirtualDeviceImpl secondDevice = createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2,
                new AssociationInfo(ASSOCIATION_ID_2, 0, null,
                        MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0));
        VirtualDeviceImpl secondDevice = createVirtualDevice(secondDeviceId, DEVICE_OWNER_UID_2);
        GenericWindowPolicyController gwpc1 =
                mDeviceImpl.createWindowPolicyController(new ArrayList<>());
        GenericWindowPolicyController gwpc2 =
@@ -526,7 +519,7 @@ public class VirtualDeviceManagerServiceTest {
        ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
        mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener);

        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uids);
        mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), uids);
        TestableLooper.get(this).processAllMessages();

        verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(uids);
@@ -539,13 +532,13 @@ public class VirtualDeviceManagerServiceTest {
        mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener);

        // Notifies that the running apps on the first virtual device has changed.
        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
        mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), uidsOnDevice1);
        TestableLooper.get(this).processAllMessages();
        verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(
                new ArraySet<>(Arrays.asList(UID_1, UID_2)));

        // Notifies that the running apps on the second virtual device has changed.
        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_2, uidsOnDevice2);
        mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId() + 1, uidsOnDevice2);
        TestableLooper.get(this).processAllMessages();
        // The union of the apps running on both virtual devices are sent to the listeners.
        verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(
@@ -553,7 +546,7 @@ public class VirtualDeviceManagerServiceTest {

        // Notifies that the running apps on the first virtual device has changed again.
        uidsOnDevice1.remove(UID_2);
        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
        mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), uidsOnDevice1);
        mLocalService.onAppsOnVirtualDeviceChanged();
        TestableLooper.get(this).processAllMessages();
        // The union of the apps running on both virtual devices are sent to the listeners.
@@ -562,7 +555,7 @@ public class VirtualDeviceManagerServiceTest {

        // Notifies that the running apps on the first virtual device has changed but with the same
        // set of UIDs.
        mVdms.notifyRunningAppsChanged(ASSOCIATION_ID_1, uidsOnDevice1);
        mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), uidsOnDevice1);
        mLocalService.onAppsOnVirtualDeviceChanged();
        TestableLooper.get(this).processAllMessages();
        // Listeners should not be notified.
@@ -1288,18 +1281,17 @@ public class VirtualDeviceManagerServiceTest {
                intent.filterEquals(blockedAppIntent)), any(), any());
    }

    private VirtualDeviceImpl createVirtualDevice(int virtualDeviceId, int ownerUid,
            AssociationInfo associationInfo) {
    private VirtualDeviceImpl createVirtualDevice(int virtualDeviceId, int ownerUid) {
        VirtualDeviceParams params = new VirtualDeviceParams
                .Builder()
                .setBlockedActivities(getBlockedActivities())
                .build();
        VirtualDeviceImpl virtualDeviceImpl = new VirtualDeviceImpl(mContext,
                associationInfo, new Binder(), ownerUid, virtualDeviceId,
                mInputController, mSensorController, (int associationId) -> {},
                mAssociationInfo, new Binder(), ownerUid, virtualDeviceId,
                mInputController, mSensorController,
                /* onDeviceCloseListener= */ (int deviceId) -> {},
                mPendingTrampolineCallback, mActivityListener, mRunningAppsChangedCallback, params);
        mVdms.addVirtualDevice(virtualDeviceImpl);
        return virtualDeviceImpl;
    }

}