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

Commit eb57142b authored by Chen Bai's avatar Chen Bai
Browse files

do wom: allow DisplayOffload to block screen turning on

Test: atest DisplayServiceTests
BUG: 303265216
Change-Id: I4d8a81a3a3c480b3b818e2be2eaa070e401669af
parent 2996824c
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -715,6 +715,14 @@ public abstract class DisplayManagerInternal {
        boolean startOffload();

        void stopOffload();

        /**
         * Called when {@link DisplayOffloadSession} tries to block screen turning on.
         *
         * @param unblocker a {@link Runnable} executed upon all work required before screen turning
         *                  on is done.
         */
        void onBlockingScreenOn(Runnable unblocker);
    }

    /** A session token that associates a internal display with a {@link DisplayOffloader}. */
@@ -734,6 +742,15 @@ public abstract class DisplayManagerInternal {
         */
        void updateBrightness(float brightness);

        /**
         * Called while display is turning to state ON to leave a small period for displayoffload
         * session to finish some work.
         *
         * @param unblocker a {@link Runnable} used by displayoffload session to notify
         *                  {@link DisplayManager} that it can continue turning screen on.
         */
        boolean blockScreenOn(Runnable unblocker);

        /** Returns whether displayoffload supports the given display state. */
        static boolean isSupportedOffloadState(int displayState) {
            return Display.isSuspendedState(displayState);
+9 −0
Original line number Diff line number Diff line
@@ -56,6 +56,15 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display
        }
    }

    @Override
    public boolean blockScreenOn(Runnable unblocker) {
        if (mDisplayOffloader == null) {
            return false;
        }
        mDisplayOffloader.onBlockingScreenOn(unblocker);
        return true;
    }

    /**
     * Start the offload session. The method returns if the session is already active.
     * @return Whether the session was started successfully
+85 −6
Original line number Diff line number Diff line
@@ -126,6 +126,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
    // To enable these logs, run:
    // 'adb shell setprop persist.log.tag.DisplayPowerController2 DEBUG && adb reboot'
    private static final boolean DEBUG = DebugUtils.isDebuggable(TAG);
    private static final String SCREEN_ON_BLOCKED_BY_DISPLAYOFFLOAD_TRACE_NAME =
            "Screen on blocked by displayoffload";

    // If true, uses the color fade on animation.
    // We might want to turn this off if we cannot get a guarantee that the screen
@@ -155,6 +157,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
    private static final int MSG_SET_DWBC_COLOR_OVERRIDE = 15;
    private static final int MSG_SET_DWBC_LOGGING_ENABLED = 16;
    private static final int MSG_SET_BRIGHTNESS_FROM_OFFLOAD = 17;
    private static final int MSG_OFFLOADING_SCREEN_ON_UNBLOCKED = 18;



@@ -339,6 +342,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
    // we are waiting for a callback to release it and unblock the screen.
    private ScreenOnUnblocker mPendingScreenOnUnblocker;
    private ScreenOffUnblocker mPendingScreenOffUnblocker;
    private Runnable mPendingScreenOnUnblockerByDisplayOffload;

    // True if we were in the process of turning off the screen.
    // This allows us to recover more gracefully from situations where we abort
@@ -348,10 +352,15 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
    // The elapsed real time when the screen on was blocked.
    private long mScreenOnBlockStartRealTime;
    private long mScreenOffBlockStartRealTime;
    private long mScreenOnBlockByDisplayOffloadStartRealTime;

    // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_* fields.
    private int mReportedScreenStateToPolicy = REPORTED_TO_POLICY_UNREPORTED;

    // Used to deduplicate the displayoffload blocking screen on logic. One block per turning on.
    // This value is reset when screen on is reported or the blocking is cancelled.
    private boolean mScreenTurningOnWasBlockedByDisplayOffload;

    // If the last recorded screen state was dozing or not.
    private boolean mDozing;

@@ -472,7 +481,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
    private boolean mBootCompleted;
    private final DisplayManagerFlags mFlags;

    private DisplayManagerInternal.DisplayOffloadSession mDisplayOffloadSession;
    private DisplayOffloadSession mDisplayOffloadSession;

    /**
     * Creates the display power controller.
@@ -772,6 +781,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal

    @Override
    public void setDisplayOffloadSession(DisplayOffloadSession session) {
        if (session == mDisplayOffloadSession) {
            return;
        }
        unblockScreenOnByDisplayOffload();
        mDisplayOffloadSession = session;
    }

@@ -1735,6 +1748,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
        // reporting the display is ready because we only need to ensure the screen is in the
        // right power state even as it continues to converge on the desired brightness.
        final boolean ready = mPendingScreenOnUnblocker == null
                && mPendingScreenOnUnblockerByDisplayOffload == null
                && (!mColorFadeEnabled || (!mColorFadeOnAnimator.isStarted()
                        && !mColorFadeOffAnimator.isStarted()))
                && mPowerState.waitUntilClean(mCleanListener);
@@ -1983,15 +1997,69 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
        }
    }

    private void blockScreenOnByDisplayOffload(DisplayOffloadSession displayOffloadSession) {
        if (mPendingScreenOnUnblockerByDisplayOffload != null || displayOffloadSession == null) {
            return;
        }
        mScreenTurningOnWasBlockedByDisplayOffload = true;

        Trace.asyncTraceBegin(
                Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_BY_DISPLAYOFFLOAD_TRACE_NAME, 0);
        mScreenOnBlockByDisplayOffloadStartRealTime = SystemClock.elapsedRealtime();

        mPendingScreenOnUnblockerByDisplayOffload =
                () -> onDisplayOffloadUnblockScreenOn(displayOffloadSession);
        if (!displayOffloadSession.blockScreenOn(mPendingScreenOnUnblockerByDisplayOffload)) {
            mPendingScreenOnUnblockerByDisplayOffload = null;
            long delay =
                    SystemClock.elapsedRealtime() - mScreenOnBlockByDisplayOffloadStartRealTime;
            Slog.w(mTag, "Tried blocking screen on for offloading but failed. So, end trace after "
                    + delay + " ms.");
            Trace.asyncTraceEnd(
                    Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_BY_DISPLAYOFFLOAD_TRACE_NAME, 0);
            return;
        }
        Slog.i(mTag, "Blocking screen on for offloading.");
    }

    private void onDisplayOffloadUnblockScreenOn(DisplayOffloadSession displayOffloadSession) {
        Message msg = mHandler.obtainMessage(MSG_OFFLOADING_SCREEN_ON_UNBLOCKED,
                displayOffloadSession);
        mHandler.sendMessage(msg);
    }

    private void unblockScreenOnByDisplayOffload() {
        if (mPendingScreenOnUnblockerByDisplayOffload == null) {
            return;
        }
        mPendingScreenOnUnblockerByDisplayOffload = null;
        long delay = SystemClock.elapsedRealtime() - mScreenOnBlockByDisplayOffloadStartRealTime;
        Slog.i(mTag, "Unblocked screen on for offloading after " + delay + " ms");
        Trace.asyncTraceEnd(
                Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_BY_DISPLAYOFFLOAD_TRACE_NAME, 0);
    }

    private boolean setScreenState(int state) {
        return setScreenState(state, false /*reportOnly*/);
    }

    private boolean setScreenState(int state, boolean reportOnly) {
        final boolean isOff = (state == Display.STATE_OFF);
        final boolean isOn = (state == Display.STATE_ON);
        final boolean changed = mPowerState.getScreenState() != state;

        if (mPowerState.getScreenState() != state
                || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
        // If the screen is turning on, give displayoffload a chance to do something before the
        // screen actually turns on.
        // TODO(b/316941732): add tests for this displayoffload screen-on blocker.
        if (isOn && changed && !mScreenTurningOnWasBlockedByDisplayOffload) {
            blockScreenOnByDisplayOffload(mDisplayOffloadSession);
        } else if (!isOn && mScreenTurningOnWasBlockedByDisplayOffload) {
            // No longer turning screen on, so unblock previous screen on blocking immediately.
            unblockScreenOnByDisplayOffload();
            mScreenTurningOnWasBlockedByDisplayOffload = false;
        }

        if (changed || mReportedScreenStateToPolicy == REPORTED_TO_POLICY_UNREPORTED) {
            // If we are trying to turn screen off, give policy a chance to do something before we
            // actually turn the screen off.
            if (isOff && !mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()) {
@@ -2007,8 +2075,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
                }
            }

            if (!reportOnly && mPowerState.getScreenState() != state
                    && readyToUpdateDisplayState()) {
            if (!reportOnly && changed && readyToUpdateDisplayState()
                    && mPendingScreenOffUnblocker == null
                    && mPendingScreenOnUnblockerByDisplayOffload == null) {
                Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);

                String propertyKey = "debug.tracing.screen_state";
@@ -2060,12 +2129,16 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
        }

        // Return true if the screen isn't blocked.
        return mPendingScreenOnUnblocker == null;
        return mPendingScreenOnUnblocker == null
                && mPendingScreenOnUnblockerByDisplayOffload == null;
    }

    private void setReportedScreenState(int state) {
        Trace.traceCounter(Trace.TRACE_TAG_POWER, "ReportedScreenStateToPolicy", state);
        mReportedScreenStateToPolicy = state;
        if (state == REPORTED_TO_POLICY_SCREEN_ON) {
            mScreenTurningOnWasBlockedByDisplayOffload = false;
        }
    }

    private void loadAmbientLightSensor() {
@@ -2813,6 +2886,12 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
                        updatePowerState();
                    }
                    break;
                case MSG_OFFLOADING_SCREEN_ON_UNBLOCKED:
                    if (mDisplayOffloadSession == msg.obj) {
                        unblockScreenOnByDisplayOffload();
                        updatePowerState();
                    }
                    break;
                case MSG_CONFIGURE_BRIGHTNESS:
                    BrightnessConfiguration brightnessConfiguration =
                            (BrightnessConfiguration) msg.obj;
+9 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.display;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -88,4 +89,12 @@ public class DisplayOffloadSessionImplTest {

        verify(mDisplayPowerController).setBrightnessFromOffload(brightness);
    }

    @Test
    public void testBlockScreenOn() {
        Runnable unblocker = () -> {};
        mSession.blockScreenOn(unblocker);

        verify(mDisplayOffloader).onBlockingScreenOn(eq(unblocker));
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -1235,6 +1235,9 @@ public class LocalDisplayAdapterTest {

            @Override
            public void stopOffload() {}

            @Override
            public void onBlockingScreenOn(Runnable unblocker) {}
        });

        mDisplayOffloadSession = new DisplayOffloadSessionImpl(mDisplayOffloader,