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

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

Merge "Tell PhoneWindowManager when we start/finish interactive changes." into mnc-dev

parents 1501da4b 416c49c4
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
@@ -945,17 +945,30 @@ public interface WindowManagerPolicy {
    public int focusChangedLw(WindowState lastFocus, WindowState newFocus);

    /**
     * Called when the device is waking up.
     * Called when the device has started waking up.
     */
    public void wakingUp();
    public void startedWakingUp();

    /**
     * Called when the device is going to sleep.
     * Called when the device has finished waking up.
     */
    public void finishedWakingUp();

    /**
     * Called when the device has started going to sleep.
     *
     * @param why {@link #OFF_BECAUSE_OF_USER}, {@link #OFF_BECAUSE_OF_ADMIN},
     * or {@link #OFF_BECAUSE_OF_TIMEOUT}.
     */
    public void startedGoingToSleep(int why);

    /**
     * Called when the device has finished going to sleep.
     *
     * @param why {@link #OFF_BECAUSE_OF_USER} or
     * {@link #OFF_BECAUSE_OF_TIMEOUT}.
     * @param why {@link #OFF_BECAUSE_OF_USER}, {@link #OFF_BECAUSE_OF_ADMIN},
     * or {@link #OFF_BECAUSE_OF_TIMEOUT}.
     */
    public void goingToSleep(int why);
    public void finishedGoingToSleep(int why);

    /**
     * Called when the device is about to turn on the screen to show content.
+32 −19
Original line number Diff line number Diff line
@@ -1455,7 +1455,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {

        // Match current screen state.
        if (!mPowerManager.isInteractive()) {
            goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
            startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
            finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
        }

        mWindowManagerInternal.registerAppTransitionListener(
@@ -5233,9 +5234,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    // Called on the PowerManager's Notifier thread.
    @Override
    public void goingToSleep(int why) {
    public void startedGoingToSleep(int why) {
        if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void finishedGoingToSleep(int why) {
        EventLog.writeEvent(70000, 0);
        if (DEBUG_WAKEUP) Slog.i(TAG, "Going to sleep...");
        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");

        // We must get this work done here because the power manager will drop
        // the wake lock and let the system suspend once this function returns.
@@ -5252,24 +5259,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
    }

    private void wakeUpFromPowerKey(long eventTime) {
        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
    }

    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
        if (!wakeInTheaterMode && isTheaterModeEnabled()) {
            return false;
        }

        mPowerManager.wakeUp(wakeTime);
        return true;
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void wakingUp() {
    public void startedWakingUp() {
        EventLog.writeEvent(70000, 1);
        if (DEBUG_WAKEUP) Slog.i(TAG, "Waking up...");
        if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up...");

        // Since goToSleep performs these functions synchronously, we must
        // do the same here.  We cannot post this work to a handler because
@@ -5297,6 +5291,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void finishedWakingUp() {
        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
    }

    private void wakeUpFromPowerKey(long eventTime) {
        wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
    }

    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
        if (!wakeInTheaterMode && isTheaterModeEnabled()) {
            return false;
        }

        mPowerManager.wakeUp(wakeTime);
        return true;
    }

    private void finishKeyguardDrawn() {
        synchronized (mLock) {
            if (!mAwake || mKeyguardDrawComplete) {
@@ -5789,7 +5802,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        synchronized (mLock) {
            mSystemBooted = true;
        }
        wakingUp();
        startedWakingUp();
        screenTurningOn(null);
    }

+136 −88
Original line number Diff line number Diff line
@@ -95,11 +95,19 @@ final class Notifier {
    private final Intent mScreenOffIntent;
    private final Intent mScreenBrightnessBoostIntent;

    // The current interactive state.
    private int mActualInteractiveState;
    private int mLastReason;

    // True if there is a pending transition that needs to be reported.
    // The current interactive state.  This is set as soon as an interactive state
    // transition begins so as to capture the reason that it happened.  At some point
    // this state will propagate to the pending state then eventually to the
    // broadcasted state over the course of reporting the transition asynchronously.
    private boolean mInteractive = true;
    private int mInteractiveChangeReason;
    private boolean mInteractiveChanging;

    // The pending interactive state that we will eventually want to broadcast.
    // This is designed so that we can collapse redundant sequences of awake/sleep
    // transition pairs while still guaranteeing that at least one transition is observed
    // whenever this happens.
    private int mPendingInteractiveState;
    private boolean mPendingWakeUpBroadcast;
    private boolean mPendingGoToSleepBroadcast;

@@ -244,113 +252,152 @@ final class Notifier {

    /**
     * Notifies that the device is changing wakefulness.
     * This function may be called even if the previous change hasn't finished in
     * which case it will assume that the state did not fully converge before the
     * next transition began and will recover accordingly.
     */
    public void onWakefulnessChangeStarted(int wakefulness, int reason) {
    public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
        final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
        if (DEBUG) {
            Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
                    + ", reason=" + reason);
                    + ", reason=" + reason + ", interactive=" + interactive);
        }

        // We handle interactive state changes once they start so that the system can
        // set everything up or the user to begin interacting with applications.
        final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
        if (interactive) {
            handleWakefulnessChange(wakefulness, interactive, reason);
        } else {
            mLastReason = reason;
        // Tell the activity manager about changes in wakefulness, not just interactivity.
        // It needs more granularity than other components.
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mActivityManagerInternal.onWakefulnessChanged(wakefulness);
            }
        });

        // Handle any early interactive state changes.
        // Finish pending incomplete ones from a previous cycle.
        if (mInteractive != interactive) {
            // Finish up late behaviors if needed.
            if (mInteractiveChanging) {
                handleLateInteractiveChange();
            }

            // Start input as soon as we start waking up or going to sleep.
            mInputManagerInternal.setInteractive(interactive);

            // Notify battery stats.
            try {
                mBatteryStats.noteInteractive(interactive);
            } catch (RemoteException ex) { }

            // Handle early behaviors.
            mInteractive = interactive;
            mInteractiveChangeReason = reason;
            mInteractiveChanging = true;
            handleEarlyInteractiveChange();
        }
    }

    /**
     * Notifies that the device has finished changing wakefulness.
     */
    public void onWakefulnessChangeFinished(int wakefulness) {
    public void onWakefulnessChangeFinished() {
        if (DEBUG) {
            Slog.d(TAG, "onWakefulnessChangeFinished: wakefulness=" + wakefulness);
            Slog.d(TAG, "onWakefulnessChangeFinished");
        }

        // Handle interactive state changes once they are finished so that the system can
        // finish pending transitions (such as turning the screen off) before causing
        // applications to change state visibly.
        final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
        if (!interactive) {
            handleWakefulnessChange(wakefulness, interactive, mLastReason);
        if (mInteractiveChanging) {
            mInteractiveChanging = false;
            handleLateInteractiveChange();
        }
    }

    private void handleWakefulnessChange(final int wakefulness, boolean interactive,
            final int reason) {
        // Tell the activity manager about changes in wakefulness, not just interactivity.
        // It needs more granularity than other components.
    /**
     * Handle early interactive state changes such as getting applications or the lock
     * screen running and ready for the user to see (such as when turning on the screen).
     */
    private void handleEarlyInteractiveChange() {
        synchronized (mLock) {
            if (mInteractive) {
                // Waking up...
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                mActivityManagerInternal.onWakefulnessChanged(wakefulness);
                        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
                        mPolicy.startedWakingUp();
                    }
                });

        // Handle changes in the overall interactive state.
        boolean interactiveChanged = false;
        synchronized (mLock) {
            // Broadcast interactive state changes.
            if (interactive) {
                // Waking up...
                interactiveChanged = (mActualInteractiveState != INTERACTIVE_STATE_AWAKE);
                if (interactiveChanged) {
                    mActualInteractiveState = INTERACTIVE_STATE_AWAKE;
                // Send interactive broadcast.
                mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
                mPendingWakeUpBroadcast = true;
                updatePendingBroadcastLocked();
            } else {
                // Going to sleep...
                // Tell the policy that we started going to sleep.
                final int why = translateOffReason(mInteractiveChangeReason);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
                            mPolicy.wakingUp();
                        mPolicy.startedGoingToSleep(why);
                    }
                });
                    updatePendingBroadcastLocked();
            }
        }
    }

    /**
     * Handle late interactive state changes once they are finished so that the system can
     * finish pending transitions (such as turning the screen off) before causing
     * applications to change state visibly.
     */
    private void handleLateInteractiveChange() {
        synchronized (mLock) {
            if (mInteractive) {
                // Finished waking up...
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mPolicy.finishedWakingUp();
                    }
                });
            } else {
                // Going to sleep...
                // Finished going to sleep...
                // This is a good time to make transitions that we don't want the user to see,
                // such as bringing the key guard to focus.  There's no guarantee for this,
                // such as bringing the key guard to focus.  There's no guarantee for this
                // however because the user could turn the device on again at any time.
                // Some things may need to be protected by other mechanisms that defer screen on.
                interactiveChanged = (mActualInteractiveState != INTERACTIVE_STATE_ASLEEP);
                if (interactiveChanged) {
                    mActualInteractiveState = INTERACTIVE_STATE_ASLEEP;
                    mPendingGoToSleepBroadcast = true;

                // Cancel pending user activity.
                if (mUserActivityPending) {
                    mUserActivityPending = false;
                    mHandler.removeMessages(MSG_USER_ACTIVITY);
                }

                // Tell the policy we finished going to sleep.
                final int why = translateOffReason(mInteractiveChangeReason);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                            int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
                            switch (reason) {
                                case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
                                    why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
                                    break;
                                case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
                                    why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
                                    break;
                            }
                        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
                            mPolicy.goingToSleep(why);
                        mPolicy.finishedGoingToSleep(why);
                    }
                });

                // Send non-interactive broadcast.
                mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;
                mPendingGoToSleepBroadcast = true;
                updatePendingBroadcastLocked();
            }
        }
    }

        // Notify battery stats.
        if (interactiveChanged) {
            try {
                mBatteryStats.noteInteractive(interactive);
            } catch (RemoteException ex) { }
    private static int translateOffReason(int reason) {
        switch (reason) {
            case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
                return WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
            case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
                return WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
            default:
                return WindowManagerPolicy.OFF_BECAUSE_OF_USER;
        }
    }

@@ -367,6 +414,7 @@ final class Notifier {
        msg.setAsynchronous(true);
        mHandler.sendMessage(msg);
    }

    /**
     * Called when there has been user activity.
     */
@@ -407,9 +455,9 @@ final class Notifier {

    private void updatePendingBroadcastLocked() {
        if (!mBroadcastInProgress
                && mActualInteractiveState != INTERACTIVE_STATE_UNKNOWN
                && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
                && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mActualInteractiveState != mBroadcastedInteractiveState)) {
                        || mPendingInteractiveState != mBroadcastedInteractiveState)) {
            mBroadcastInProgress = true;
            mSuspendBlocker.acquire();
            Message msg = mHandler.obtainMessage(MSG_BROADCAST);
@@ -444,7 +492,7 @@ final class Notifier {
            } else if (mBroadcastedInteractiveState == INTERACTIVE_STATE_AWAKE) {
                // Broadcasted power state is awake.  Send asleep if needed.
                if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mActualInteractiveState == INTERACTIVE_STATE_ASLEEP) {
                        || mPendingInteractiveState == INTERACTIVE_STATE_ASLEEP) {
                    mPendingGoToSleepBroadcast = false;
                    mBroadcastedInteractiveState = INTERACTIVE_STATE_ASLEEP;
                } else {
@@ -454,7 +502,7 @@ final class Notifier {
            } else {
                // Broadcasted power state is asleep.  Send awake if needed.
                if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mActualInteractiveState == INTERACTIVE_STATE_AWAKE) {
                        || mPendingInteractiveState == INTERACTIVE_STATE_AWAKE) {
                    mPendingWakeUpBroadcast = false;
                    mBroadcastedInteractiveState = INTERACTIVE_STATE_AWAKE;
                } else {
+8 −8
Original line number Diff line number Diff line
@@ -1217,8 +1217,6 @@ public final class PowerManagerService extends SystemService

    private void setWakefulnessLocked(int wakefulness, int reason) {
        if (mWakefulness != wakefulness) {
            finishWakefulnessChangeLocked();

            mWakefulness = wakefulness;
            mWakefulnessChanging = true;
            mDirty |= DIRTY_WAKEFULNESS;
@@ -1226,10 +1224,14 @@ public final class PowerManagerService extends SystemService
        }
    }

    private void finishWakefulnessChangeLocked() {
        if (mWakefulnessChanging) {
            mNotifier.onWakefulnessChangeFinished(mWakefulness);
    private void finishWakefulnessChangeIfNeededLocked() {
        if (mWakefulnessChanging && mDisplayReady) {
            if (mWakefulness == WAKEFULNESS_DOZING
                    && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {
                return; // wait until dream has enabled dozing
            }
            mWakefulnessChanging = false;
            mNotifier.onWakefulnessChangeFinished();
        }
    }

@@ -1280,9 +1282,7 @@ public final class PowerManagerService extends SystemService
            updateDreamLocked(dirtyPhase2, displayBecameReady);

            // Phase 4: Send notifications, if needed.
            if (mDisplayReady) {
                finishWakefulnessChangeLocked();
            }
            finishWakefulnessChangeIfNeededLocked();

            // Phase 5: Update suspend blocker.
            // Because we might release the last suspend blocker here, we need to make sure