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

Commit 54308359 authored by Jeff Brown's avatar Jeff Brown
Browse files

Ensure we send at least one wakeup/gotosleep transition.

This fixes an issue where the device would not lock immediately
when the user quickly pressed power off / power on even if
configured to do so.  We were suppressing the screen off
and wake up broadcast in this case.

Now we make sure to always send at least one broadcast to
indicate the transition.  We still collapse back-to-back
full cycle transitions though so as not to end up enqueuing
useless broadcasts.

Bug: 7061116
Change-Id: I7211c5fd963c271c2b0aceb4d2f746063c629079
parent 93cbbb25
Loading
Loading
Loading
Loading
+48 −16
Original line number Diff line number Diff line
@@ -39,17 +39,20 @@ import android.view.WindowManagerPolicy.ScreenOnListener;

/**
 * Sends broadcasts about important power state changes.
 *
 * <p>
 * This methods of this class may be called by the power manager service while
 * its lock is being held.  Internally it takes care of sending broadcasts to
 * notify other components of the system or applications asynchronously.
 *
 * </p><p>
 * The notifier is designed to collapse unnecessary broadcasts when it is not
 * possible for the system to have observed an intermediate state.
 *
 * For example, if the device wakes up, goes to sleep and wakes up again immediately
 * before the go to sleep broadcast has been sent, then no broadcast will be
 * sent about the system going to sleep and waking up.
 * </p><p>
 * For example, if the device wakes up, goes to sleep, wakes up again and goes to
 * sleep again before the wake up notification is sent, then the system will
 * be told about only one wake up and sleep.  However, we always notify the
 * fact that at least one transition occurred.  It is especially important to
 * tell the system when we go to sleep so that it can lock the keyguard if needed.
 * </p>
 */
