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

Commit c300e970 authored by Rupesh Bansal's avatar Rupesh Bansal
Browse files

Added support for not registering for RR events by default

We historically used to register any user subscribing to display changes
via DisplayManager::registerDisplayListener for refresh rate changes.
Going forward, this behaviour is being changed to subscribe them to refresh rate changes only when they explicitly request for it

Bug: 391828526
Flag: com.android.server.display.feature.flags.delay_implicit_rr_registration_until_rr_accessed
Test: atest DisplayEventTest
Change-Id: If218ba7b49f11ca369aee76230b4ea0a28469a68
parent 7fd1b808
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1737,6 +1737,7 @@ package android.hardware.display {
    method @NonNull public int[] getUserDisabledHdrTypes();
    method public boolean isMinimalPostProcessingRequested(int);
    method @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public void overrideHdrTypes(int, @NonNull int[]);
    method @FlaggedApi("com.android.server.display.feature.flags.delay_implicit_rr_registration_until_rr_accessed") public void resetImplicitRefreshRateCallbackStatus();
    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAreUserDisabledHdrTypesAllowed(boolean);
    method @RequiresPermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) public void setGlobalUserPreferredDisplayMode(@NonNull android.view.Display.Mode);
    method @RequiresPermission(android.Manifest.permission.MODIFY_HDR_CONVERSION_MODE) public void setHdrConversionMode(@NonNull android.hardware.display.HdrConversionMode);
