Cleanup Keyguard handling when turning off screen

Before, Keyguard was shown whenever PhoneWindowManager went to sleep.
However, this was too early on some devices, and too late on others.
Now, the callbacks are split up into two phases: startedGoingToSleep
and finishedGoingToSleep. In the first callback, we decide what to
do and play the lock sound if necessary. In the second callback, we
actually show the Keyguard, or reset its state necessary, so it
doesn't interfere with the screen off animation.

Bug: 17929748
Bug: 20782303
Change-Id: I4c4406595b07b7589d64f380cd3fa96bed3d20ee
This commit is contained in:
Jorim Jaggi
2015-05-27 15:39:09 -07:00
parent cb81d18367
commit d175b6cfe0
6 changed files with 121 additions and 68 deletions

View File

@@ -22,6 +22,7 @@ import com.android.internal.policy.IKeyguardExitCallback;
import android.os.Bundle;
oneway interface IKeyguardService {
/**
* Sets the Keyguard as occluded when a window dismisses the Keyguard with flag
* FLAG_SHOW_ON_LOCK_SCREEN.
@@ -36,8 +37,27 @@ oneway interface IKeyguardService {
void dismiss();
void onDreamingStarted();
void onDreamingStopped();
void onScreenTurnedOff(int reason);
void onScreenTurnedOn(IKeyguardShowCallback callback);
/**
* 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}.
*/
void onStartedGoingToSleep(int reason);
/**
* Called when the device has finished going to sleep.
*
* @param why {@link #OFF_BECAUSE_OF_USER}, {@link #OFF_BECAUSE_OF_ADMIN},
* or {@link #OFF_BECAUSE_OF_TIMEOUT}.
*/
void onFinishedGoingToSleep(int reason);
/**
* Called when the device has started waking up.
*/
void onStartedWakingUp(IKeyguardShowCallback callback);
void setKeyguardEnabled(boolean enabled);
void onSystemReady();
void doKeyguardTimeout(in Bundle options);

View File

@@ -108,15 +108,21 @@ public class KeyguardService extends Service {
}
@Override // Binder interface
public void onScreenTurnedOff(int reason) {
public void onStartedGoingToSleep(int reason) {
checkPermission();
mKeyguardViewMediator.onScreenTurnedOff(reason);
mKeyguardViewMediator.onStartedGoingToSleep(reason);
}
@Override // Binder interface
public void onScreenTurnedOn(IKeyguardShowCallback callback) {
public void onFinishedGoingToSleep(int reason) {
checkPermission();
mKeyguardViewMediator.onScreenTurnedOn(callback);
mKeyguardViewMediator.onFinishedGoingToSleep(reason);
}
@Override // Binder interface
public void onStartedWakingUp(IKeyguardShowCallback callback) {
checkPermission();
mKeyguardViewMediator.onStartedWakingUp(callback);
}
@Override // Binder interface

View File

@@ -188,11 +188,6 @@ public class KeyguardViewMediator extends SystemUI {
private boolean mBootCompleted;
private boolean mBootSendUserPresent;
// Whether the next call to playSounds() should be skipped. Defaults to
// true because the first lock (on boot) should be silent.
private boolean mSuppressNextLockSound = true;
/** High level access to the power manager for WakeLocks */
private PowerManager mPM;
@@ -255,7 +250,7 @@ public class KeyguardViewMediator extends SystemUI {
private KeyguardUpdateMonitor mUpdateMonitor;
private boolean mScreenOn;
private boolean mDeviceInteractive;
// last known state of the cellular connection
private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
@@ -306,6 +301,18 @@ public class KeyguardViewMediator extends SystemUI {
private final ArrayList<IKeyguardStateCallback> mKeyguardStateCallbacks = new ArrayList<>();
/**
* When starting going to sleep, we figured out that we need to reset Keyguard state and this
* should be committed when finished going to sleep.
*/
private boolean mPendingReset;
/**
* When starting goign to sleep, we figured out that we need to lock Keyguard and this should be
* committed when finished going to sleep.
*/
private boolean mPendingLock;
KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -341,7 +348,7 @@ public class KeyguardViewMediator extends SystemUI {
public void onPhoneStateChanged(int phoneState) {
synchronized (KeyguardViewMediator.this) {
if (TelephonyManager.CALL_STATE_IDLE == phoneState // call ending
&& !mScreenOn // screen off
&& !mDeviceInteractive // screen off
&& mExternallyEnabled) { // not disabled by any app
// note: this is a way to gracefully reenable the keyguard when the call
@@ -514,7 +521,7 @@ public class KeyguardViewMediator extends SystemUI {
@Override
public boolean isScreenOn() {
return mScreenOn;
return mDeviceInteractive;
}
};
@@ -550,7 +557,7 @@ public class KeyguardViewMediator extends SystemUI {
mViewMediatorCallback, mLockPatternUtils);
final ContentResolver cr = mContext.getContentResolver();
mScreenOn = mPM.isScreenOn();
mDeviceInteractive = mPM.isInteractive();
mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);
@@ -613,23 +620,18 @@ public class KeyguardViewMediator extends SystemUI {
* @param why either {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_USER} or
* {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT}.
*/
public void onScreenTurnedOff(int why) {
public void onStartedGoingToSleep(int why) {
if (DEBUG) Log.d(TAG, "onStartedGoingToSleep(" + why + ")");
synchronized (this) {
mScreenOn = false;
if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")");
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
mDeviceInteractive = false;
// Lock immediately based on setting if secure (user has a pin/pattern/password).
// This also "locks" the device when not secure to provide easy access to the
// camera while preventing unwanted input.
int currentUser = KeyguardUpdateMonitor.getCurrentUser();
final boolean lockImmediately =
mLockPatternUtils.getPowerButtonInstantlyLocks(currentUser)
|| !mLockPatternUtils.isSecure(currentUser);
notifyScreenOffLocked();
mLockPatternUtils.getPowerButtonInstantlyLocks(currentUser)
|| !mLockPatternUtils.isSecure(currentUser);
if (mExitSecureCallback != null) {
if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
@@ -643,12 +645,37 @@ public class KeyguardViewMediator extends SystemUI {
hideLocked();
}
} else if (mShowing) {
resetStateLocked();
mPendingReset = true;
} else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
|| (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
|| (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
doKeyguardLaterLocked();
} else {
} else if (!mLockPatternUtils.isLockScreenDisabled(currentUser)) {
mPendingLock = true;
}
if (mPendingLock || mPendingReset) {
playSounds(true);
}
}
}
public void onFinishedGoingToSleep(int why) {
if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + why + ")");
synchronized (this) {
mDeviceInteractive = false;
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
notifyScreenOffLocked();
if (mPendingReset) {
resetStateLocked();
mPendingReset = false;
}
if (mPendingLock) {
doKeyguardLocked(null);
mPendingLock = false;
}
}
KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurnedOff(why);
@@ -686,7 +713,6 @@ public class KeyguardViewMediator extends SystemUI {
if (timeout <= 0) {
// Lock now
mSuppressNextLockSound = true;
doKeyguardLocked(null);
} else {
// Lock in the future
@@ -706,13 +732,15 @@ public class KeyguardViewMediator extends SystemUI {
}
/**
* Let's us know the screen was turned on.
* Let's us know when the device is waking up.
*/
public void onScreenTurnedOn(IKeyguardShowCallback callback) {
public void onStartedWakingUp(IKeyguardShowCallback callback) {
// TODO: Rename all screen off/on references to interactive/sleeping
synchronized (this) {
mScreenOn = true;
mDeviceInteractive = true;
cancelDoKeyguardLaterLocked();
if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
if (DEBUG) Log.d(TAG, "onStartedWakingUp, seq = " + mDelayedShowingSequence);
if (callback != null) {
notifyScreenOnLocked(callback);
}
@@ -737,7 +765,8 @@ public class KeyguardViewMediator extends SystemUI {
*/
public void onDreamingStarted() {
synchronized (this) {
if (mScreenOn && mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
if (mDeviceInteractive
&& mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
doKeyguardLaterLocked();
}
}
@@ -748,7 +777,7 @@ public class KeyguardViewMediator extends SystemUI {
*/
public void onDreamingStopped() {
synchronized (this) {
if (mScreenOn) {
if (mDeviceInteractive) {
cancelDoKeyguardLaterLocked();
}
}
@@ -1100,8 +1129,6 @@ public class KeyguardViewMediator extends SystemUI {
+ sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
synchronized (KeyguardViewMediator.this) {
if (mDelayedShowingSequence == sequence) {
// Don't play lockscreen SFX if the screen went off due to timeout.
mSuppressNextLockSound = true;
doKeyguardLocked(null);
}
}
@@ -1252,13 +1279,6 @@ public class KeyguardViewMediator extends SystemUI {
}
private void playSounds(boolean locked) {
// User feedback for keyguard.
if (mSuppressNextLockSound) {
mSuppressNextLockSound = false;
return;
}
playSound(locked ? mLockSoundId : mUnlockSoundId);
}
@@ -1283,9 +1303,6 @@ public class KeyguardViewMediator extends SystemUI {
}
private void playTrustedSound() {
if (mSuppressNextLockSound) {
return;
}
playSound(mTrustedSoundId);
}
@@ -1318,9 +1335,6 @@ public class KeyguardViewMediator extends SystemUI {
adjustStatusBarLocked();
userActivity();
// Do this at the end to not slow down display of the keyguard.
playSounds(true);
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();

View File

@@ -5236,6 +5236,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void startedGoingToSleep(int why) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedGoingToSleep(why);
}
}
// Called on the PowerManager's Notifier thread.
@@ -5253,9 +5256,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateOrientationListenerLp();
updateLockScreenTimeout();
}
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onScreenTurnedOff(why);
mKeyguardDelegate.onFinishedGoingToSleep(why);
}
}
@@ -5283,7 +5285,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onScreenTurnedOn(mKeyguardDelegateCallback);
mKeyguardDelegate.onStartedWakingUp(mKeyguardDelegateCallback);
// ... eventually calls finishKeyguardDrawn
} else {
if (DEBUG_WAKEUP) Slog.d(TAG, "null mKeyguardDelegate: setting mKeyguardDrawComplete.");

View File

@@ -56,10 +56,8 @@ public class KeyguardServiceDelegate {
boolean systemIsReady;
boolean deviceHasKeyguard;
public boolean enabled;
public boolean dismissable;
public int offReason;
public int currentUser;
public boolean screenIsOn;
public boolean bootCompleted;
};
@@ -138,7 +136,7 @@ public class KeyguardServiceDelegate {
// If the system is ready, it means keyguard crashed and restarted.
mKeyguardService.onSystemReady();
// This is used to hide the scrim once keyguard displays.
mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(
mKeyguardService.onStartedWakingUp(new KeyguardShowDelegate(
mShowListenerWhenConnect));
mShowListenerWhenConnect = null;
}
@@ -218,10 +216,10 @@ public class KeyguardServiceDelegate {
mKeyguardState.dreaming = false;
}
public void onScreenTurnedOn(final ShowListener showListener) {
public void onStartedWakingUp(final ShowListener showListener) {
if (mKeyguardService != null) {
if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + showListener + ")");
mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(showListener));
mKeyguardService.onStartedWakingUp(new KeyguardShowDelegate(showListener));
} else {
// try again when we establish a connection
Slog.w(TAG, "onScreenTurnedOn(): no keyguard service!");
@@ -230,15 +228,19 @@ public class KeyguardServiceDelegate {
mShowListenerWhenConnect = showListener;
showScrim();
}
mKeyguardState.screenIsOn = true;
}
public void onScreenTurnedOff(int why) {
public void onStartedGoingToSleep(int why) {
if (mKeyguardService != null) {
mKeyguardService.onScreenTurnedOff(why);
mKeyguardService.onStartedGoingToSleep(why);
}
mKeyguardState.offReason = why;
mKeyguardState.screenIsOn = false;
}
public void onFinishedGoingToSleep(int why) {
if (mKeyguardService != null) {
mKeyguardService.onFinishedGoingToSleep(why);
}
}
public void setKeyguardEnabled(boolean enabled) {

View File

@@ -105,19 +105,28 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
@Override // Binder interface
public void onScreenTurnedOff(int reason) {
@Override
public void onStartedGoingToSleep(int reason) {
try {
mService.onScreenTurnedOff(reason);
mService.onStartedGoingToSleep(reason);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
@Override // Binder interface
public void onScreenTurnedOn(IKeyguardShowCallback result) {
@Override
public void onFinishedGoingToSleep(int reason) {
try {
mService.onScreenTurnedOn(result);
mService.onFinishedGoingToSleep(reason);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
@Override
public void onStartedWakingUp(IKeyguardShowCallback callback) {
try {
mService.onStartedWakingUp(callback);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}