final class Notifier {
    private static final String TAG = "PowerManagerNotifier";
@@ -79,6 +82,10 @@ final class Notifier {
    private int mActualPowerState;
    private int mLastGoToSleepReason;

    // True if there is a pending transition that needs to be reported.
    private boolean mPendingWakeUpBroadcast;
    private boolean mPendingGoToSleepBroadcast;

    // The currently broadcasted power state.  This reflects what other parts of the
    // system have observed.
    private int mBroadcastedPowerState;
@@ -219,6 +226,7 @@ final class Notifier {
        synchronized (mLock) {
            if (mActualPowerState != POWER_STATE_AWAKE) {
                mActualPowerState = POWER_STATE_AWAKE;
                mPendingWakeUpBroadcast = true;
                updatePendingBroadcastLocked();
            }
        }
@@ -264,6 +272,7 @@ final class Notifier {
        synchronized (mLock) {
            if (mActualPowerState != POWER_STATE_ASLEEP) {
                mActualPowerState = POWER_STATE_ASLEEP;
                mPendingGoToSleepBroadcast = true;
                if (mUserActivityPending) {
                    mUserActivityPending = false;
                    mHandler.removeMessages(MSG_USER_ACTIVITY);
@@ -300,7 +309,8 @@ final class Notifier {
    private void updatePendingBroadcastLocked() {
        if (!mBroadcastInProgress
                && mActualPowerState != POWER_STATE_UNKNOWN
                && mActualPowerState != mBroadcastedPowerState) {
                && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mActualPowerState != mBroadcastedPowerState)) {
            mBroadcastInProgress = true;
            mSuspendBlocker.acquire();
            Message msg = mHandler.obtainMessage(MSG_BROADCAST);
@@ -309,6 +319,11 @@ final class Notifier {
        }
    }

    private void finishPendingBroadcastLocked() {
        mBroadcastInProgress = false;
        mSuspendBlocker.release();
    }

    private void sendUserActivity() {
        synchronized (mLock) {
            if (!mUserActivityPending) {
@@ -324,18 +339,35 @@ final class Notifier {
        final int powerState;
        final int goToSleepReason;
        synchronized (mLock) {
            if (mActualPowerState == POWER_STATE_UNKNOWN
                    || mActualPowerState == mBroadcastedPowerState) {
                mBroadcastInProgress = false;
                mSuspendBlocker.release();
            if (mBroadcastedPowerState == POWER_STATE_UNKNOWN) {
                // Broadcasted power state is unknown.  Send wake up.
                mPendingWakeUpBroadcast = false;
                mBroadcastedPowerState = POWER_STATE_AWAKE;
            } else if (mBroadcastedPowerState == POWER_STATE_AWAKE) {
                // Broadcasted power state is awake.  Send asleep if needed.
                if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mActualPowerState == POWER_STATE_ASLEEP) {
                    mPendingGoToSleepBroadcast = false;
                    mBroadcastedPowerState = POWER_STATE_ASLEEP;
                } else {
                    finishPendingBroadcastLocked();
                    return;
                }
            } else {
                // Broadcasted power state is asleep.  Send awake if needed.
                if (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
                        || mActualPowerState == POWER_STATE_AWAKE) {
                    mPendingWakeUpBroadcast = false;
                    mBroadcastedPowerState = POWER_STATE_AWAKE;
                } else {
                    finishPendingBroadcastLocked();
                    return;
                }
            }

            powerState = mActualPowerState;
            goToSleepReason = mLastGoToSleepReason;

            mBroadcastedPowerState = powerState;
            mBroadcastStartTime = SystemClock.uptimeMillis();
            powerState = mBroadcastedPowerState;
            goToSleepReason = mLastGoToSleepReason;
        }

        EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
+15 −14
Original line number Diff line number Diff line
@@ -828,9 +828,9 @@ public final class PowerManagerService extends IPowerManager.Stub
        switch (mWakefulness) {
            case WAKEFULNESS_ASLEEP:
                Slog.i(TAG, "Waking up from sleep...");
                sendPendingNotificationsLocked();
                mNotifier.onWakeUpStarted();
                mSendWakeUpFinishedNotificationWhenReady = true;
                mSendGoToSleepFinishedNotificationWhenReady = false;
                break;
            case WAKEFULNESS_DREAMING:
                Slog.i(TAG, "Waking up from dream...");
@@ -901,12 +901,13 @@ public final class PowerManagerService extends IPowerManager.Stub
                break;
        }

        sendPendingNotificationsLocked();
        mNotifier.onGoToSleepStarted(reason);
        mSendGoToSleepFinishedNotificationWhenReady = true;

        mLastSleepTime = eventTime;
        mDirty |= DIRTY_WAKEFULNESS;
        mWakefulness = WAKEFULNESS_ASLEEP;
        mNotifier.onGoToSleepStarted(reason);
        mSendGoToSleepFinishedNotificationWhenReady = true;
        mSendWakeUpFinishedNotificationWhenReady = false;

        // Report the number of wake locks that will be cleared by going to sleep.
        int numWakeLocksCleared = 0;
@@ -1005,7 +1006,9 @@ public final class PowerManagerService extends IPowerManager.Stub
        updateDisplayPowerStateLocked(dirtyPhase2);

        // Phase 3: Send notifications, if needed.
        if (mDisplayReady) {
            sendPendingNotificationsLocked();
        }

        // Phase 4: Update suspend blocker.
        // Because we might release the last suspend blocker here, we need to make sure
@@ -1014,7 +1017,6 @@ public final class PowerManagerService extends IPowerManager.Stub
    }

    private void sendPendingNotificationsLocked() {
        if (mDisplayReady) {
        if (mSendWakeUpFinishedNotificationWhenReady) {
            mSendWakeUpFinishedNotificationWhenReady = false;
            mNotifier.onWakeUpFinished();
@@ -1024,7 +1026,6 @@ public final class PowerManagerService extends IPowerManager.Stub
            mNotifier.onGoToSleepFinished();
        }
    }
    }

    /**
     * Updates the value of mIsPowered.