diff options
2 files changed, 67 insertions, 1 deletions
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index b338d89a0169..947bd9c57e63 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -126,7 +126,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub private final VirtualDeviceManagerService mService; private final PendingTrampolineCallback mPendingTrampolineCallback; private final int mOwnerUid; - private final int mDeviceId; + private int mDeviceId; // Thou shall not hold the mVirtualDeviceLock over the mInputController calls. // Holding the lock can lead to lock inversion with GlobalWindowManagerLock. // 1. After display is created the window manager calls into VDM during construction @@ -404,6 +404,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub super.close_enforcePermission(); // Remove about-to-be-closed virtual device from the service before butchering it. mService.removeVirtualDevice(mDeviceId); + mDeviceId = Context.DEVICE_ID_INVALID; VirtualDisplayWrapper[] virtualDisplaysToBeReleased; synchronized (mVirtualDeviceLock) { diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java index 3b1983f55fb6..eec898f21800 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java @@ -66,7 +66,9 @@ import com.android.server.wm.ActivityTaskManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; @@ -86,6 +88,14 @@ public class VirtualDeviceManagerService extends SystemService { private static AtomicInteger sNextUniqueIndex = new AtomicInteger( Context.DEVICE_ID_DEFAULT + 1); + private final CompanionDeviceManager.OnAssociationsChangedListener mCdmAssociationListener = + new CompanionDeviceManager.OnAssociationsChangedListener() { + @Override + public void onAssociationsChanged(@NonNull List<AssociationInfo> associations) { + syncVirtualDevicesToCdmAssociations(associations); + } + }; + /** * Mapping from device IDs to virtual devices. */ @@ -204,11 +214,56 @@ public class VirtualDeviceManagerService extends SystemService { final long identity = Binder.clearCallingIdentity(); try { getContext().sendBroadcastAsUser(i, UserHandle.ALL); + + synchronized (mVirtualDeviceManagerLock) { + if (mVirtualDevices.size() == 0) { + unregisterCdmAssociationListener(); + } + } } finally { Binder.restoreCallingIdentity(identity); } } + private void syncVirtualDevicesToCdmAssociations(List<AssociationInfo> associations) { + Set<VirtualDeviceImpl> virtualDevicesToRemove = new HashSet<>(); + synchronized (mVirtualDeviceManagerLock) { + if (mVirtualDevices.size() == 0) { + return; + } + + Set<Integer> activeAssociationIds = new HashSet<>(associations.size()); + for (AssociationInfo association : associations) { + activeAssociationIds.add(association.getId()); + } + + for (int i = 0; i < mVirtualDevices.size(); i++) { + VirtualDeviceImpl virtualDevice = mVirtualDevices.valueAt(i); + if (!activeAssociationIds.contains(virtualDevice.getAssociationId())) { + virtualDevicesToRemove.add(virtualDevice); + } + } + } + + for (VirtualDeviceImpl virtualDevice : virtualDevicesToRemove) { + virtualDevice.close(); + } + + } + + private void registerCdmAssociationListener() { + final CompanionDeviceManager cdm = getContext().getSystemService( + CompanionDeviceManager.class); + cdm.addOnAssociationsChangedListener(getContext().getMainExecutor(), + mCdmAssociationListener); + } + + private void unregisterCdmAssociationListener() { + final CompanionDeviceManager cdm = getContext().getSystemService( + CompanionDeviceManager.class); + cdm.removeOnAssociationsChangedListener(mCdmAssociationListener); + } + class VirtualDeviceManagerImpl extends IVirtualDeviceManager.Stub { private final VirtualDeviceImpl.PendingTrampolineCallback mPendingTrampolineCallback = @@ -254,7 +309,17 @@ public class VirtualDeviceManagerService extends SystemService { if (associationInfo == null) { throw new IllegalArgumentException("No association with ID " + associationId); } + synchronized (mVirtualDeviceManagerLock) { + if (mVirtualDevices.size() == 0) { + final long callindId = Binder.clearCallingIdentity(); + try { + registerCdmAssociationListener(); + } finally { + Binder.restoreCallingIdentity(callindId); + } + } + final UserHandle userHandle = getCallingUserHandle(); final CameraAccessController cameraAccessController = getCameraAccessController(userHandle); |