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

Commit 62434d6a authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Reduce latency from doze to screen on." into lmp-dev

parents ee33c661 0a434776
Loading
Loading
Loading
Loading
+46 −11
Original line number Diff line number Diff line
@@ -227,6 +227,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    // turning off the screen.
    private boolean mPendingScreenOff;

    // True if we have unfinished business and are holding a suspend blocker.
    private boolean mUnfinishedBusiness;

    // The elapsed real time when the screen on was blocked.
    private long mScreenOnBlockStartRealTime;

@@ -633,22 +636,42 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            mAppliedLowPower = true;
        }

        // Animate the screen brightness when the screen is on.
        if (state != Display.STATE_OFF) {
            animateScreenBrightness(brightness, slowChange
                    ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
        }

        // Animate the screen state change unless already animating.
        animateScreenStateChange(state, performScreenOffTransition);

        // Report whether the display is ready for use and all changes have been applied.
        if (mustNotify
                && mPendingScreenOnUnblocker == null
        // Animate the screen brightness when the screen is on or dozing.
        // Skip the animation when the screen is off or suspended.
        final int actualState = mPowerState.getScreenState();
        if (actualState == Display.STATE_ON || actualState == Display.STATE_DOZE) {
            animateScreenBrightness(brightness,
                    slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
        } else {
            animateScreenBrightness(brightness, 0);
        }

        // Determine whether the display is ready for use in the newly requested state.
        // Note that we do not wait for the brightness ramp animation to complete before
        // 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
                && !mColorFadeOnAnimator.isStarted()
                && !mColorFadeOffAnimator.isStarted()
                && !mScreenBrightnessRampAnimator.isAnimating()
                && mPowerState.waitUntilClean(mCleanListener)) {
                && mPowerState.waitUntilClean(mCleanListener);
        final boolean finished = ready
                && !mScreenBrightnessRampAnimator.isAnimating();

        // Grab a wake lock if we have unfinished business.
        if (!finished && !mUnfinishedBusiness) {
            if (DEBUG) {
                Slog.d(TAG, "Unfinished business...");
            }
            mCallbacks.acquireSuspendBlocker();
            mUnfinishedBusiness = true;
        }

        // Notify the power manager when ready.
        if (ready && mustNotify) {
            // Send state change.
            synchronized (mLock) {
                if (!mPendingRequestChangedLocked) {
                    mDisplayReadyLocked = true;
@@ -660,6 +683,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            }
            sendOnStateChangedWithWakelock();
        }

        // Release the wake lock when we have no unfinished business.
        if (finished && mUnfinishedBusiness) {
            if (DEBUG) {
                Slog.d(TAG, "Finished business...");
            }
            mUnfinishedBusiness = false;
            mCallbacks.releaseSuspendBlocker();
        }
    }

    @Override
@@ -723,6 +755,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    }

    private void animateScreenBrightness(int target, int rate) {
        if (DEBUG) {
            Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
        }
        if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
            try {
                mBatteryStats.noteScreenBrightness(target);
+66 −62
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ final class DisplayPowerState {
        mBacklight = backlight;
        mColorFade = electronBeam;
        mPhotonicModulator = new PhotonicModulator();
        mPhotonicModulator.start();

        // At boot time, we know that the screen is on and the electron beam
        // animation is not playing.  We don't know the screen's brightness though,
@@ -336,7 +337,7 @@ final class DisplayPowerState {
    /**
     * Updates the state of the screen and backlight asynchronously on a separate thread.
     */
    private final class PhotonicModulator {
    private final class PhotonicModulator extends Thread {
        private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
        private static final int INITIAL_BACKLIGHT = -1; // unknown

@@ -361,7 +362,7 @@ final class DisplayPowerState {

                    if (!mChangeInProgress) {
                        mChangeInProgress = true;
                        AsyncTask.THREAD_POOL_EXECUTOR.execute(mTask);
                        mLock.notifyAll();
                    }
                }
                return !mChangeInProgress;
@@ -369,6 +370,7 @@ final class DisplayPowerState {
        }

        public void dump(PrintWriter pw) {
            synchronized (mLock) {
                pw.println();
                pw.println("Photonic Modulator State:");
                pw.println("  mPendingState=" + Display.stateToString(mPendingState));
@@ -377,12 +379,12 @@ final class DisplayPowerState {
                pw.println("  mActualBacklight=" + mActualBacklight);
                pw.println("  mChangeInProgress=" + mChangeInProgress);
            }
        }

        private final Runnable mTask = new Runnable() {
        @Override
        public void run() {
                // Apply pending changes until done.
            for (;;) {
                // Get pending change.
                final int state;
                final boolean stateChanged;
                final int backlight;
@@ -393,13 +395,19 @@ final class DisplayPowerState {
                    backlight = mPendingBacklight;
                    backlightChanged = (backlight != mActualBacklight);
                    if (!stateChanged && !backlightChanged) {
                        // All changed applied, notify outer class and wait for more.
                        mChangeInProgress = false;
                            break;
                        postScreenUpdateThreadSafe();
                        try {
                            mLock.wait();
                        } catch (InterruptedException ex) { }
                        continue;
                    }
                    mActualState = state;
                    mActualBacklight = backlight;
                }

                // Apply pending change.
                if (DEBUG) {
                    Slog.d(TAG, "Updating screen state: state="
                            + Display.stateToString(state) + ", backlight=" + backlight);
@@ -415,9 +423,6 @@ final class DisplayPowerState {
                    requestDisplayState(state);
                }
            }

                // Let the outer class know that all changes have been applied.
                postScreenUpdateThreadSafe();
        }

        private void requestDisplayState(int state) {
@@ -438,6 +443,5 @@ final class DisplayPowerState {
                Trace.traceEnd(Trace.TRACE_TAG_POWER);
            }
        }
        };
    }
}
+29 −13
Original line number Diff line number Diff line
@@ -50,21 +50,33 @@ final class RampAnimator<T> {
    /**
     * Starts animating towards the specified value.
     *
     * If this is the first time the property is being set, the value jumps
     * directly to the target.
     * If this is the first time the property is being set or if the rate is 0,
     * the value jumps directly to the target.
     *
     * @param target The target value.
     * @param rate The convergence rate, in units per second.
     * @param rate The convergence rate in units per second, or 0 to set the value immediately.
     * @return True if the target differs from the previous target.
     */
    public boolean animateTo(int target, int rate) {
        // Immediately jump to the target the first time.
        if (mFirstTime) {
        if (mFirstTime || rate <= 0) {
            if (mFirstTime || target != mCurrentValue) {
                mFirstTime = false;
            mProperty.setValue(mObject, target);
                mRate = 0;
                mTargetValue = target;
                mCurrentValue = target;
                mProperty.setValue(mObject, target);
                if (mAnimating) {
                    mAnimating = false;
                    cancelAnimationCallback();
                }
                if (mListener != null) {
                    mListener.onAnimationEnd();
                }
                return true;
            }
            return false;
        }

        // Adjust the rate based on the closest target.
        // If a faster rate is specified, then use the new rate so that we converge
@@ -88,7 +100,7 @@ final class RampAnimator<T> {
            mAnimating = true;
            mAnimatedValue = mCurrentValue;
            mLastFrameTimeNanos = System.nanoTime();
            postCallback();
            postAnimationCallback();
        }

        return changed;
@@ -108,11 +120,15 @@ final class RampAnimator<T> {
        mListener = listener;
    }

    private void postCallback() {
        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mCallback, null);
    private void postAnimationCallback() {
        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
    }

    private void cancelAnimationCallback() {
        mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
    }

    private final Runnable mCallback = new Runnable() {
    private final Runnable mAnimationCallback = new Runnable() {
        @Override // Choreographer callback
        public void run() {
            final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
@@ -144,7 +160,7 @@ final class RampAnimator<T> {
            }

            if (mTargetValue != mCurrentValue) {
                postCallback();
                postAnimationCallback();
            } else {
                mAnimating = false;
                if (mListener != null) {