@@ -116,6 +116,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
116116 private static final int KEYGUARD_DONE_AUTHENTICATING = 11 ;
117117 private static final int SET_HIDDEN = 12 ;
118118 private static final int KEYGUARD_TIMEOUT = 13 ;
119+ private static final int REPORT_SHOW_DONE = 14 ;
119120
120121 /**
121122 * The default amount of time we stay awake (used for all key input)
@@ -238,6 +239,8 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
238239
239240 private boolean mScreenOn = false ;
240241
242+ private boolean mShowPending = false ;
243+
241244 // last known state of the cellular connection
242245 private String mPhoneState = TelephonyManager .EXTRA_STATE_IDLE ;
243246
@@ -306,7 +309,7 @@ public void onSystemReady() {
306309 synchronized (this ) {
307310 if (DEBUG ) Log .d (TAG , "onSystemReady" );
308311 mSystemReady = true ;
309- doKeyguard ();
312+ doKeyguardLocked ();
310313 }
311314 }
312315
@@ -363,7 +366,7 @@ public void onScreenTurnedOff(int why) {
363366 if (timeout <= 0 ) {
364367 // Lock now
365368 mSuppressNextLockSound = true ;
366- doKeyguard ();
369+ doKeyguardLocked ();
367370 } else {
368371 // Lock in the future
369372 long when = SystemClock .elapsedRealtime () + timeout ;
@@ -379,7 +382,19 @@ public void onScreenTurnedOff(int why) {
379382 } else if (why == WindowManagerPolicy .OFF_BECAUSE_OF_PROX_SENSOR ) {
380383 // Do not enable the keyguard if the prox sensor forced the screen off.
381384 } else {
382- doKeyguard ();
385+ if (!doKeyguardLocked () && why == WindowManagerPolicy .OFF_BECAUSE_OF_USER ) {
386+ // The user has explicitly turned off the screen, causing it
387+ // to lock. We want to block here until the keyguard window
388+ // has shown, so the power manager won't complete the screen
389+ // off flow until that point, so we know it won't turn *on*
390+ // the screen until this is done.
391+ while (mShowPending ) {
392+ try {
393+ wait ();
394+ } catch (InterruptedException e ) {
395+ }
396+ }
397+ }
383398 }
384399 }
385400 }
@@ -553,56 +568,58 @@ public boolean doLidChangeTq(boolean isLidOpen) {
553568 }
554569
555570 /**
556- * Enable the keyguard if the settings are appropriate.
571+ * Enable the keyguard if the settings are appropriate. Return true if all
572+ * work that will happen is done; returns false if the caller can wait for
573+ * the keyguard to be shown.
557574 */
558- private void doKeyguard () {
559- synchronized (this ) {
560- // if another app is disabling us, don't show
561- if (!mExternallyEnabled ) {
562- if (DEBUG ) Log .d (TAG , "doKeyguard: not showing because externally disabled" );
563-
564- // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
565- // for an occasional ugly flicker in this situation:
566- // 1) receive a call with the screen on (no keyguard) or make a call
567- // 2) screen times out
568- // 3) user hits key to turn screen back on
569- // instead, we reenable the keyguard when we know the screen is off and the call
570- // ends (see the broadcast receiver below)
571- // TODO: clean this up when we have better support at the window manager level
572- // for apps that wish to be on top of the keyguard
573- return ;
574- }
575-
576- // if the keyguard is already showing, don't bother
577- if (mKeyguardViewManager .isShowing ()) {
578- if (DEBUG ) Log .d (TAG , "doKeyguard: not showing because it is already showing" );
579- return ;
580- }
575+ private boolean doKeyguardLocked () {
576+ // if another app is disabling us, don't show
577+ if (!mExternallyEnabled ) {
578+ if (DEBUG ) Log .d (TAG , "doKeyguard: not showing because externally disabled" );
579+
580+ // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
581+ // for an occasional ugly flicker in this situation:
582+ // 1) receive a call with the screen on (no keyguard) or make a call
583+ // 2) screen times out
584+ // 3) user hits key to turn screen back on
585+ // instead, we reenable the keyguard when we know the screen is off and the call
586+ // ends (see the broadcast receiver below)
587+ // TODO: clean this up when we have better support at the window manager level
588+ // for apps that wish to be on top of the keyguard
589+ return true ;
590+ }
581591
582- // if the setup wizard hasn't run yet, don't show
583- final boolean requireSim = !SystemProperties .getBoolean ("keyguard.no_require_sim" ,
584- false );
585- final boolean provisioned = mUpdateMonitor .isDeviceProvisioned ();
586- final IccCard .State state = mUpdateMonitor .getSimState ();
587- final boolean lockedOrMissing = state .isPinLocked ()
588- || ((state == IccCard .State .ABSENT
589- || state == IccCard .State .PERM_DISABLED )
590- && requireSim );
591-
592- if (!lockedOrMissing && !provisioned ) {
593- if (DEBUG ) Log .d (TAG , "doKeyguard: not showing because device isn't provisioned"
594- + " and the sim is not locked or missing" );
595- return ;
596- }
592+ // if the keyguard is already showing, don't bother
593+ if (mKeyguardViewManager .isShowing ()) {
594+ if (DEBUG ) Log .d (TAG , "doKeyguard: not showing because it is already showing" );
595+ return true ;
596+ }
597597
598- if (mLockPatternUtils .isLockScreenDisabled ()) {
599- if (DEBUG ) Log .d (TAG , "doKeyguard: not showing because lockscreen is off" );
600- return ;
601- }
598+ // if the setup wizard hasn't run yet, don't show
599+ final boolean requireSim = !SystemProperties .getBoolean ("keyguard.no_require_sim" ,
600+ false );
601+ final boolean provisioned = mUpdateMonitor .isDeviceProvisioned ();
602+ final IccCard .State state = mUpdateMonitor .getSimState ();
603+ final boolean lockedOrMissing = state .isPinLocked ()
604+ || ((state == IccCard .State .ABSENT
605+ || state == IccCard .State .PERM_DISABLED )
606+ && requireSim );
607+
608+ if (!lockedOrMissing && !provisioned ) {
609+ if (DEBUG ) Log .d (TAG , "doKeyguard: not showing because device isn't provisioned"
610+ + " and the sim is not locked or missing" );
611+ return true ;
612+ }
602613
603- if (DEBUG ) Log .d (TAG , "doKeyguard: showing the lock screen" );
604- showLocked ();
614+ if (mLockPatternUtils .isLockScreenDisabled ()) {
615+ if (DEBUG ) Log .d (TAG , "doKeyguard: not showing because lockscreen is off" );
616+ return true ;
605617 }
618+
619+ if (DEBUG ) Log .d (TAG , "doKeyguard: showing the lock screen" );
620+ mShowPending = true ;
621+ showLocked ();
622+ return false ;
606623 }
607624
608625 /**
@@ -696,41 +713,49 @@ public void onSimStateChanged(IccCard.State simState) {
696713 case ABSENT :
697714 // only force lock screen in case of missing sim if user hasn't
698715 // gone through setup wizard
699- if (!mUpdateMonitor .isDeviceProvisioned ()) {
700- if (!isShowing ()) {
701- if (DEBUG ) Log .d (TAG , "ICC_ABSENT isn't showing,"
702- + " we need to show the keyguard since the "
703- + "device isn't provisioned yet." );
704- doKeyguard ();
705- } else {
706- resetStateLocked ();
716+ synchronized (this ) {
717+ if (!mUpdateMonitor .isDeviceProvisioned ()) {
718+ if (!isShowing ()) {
719+ if (DEBUG ) Log .d (TAG , "ICC_ABSENT isn't showing,"
720+ + " we need to show the keyguard since the "
721+ + "device isn't provisioned yet." );
722+ doKeyguardLocked ();
723+ } else {
724+ resetStateLocked ();
725+ }
707726 }
708727 }
709728 break ;
710729 case PIN_REQUIRED :
711730 case PUK_REQUIRED :
712- if (!isShowing ()) {
713- if (DEBUG ) Log .d (TAG , "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, we need "
714- + "to show the keyguard so the user can enter their sim pin" );
715- doKeyguard ();
716- } else {
717- resetStateLocked ();
731+ synchronized (this ) {
732+ if (!isShowing ()) {
733+ if (DEBUG ) Log .d (TAG , "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, we need "
734+ + "to show the keyguard so the user can enter their sim pin" );
735+ doKeyguardLocked ();
736+ } else {
737+ resetStateLocked ();
738+ }
718739 }
719740 break ;
720741 case PERM_DISABLED :
721- if (!isShowing ()) {
722- if (DEBUG ) Log .d (TAG , "PERM_DISABLED and "
723- + "keygaurd isn't showing." );
724- doKeyguard ();
725- } else {
726- if (DEBUG ) Log .d (TAG , "PERM_DISABLED, resetStateLocked to"
727- + "show permanently disabled message in lockscreen." );
728- resetStateLocked ();
742+ synchronized (this ) {
743+ if (!isShowing ()) {
744+ if (DEBUG ) Log .d (TAG , "PERM_DISABLED and "
745+ + "keygaurd isn't showing." );
746+ doKeyguardLocked ();
747+ } else {
748+ if (DEBUG ) Log .d (TAG , "PERM_DISABLED, resetStateLocked to"
749+ + "show permanently disabled message in lockscreen." );
750+ resetStateLocked ();
751+ }
729752 }
730753 break ;
731754 case READY :
732- if (isShowing ()) {
733- resetStateLocked ();
755+ synchronized (this ) {
756+ if (isShowing ()) {
757+ resetStateLocked ();
758+ }
734759 }
735760 break ;
736761 }
@@ -751,27 +776,31 @@ public void onReceive(Context context, Intent intent) {
751776 if (DEBUG ) Log .d (TAG , "received DELAYED_KEYGUARD_ACTION with seq = "
752777 + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence );
753778
754- if (mDelayedShowingSequence == sequence ) {
755- // Don't play lockscreen SFX if the screen went off due to
756- // timeout.
757- mSuppressNextLockSound = true ;
758-
759- doKeyguard ();
779+ synchronized (KeyguardViewMediator .this ) {
780+ if (mDelayedShowingSequence == sequence ) {
781+ // Don't play lockscreen SFX if the screen went off due to
782+ // timeout.
783+ mSuppressNextLockSound = true ;
784+
785+ doKeyguardLocked ();
786+ }
760787 }
761788 } else if (TelephonyManager .ACTION_PHONE_STATE_CHANGED .equals (action )) {
762789 mPhoneState = intent .getStringExtra (TelephonyManager .EXTRA_STATE );
763790
764- if (TelephonyManager .EXTRA_STATE_IDLE .equals (mPhoneState ) // call ending
765- && !mScreenOn // screen off
766- && mExternallyEnabled ) { // not disabled by any app
767-
768- // note: this is a way to gracefully reenable the keyguard when the call
769- // ends and the screen is off without always reenabling the keyguard
770- // each time the screen turns off while in call (and having an occasional ugly
771- // flicker while turning back on the screen and disabling the keyguard again).
772- if (DEBUG ) Log .d (TAG , "screen is off and call ended, let's make sure the "
773- + "keyguard is showing" );
774- doKeyguard ();
791+ synchronized (KeyguardViewMediator .this ) {
792+ if (TelephonyManager .EXTRA_STATE_IDLE .equals (mPhoneState ) // call ending
793+ && !mScreenOn // screen off
794+ && mExternallyEnabled ) { // not disabled by any app
795+
796+ // note: this is a way to gracefully reenable the keyguard when the call
797+ // ends and the screen is off without always reenabling the keyguard
798+ // each time the screen turns off while in call (and having an occasional ugly
799+ // flicker while turning back on the screen and disabling the keyguard again).
800+ if (DEBUG ) Log .d (TAG , "screen is off and call ended, let's make sure the "
801+ + "keyguard is showing" );
802+ doKeyguardLocked ();
803+ }
775804 }
776805 }
777806 }
@@ -962,7 +991,15 @@ public void handleMessage(Message msg) {
962991 handleSetHidden (msg .arg1 != 0 );
963992 break ;
964993 case KEYGUARD_TIMEOUT :
965- doKeyguard ();
994+ synchronized (KeyguardViewMediator .this ) {
995+ doKeyguardLocked ();
996+ }
997+ break ;
998+ case REPORT_SHOW_DONE :
999+ synchronized (KeyguardViewMediator .this ) {
1000+ mShowPending = false ;
1001+ KeyguardViewMediator .this .notifyAll ();
1002+ }
9661003 break ;
9671004 }
9681005 }
@@ -1062,8 +1099,6 @@ private void handleShow() {
10621099 if (DEBUG ) Log .d (TAG , "handleShow" );
10631100 if (!mSystemReady ) return ;
10641101
1065- playSounds (true );
1066-
10671102 mKeyguardViewManager .show ();
10681103 mShowing = true ;
10691104 adjustUserActivityLocked ();
@@ -1072,7 +1107,17 @@ private void handleShow() {
10721107 ActivityManagerNative .getDefault ().closeSystemDialogs ("lock" );
10731108 } catch (RemoteException e ) {
10741109 }
1110+
1111+ // Do this at the end to not slow down display of the keyguard.
1112+ playSounds (true );
1113+
10751114 mShowKeyguardWakeLock .release ();
1115+
1116+ // We won't say the show is done yet because the view hierarchy
1117+ // still needs to do the traversal. Posting this message allows
1118+ // us to hold off until that is done.
1119+ Message msg = mHandler .obtainMessage (REPORT_SHOW_DONE );
1120+ mHandler .sendMessage (msg );
10761121 }
10771122 }
10781123
0 commit comments