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

Commit 32b90fc3 authored by Scott Mertz's avatar Scott Mertz Committed by Gerrit Code Review
Browse files

Acquire wakelock until dream service acknowledges dream state change

Fixes a bug where the system can enter suspend before the dream service
can handle the state change.  This manifests in the DozeService failing
to enable the sensors used to determine if it should pulse the screen
by the time the system goes into full suspend.

This doesn't completely address the asynchronous nature of the
DreamManagerService startDream method.  There's still 2 more asynchronous
calls before the ACTION_DREAMING_STARTED is sent out, but testing shows
this is 'good enough'.

OPO-681
Change-Id: Id6ddc33bc367c1a0182df95374817577006a5b98
parent c8bbaca3
Loading
Loading
Loading
Loading
+55 −5
Original line number Original line Diff line number Diff line
@@ -112,6 +112,8 @@ public final class PowerManagerService extends SystemService
    private static final int MSG_SANDMAN = 2;
    private static final int MSG_SANDMAN = 2;
    // Message: Sent when the screen brightness boost expires.
    // Message: Sent when the screen brightness boost expires.
    private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
    private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
    // Message: Sent when the sandman fails to acknowledge the dream state change.
    private static final int MSG_SANDMAN_TIMEOUT = 4;


    private static final int MSG_WAKE_UP = 5;
    private static final int MSG_WAKE_UP = 5;


@@ -139,6 +141,8 @@ public final class PowerManagerService extends SystemService
    private static final int DIRTY_DOCK_STATE = 1 << 10;
    private static final int DIRTY_DOCK_STATE = 1 << 10;
    // Dirty bit: brightness boost changed
    // Dirty bit: brightness boost changed
    private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
    private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
    // Dirty bit: sandman state changed
    private static final int DIRTY_SANDMAN_STATE = 1 << 12;


    // Summarizes the state of all active wakelocks.
    // Summarizes the state of all active wakelocks.
    private static final int WAKE_LOCK_CPU = 1 << 0;
    private static final int WAKE_LOCK_CPU = 1 << 0;
@@ -183,6 +187,9 @@ public final class PowerManagerService extends SystemService
    // Max time (microseconds) to allow a CPU boost for
    // Max time (microseconds) to allow a CPU boost for
    private static final int MAX_CPU_BOOST_TIME = 5000000;
    private static final int MAX_CPU_BOOST_TIME = 5000000;


    // Max time (milliseconds) to wait for the sandman to acknowledge dream state changes
    private static final int SANDMAN_RESPONSE_TIMEOUT = 2 * 1000;

    private final Context mContext;
    private final Context mContext;
    private final ServiceThread mHandlerThread;
    private final ServiceThread mHandlerThread;
    private final PowerManagerHandler mHandler;
    private final PowerManagerHandler mHandler;
@@ -282,6 +289,13 @@ public final class PowerManagerService extends SystemService
    // True if the display suspend blocker has been acquired.
    // True if the display suspend blocker has been acquired.
    private boolean mHoldingDisplaySuspendBlocker;
    private boolean mHoldingDisplaySuspendBlocker;


    // The suspend blocker used to keep the CPU alive when dreams are requesting to be
    // started.
    private final SuspendBlocker mDreamSuspendBlocker;

    // True if the dream suspend blocker has been acquired.
    private boolean mHoldingDreamSuspendBlocker;

    // True if systemReady() has been called.
    // True if systemReady() has been called.
    private boolean mSystemReady;
    private boolean mSystemReady;


