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

Commit 60bf52d1 authored by Rupesh Bansal's avatar Rupesh Bansal Committed by Android (Google) Code Review
Browse files

Merge changes from topic "display_listener_improvements" into main

* changes:
  Send display property change events in onDisplayChanged callbacks
  Add API to register for display property changes
parents d5f0283e 09d6e260
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -20628,8 +20628,14 @@ package android.hardware.display {
    method @NonNull public android.hardware.display.HdrConversionMode getHdrConversionMode();
    method public int getMatchContentFrameRateUserPreference();
    method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler);
    method @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public void registerDisplayListener(@NonNull java.util.concurrent.Executor, long, @NonNull android.hardware.display.DisplayManager.DisplayListener);
    method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
    field public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_ADDED = 1L; // 0x1L
    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_CHANGED = 4L; // 0x4L
    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_REFRESH_RATE = 8L; // 0x8L
    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_REMOVED = 2L; // 0x2L
    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_STATE = 16L; // 0x10L
    field public static final int MATCH_CONTENT_FRAMERATE_ALWAYS = 2; // 0x2
    field public static final int MATCH_CONTENT_FRAMERATE_NEVER = 0; // 0x0
    field public static final int MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY = 1; // 0x1
+43 −12
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.HdrCapabilities.HdrType;
import static android.view.Display.INVALID_DISPLAY;

import static com.android.server.display.feature.flags.Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS;

