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

Commit 69073040 authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 62434d6a: Merge "Reduce latency from doze to screen on." into lmp-dev

* commit '62434d6a':
  Reduce latency from doze to screen on.
parents e4495131 62434d6a
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) {