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

Commit f71c33a6 authored by Adrian Roos's avatar Adrian Roos Committed by android-build-merger
Browse files

Hold WakeLock while DreamService starts am: 7445c0bb

am: 5e18c826

Change-Id: I4c8d223c8968f554ceabd9dd80bb55e19a5b7e34
parents 7a2b8a93 5e18c826
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -1358,5 +1358,34 @@ public final class PowerManager {
                    + " held=" + mHeld + ", refCount=" + mCount + "}";
            }
        }

        /**
         * Wraps a Runnable such that this method immediately acquires the wake lock and then
         * once the Runnable is done the wake lock is released.
         *
         * <p>Example:
         *
         * <pre>
         * mHandler.post(mWakeLock.wrap(() -> {
         *     // do things on handler, lock is held while we're waiting for this
         *     // to get scheduled and until the runnable is done executing.
         * });
         * </pre>
         *
         * <p>Note: you must make sure that the Runnable eventually gets executed, otherwise you'll
         *    leak the wakelock!
         *
         * @hide
         */
        public Runnable wrap(Runnable r) {
            acquire();
            return () -> {
                try {
                    r.run();
                } finally {
                    release();
                }
            };
        }
    }
}
+92 −68
Original line number Diff line number Diff line
@@ -192,6 +192,9 @@ public class DreamService extends Service implements Window.Callback {

    private boolean mDebug = false;

    private PowerManager.WakeLock mWakeLock;
    private boolean mWakeLockAcquired;

    public DreamService() {
        mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
    }
@@ -786,6 +789,8 @@ public class DreamService extends Service implements Window.Callback {
    public void onCreate() {
        if (mDebug) Slog.v(TAG, "onCreate()");
        super.onCreate();
        mWakeLock = getSystemService(PowerManager.class)
                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DreamService");
    }

    /**
@@ -825,9 +830,21 @@ public class DreamService extends Service implements Window.Callback {
    @Override
    public final IBinder onBind(Intent intent) {
        if (mDebug) Slog.v(TAG, "onBind() intent = " + intent);

        // Need to stay awake until we dispatch onDreamingStarted. This is released either in
        // attach() or onDestroy().
        mWakeLock.acquire(5000);
        mWakeLockAcquired = true;
        return new DreamServiceWrapper();
    }

    private void releaseWakeLockIfNeeded() {
        if (mWakeLockAcquired) {
            mWakeLock.release();
            mWakeLockAcquired = false;
        }
    }

    /**
     * Stops the dream and detaches from the window.
     * <p>
@@ -904,6 +921,8 @@ public class DreamService extends Service implements Window.Callback {
        detach();

        super.onDestroy();

        releaseWakeLockIfNeeded(); // for acquire in onBind()
    }

    // end public api
@@ -944,6 +963,7 @@ public class DreamService extends Service implements Window.Callback {
     * @param windowToken A window token that will allow a window to be created in the correct layer.
     */
    private final void attach(IBinder windowToken, boolean canDoze) {
        try {
            if (mWindowToken != null) {
                Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken);
                return;
@@ -970,8 +990,10 @@ public class DreamService extends Service implements Window.Callback {
                mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
                mWindow.setFormat(PixelFormat.OPAQUE);

            if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
                if (mDebug) {
                    Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
                            windowToken, WindowManager.LayoutParams.TYPE_DREAM));
                }

                WindowManager.LayoutParams lp = mWindow.getAttributes();
                lp.type = WindowManager.LayoutParams.TYPE_DREAM;
@@ -1011,16 +1033,18 @@ public class DreamService extends Service implements Window.Callback {
            // which is posted to the handler by addView, so we post onDreamingStarted
            // to the handler also.  Need to watch out here in case detach occurs before
            // this callback is invoked.
        mHandler.post(new Runnable() {
            @Override
            public void run() {
            mHandler.post(mWakeLock.wrap(() -> {
                if (mWindow != null || mWindowless) {
                    if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
                    if (mDebug) {
                        Slog.v(TAG, "Calling onDreamingStarted()");
                    }
                    mStarted = true;
                    onDreamingStarted();
                }
            }));
        } finally {
            releaseWakeLockIfNeeded(); // for acquire in onBind
        }
        });
    }

    private boolean getWindowFlagValue(int flag, boolean defaultValue) {
+26 −7
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.IBinder.DeathRecipient;
import android.os.SystemClock;
@@ -116,19 +117,19 @@ final class DreamController {
    }

    public void startDream(Binder token, ComponentName name,
            boolean isTest, boolean canDoze, int userId) {
            boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
        stopDream(true /*immediate*/);

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream");
        try {
            // Close the notification shade. Don't need to send to all, but better to be explicit.
            // Close the notification shade. No need to send to all, but better to be explicit.
            mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);

            Slog.i(TAG, "Starting dream: name=" + name
                    + ", isTest=" + isTest + ", canDoze=" + canDoze
                    + ", userId=" + userId);

            mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId);
            mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId, wakeLock);

            mDreamStartTime = SystemClock.elapsedRealtime();
            MetricsLogger.visible(mContext,
@@ -230,6 +231,7 @@ final class DreamController {
            if (oldDream.mBound) {
                mContext.unbindService(oldDream);
            }
            oldDream.releaseWakeLockIfNeeded();

            try {
                mIWindowManager.removeWindowToken(oldDream.mToken);
@@ -280,6 +282,7 @@ final class DreamController {
        public final boolean mCanDoze;
        public final int mUserId;

        public PowerManager.WakeLock mWakeLock;
        public boolean mBound;
        public boolean mConnected;
        public IDreamService mService;
@@ -288,12 +291,17 @@ final class DreamController {
        public boolean mWakingGently;

        public DreamRecord(Binder token, ComponentName name,
                boolean isTest, boolean canDoze, int userId) {
                boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
            mToken = token;
            mName = name;
            mIsTest = isTest;
            mCanDoze = canDoze;
            mUserId  = userId;
            mWakeLock = wakeLock;
            // Hold the lock while we're waiting for the service to connect. Released either when
            // DreamService connects (and is then responsible for keeping the device awake) or
            // dreaming stops.
            mWakeLock.acquire();
        }

        // May be called on any thread.
@@ -316,14 +324,25 @@ final class DreamController {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        mConnected = true;
                        if (mCurrentDream == DreamRecord.this && mService == null) {
                            attach(IDreamService.Stub.asInterface(service));
                        }
                    } finally {
                        releaseWakeLockIfNeeded();
                    }
                }
            });
        }

        private void releaseWakeLockIfNeeded() {
            if (mWakeLock != null) {
                mWakeLock.release();
                mWakeLock = null;
            }
        }

        // May be called on any thread.
        @Override
        public void onServiceDisconnected(ComponentName name) {
+4 −6
Original line number Diff line number Diff line
@@ -370,12 +370,10 @@ public final class DreamManagerService extends SystemService {
        mCurrentDreamCanDoze = canDoze;
        mCurrentDreamUserId = userId;

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mController.startDream(newToken, name, isTest, canDoze, userId);
            }
        });
        PowerManager.WakeLock wakeLock = mPowerManager
                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
        mHandler.post(wakeLock.wrap(
                () -> mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock)));
    }

    private void stopDreamLocked(final boolean immediate) {