Loading core/java/android/companion/virtual/VirtualDeviceManager.java +5 −5 Original line number Diff line number Diff line Loading @@ -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(); } Loading services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +8 −7 Original line number Diff line number Diff line Loading @@ -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<>(); Loading Loading @@ -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, Loading @@ -168,7 +168,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub deviceId, /* inputController= */ null, /* sensorController= */ null, listener, onDeviceCloseListener, pendingTrampolineCallback, activityListener, runningAppsChangedCallback, Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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(); Loading Loading @@ -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: "); Loading Loading @@ -839,7 +840,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } interface OnDeviceCloseListener { void onClose(int associationId); void onClose(int deviceId); } interface PendingTrampolineCallback { Loading services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +44 −50 Original line number Diff line number Diff line Loading @@ -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<>(); Loading Loading @@ -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(); } Loading Loading @@ -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(); } Loading @@ -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); } } Loading Loading @@ -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; } } Loading @@ -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"); } Loading Loading @@ -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++) { Loading @@ -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 { Loading services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +16 −24 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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 Loading Loading @@ -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); Loading @@ -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); Loading Loading @@ -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<>()); Loading @@ -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 = Loading Loading @@ -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); Loading @@ -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( Loading @@ -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. Loading @@ -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. Loading Loading @@ -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; } } Loading
core/java/android/companion/virtual/VirtualDeviceManager.java +5 −5 Original line number Diff line number Diff line Loading @@ -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(); } Loading
services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +8 −7 Original line number Diff line number Diff line Loading @@ -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<>(); Loading Loading @@ -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, Loading @@ -168,7 +168,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub deviceId, /* inputController= */ null, /* sensorController= */ null, listener, onDeviceCloseListener, pendingTrampolineCallback, activityListener, runningAppsChangedCallback, Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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(); Loading Loading @@ -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: "); Loading Loading @@ -839,7 +840,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } interface OnDeviceCloseListener { void onClose(int associationId); void onClose(int deviceId); } interface PendingTrampolineCallback { Loading
services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +44 −50 Original line number Diff line number Diff line Loading @@ -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<>(); Loading Loading @@ -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(); } Loading Loading @@ -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(); } Loading @@ -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); } } Loading Loading @@ -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; } } Loading @@ -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"); } Loading Loading @@ -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++) { Loading @@ -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 { Loading
services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +16 −24 Original line number Diff line number Diff line Loading @@ -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"; Loading Loading @@ -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 Loading Loading @@ -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); Loading @@ -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); Loading Loading @@ -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<>()); Loading @@ -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 = Loading Loading @@ -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); Loading @@ -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( Loading @@ -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. Loading @@ -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. Loading Loading @@ -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; } }