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

Commit ca56ab76 authored by Piotr Wilczyński's avatar Piotr Wilczyński Committed by Android (Google) Code Review
Browse files

Merge "Limit the number of virtual displays" into main

parents e38e878f f4f91bef
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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>
+3 −0
Original line number Diff line number Diff line
@@ -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" />
+6 −5
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -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.
@@ -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);
            }
+72 −8
Original line number Diff line number Diff line
@@ -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;

@@ -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;

@@ -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) {
@@ -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;

@@ -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) {
@@ -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;
        }
@@ -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);
@@ -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) {
@@ -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;
@@ -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);
+10 −0
Original line number Diff line number Diff line
@@ -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
@@ -416,6 +421,10 @@ public class DisplayManagerFlags {
        return mNewHdrBrightnessModifier.isEnabled();
    }

    public boolean isVirtualDisplayLimitEnabled() {
        return mVirtualDisplayLimit.isEnabled();
    }

    /**
     * @return Whether the useDozeBrightness parameter should be used
     */
@@ -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