+65 −9
Original line number Diff line number Diff line
@@ -851,6 +851,12 @@ public final class DisplayManager {
     * Registers a display listener to receive notifications about when
     * displays are added, removed or changed.
     *
     * Because of the high frequency at which the refresh rate can change, clients will be
     * registered for refresh rate change callbacks only when they request for refresh rate
     * data({@link Display#getRefreshRate()}. Or alternately, you can consider using
     * {@link #registerDisplayListener(Executor, long, DisplayListener)} and explicitly subscribe to
     * {@link #EVENT_TYPE_DISPLAY_REFRESH_RATE} event
     *
     * We encourage to use {@link #registerDisplayListener(Executor, long, DisplayListener)}
     * instead to subscribe for explicit events of interest
     *
@@ -863,8 +869,8 @@ public final class DisplayManager {
    public void registerDisplayListener(DisplayListener listener, Handler handler) {
        registerDisplayListener(listener, handler, EVENT_TYPE_DISPLAY_ADDED
                | EVENT_TYPE_DISPLAY_CHANGED
                | EVENT_TYPE_DISPLAY_REFRESH_RATE
                | EVENT_TYPE_DISPLAY_REMOVED);
                | EVENT_TYPE_DISPLAY_REMOVED, 0,
                ActivityThread.currentPackageName(), /* isEventFilterExplicit */ false);
    }

    /**
@@ -882,9 +888,8 @@ public final class DisplayManager {
     */
    public void registerDisplayListener(@NonNull DisplayListener listener,
            @Nullable Handler handler, @EventType long eventFilter) {
        mGlobal.registerDisplayListener(listener, handler,
                mGlobal.mapFiltersToInternalEventFlag(eventFilter, 0),
                ActivityThread.currentPackageName());
        registerDisplayListener(listener, handler, eventFilter, 0,
                ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true);
    }

    /**
@@ -901,9 +906,8 @@ public final class DisplayManager {
    @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public void registerDisplayListener(@NonNull Executor executor, @EventType long eventFilter,
            @NonNull DisplayListener listener) {
        mGlobal.registerDisplayListener(listener, executor,
                mGlobal.mapFiltersToInternalEventFlag(eventFilter, 0),
                ActivityThread.currentPackageName());
        registerDisplayListener(listener, executor, eventFilter, 0,
                ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true);
    }

    /**
@@ -924,9 +928,39 @@ public final class DisplayManager {
    public void registerDisplayListener(@NonNull DisplayListener listener,
            @Nullable Handler handler, @EventType long eventFilter,
            @PrivateEventType long privateEventFilter) {
        registerDisplayListener(listener, handler, eventFilter, privateEventFilter,
                ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true);
    }

    /**
     * Registers a display listener to receive notifications about given display event types.
     *
     * @param listener The listener to register.
     * @param handler The handler on which the listener should be invoked, or null
     * if the listener should be invoked on the calling thread's looper.
     * @param eventFilter A bitmask of the event types for which this listener is subscribed.
     * @param privateEventFilter A bitmask of the private event types for which this listener
     *                          is subscribed.
     * @param isEventFilterExplicit Indicates if the client explicitly supplied the display events
     *                          to be subscribed to.
     *
     */
    private void registerDisplayListener(@NonNull DisplayListener listener,
            @Nullable Handler handler, @EventType long eventFilter,
            @PrivateEventType long privateEventFilter, String packageName,
            boolean isEventFilterExplicit) {
        mGlobal.registerDisplayListener(listener, handler,
                mGlobal.mapFiltersToInternalEventFlag(eventFilter, privateEventFilter),
                ActivityThread.currentPackageName());
                packageName, /* isEventFilterExplicit */ isEventFilterExplicit);
    }

    private void registerDisplayListener(@NonNull DisplayListener listener,
            Executor executor, @EventType long eventFilter,
            @PrivateEventType long privateEventFilter, String packageName,
            boolean isEventFilterExplicit) {
        mGlobal.registerDisplayListener(listener, executor,
                mGlobal.mapFiltersToInternalEventFlag(eventFilter, privateEventFilter),
                packageName, /* isEventFilterExplicit */ isEventFilterExplicit);
    }

    /**
@@ -1145,6 +1179,28 @@ public final class DisplayManager {
        return mGlobal.getUserDisabledHdrTypes();
    }

    /**
     * Resets the behavior that automatically registers clients for refresh rate change callbacks
     * when they register via {@link #registerDisplayListener(DisplayListener, Handler)}
     *
     * <p>By default, clients are not registered for refresh rate change callbacks via
     * {@link #registerDisplayListener(DisplayListener, Handler)}. However, calling
     * {@link Display#getRefreshRate()} triggers automatic registration for existing and future
     * {@link DisplayListener} instances. This method reverts this behavior, preventing new
     * clients from being automatically registered for refresh rate change callbacks. Note that the
     * existing ones will continue to stay registered
     *
     * <p>In essence, this method returns the system to its initial state, where explicit calls to
     * {{@link Display#getRefreshRate()} are required to receive refresh rate change notifications.
     *
     * @hide
     */
    @FlaggedApi(Flags.FLAG_DELAY_IMPLICIT_RR_REGISTRATION_UNTIL_RR_ACCESSED)
    @TestApi
    public void resetImplicitRefreshRateCallbackStatus() {
        mGlobal.resetImplicitRefreshRateCallbackStatus();
    }

    /**
     * Overrides HDR modes for a display device.
     *
+96 −7
Original line number Diff line number Diff line
@@ -187,6 +187,9 @@ public final class DisplayManagerGlobal {

    private final Binder mToken = new Binder();

    // Guarded by mLock
    private boolean mShouldImplicitlyRegisterRrChanges = false;

    @VisibleForTesting
    public DisplayManagerGlobal(IDisplayManager dm) {
        mDm = dm;
@@ -390,16 +393,36 @@ public final class DisplayManagerGlobal {
     * the handler for the main thread.
     * If that is still null, a runtime exception will be thrown.
     * @param packageName of the calling package.
     * @param isEventFilterExplicit Indicates if the client explicitly supplied the display events
     *                              to be subscribed to.
     */
    public void registerDisplayListener(@NonNull DisplayListener listener,
            @Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask,
            String packageName) {
            String packageName, boolean isEventFilterExplicit) {
        Looper looper = getLooperForHandler(handler);
        Handler springBoard = new Handler(looper);
        registerDisplayListener(listener, new HandlerExecutor(springBoard), internalEventFlagsMask,
                packageName);
                packageName, isEventFilterExplicit);
    }

    /**
     * Register a listener for display-related changes.
     *
     * @param listener The listener that will be called when display changes occur.
     * @param handler Handler for the thread that will be receiving the callbacks. May be null.
     * If null, listener will use the handler for the current thread, and if still null,
     * the handler for the main thread.
     * If that is still null, a runtime exception will be thrown.
     * @param internalEventFlagsMask Mask of events to be listened to.
     * @param packageName of the calling package.
     */
    public void registerDisplayListener(@NonNull DisplayListener listener,
            @Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask,
            String packageName) {
        registerDisplayListener(listener, handler, internalEventFlagsMask, packageName, true);
    }


    /**
     * Register a listener for display-related changes.
     *
@@ -407,10 +430,12 @@ public final class DisplayManagerGlobal {
     * @param executor Executor for the thread that will be receiving the callbacks. Cannot be null.
     * @param internalEventFlagsMask Mask of events to be listened to.
     * @param packageName of the calling package.
     * @param isEventFilterExplicit Indicates if the explicit events to be subscribed to
     *                                     were supplied or not
     */
    public void registerDisplayListener(@NonNull DisplayListener listener,
            @NonNull Executor executor, @InternalEventFlag long internalEventFlagsMask,
            String packageName) {
            String packageName, boolean isEventFilterExplicit) {
        if (listener == null) {
            throw new IllegalArgumentException("listener must not be null");
        }
@@ -429,7 +454,7 @@ public final class DisplayManagerGlobal {
            int index = findDisplayListenerLocked(listener);
            if (index < 0) {
                mDisplayListeners.add(new DisplayListenerDelegate(listener, executor,
                        internalEventFlagsMask, packageName));
                        internalEventFlagsMask, packageName, isEventFilterExplicit));
                registerCallbackIfNeededLocked();
            } else {
                mDisplayListeners.get(index).setEventsMask(internalEventFlagsMask);
@@ -439,6 +464,22 @@ public final class DisplayManagerGlobal {
        }
    }


    /**
     * Registers all the clients to INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE events if qualified
     */
    public void registerForRefreshRateChanges() {
        if (!Flags.delayImplicitRrRegistrationUntilRrAccessed()) {
            return;
        }
        synchronized (mLock) {
            if (!mShouldImplicitlyRegisterRrChanges) {
                mShouldImplicitlyRegisterRrChanges = true;
                updateCallbackIfNeededLocked();
            }
        }
    }

    public void unregisterDisplayListener(DisplayListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener must not be null");
@@ -521,8 +562,14 @@ public final class DisplayManagerGlobal {
        long mask = 0;
        final int numListeners = mDisplayListeners.size();
        for (int i = 0; i < numListeners; i++) {
            mask |= mDisplayListeners.get(i).mInternalEventFlagsMask;
            DisplayListenerDelegate displayListenerDelegate = mDisplayListeners.get(i);
            if (!Flags.delayImplicitRrRegistrationUntilRrAccessed()
                    || mShouldImplicitlyRegisterRrChanges) {
                displayListenerDelegate.implicitlyRegisterForRRChanges();
            }
            mask |= displayListenerDelegate.mInternalEventFlagsMask;
        }

        if (mDispatchNativeCallbacks) {
            mask |= INTERNAL_EVENT_FLAG_DISPLAY_ADDED
                    | INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
@@ -801,6 +848,18 @@ public final class DisplayManagerGlobal {
        }
    }

    /**
     * Resets the implicit registration of refresh rate change callbacks
     *
     */
    public void resetImplicitRefreshRateCallbackStatus() {
        if (Flags.delayImplicitRrRegistrationUntilRrAccessed()) {
            synchronized (mLock) {
                mShouldImplicitlyRegisterRrChanges = false;
            }
        }
    }

    /**
     * Overrides HDR modes for a display device.
     *
@@ -1439,21 +1498,27 @@ public final class DisplayManagerGlobal {
        }
    }

    private static final class DisplayListenerDelegate {
    @VisibleForTesting
    static final class DisplayListenerDelegate {
        public final DisplayListener mListener;
        public volatile long mInternalEventFlagsMask;

        // Indicates if the client explicitly supplied the display events to be subscribed to.
        private final boolean mIsEventFilterExplicit;

        private final DisplayInfo mDisplayInfo = new DisplayInfo();
        private final Executor mExecutor;
        private AtomicLong mGenerationId = new AtomicLong(1);
        private final String mPackageName;

        DisplayListenerDelegate(DisplayListener listener, @NonNull Executor executor,
                @InternalEventFlag long internalEventFlag, String packageName) {
                @InternalEventFlag long internalEventFlag, String packageName,
                boolean isEventFilterExplicit) {
            mExecutor = executor;
            mListener = listener;
            mInternalEventFlagsMask = internalEventFlag;
            mPackageName = packageName;
            mIsEventFilterExplicit = isEventFilterExplicit;
        }

        void sendDisplayEvent(int displayId, @DisplayEvent int event, @Nullable DisplayInfo info,
@@ -1470,6 +1535,11 @@ public final class DisplayManagerGlobal {
            });
        }

        @VisibleForTesting
        boolean isEventFilterExplicit() {
            return mIsEventFilterExplicit;
        }

        void clearEvents() {
            mGenerationId.incrementAndGet();
        }
@@ -1478,6 +1548,17 @@ public final class DisplayManagerGlobal {
            mInternalEventFlagsMask = newInternalEventFlagsMask;
        }

        private void implicitlyRegisterForRRChanges() {
            // For backward compatibility, if the user didn't supply the explicit events while
            // subscribing, register them to refresh rate change events if they subscribed to
            // display changed events
            if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED) != 0
                    && !mIsEventFilterExplicit) {
                setEventsMask(mInternalEventFlagsMask
                        | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE);
            }
        }

        private void handleDisplayEventInner(int displayId, @DisplayEvent int event,
                @Nullable DisplayInfo info, boolean forceUpdate) {
            if (extraLogging()) {
@@ -1677,6 +1758,9 @@ public final class DisplayManagerGlobal {
    public void registerNativeChoreographerForRefreshRateCallbacks() {
        synchronized (mLock) {
            mDispatchNativeCallbacks = true;
            if (Flags.delayImplicitRrRegistrationUntilRrAccessed()) {
                mShouldImplicitlyRegisterRrChanges = true;
            }
            registerCallbackIfNeededLocked();
            updateCallbackIfNeededLocked();
            DisplayInfo display = getDisplayInfoLocked(Display.DEFAULT_DISPLAY);
@@ -1806,4 +1890,9 @@ public final class DisplayManagerGlobal {

        return baseEventMask;
    }

    @VisibleForTesting
    CopyOnWriteArrayList<DisplayListenerDelegate> getDisplayListeners() {
        return mDisplayListeners;
    }
}
+6 −1
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ public final class Display {
    private final String mOwnerPackageName;
    private final Resources mResources;
    private DisplayAdjustments mDisplayAdjustments;
    private boolean mRefreshRateChangesRegistered;

    @UnsupportedAppUsage
    private DisplayInfo mDisplayInfo; // never null
@@ -1217,6 +1218,10 @@ public final class Display {
     */
    public float getRefreshRate() {
        synchronized (mLock) {
            if (!mRefreshRateChangesRegistered) {
                DisplayManagerGlobal.getInstance().registerForRefreshRateChanges();
                mRefreshRateChangesRegistered = true;
            }
            updateDisplayInfoLocked();
            return mDisplayInfo.getRefreshRate();
        }
@@ -1601,7 +1606,7 @@ public final class Display {
                                    .INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
                            | DisplayManagerGlobal
                                    .INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
                    ActivityThread.currentPackageName());
                    ActivityThread.currentPackageName(), /* isEventFilterImplicit */ true);
        }

    }
+107 −9

File changed.

Preview size limit exceeded, changes collapsed.

Loading