Loading core/res/res/values/config.xml +8 −0 Original line number Diff line number Diff line Loading @@ -6918,6 +6918,14 @@ entering the corresponding modes --> <string name="config_rearDisplayPhysicalAddress" translatable="false"></string> <!-- The maximum number of virtual displays that can exist at the same time. It must be >= 1. --> <integer name="config_virtualDisplayLimit">100</integer> <!-- The maximum number of virtual displays per package that can exist at the same time. It must be >= 1. --> <integer name="config_virtualDisplayLimitPerPackage">50</integer> <!-- List of certificate to be used for font fs-verity integrity verification --> <string-array translatable="false" name="config_fontManagerServiceCerts"> </string-array> Loading core/res/res/values/symbols.xml +3 −0 Original line number Diff line number Diff line Loading @@ -5240,6 +5240,9 @@ <java-symbol type="integer" name="config_deviceStateConcurrentRearDisplay" /> <java-symbol type="string" name="config_rearDisplayPhysicalAddress" /> <java-symbol type="integer" name="config_virtualDisplayLimit" /> <java-symbol type="integer" name="config_virtualDisplayLimitPerPackage" /> <!-- For app language picker --> <java-symbol type="string" name="system_locale_title" /> <java-symbol type="layout" name="app_language_picker_system_default" /> Loading services/core/java/com/android/server/display/DisplayManagerService.java +6 −5 Original line number Diff line number Diff line Loading @@ -1978,7 +1978,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()); releaseVirtualDisplayInternal(callback.asBinder(), callingUid); return Display.INVALID_DISPLAY; } else if (projection != null) { // Indicate that this projection has been used to record, and can't be used Loading Loading @@ -2067,7 +2067,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()); mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder(), callingUid); mDisplayDeviceRepo.onDisplayDeviceEvent(device, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); return -1; Loading @@ -2094,14 +2094,14 @@ public final class DisplayManagerService extends SystemService { } } private void releaseVirtualDisplayInternal(IBinder appToken) { private void releaseVirtualDisplayInternal(IBinder appToken, int callingUid) { synchronized (mSyncRoot) { if (mVirtualDisplayAdapter == null) { return; } DisplayDevice device = mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken, callingUid); Slog.d(TAG, "Virtual Display: Display Device released"); if (device != null) { // TODO: multi-display - handle virtual displays the same as other display adapters. Loading Loading @@ -4620,9 +4620,10 @@ 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()); releaseVirtualDisplayInternal(callback.asBinder(), callingUid); } finally { Binder.restoreCallingIdentity(token); } Loading services/core/java/com/android/server/display/VirtualDisplayAdapter.java +72 −8 Original line number Diff line number Diff line Loading @@ -55,12 +55,14 @@ import android.os.RemoteException; import android.os.SystemProperties; import android.util.ArrayMap; import android.util.Slog; import android.util.SparseIntArray; import android.view.Display; import android.view.DisplayCutout; import android.view.DisplayShape; import android.view.Surface; import android.view.SurfaceControl; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.feature.DisplayManagerFlags; Loading @@ -85,6 +87,11 @@ public class VirtualDisplayAdapter extends DisplayAdapter { private static final AtomicInteger sNextUniqueIndex = new AtomicInteger(0); private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices = new ArrayMap<>(); private final int mMaxDevices; private final int mMaxDevicesPerPackage; private final SparseIntArray mNoOfDevicesPerPackage = new SparseIntArray(); private final Handler mHandler; private final SurfaceControlDisplayFactory mSurfaceControlDisplayFactory; Loading Loading @@ -114,8 +121,31 @@ public class VirtualDisplayAdapter extends DisplayAdapter { super(syncRoot, context, handler, listener, TAG, featureFlags); mHandler = handler; mSurfaceControlDisplayFactory = surfaceControlDisplayFactory; mMaxDevices = context.getResources().getInteger(R.integer.config_virtualDisplayLimit); if (mMaxDevices < 1) { throw new IllegalArgumentException("The limit of virtual displays must be >= 1"); } mMaxDevicesPerPackage = context.getResources().getInteger(R.integer.config_virtualDisplayLimitPerPackage); if (mMaxDevicesPerPackage < 1) { throw new IllegalArgumentException( "The limit of virtual displays per package must be >= 1"); } } /** * Create a virtual display * @param callback The callback * @param projection The media projection * @param ownerUid The UID of the package creating a display * @param ownerPackageName The name of the package creating a display * @param uniqueId The unique ID of the display device * @param surface The surface * @param flags The flags * @param virtualDisplayConfig The config * @return The display device created */ public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback, IMediaProjection projection, int ownerUid, String ownerPackageName, String uniqueId, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig) { Loading @@ -126,6 +156,22 @@ public class VirtualDisplayAdapter extends DisplayAdapter { return null; } if (getFeatureFlags().isVirtualDisplayLimitEnabled() && mVirtualDisplayDevices.size() >= mMaxDevices) { Slog.w(TAG, "Rejecting request to create private virtual display because " + mMaxDevices + " devices already exist."); return null; } int noOfDevices = mNoOfDevicesPerPackage.get(ownerUid, /* valueIfKeyNotFound= */ 0); if (getFeatureFlags().isVirtualDisplayLimitEnabled() && noOfDevices >= mMaxDevicesPerPackage) { Slog.w(TAG, "Rejecting request to create private virtual display because " + mMaxDevicesPerPackage + " devices already exist for package " + ownerPackageName + "."); return null; } String name = virtualDisplayConfig.getName(); boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0; Loading @@ -140,6 +186,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { projection, mediaProjectionCallback, uniqueId, virtualDisplayConfig); mVirtualDisplayDevices.put(appToken, device); if (getFeatureFlags().isVirtualDisplayLimitEnabled()) { mNoOfDevicesPerPackage.put(ownerUid, noOfDevices + 1); } try { if (projection != null) { Loading @@ -150,7 +199,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { appToken.linkToDeath(device, 0); } catch (RemoteException ex) { Slog.e(TAG, "Virtual Display: error while setting up VirtualDisplayDevice", ex); mVirtualDisplayDevices.remove(appToken); removeVirtualDisplayDeviceLocked(appToken, ownerUid); device.destroyLocked(false); return null; } Loading Loading @@ -194,8 +243,15 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } } public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) { VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken); /** * 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); if (device != null) { Slog.v(TAG, "Release VirtualDisplay " + device.mName); device.destroyLocked(true); Loading Loading @@ -228,10 +284,6 @@ public class VirtualDisplayAdapter extends DisplayAdapter { : ("," + uid + "," + config.getName() + "," + sNextUniqueIndex.getAndIncrement())); } private void handleBinderDiedLocked(IBinder appToken) { mVirtualDisplayDevices.remove(appToken); } private void handleMediaProjectionStoppedLocked(IBinder appToken) { VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); if (device != null) { Loading @@ -241,6 +293,18 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } } private VirtualDisplayDevice removeVirtualDisplayDeviceLocked(IBinder appToken, int ownerUid) { int noOfDevices = mNoOfDevicesPerPackage.get(ownerUid, /* valueIfKeyNotFound= */ 0); if (getFeatureFlags().isVirtualDisplayLimitEnabled()) { if (noOfDevices <= 1) { mNoOfDevicesPerPackage.delete(ownerUid); } else { mNoOfDevicesPerPackage.put(ownerUid, noOfDevices - 1); } } return mVirtualDisplayDevices.remove(appToken); } private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient { private static final int PENDING_SURFACE_CHANGE = 0x01; private static final int PENDING_RESIZE = 0x02; Loading Loading @@ -300,7 +364,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { @Override public void binderDied() { synchronized (getSyncRoot()) { handleBinderDiedLocked(mAppToken); removeVirtualDisplayDeviceLocked(mAppToken, mOwnerUid); Slog.i(TAG, "Virtual display device released because application token died: " + mOwnerPackageName); destroyLocked(false); Loading services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +10 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,11 @@ public class DisplayManagerFlags { Flags.FLAG_IDLE_SCREEN_CONFIG_IN_SUBSCRIBING_LIGHT_SENSOR, Flags::idleScreenConfigInSubscribingLightSensor); private final FlagState mVirtualDisplayLimit = new FlagState( Flags.FLAG_VIRTUAL_DISPLAY_LIMIT, Flags::virtualDisplayLimit); private final FlagState mNormalBrightnessForDozeParameter = new FlagState( Flags.FLAG_NORMAL_BRIGHTNESS_FOR_DOZE_PARAMETER, Flags::normalBrightnessForDozeParameter Loading Loading @@ -416,6 +421,10 @@ public class DisplayManagerFlags { return mNewHdrBrightnessModifier.isEnabled(); } public boolean isVirtualDisplayLimitEnabled() { return mVirtualDisplayLimit.isEnabled(); } /** * @return Whether the useDozeBrightness parameter should be used */ Loading Loading @@ -487,6 +496,7 @@ public class DisplayManagerFlags { pw.println(" " + mOffloadDozeOverrideHoldsWakelock); pw.println(" " + mOffloadSessionCancelBlockScreenOn); pw.println(" " + mNewHdrBrightnessModifier); pw.println(" " + mVirtualDisplayLimit); pw.println(" " + mNormalBrightnessForDozeParameter); pw.println(" " + mIdleScreenConfigInSubscribingLightSensor); pw.println(" " + mEnableBatteryStatsForAllDisplays); Loading Loading
core/res/res/values/config.xml +8 −0 Original line number Diff line number Diff line Loading @@ -6918,6 +6918,14 @@ entering the corresponding modes --> <string name="config_rearDisplayPhysicalAddress" translatable="false"></string> <!-- The maximum number of virtual displays that can exist at the same time. It must be >= 1. --> <integer name="config_virtualDisplayLimit">100</integer> <!-- The maximum number of virtual displays per package that can exist at the same time. It must be >= 1. --> <integer name="config_virtualDisplayLimitPerPackage">50</integer> <!-- List of certificate to be used for font fs-verity integrity verification --> <string-array translatable="false" name="config_fontManagerServiceCerts"> </string-array> Loading
core/res/res/values/symbols.xml +3 −0 Original line number Diff line number Diff line Loading @@ -5240,6 +5240,9 @@ <java-symbol type="integer" name="config_deviceStateConcurrentRearDisplay" /> <java-symbol type="string" name="config_rearDisplayPhysicalAddress" /> <java-symbol type="integer" name="config_virtualDisplayLimit" /> <java-symbol type="integer" name="config_virtualDisplayLimitPerPackage" /> <!-- For app language picker --> <java-symbol type="string" name="system_locale_title" /> <java-symbol type="layout" name="app_language_picker_system_default" /> Loading
services/core/java/com/android/server/display/DisplayManagerService.java +6 −5 Original line number Diff line number Diff line Loading @@ -1978,7 +1978,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()); releaseVirtualDisplayInternal(callback.asBinder(), callingUid); return Display.INVALID_DISPLAY; } else if (projection != null) { // Indicate that this projection has been used to record, and can't be used Loading Loading @@ -2067,7 +2067,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()); mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder(), callingUid); mDisplayDeviceRepo.onDisplayDeviceEvent(device, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); return -1; Loading @@ -2094,14 +2094,14 @@ public final class DisplayManagerService extends SystemService { } } private void releaseVirtualDisplayInternal(IBinder appToken) { private void releaseVirtualDisplayInternal(IBinder appToken, int callingUid) { synchronized (mSyncRoot) { if (mVirtualDisplayAdapter == null) { return; } DisplayDevice device = mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken, callingUid); Slog.d(TAG, "Virtual Display: Display Device released"); if (device != null) { // TODO: multi-display - handle virtual displays the same as other display adapters. Loading Loading @@ -4620,9 +4620,10 @@ 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()); releaseVirtualDisplayInternal(callback.asBinder(), callingUid); } finally { Binder.restoreCallingIdentity(token); } Loading
services/core/java/com/android/server/display/VirtualDisplayAdapter.java +72 −8 Original line number Diff line number Diff line Loading @@ -55,12 +55,14 @@ import android.os.RemoteException; import android.os.SystemProperties; import android.util.ArrayMap; import android.util.Slog; import android.util.SparseIntArray; import android.view.Display; import android.view.DisplayCutout; import android.view.DisplayShape; import android.view.Surface; import android.view.SurfaceControl; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.feature.DisplayManagerFlags; Loading @@ -85,6 +87,11 @@ public class VirtualDisplayAdapter extends DisplayAdapter { private static final AtomicInteger sNextUniqueIndex = new AtomicInteger(0); private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices = new ArrayMap<>(); private final int mMaxDevices; private final int mMaxDevicesPerPackage; private final SparseIntArray mNoOfDevicesPerPackage = new SparseIntArray(); private final Handler mHandler; private final SurfaceControlDisplayFactory mSurfaceControlDisplayFactory; Loading Loading @@ -114,8 +121,31 @@ public class VirtualDisplayAdapter extends DisplayAdapter { super(syncRoot, context, handler, listener, TAG, featureFlags); mHandler = handler; mSurfaceControlDisplayFactory = surfaceControlDisplayFactory; mMaxDevices = context.getResources().getInteger(R.integer.config_virtualDisplayLimit); if (mMaxDevices < 1) { throw new IllegalArgumentException("The limit of virtual displays must be >= 1"); } mMaxDevicesPerPackage = context.getResources().getInteger(R.integer.config_virtualDisplayLimitPerPackage); if (mMaxDevicesPerPackage < 1) { throw new IllegalArgumentException( "The limit of virtual displays per package must be >= 1"); } } /** * Create a virtual display * @param callback The callback * @param projection The media projection * @param ownerUid The UID of the package creating a display * @param ownerPackageName The name of the package creating a display * @param uniqueId The unique ID of the display device * @param surface The surface * @param flags The flags * @param virtualDisplayConfig The config * @return The display device created */ public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback, IMediaProjection projection, int ownerUid, String ownerPackageName, String uniqueId, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig) { Loading @@ -126,6 +156,22 @@ public class VirtualDisplayAdapter extends DisplayAdapter { return null; } if (getFeatureFlags().isVirtualDisplayLimitEnabled() && mVirtualDisplayDevices.size() >= mMaxDevices) { Slog.w(TAG, "Rejecting request to create private virtual display because " + mMaxDevices + " devices already exist."); return null; } int noOfDevices = mNoOfDevicesPerPackage.get(ownerUid, /* valueIfKeyNotFound= */ 0); if (getFeatureFlags().isVirtualDisplayLimitEnabled() && noOfDevices >= mMaxDevicesPerPackage) { Slog.w(TAG, "Rejecting request to create private virtual display because " + mMaxDevicesPerPackage + " devices already exist for package " + ownerPackageName + "."); return null; } String name = virtualDisplayConfig.getName(); boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0; Loading @@ -140,6 +186,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { projection, mediaProjectionCallback, uniqueId, virtualDisplayConfig); mVirtualDisplayDevices.put(appToken, device); if (getFeatureFlags().isVirtualDisplayLimitEnabled()) { mNoOfDevicesPerPackage.put(ownerUid, noOfDevices + 1); } try { if (projection != null) { Loading @@ -150,7 +199,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { appToken.linkToDeath(device, 0); } catch (RemoteException ex) { Slog.e(TAG, "Virtual Display: error while setting up VirtualDisplayDevice", ex); mVirtualDisplayDevices.remove(appToken); removeVirtualDisplayDeviceLocked(appToken, ownerUid); device.destroyLocked(false); return null; } Loading Loading @@ -194,8 +243,15 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } } public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) { VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken); /** * 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); if (device != null) { Slog.v(TAG, "Release VirtualDisplay " + device.mName); device.destroyLocked(true); Loading Loading @@ -228,10 +284,6 @@ public class VirtualDisplayAdapter extends DisplayAdapter { : ("," + uid + "," + config.getName() + "," + sNextUniqueIndex.getAndIncrement())); } private void handleBinderDiedLocked(IBinder appToken) { mVirtualDisplayDevices.remove(appToken); } private void handleMediaProjectionStoppedLocked(IBinder appToken) { VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken); if (device != null) { Loading @@ -241,6 +293,18 @@ public class VirtualDisplayAdapter extends DisplayAdapter { } } private VirtualDisplayDevice removeVirtualDisplayDeviceLocked(IBinder appToken, int ownerUid) { int noOfDevices = mNoOfDevicesPerPackage.get(ownerUid, /* valueIfKeyNotFound= */ 0); if (getFeatureFlags().isVirtualDisplayLimitEnabled()) { if (noOfDevices <= 1) { mNoOfDevicesPerPackage.delete(ownerUid); } else { mNoOfDevicesPerPackage.put(ownerUid, noOfDevices - 1); } } return mVirtualDisplayDevices.remove(appToken); } private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient { private static final int PENDING_SURFACE_CHANGE = 0x01; private static final int PENDING_RESIZE = 0x02; Loading Loading @@ -300,7 +364,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter { @Override public void binderDied() { synchronized (getSyncRoot()) { handleBinderDiedLocked(mAppToken); removeVirtualDisplayDeviceLocked(mAppToken, mOwnerUid); Slog.i(TAG, "Virtual display device released because application token died: " + mOwnerPackageName); destroyLocked(false); Loading
services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +10 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,11 @@ public class DisplayManagerFlags { Flags.FLAG_IDLE_SCREEN_CONFIG_IN_SUBSCRIBING_LIGHT_SENSOR, Flags::idleScreenConfigInSubscribingLightSensor); private final FlagState mVirtualDisplayLimit = new FlagState( Flags.FLAG_VIRTUAL_DISPLAY_LIMIT, Flags::virtualDisplayLimit); private final FlagState mNormalBrightnessForDozeParameter = new FlagState( Flags.FLAG_NORMAL_BRIGHTNESS_FOR_DOZE_PARAMETER, Flags::normalBrightnessForDozeParameter Loading Loading @@ -416,6 +421,10 @@ public class DisplayManagerFlags { return mNewHdrBrightnessModifier.isEnabled(); } public boolean isVirtualDisplayLimitEnabled() { return mVirtualDisplayLimit.isEnabled(); } /** * @return Whether the useDozeBrightness parameter should be used */ Loading Loading @@ -487,6 +496,7 @@ public class DisplayManagerFlags { pw.println(" " + mOffloadDozeOverrideHoldsWakelock); pw.println(" " + mOffloadSessionCancelBlockScreenOn); pw.println(" " + mNewHdrBrightnessModifier); pw.println(" " + mVirtualDisplayLimit); pw.println(" " + mNormalBrightnessForDozeParameter); pw.println(" " + mIdleScreenConfigInSubscribingLightSensor); pw.println(" " + mEnableBatteryStatsForAllDisplays); Loading