Skip to content

Commit 3326459

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Fix issue #4279860: previous UI flashes before showing lock screen..."
2 parents a8120ea + 29aae6f commit 3326459

File tree

11 files changed

+328
-120
lines changed

11 files changed

+328
-120
lines changed

core/java/android/view/IWindowManager.aidl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,9 @@ interface IWindowManager
218218
* Called by the settings application to temporarily set the pointer speed.
219219
*/
220220
void setPointerSpeed(int speed);
221+
222+
/**
223+
* Block until all windows the window manager knows about have been drawn.
224+
*/
225+
void waitForAllDrawn();
221226
}

core/java/android/view/WindowManager.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ public static class LayoutParams extends ViewGroup.LayoutParams
177177
@ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"),
178178
@ViewDebug.IntToString(from = TYPE_INPUT_METHOD, to = "TYPE_INPUT_METHOD"),
179179
@ViewDebug.IntToString(from = TYPE_INPUT_METHOD_DIALOG, to = "TYPE_INPUT_METHOD_DIALOG"),
180-
@ViewDebug.IntToString(from = TYPE_SECURE_SYSTEM_OVERLAY, to = "TYPE_SECURE_SYSTEM_OVERLAY")
180+
@ViewDebug.IntToString(from = TYPE_SECURE_SYSTEM_OVERLAY, to = "TYPE_SECURE_SYSTEM_OVERLAY"),
181+
@ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS")
181182
})
182183
public int type;
183184

@@ -400,6 +401,13 @@ public static class LayoutParams extends ViewGroup.LayoutParams
400401
*/
401402
public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;
402403

404+
/**
405+
* Window type: The boot progress dialog, goes on top of everything
406+
* in the world.
407+
* @hide
408+
*/
409+
public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;
410+
403411
/**
404412
* End of types of system windows.
405413
*/

core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
public class TargetDrawable {
2727
private static final String TAG = "TargetDrawable";
28+
private static final boolean DEBUG = false;
29+
2830
public static final int[] STATE_ACTIVE =
2931
{ android.R.attr.state_enabled, android.R.attr.state_active };
3032
public static final int[] STATE_INACTIVE =
@@ -139,11 +141,13 @@ private void resizeDrawables() {
139141
maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
140142
maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
141143
}
142-
Log.v(TAG, "union of childDrawable rects " + d + " to: " + maxWidth + "x" + maxHeight);
144+
if (DEBUG) Log.v(TAG, "union of childDrawable rects " + d + " to: "
145+
+ maxWidth + "x" + maxHeight);
143146
d.setBounds(0, 0, maxWidth, maxHeight);
144147
for (int i = 0; i < d.getStateCount(); i++) {
145148
Drawable childDrawable = d.getStateDrawable(i);
146-
Log.v(TAG, "sizing drawable " + childDrawable + " to: " + maxWidth + "x" + maxHeight);
149+
if (DEBUG) Log.v(TAG, "sizing drawable " + childDrawable + " to: "
150+
+ maxWidth + "x" + maxHeight);
147151
childDrawable.setBounds(0, 0, maxWidth, maxHeight);
148152
}
149153
} else if (mDrawable != null) {

policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
*
4444
*/
4545
class KeyguardStatusViewManager implements OnClickListener {
46-
private static final boolean DEBUG = true;
46+
private static final boolean DEBUG = false;
4747
private static final String TAG = "KeyguardStatusView";
4848

4949
public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;

policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java

Lines changed: 137 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)