@@ -543,6 +557,7 @@ public final class PowerManagerService extends SystemService
        synchronized (mLock) {
        synchronized (mLock) {
            mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
            mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
            mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
            mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
            mDreamSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Dreams");
            mDisplaySuspendBlocker.acquire();
            mDisplaySuspendBlocker.acquire();
            mHoldingDisplaySuspendBlocker = true;
            mHoldingDisplaySuspendBlocker = true;
            mHalAutoSuspendModeEnabled = false;
            mHalAutoSuspendModeEnabled = false;
@@ -1927,15 +1942,16 @@ public final class PowerManagerService extends SystemService
                | DIRTY_PROXIMITY_POSITIVE
                | DIRTY_PROXIMITY_POSITIVE
                | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
                | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
            if (mDisplayReady) {
            if (mDisplayReady) {
                scheduleSandmanLocked();
                scheduleSandmanLocked(false);
            }
            }
        }
        }
    }
    }


    private void scheduleSandmanLocked() {
    private void scheduleSandmanLocked(boolean fromDreamService) {
        if (!mSandmanScheduled) {
        if (!mSandmanScheduled) {
            mSandmanScheduled = true;
            mSandmanScheduled = true;
            Message msg = mHandler.obtainMessage(MSG_SANDMAN);
            Message msg = mHandler.obtainMessage(MSG_SANDMAN);
            msg.arg1 = fromDreamService ? 1 : 0;
            msg.setAsynchronous(true);
            msg.setAsynchronous(true);
            mHandler.sendMessage(msg);
            mHandler.sendMessage(msg);
        }
        }
@@ -1948,7 +1964,7 @@ public final class PowerManagerService extends SystemService
     * the dream and we don't want to hold our lock while doing so.  There is a risk that
     * the dream and we don't want to hold our lock while doing so.  There is a risk that
     * the device will wake or go to sleep in the meantime so we have to handle that case.
     * the device will wake or go to sleep in the meantime so we have to handle that case.
     */
     */
    private void handleSandman() { // runs on handler thread
    private void handleSandman(boolean fromDreamService) { // runs on handler thread
        // Handle preconditions.
        // Handle preconditions.
        final boolean startDreaming;
        final boolean startDreaming;
        final int wakefulness;
        final int wakefulness;
@@ -1961,6 +1977,30 @@ public final class PowerManagerService extends SystemService
            } else {
            } else {
                startDreaming = false;
                startDreaming = false;
            }
            }
            // We hold the display suspend blocker as long as mSandmanSummoned is true
            // That guarantees this code to be run before the system enters suspend.  However,
            // once we exit this lock, we are no longer guaranteed to stay awake.  Hold a wake
            // lock that is released once the dream service has acknowledged the request
            // to start.
            if (mDreamManager != null) {
                if (startDreaming) {
                    if (!mHoldingDreamSuspendBlocker) {
                        mDreamSuspendBlocker.acquire();
                        mHoldingDreamSuspendBlocker = true;
                        Message msg = mHandler.obtainMessage(MSG_SANDMAN_TIMEOUT);
                        msg.setAsynchronous(true);
                        mHandler.sendMessageDelayed(msg, SANDMAN_RESPONSE_TIMEOUT);
                        mDirty |= DIRTY_SANDMAN_STATE;
                        updatePowerStateLocked();
                    }
                } else if (fromDreamService) {
                    mHandler.removeMessages(MSG_SANDMAN_TIMEOUT);
                    if (mHoldingDreamSuspendBlocker) {
                        mDreamSuspendBlocker.release();
                        mHoldingDreamSuspendBlocker = false;
                    }
                }
            }
        }
        }


        // Start dreaming if needed.
        // Start dreaming if needed.
@@ -2390,6 +2430,11 @@ public final class PowerManagerService extends SystemService
        if (mScreenBrightnessBoostInProgress) {
        if (mScreenBrightnessBoostInProgress) {
            return true;
            return true;
        }
        }

        if (mSandmanSummoned) {
            return true;
        }

        // Let the system suspend if the screen is off or dozing.
        // Let the system suspend if the screen is off or dozing.
        return false;
        return false;
    }
    }
@@ -2985,7 +3030,7 @@ public final class PowerManagerService extends SystemService
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
            synchronized (mLock) {
            synchronized (mLock) {
                scheduleSandmanLocked();
                scheduleSandmanLocked(true);
            }
            }
        }
        }
    }
    }
@@ -3042,7 +3087,8 @@ public final class PowerManagerService extends SystemService
                    handleUserActivityTimeout();
                    handleUserActivityTimeout();
                    break;
                    break;
                case MSG_SANDMAN:
                case MSG_SANDMAN:
                    handleSandman();
                    boolean fromDreamService = msg.arg1 == 1;
                    handleSandman(fromDreamService);
                    break;
                    break;
                case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
                case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
                    handleScreenBrightnessBoostTimeout();
                    handleScreenBrightnessBoostTimeout();
@@ -3051,6 +3097,10 @@ public final class PowerManagerService extends SystemService
                    cleanupProximity();
                    cleanupProximity();
                    ((Runnable) msg.obj).run();
                    ((Runnable) msg.obj).run();
                    break;
                    break;
                case MSG_SANDMAN_TIMEOUT:
                    Slog.w(TAG, "Sandman unresponsive, releasing suspend blocker");
                    handleSandman(true);
                    break;
            }
            }
        }
        }
    }
    }