diff options
4 files changed, 29 insertions, 28 deletions
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 452dc5f97d12..0b633bd9c549 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2042,7 +2042,7 @@ public final class DisplayManagerService extends SystemService { // handles stopping the projection. Slog.w(TAG, "Content Recording: failed to start mirroring - " + "releasing virtual display " + displayId); - releaseVirtualDisplayInternal(callback.asBinder(), callingUid); + releaseVirtualDisplayInternal(callback.asBinder()); return Display.INVALID_DISPLAY; } else if (projection != null) { // Indicate that this projection has been used to record, and can't be used @@ -2131,7 +2131,7 @@ public final class DisplayManagerService extends SystemService { // Something weird happened and the logical display was not created. Slog.w(TAG, "Rejecting request to create virtual display " + "because the logical display was not created."); - mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder(), callingUid); + mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder()); mDisplayDeviceRepo.onDisplayDeviceEvent(device, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); return -1; @@ -2158,14 +2158,14 @@ public final class DisplayManagerService extends SystemService { } } - private void releaseVirtualDisplayInternal(IBinder appToken, int callingUid) { + private void releaseVirtualDisplayInternal(IBinder appToken) { synchronized (mSyncRoot) { if (mVirtualDisplayAdapter == null) { return; } DisplayDevice device = - mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken, callingUid); + mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); Slog.d(TAG, "Virtual Display: Display Device released"); if (device != null) { // TODO: multi-display - handle virtual displays the same as other display adapters. @@ -4789,10 +4789,9 @@ public final class DisplayManagerService extends SystemService { @Override // Binder call public void releaseVirtualDisplay(IVirtualDisplayCallback callback) { - final int callingUid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { - releaseVirtualDisplayInternal(callback.asBinder(), callingUid); + releaseVirtualDisplayInternal(callback.asBinder()); } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 836f4ede8f57..f14e452ab8d3 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -91,6 +91,13 @@ public class VirtualDisplayAdapter extends DisplayAdapter { private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices = new ArrayMap<>(); + // When a virtual display is created, the mapping (appToken -> ownerUid) is stored here. That + // way, when the display is released later, we can retrieve the ownerUid and decrement + // the number of virtual displays that exist for that ownerUid. We can't use + // Binder.getCallingUid() because the display might be released by the system process and not + // the process that created the display. + private final ArrayMap<IBinder, Integer> mOwnerUids = new ArrayMap<>(); + private final int mMaxDevices; private final int mMaxDevicesPerPackage; private final SparseIntArray mNoOfDevicesPerPackage = new SparseIntArray(); @@ -194,6 +201,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mVirtualDisplayDevices.put(appToken, device); if (getFeatureFlags().isVirtualDisplayLimitEnabled()) { mNoOfDevicesPerPackage.put(ownerUid, noOfDevices + 1); + mOwnerUids.put(appToken, ownerUid); } try { @@ -205,7 +213,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { appToken.linkToDeath(device, 0); } catch (RemoteException ex) { Slog.e(TAG, "Virtual Display: error while setting up VirtualDisplayDevice", ex); - removeVirtualDisplayDeviceLocked(appToken, ownerUid); + removeVirtualDisplayDeviceLocked(appToken); device.destroyLocked(false); return null; } @@ -252,12 +260,10 @@ public class VirtualDisplayAdapter extends DisplayAdapter { /** * Release a virtual display that was previously created * @param appToken The token to identify the display - * @param ownerUid The UID of the package, used to keep track of and limit the number of - * displays created per package * @return The display device that has been removed */ - public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken, int ownerUid) { - VirtualDisplayDevice device = removeVirtualDisplayDeviceLocked(appToken, ownerUid); + public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) { + VirtualDisplayDevice device = removeVirtualDisplayDeviceLocked(appToken); if (device != null) { Slog.v(TAG, "Release VirtualDisplay " + device.mName); device.destroyLocked(true); @@ -299,11 +305,13 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } } - private VirtualDisplayDevice removeVirtualDisplayDeviceLocked(IBinder appToken, int ownerUid) { - int noOfDevices = mNoOfDevicesPerPackage.get(ownerUid, /* valueIfKeyNotFound= */ 0); + private VirtualDisplayDevice removeVirtualDisplayDeviceLocked(IBinder appToken) { if (getFeatureFlags().isVirtualDisplayLimitEnabled()) { + int ownerUid = mOwnerUids.get(appToken); + int noOfDevices = mNoOfDevicesPerPackage.get(ownerUid, /* valueIfKeyNotFound= */ 0); if (noOfDevices <= 1) { mNoOfDevicesPerPackage.delete(ownerUid); + mOwnerUids.remove(appToken); } else { mNoOfDevicesPerPackage.put(ownerUid, noOfDevices - 1); } @@ -378,7 +386,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { @Override public void binderDied() { synchronized (getSyncRoot()) { - removeVirtualDisplayDeviceLocked(mAppToken, mOwnerUid); + removeVirtualDisplayDeviceLocked(mAppToken); Slog.i(TAG, "Virtual display device released because application token died: " + mOwnerPackageName); destroyLocked(false); diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java index 365cbaed2aac..724f083018f2 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -3708,7 +3708,7 @@ public class DisplayManagerServiceTest { eq(config)); bs.releaseVirtualDisplay(mMockAppToken); - verify(mMockVirtualDisplayAdapter).releaseVirtualDisplayLocked(binder, callingUid); + verify(mMockVirtualDisplayAdapter).releaseVirtualDisplayLocked(binder); } @Test diff --git a/services/tests/displayservicetests/src/com/android/server/display/VirtualDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/VirtualDisplayAdapterTest.java index dbd5c65f9ba3..9287b3004279 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/VirtualDisplayAdapterTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/VirtualDisplayAdapterTest.java @@ -118,14 +118,13 @@ public class VirtualDisplayAdapterTest { public void testCreateAndReleaseVirtualDisplay() { VirtualDisplayConfig config = new VirtualDisplayConfig.Builder("test", /* width= */ 1, /* height= */ 1, /* densityDpi= */ 1).build(); - int ownerUid = 10; DisplayDevice result = mAdapter.createVirtualDisplayLocked(mMockCallback, - /* projection= */ null, ownerUid, /* packageName= */ "testpackage", + /* projection= */ null, /* ownerUid= */ 10, /* packageName= */ "testpackage", /* uniqueId= */ "uniqueId", /* surface= */ null, /* flags= */ 0, config); assertNotNull(result); - result = mAdapter.releaseVirtualDisplayLocked(mMockBinder, ownerUid); + result = mAdapter.releaseVirtualDisplayLocked(mMockBinder); assertNotNull(result); } @@ -230,7 +229,6 @@ public class VirtualDisplayAdapterTest { // Displays for the same package for (int i = 0; i < MAX_DEVICES_PER_PACKAGE * 2; i++) { - // Same owner UID IVirtualDisplayCallback callback = createCallback(); DisplayDevice device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, 1234, "test.package", "123", @@ -240,7 +238,6 @@ public class VirtualDisplayAdapterTest { // Displays for different packages for (int i = 0; i < MAX_DEVICES * 2; i++) { - // Same owner UID IVirtualDisplayCallback callback = createCallback(); DisplayDevice device = mAdapter.createVirtualDisplayLocked(callback, mMediaProjectionMock, 1234 + i, "test.package", "123", @@ -270,8 +267,7 @@ public class VirtualDisplayAdapterTest { } // Release one display - DisplayDevice device = mAdapter.releaseVirtualDisplayLocked(callbacks.get(0).asBinder(), - ownerUid); + DisplayDevice device = mAdapter.releaseVirtualDisplayLocked(callbacks.get(0).asBinder()); assertNotNull(device); callbacks.remove(0); @@ -292,7 +288,7 @@ public class VirtualDisplayAdapterTest { // Release all the displays for (IVirtualDisplayCallback cb : callbacks) { - device = mAdapter.releaseVirtualDisplayLocked(cb.asBinder(), ownerUid); + device = mAdapter.releaseVirtualDisplayLocked(cb.asBinder()); assertNotNull(device); } callbacks.clear(); @@ -342,8 +338,7 @@ public class VirtualDisplayAdapterTest { } // Release one display - DisplayDevice device = mAdapter.releaseVirtualDisplayLocked(callbacks.get(0).asBinder(), - firstOwnerUid); + DisplayDevice device = mAdapter.releaseVirtualDisplayLocked(callbacks.get(0).asBinder()); assertNotNull(device); callbacks.remove(0); @@ -363,9 +358,8 @@ public class VirtualDisplayAdapterTest { assertNull(device); // Release all the displays - for (int i = 0; i < callbacks.size(); i++) { - device = mAdapter.releaseVirtualDisplayLocked(callbacks.get(i).asBinder(), - firstOwnerUid + i); + for (IVirtualDisplayCallback iVirtualDisplayCallback : callbacks) { + device = mAdapter.releaseVirtualDisplayLocked(iVirtualDisplayCallback.asBinder()); assertNotNull(device); } callbacks.clear(); |