import android.Manifest;
import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
@@ -576,6 +578,8 @@ public final class DisplayManager {
            EVENT_FLAG_DISPLAY_ADDED,
            EVENT_FLAG_DISPLAY_CHANGED,
            EVENT_FLAG_DISPLAY_REMOVED,
            EVENT_FLAG_DISPLAY_REFRESH_RATE,
            EVENT_FLAG_DISPLAY_STATE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EventFlag {}
@@ -596,8 +600,8 @@ public final class DisplayManager {
     *
     * @see #registerDisplayListener(DisplayListener, Handler, long)
     *
     * @hide
     */
    @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public static final long EVENT_FLAG_DISPLAY_ADDED = 1L << 0;

    /**
@@ -605,8 +609,8 @@ public final class DisplayManager {
     *
     * @see #registerDisplayListener(DisplayListener, Handler, long)
     *
     * @hide
     */
    @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public static final long EVENT_FLAG_DISPLAY_REMOVED = 1L << 1;

    /**
@@ -614,10 +618,27 @@ public final class DisplayManager {
     *
     * @see #registerDisplayListener(DisplayListener, Handler, long)
     *
     * @hide
     */
    @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2;


    /**
     * Event flag to register for a display's refresh rate changes.
     *
     * @see #registerDisplayListener(DisplayListener, Handler, long)
     */
    @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public static final long EVENT_FLAG_DISPLAY_REFRESH_RATE = 1L << 3;

    /**
     * Event flag to register for a display state changes.
     *
     * @see #registerDisplayListener(DisplayListener, Handler, long)
     */
    @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public static final long EVENT_FLAG_DISPLAY_STATE = 1L << 4;

    /**
     * Event flag to register for a display's brightness changes. This notification is sent
     * through the {@link DisplayListener#onDisplayChanged} callback method. New brightness
@@ -787,9 +808,6 @@ public final class DisplayManager {
     * if the listener should be invoked on the calling thread's looper.
     * @param eventFlags A bitmask of the event types for which this listener is subscribed.
     *
     * @see #EVENT_FLAG_DISPLAY_ADDED
     * @see #EVENT_FLAG_DISPLAY_CHANGED
     * @see #EVENT_FLAG_DISPLAY_REMOVED
     * @see #registerDisplayListener(DisplayListener, Handler)
     * @see #unregisterDisplayListener
     *
@@ -802,6 +820,25 @@ public final class DisplayManager {
                ActivityThread.currentPackageName());
    }

    /**
     * Registers a display listener to receive notifications about given display event types.
     *
     * @param listener The listener to register.
     * @param executor Executor for the thread that will be receiving the callbacks. Cannot be null.
     * @param eventFlags A bitmask of the event types for which this listener is subscribed.
     *
     * @see #registerDisplayListener(DisplayListener, Handler)
     * @see #unregisterDisplayListener
     *
     */
    @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public void registerDisplayListener(@NonNull Executor executor, @EventFlag long eventFlags,
            @NonNull DisplayListener listener) {
        mGlobal.registerDisplayListener(listener, executor,
                mGlobal.mapFlagsToInternalEventFlag(eventFlags, 0),
                ActivityThread.currentPackageName());
    }

    /**
     * Registers a display listener to receive notifications about given display event types.
     *
@@ -812,12 +849,6 @@ public final class DisplayManager {
     * @param privateEventFlags A bitmask of the private event types for which this listener
     *                          is subscribed.
     *
     * @see #EVENT_FLAG_DISPLAY_ADDED
     * @see #EVENT_FLAG_DISPLAY_CHANGED
     * @see #EVENT_FLAG_DISPLAY_REMOVED
     * @see #PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
     * @see #PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED
     * @see #PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED
     * @see #registerDisplayListener(DisplayListener, Handler)
     * @see #unregisterDisplayListener
     *
+36 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import android.view.DisplayInfo;
import android.view.Surface;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.feature.flags.Flags;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -108,6 +109,8 @@ public final class DisplayManagerGlobal {
            EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED,
            EVENT_DISPLAY_CONNECTED,
            EVENT_DISPLAY_DISCONNECTED,
            EVENT_DISPLAY_REFRESH_RATE_CHANGED,
            EVENT_DISPLAY_STATE_CHANGED
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface DisplayEvent {}
@@ -119,6 +122,8 @@ public final class DisplayManagerGlobal {
    public static final int EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED = 5;
    public static final int EVENT_DISPLAY_CONNECTED = 6;
    public static final int EVENT_DISPLAY_DISCONNECTED = 7;
    public static final int EVENT_DISPLAY_REFRESH_RATE_CHANGED = 8;
    public static final int EVENT_DISPLAY_STATE_CHANGED = 9;

    @LongDef(prefix = {"INTERNAL_EVENT_DISPLAY"}, flag = true, value = {
            INTERNAL_EVENT_FLAG_DISPLAY_ADDED,
@@ -127,6 +132,8 @@ public final class DisplayManagerGlobal {
            INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED,
            INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
            INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
            INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
            INTERNAL_EVENT_FLAG_DISPLAY_STATE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface InternalEventFlag {}
@@ -137,6 +144,8 @@ public final class DisplayManagerGlobal {
    public static final long INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED = 1L << 3;
    public static final long INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED = 1L << 4;
    public static final long INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED = 1L << 5;
    public static final long INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE = 1L << 6;
    public static final long INTERNAL_EVENT_FLAG_DISPLAY_STATE = 1L << 7;

    @UnsupportedAppUsage
    private static DisplayManagerGlobal sInstance;
@@ -1427,6 +1436,18 @@ public final class DisplayManagerGlobal {
                        mListener.onDisplayDisconnected(displayId);
                    }
                    break;
                case EVENT_DISPLAY_REFRESH_RATE_CHANGED:
                    if ((mInternalEventFlagsMask
                            & INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE) != 0) {
                        mListener.onDisplayChanged(displayId);
                    }
                    break;
                case EVENT_DISPLAY_STATE_CHANGED:
                    if ((mInternalEventFlagsMask
                            & INTERNAL_EVENT_FLAG_DISPLAY_STATE) != 0) {
                        mListener.onDisplayChanged(displayId);
                    }
                    break;
            }
            if (DEBUG) {
                Trace.endSection();
@@ -1566,6 +1587,10 @@ public final class DisplayManagerGlobal {
                return "EVENT_DISPLAY_CONNECTED";
            case EVENT_DISPLAY_DISCONNECTED:
                return "EVENT_DISPLAY_DISCONNECTED";
            case EVENT_DISPLAY_REFRESH_RATE_CHANGED:
                return "EVENT_DISPLAY_REFRESH_RATE_CHANGED";
            case EVENT_DISPLAY_STATE_CHANGED:
                return "EVENT_DISPLAY_STATE_CHANGED";
        }
        return "UNKNOWN";
    }
@@ -1630,6 +1655,17 @@ public final class DisplayManagerGlobal {
            baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
        }

        if (Flags.displayListenerPerformanceImprovements()) {
            if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_REFRESH_RATE) != 0) {
                baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE;
            }

            if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_STATE) != 0) {
                baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_STATE;
            }
        }


        return baseEventMask;
    }
}
+89 −0
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@

package android.hardware.display;

import static android.hardware.display.DisplayManagerGlobal.EVENT_DISPLAY_STATE_CHANGED;
import static android.hardware.display.DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE;
import static android.hardware.display.DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_STATE;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -28,13 +33,19 @@ import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.view.DisplayInfo;

import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.server.display.feature.flags.Flags;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -55,6 +66,10 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class DisplayManagerGlobalTest {

    @Rule
    public final CheckFlagsRule mCheckFlagsRule =
            DeviceFlagsValueProvider.createCheckFlagsRule();

    private static final long ALL_DISPLAY_EVENTS =
            DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
            | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
@@ -116,6 +131,33 @@ public class DisplayManagerGlobalTest {
        Mockito.verifyNoMoreInteractions(mListener);
    }

    @Test
    @RequiresFlagsEnabled(Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public void testDisplayListenerIsCalled_WhenDisplayPropertyChangeEventOccurs()
            throws RemoteException {
        mDisplayManagerGlobal.registerDisplayListener(mListener, mHandler,
                INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE
                        | INTERNAL_EVENT_FLAG_DISPLAY_STATE,
                null);
        Mockito.verify(mDisplayManager)
                .registerCallbackWithEventMask(mCallbackCaptor.capture(), anyLong());
        IDisplayManagerCallback callback = mCallbackCaptor.getValue();

        int displayId = 1;

        Mockito.reset(mListener);
        callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REFRESH_RATE_CHANGED);
        waitForHandler();
        Mockito.verify(mListener).onDisplayChanged(eq(displayId));
        Mockito.verifyNoMoreInteractions(mListener);

        Mockito.reset(mListener);
        callback.onDisplayEvent(displayId, EVENT_DISPLAY_STATE_CHANGED);
        waitForHandler();
        Mockito.verify(mListener).onDisplayChanged(eq(displayId));
        Mockito.verifyNoMoreInteractions(mListener);
    }

    @Test
    public void testDisplayListenerIsNotCalled_WhenClientIsNotSubscribed() throws RemoteException {
        // First we subscribe to all events in order to test that the subsequent calls to
@@ -231,6 +273,53 @@ public class DisplayManagerGlobalTest {
        verify(mListener2, never()).onDisplayChanged(anyInt());
    }

    @Test
    @RequiresFlagsEnabled(Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
    public void testMapFlagsToInternalEventFlag() {
        // Test public flags mapping
        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(DisplayManager.EVENT_FLAG_DISPLAY_ADDED, 0));
        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED, 0));
        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED, 0));
        assertEquals(INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(
                                DisplayManager.EVENT_FLAG_DISPLAY_REFRESH_RATE,
                                0));
        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_STATE,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(
                                DisplayManager.EVENT_FLAG_DISPLAY_STATE,
                                0));

        // test private flags mapping
        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(0,
                                DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED));
        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(0,
                                DisplayManager.PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED));
        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(0,
                                DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));

        // Test both public and private flags mapping
        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED
                        | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
                mDisplayManagerGlobal
                        .mapFlagsToInternalEventFlag(
                                DisplayManager.EVENT_FLAG_DISPLAY_REFRESH_RATE,
                                DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
    }

    private void waitForHandler() {
        mHandler.runWithScissors(() -> {
        }, 0);
+22 −0
Original line number Diff line number Diff line
@@ -2460,6 +2460,15 @@ public final class DisplayManagerService extends SystemService {
                DisplayManagerGlobal.EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED);
    }

    private void handleLogicalDisplayRefreshRateChangedLocked(@NonNull LogicalDisplay display) {
        sendDisplayEventIfEnabledLocked(display,
                DisplayManagerGlobal.EVENT_DISPLAY_REFRESH_RATE_CHANGED);
    }

    private void handleLogicalDisplayStateChangedLocked(@NonNull LogicalDisplay display) {
        sendDisplayEventIfEnabledLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_STATE_CHANGED);
    }

    private void notifyDefaultDisplayDeviceUpdated(LogicalDisplay display) {
        mDisplayModeDirector.defaultDisplayDeviceUpdated(display.getPrimaryDisplayDeviceLocked()
                .mDisplayDeviceConfig);
@@ -3991,6 +4000,12 @@ public final class DisplayManagerService extends SystemService {
                case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DISCONNECTED:
                    handleLogicalDisplayDisconnectedLocked(display);
                    break;
                case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED:
                    handleLogicalDisplayRefreshRateChangedLocked(display);
                    break;
                case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_STATE_CHANGED:
                    handleLogicalDisplayStateChangedLocked(display);
                    break;
            }
        }

@@ -4198,6 +4213,13 @@ public final class DisplayManagerService extends SystemService {
                    return (mask
                            & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED)
                            != 0;
                case DisplayManagerGlobal.EVENT_DISPLAY_REFRESH_RATE_CHANGED:
                    return (mask
                            & DisplayManagerGlobal
                            .INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE) != 0;
                case DisplayManagerGlobal.EVENT_DISPLAY_STATE_CHANGED:
                    return (mask & DisplayManagerGlobal
                            .INTERNAL_EVENT_FLAG_DISPLAY_STATE) != 0;
                default:
                    // This should never happen.
                    Slog.e(TAG, "Unknown display event " + event);
Loading