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

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

Merge "Fix delayed offload session start issue" into main

parents 2b8a44d8 79916028
Loading
Loading
Loading
Loading
+26 −32
Original line number Diff line number Diff line
@@ -492,6 +492,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    // Used to scale the brightness in doze mode
    private float mDozeScaleFactor;

    // Used to keep track of the display state from the latest request to override the doze screen
    // state.
    @GuardedBy("mLock")
    private int mPendingOverrideDozeScreenStateLocked;

    /**
     * Creates the display power controller.
     */
@@ -803,16 +808,29 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    @Override
    public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) {
        Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState));
        mHandler.postAtTime(() -> {
            if (mDisplayOffloadSession == null
                    || !(DisplayOffloadSession.isSupportedOffloadState(displayState)
        if (mDisplayOffloadSession != null
                && (DisplayOffloadSession.isSupportedOffloadState(displayState)
                || displayState == Display.STATE_UNKNOWN)) {
                return;
            if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) {
                mWakelockController.acquireWakelock(
                        WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE);
            }
            synchronized (mLock) {
                mPendingOverrideDozeScreenStateLocked = displayState;
            }
            mHandler.postAtTime(() -> {
                synchronized (mLock) {
                    mDisplayStateController
                            .overrideDozeScreenState(mPendingOverrideDozeScreenStateLocked, reason);
                }
            mDisplayStateController.overrideDozeScreenState(displayState, reason);
                updatePowerState();
                if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) {
                    mWakelockController.releaseWakelock(
                            WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE);
                }
            }, mClock.uptimeMillis());
        }
    }

    @Override
    public void setDisplayOffloadSession(DisplayOffloadSession session) {
@@ -1338,30 +1356,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
        }

        if (mFlags.isOffloadDozeOverrideHoldsWakelockEnabled()) {
            // Sometimes, a display-state change can come without an associated PowerRequest,
            // as with DisplayOffload.  For those cases, we have to make sure to also mark the
            // display as "not ready" so that we can inform power-manager when the state-change is
            // complete.
            if (mPowerState.getScreenState() != state) {
                final boolean wasReady;
                synchronized (mLock) {
                    wasReady = mDisplayReadyLocked;
                    mDisplayReadyLocked = false;
                    mustNotify = true;
                }

                if (wasReady) {
                    // If we went from ready to not-ready from the state-change (instead of a
                    // PowerRequest) there's a good chance that nothing is keeping PowerManager
                    // from suspending. Grab the unfinished business suspend blocker to keep the
                    // device awake until the display-state change goes into effect.
                    mWakelockController.acquireWakelock(
                            WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
                }
            }
        }

        // Animate the screen state change unless already animating.
        // The transition may be deferred, so after this point we will use the
        // actual state instead of the desired one.
+72 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.hardware.display.DisplayManagerInternal;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.utils.DebugUtils;

@@ -37,7 +38,8 @@ public final class WakelockController {
    public static final int WAKE_LOCK_PROXIMITY_NEGATIVE = 2;
    public static final int WAKE_LOCK_PROXIMITY_DEBOUNCE = 3;
    public static final int WAKE_LOCK_STATE_CHANGED = 4;
    public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 5;
    public static final int WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE = 5;
    public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 6;

    @VisibleForTesting
    static final int WAKE_LOCK_MAX = WAKE_LOCK_UNFINISHED_BUSINESS;
@@ -53,18 +55,23 @@ public final class WakelockController {
            WAKE_LOCK_PROXIMITY_NEGATIVE,
            WAKE_LOCK_PROXIMITY_DEBOUNCE,
            WAKE_LOCK_STATE_CHANGED,
            WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE,
            WAKE_LOCK_UNFINISHED_BUSINESS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface WAKE_LOCK_TYPE {
    }

    private final Object mLock = new Object();

    // Asynchronous callbacks into the power manager service.
    // Only invoked from the handler thread while no locks are held.
    private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks;

    // Identifiers for suspend blocker acquisition requests
    private final String mSuspendBlockerIdUnfinishedBusiness;
    @GuardedBy("mLock")
    private final String mSuspendBlockerOverrideDozeScreenState;
    private final String mSuspendBlockerIdOnStateChanged;
    private final String mSuspendBlockerIdProxPositive;
    private final String mSuspendBlockerIdProxNegative;
@@ -73,6 +80,10 @@ public final class WakelockController {
    // True if we have unfinished business and are holding a suspend-blocker.
    private boolean mUnfinishedBusiness;

    // True if we have are holding a suspend-blocker to override the doze screen state.
    @GuardedBy("mLock")
    private boolean mIsOverrideDozeScreenStateAcquired;

    // True if we have have debounced the proximity change impact and are holding a suspend-blocker.
    private boolean mHasProximityDebounced;

@@ -108,6 +119,7 @@ public final class WakelockController {
        mTag = TAG + "[" + mDisplayId + "]";
        mDisplayPowerCallbacks = callbacks;
        mSuspendBlockerIdUnfinishedBusiness = "[" + displayId + "]unfinished business";
        mSuspendBlockerOverrideDozeScreenState =  "[" + displayId + "]override doze screen state";
        mSuspendBlockerIdOnStateChanged = "[" + displayId + "]on state changed";
        mSuspendBlockerIdProxPositive = "[" + displayId + "]prox positive";
        mSuspendBlockerIdProxNegative = "[" + displayId + "]prox negative";
@@ -154,6 +166,10 @@ public final class WakelockController {
                return acquireProxDebounceSuspendBlocker();
            case WAKE_LOCK_STATE_CHANGED:
                return acquireStateChangedSuspendBlocker();
            case WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE:
                synchronized (mLock) {
                    return acquireOverrideDozeScreenStateSuspendBlockerLocked();
                }
            case WAKE_LOCK_UNFINISHED_BUSINESS:
                return acquireUnfinishedBusinessSuspendBlocker();
            default:
@@ -171,6 +187,10 @@ public final class WakelockController {
                return releaseProxDebounceSuspendBlocker();
            case WAKE_LOCK_STATE_CHANGED:
                return releaseStateChangedSuspendBlocker();
            case WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE:
                synchronized (mLock) {
                    return releaseOverrideDozeScreenStateSuspendBlockerLocked();
                }
            case WAKE_LOCK_UNFINISHED_BUSINESS:
                return releaseUnfinishedBusinessSuspendBlocker();
            default:
@@ -219,6 +239,42 @@ public final class WakelockController {
        return false;
    }

    /**
     * Acquires the suspend blocker to override the doze screen state and notifies the
     * PowerManagerService about the changes. Note that this utility is syncronized because a
     * request to override the doze screen state can come from a non-power thread.
     */
    @GuardedBy("mLock")
    private boolean acquireOverrideDozeScreenStateSuspendBlockerLocked() {
        // Grab a wake lock if we have unfinished business.
        if (!mIsOverrideDozeScreenStateAcquired) {
            if (DEBUG) {
                Slog.d(mTag, "Acquiring suspend blocker to override the doze screen state...");
            }
            mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerOverrideDozeScreenState);
            mIsOverrideDozeScreenStateAcquired = true;
            return true;
        }
        return false;
    }

    /**
     * Releases the override doze screen state suspend blocker and notifies the PowerManagerService
     * about the changes.
     */
    @GuardedBy("mLock")
    private boolean releaseOverrideDozeScreenStateSuspendBlockerLocked() {
        if (mIsOverrideDozeScreenStateAcquired) {
            if (DEBUG) {
                Slog.d(mTag, "Finished overriding doze screen state...");
            }
            mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerOverrideDozeScreenState);
            mIsOverrideDozeScreenStateAcquired = false;
            return true;
        }
        return false;
    }

    /**
     * Acquires the unfinished business wakelock and notifies the PowerManagerService about the
     * changes.
@@ -366,6 +422,7 @@ public final class WakelockController {
        pw.println("  mOnStateChangePending=" + isOnStateChangedPending());
        pw.println("  mOnProximityPositiveMessages=" + isProximityPositiveAcquired());
        pw.println("  mOnProximityNegativeMessages=" + isProximityNegativeAcquired());
        pw.println("  mIsOverrideDozeScreenStateAcquired=" + isOverrideDozeScreenStateAcquired());
    }

    @VisibleForTesting
@@ -393,6 +450,13 @@ public final class WakelockController {
        return mSuspendBlockerIdProxDebounce;
    }

    @VisibleForTesting
    String getSuspendBlockerOverrideDozeScreenState() {
        synchronized (mLock) {
            return mSuspendBlockerOverrideDozeScreenState;
        }
    }

    @VisibleForTesting
    boolean hasUnfinishedBusiness() {
        return mUnfinishedBusiness;
@@ -417,4 +481,11 @@ public final class WakelockController {
    boolean hasProximitySensorDebounced() {
        return mHasProximityDebounced;
    }

    @VisibleForTesting
    boolean isOverrideDozeScreenStateAcquired() {
        synchronized (mLock) {
            return mIsOverrideDozeScreenStateAcquired;
        }
    }
}
+8 −3
Original line number Diff line number Diff line
@@ -1621,16 +1621,21 @@ public final class DisplayPowerControllerTest {
        advanceTime(1); // Run updatePowerState

        reset(mHolder.wakelockController);
        when(mHolder.wakelockController
                .acquireWakelock(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE))
                .thenReturn(true);
        mHolder.dpc.overrideDozeScreenState(
                supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY);
        advanceTime(1); // Run updatePowerState

        // Should get a wakelock to notify powermanager
        verify(mHolder.wakelockController, atLeastOnce()).acquireWakelock(
                eq(WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS));
        verify(mHolder.wakelockController).acquireWakelock(
                eq(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE));

        advanceTime(1); // Run updatePowerState
        verify(mHolder.displayPowerState)
                .setScreenState(supportedTargetState, Display.STATE_REASON_DEFAULT_POLICY);
        verify(mHolder.wakelockController).releaseWakelock(
                eq(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE));
    }

    @Test
+24 −0
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ public final class WakelockControllerTest {
                "[" + DISPLAY_ID + "]prox negative");
        assertEquals(mWakelockController.getSuspendBlockerProxDebounceId(),
                "[" + DISPLAY_ID + "]prox debounce");
        assertEquals(mWakelockController.getSuspendBlockerOverrideDozeScreenState(),
                "[" + DISPLAY_ID + "]override doze screen state");
    }

    @Test
@@ -161,6 +163,28 @@ public final class WakelockControllerTest {
                .releaseSuspendBlocker(mWakelockController.getSuspendBlockerProxDebounceId());
    }

    @Test
    public void acquireOverrideDozeScreenStateSuspendBlocker() throws Exception {
        // Acquire the suspend blocker
        verifyWakelockAcquisitionAndReaquisition(WakelockController
                        .WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE,
                () -> mWakelockController.isOverrideDozeScreenStateAcquired());

        // Verify acquire happened only once
        verify(mDisplayPowerCallbacks, times(1))
                .acquireSuspendBlocker(mWakelockController
                        .getSuspendBlockerOverrideDozeScreenState());

        // Release the suspend blocker
        verifyWakelockReleaseAndRerelease(WakelockController.WAKE_LOCK_OVERRIDE_DOZE_SCREEN_STATE,
                () -> mWakelockController.isOverrideDozeScreenStateAcquired());

        // Verify suspend blocker was released only once
        verify(mDisplayPowerCallbacks, times(1))
                .releaseSuspendBlocker(mWakelockController
                        .getSuspendBlockerOverrideDozeScreenState());
    }

    @Test
    public void proximityPositiveRunnableWorksAsExpected() {
        // Acquire the suspend blocker twice