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

Commit 983ee099 authored by Mike Lockwood's avatar Mike Lockwood
Browse files

Fix deadlock in WindowManagerService.reenableKeyguard()



If reenableKeyguard() is called before the previous disableKeyguard() call is processed,
then TokenWatcher.sendNotificationLocked() will cancel the request, resulting in neither
the TokenWatcher acquired() or released() methods being called.
In that case, reenableKeyguard() will hang waiting for released() to set
mWaitingUntilKeyguardReenabled to false.  Now we only wait in reenableKeyguard()
if the TokenWatcher acquired() method is called and the keyguard has actually been disabled.

This should fix bug b/2270192

Change-Id: Id886fb28df607dbb4543124f2db6997121d6a682
Signed-off-by: default avatarMike Lockwood <lockwood@android.com>
parent e7800946
Loading
Loading
Loading
Loading
+25 −19
Original line number Diff line number Diff line
@@ -224,20 +224,22 @@ public class WindowManagerService extends IWindowManager.Stub
    /**
     * Condition waited on by {@link #reenableKeyguard} to know the call to
     * the window policy has finished.
     * This is set to true only if mKeyguardTokenWatcher.acquired() has
     * actually disabled the keyguard.
     */
    private boolean mWaitingUntilKeyguardReenabled = false;
    private boolean mKeyguardDisabled = false;


    final TokenWatcher mKeyguardDisabled = new TokenWatcher(
            new Handler(), "WindowManagerService.mKeyguardDisabled") {
    final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
            new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
        public void acquired() {
            mPolicy.enableKeyguard(false);
            mKeyguardDisabled = true;
        }
        public void released() {
            mPolicy.enableKeyguard(true);
            synchronized (mKeyguardDisabled) {
                mWaitingUntilKeyguardReenabled = false;
                mKeyguardDisabled.notifyAll();
            synchronized (mKeyguardTokenWatcher) {
                mKeyguardDisabled = false;
                mKeyguardTokenWatcher.notifyAll();
            }
        }
    };
@@ -4040,8 +4042,8 @@ public class WindowManagerService extends IWindowManager.Stub
            != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
        }
        synchronized (mKeyguardDisabled) {
            mKeyguardDisabled.acquire(token, tag);
        synchronized (mKeyguardTokenWatcher) {
            mKeyguardTokenWatcher.acquire(token, tag);
        }
    }

@@ -4050,16 +4052,20 @@ public class WindowManagerService extends IWindowManager.Stub
            != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
        }
        synchronized (mKeyguardDisabled) {
            mKeyguardDisabled.release(token);

            if (!mKeyguardDisabled.isAcquired()) {
                // if we are the last one to reenable the keyguard wait until
                // we have actaully finished reenabling until returning
                mWaitingUntilKeyguardReenabled = true;
                while (mWaitingUntilKeyguardReenabled) {
        synchronized (mKeyguardTokenWatcher) {
            mKeyguardTokenWatcher.release(token);

            if (!mKeyguardTokenWatcher.isAcquired()) {
                // If we are the last one to reenable the keyguard wait until
                // we have actaully finished reenabling until returning.
                // It is possible that reenableKeyguard() can be called before
                // the previous disableKeyguard() is handled, in which case
                // neither mKeyguardTokenWatcher.acquired() or released() would
                // be called.  In that case mKeyguardDisabled will be false here
                // and we have nothing to wait for.
                while (mKeyguardDisabled) {
                    try {
                        mKeyguardDisabled.wait();
                        mKeyguardTokenWatcher.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
@@ -10863,7 +10869,7 @@ public class WindowManagerService extends IWindowManager.Stub

    public void monitor() {
        synchronized (mWindowMap) { }
        synchronized (mKeyguardDisabled) { }
        synchronized (mKeyguardTokenWatcher) { }
        synchronized (mKeyWaiter) { }
    }