Skip to content

Commit 3f5f83b

Browse files
author
Jim Miller
committed
Fix 5326463: rework sim state handling in lockscreen
Previously it was possible to get an inconsistent state because there were two paths that updated the lock screen sim state. This reworks the data flow to ensure the same path is always used to update the state. KeyguardUpdateMonitor now correctly updates the entire state of the callee whenever a new callback is registered. In addition, KeyguardUpdateMonitor now caches the phone state in order to avoid a round-trip binder call in updateEmergencyCallButtonState(). This avoids a condition that could make lockscreen unresponsive while updating the emergency call button state. KeyguardStatusViewManager also ensures the TransportControlView is hidden when created to ensure we don't inappropriately update the carrier line while waiting for the first callbacks to update the status lines. Change-Id: I6b3975b703a7d90bac8d0fe29fbc0f1d9c5e0e7d
1 parent dd33bf0 commit 3f5f83b

4 files changed

Lines changed: 88 additions & 56 deletions

File tree

core/java/com/android/internal/widget/LockPatternUtils.java

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -936,20 +936,24 @@ public boolean isSecure() {
936936
*
937937
* If there's currently a call in progress, the button will take them to the call
938938
* @param button the button to update
939+
* @param the phone state:
940+
* {@link TelephonyManager#CALL_STATE_IDLE}
941+
* {@link TelephonyManager#CALL_STATE_RINGING}
942+
* {@link TelephonyManager#CALL_STATE_OFFHOOK}
939943
* @param showIfCapable indicates whether the button should be shown if emergency calls are
940944
* possible on the device
941945
*/
942-
public void updateEmergencyCallButtonState(Button button, boolean showIfCapable) {
946+
public void updateEmergencyCallButtonState(Button button, int phoneState,
947+
boolean showIfCapable) {
943948
if (isEmergencyCallCapable() && showIfCapable) {
944949
button.setVisibility(View.VISIBLE);
945950
} else {
946951
button.setVisibility(View.GONE);
947952
return;
948953
}
949954

950-
int newState = TelephonyManager.getDefault().getCallState();
951955
int textId;
952-
if (newState == TelephonyManager.CALL_STATE_OFFHOOK) {
956+
if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
953957
// show "return to call" text and show phone icon
954958
textId = R.string.lockscreen_return_to_call;
955959
int phoneCallIcon = R.drawable.stat_sys_phone_call;
@@ -979,22 +983,4 @@ public boolean resumeCall() {
979983
}
980984
return false;
981985
}
982-
983-
/**
984-
* Performs concentenation of PLMN/SPN
985-
* @param plmn
986-
* @param spn
987-
* @return
988-
*/
989-
public static CharSequence getCarrierString(CharSequence plmn, CharSequence spn) {
990-
if (plmn != null && spn == null) {
991-
return plmn;
992-
} else if (plmn != null && spn != null) {
993-
return plmn + "|" + spn;
994-
} else if (plmn == null && spn != null) {
995-
return spn;
996-
} else {
997-
return "";
998-
}
999-
}
1000986
}

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

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class KeyguardStatusViewManager implements OnClickListener {
5858
private static final int CARRIER_HELP_TEXT = 12;
5959
private static final int HELP_MESSAGE_TEXT = 13;
6060
private static final int OWNER_INFO = 14;
61+
private static final int BATTERY_INFO = 15;
6162

6263
private StatusMode mStatus;
6364
private String mDateFormatString;
@@ -84,6 +85,9 @@ class KeyguardStatusViewManager implements OnClickListener {
8485
// last known battery level
8586
private int mBatteryLevel = 100;
8687

88+
// last known SIM state
89+
protected State mSimState;
90+
8791
private LockPatternUtils mLockPatternUtils;
8892
private KeyguardUpdateMonitor mUpdateMonitor;
8993
private Button mEmergencyCallButton;
@@ -98,6 +102,8 @@ class KeyguardStatusViewManager implements OnClickListener {
98102
private boolean mShowingStatus;
99103
private KeyguardScreenCallback mCallback;
100104
private final boolean mShowEmergencyButtonByDefault;
105+
private CharSequence mPlmn;
106+
private CharSequence mSpn;
101107

102108
private class TransientTextManager {
103109
private TextView mTextView;
@@ -151,6 +157,7 @@ public void run() {
151157
public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
152158
LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,
153159
boolean showEmergencyButtonByDefault) {
160+
if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
154161
mContainer = view;
155162
mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
156163
mLockPatternUtils = lockPatternUtils;
@@ -165,6 +172,12 @@ public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
165172
mTransportView = (TransportControlView) findViewById(R.id.transport);
166173
mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
167174
mShowEmergencyButtonByDefault = showEmergencyButtonByDefault;
175+
176+
// Hide transport control view until we know we need to show it.
177+
if (mTransportView != null) {
178+
mTransportView.setVisibility(View.GONE);
179+
}
180+
168181
if (mEmergencyCallButton != null) {
169182
mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
170183
mEmergencyCallButton.setOnClickListener(this);
@@ -173,8 +186,6 @@ public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
173186

174187
mTransientTextManager = new TransientTextManager(mCarrierView);
175188

176-
updateEmergencyCallButtonState();
177-
178189
resetStatusInfo();
179190
refreshDate();
180191
updateOwnerInfo();
@@ -187,10 +198,6 @@ public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
187198
v.setSelected(true);
188199
}
189200
}
190-
191-
// until we get an update...
192-
setCarrierText(LockPatternUtils.getCarrierString(
193-
mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn()));
194201
}
195202

196203
private boolean inWidgetMode() {
@@ -248,6 +255,7 @@ private void update(int what, CharSequence string) {
248255
case INSTRUCTION_TEXT:
249256
case CARRIER_HELP_TEXT:
250257
case HELP_MESSAGE_TEXT:
258+
case BATTERY_INFO:
251259
mTransientTextManager.post(string, 0, INSTRUCTION_RESET_DELAY);
252260
break;
253261

@@ -262,15 +270,16 @@ private void update(int what, CharSequence string) {
262270
}
263271

264272
public void onPause() {
273+
if (DEBUG) Log.v(TAG, "onPause()");
265274
mUpdateMonitor.removeCallback(mInfoCallback);
266275
mUpdateMonitor.removeCallback(mSimStateCallback);
267276
}
268277

269278
/** {@inheritDoc} */
270279
public void onResume() {
280+
if (DEBUG) Log.v(TAG, "onResume()");
271281
mUpdateMonitor.registerInfoCallback(mInfoCallback);
272282
mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
273-
updateEmergencyCallButtonState();
274283
resetStatusInfo();
275284
}
276285

@@ -399,7 +408,12 @@ void refreshDate() {
399408
* Determine the current status of the lock screen given the sim state and other stuff.
400409
*/
401410
public StatusMode getStatusForIccState(IccCard.State simState) {
402-
boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
411+
// Since reading the SIM may take a while, we assume it is present until told otherwise.
412+
if (simState == null) {
413+
return StatusMode.Normal;
414+
}
415+
416+
final boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
403417
&& (simState == IccCard.State.ABSENT || simState == IccCard.State.PERM_DISABLED));
404418

405419
// Assume we're NETWORK_LOCKED if not provisioned
@@ -435,22 +449,21 @@ private Context getContext() {
435449
*
436450
* @param simState
437451
*/
438-
private void updateWithSimStatus(State simState) {
439-
// The emergency call button no longer appears on this screen.
440-
if (DEBUG) Log.d(TAG, "updateLayout: status=" + mStatus);
452+
private void updateCarrierTextWithSimStatus(State simState) {
453+
if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState);
441454

442455
CharSequence carrierText = null;
443456
int carrierHelpTextId = 0;
444457
mUnlockDisabledDueToSimState = false;
445458
mStatus = getStatusForIccState(simState);
459+
mSimState = simState;
446460
switch (mStatus) {
447461
case Normal:
448-
carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
449-
mUpdateMonitor.getTelephonySpn());
462+
carrierText = makeCarierString(mPlmn, mSpn);
450463
break;
451464

452465
case NetworkLocked:
453-
carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
466+
carrierText = makeCarierString(mPlmn,
454467
getContext().getText(R.string.lockscreen_network_locked_message));
455468
carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
456469
break;
@@ -467,19 +480,19 @@ private void updateWithSimStatus(State simState) {
467480
break;
468481

469482
case SimMissingLocked:
470-
carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
483+
carrierText = makeCarierString(mPlmn,
471484
getContext().getText(R.string.lockscreen_missing_sim_message_short));
472485
carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
473486
mUnlockDisabledDueToSimState = true;
474487
break;
475488

476489
case SimLocked:
477-
carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
490+
carrierText = makeCarierString(mPlmn,
478491
getContext().getText(R.string.lockscreen_sim_locked_message));
479492
break;
480493

481494
case SimPukLocked:
482-
carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
495+
carrierText = makeCarierString(mPlmn,
483496
getContext().getText(R.string.lockscreen_sim_puk_locked_message));
484497
if (!mLockPatternUtils.isPukUnlockScreenEnable()) {
485498
mUnlockDisabledDueToSimState = true;
@@ -489,7 +502,6 @@ private void updateWithSimStatus(State simState) {
489502

490503
setCarrierText(carrierText);
491504
setCarrierHelpText(carrierHelpTextId);
492-
updateEmergencyCallButtonState();
493505
}
494506

495507
private View findViewById(int id) {
@@ -552,10 +564,11 @@ public boolean shouldShowStatusLines() {
552564
}
553565
}
554566

555-
private void updateEmergencyCallButtonState() {
567+
private void updateEmergencyCallButtonState(int phoneState) {
556568
if (mEmergencyCallButton != null) {
557569
boolean showIfCapable = mShowEmergencyButtonByDefault || mUnlockDisabledDueToSimState;
558-
mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton, showIfCapable);
570+
mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
571+
phoneState, showIfCapable);
559572
}
560573
}
561574

@@ -567,23 +580,26 @@ public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
567580
mShowingBatteryInfo = showBatteryInfo;
568581
mPluggedIn = pluggedIn;
569582
mBatteryLevel = batteryLevel;
570-
updateStatusLines(true);
583+
final MutableInt tmpIcon = new MutableInt(0);
584+
update(BATTERY_INFO, getAltTextMessage(tmpIcon));
571585
}
572586

573587
public void onTimeChanged() {
574588
refreshDate();
575589
}
576590

577591
public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
578-
setCarrierText(LockPatternUtils.getCarrierString(plmn, spn));
592+
mPlmn = plmn;
593+
mSpn = spn;
594+
updateCarrierTextWithSimStatus(mSimState);
579595
}
580596

581597
public void onRingerModeChanged(int state) {
582598

583599
}
584600

585-
public void onPhoneStateChanged(String newState) {
586-
updateEmergencyCallButtonState();
601+
public void onPhoneStateChanged(int phoneState) {
602+
updateEmergencyCallButtonState(phoneState);
587603
}
588604

589605
/** {@inheritDoc} */
@@ -595,7 +611,7 @@ public void onClockVisibilityChanged() {
595611
private SimStateCallback mSimStateCallback = new SimStateCallback() {
596612

597613
public void onSimStateChanged(State simState) {
598-
updateWithSimStatus(simState);
614+
updateCarrierTextWithSimStatus(simState);
599615
}
600616
};
601617

@@ -604,4 +620,22 @@ public void onClick(View v) {
604620
mCallback.takeEmergencyCallAction();
605621
}
606622
}
623+
624+
/**
625+
* Performs concentenation of PLMN/SPN
626+
* @param plmn
627+
* @param spn
628+
* @return
629+
*/
630+
private static CharSequence makeCarierString(CharSequence plmn, CharSequence spn) {
631+
if (plmn != null && spn == null) {
632+
return plmn;
633+
} else if (plmn != null && spn != null) {
634+
return plmn + "|" + spn;
635+
} else if (plmn == null && spn != null) {
636+
return spn;
637+
} else {
638+
return "";
639+
}
640+
}
607641
}

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

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ public class KeyguardUpdateMonitor {
8888
private ArrayList<InfoCallback> mInfoCallbacks = Lists.newArrayList();
8989
private ArrayList<SimStateCallback> mSimStateCallbacks = Lists.newArrayList();
9090
private ContentObserver mContentObserver;
91+
private int mRingMode;
92+
private int mPhoneState;
9193

9294
// messages for the handler
9395
private static final int MSG_TIME_UPDATE = 301;
@@ -271,13 +273,21 @@ public void onReceive(Context context, Intent intent) {
271273

272274
protected void handlePhoneStateChanged(String newState) {
273275
if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
276+
if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
277+
mPhoneState = TelephonyManager.CALL_STATE_IDLE;
278+
} else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
279+
mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
280+
} else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
281+
mPhoneState = TelephonyManager.CALL_STATE_RINGING;
282+
}
274283
for (int i = 0; i < mInfoCallbacks.size(); i++) {
275-
mInfoCallbacks.get(i).onPhoneStateChanged(newState);
284+
mInfoCallbacks.get(i).onPhoneStateChanged(mPhoneState);
276285
}
277286
}
278287

279288
protected void handleRingerModeChange(int mode) {
280289
if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
290+
mRingMode = mode;
281291
for (int i = 0; i < mInfoCallbacks.size(); i++) {
282292
mInfoCallbacks.get(i).onRingerModeChanged(mode);
283293
}
@@ -459,7 +469,7 @@ interface InfoCallback {
459469
* {@link TelephonyManager@EXTRA_STATE_RINGING}
460470
* {@link TelephonyManager#EXTRA_STATE_OFFHOOK
461471
*/
462-
void onPhoneStateChanged(String newState);
472+
void onPhoneStateChanged(int phoneState);
463473

464474
/**
465475
* Called when visibility of lockscreen clock changes, such as when
@@ -484,8 +494,12 @@ interface SimStateCallback {
484494
public void registerInfoCallback(InfoCallback callback) {
485495
if (!mInfoCallbacks.contains(callback)) {
486496
mInfoCallbacks.add(callback);
487-
// notify the register the current state right away
488-
// TODO: need call other callback methods
497+
// Notify listener of the current state
498+
callback.onRefreshBatteryInfo(shouldShowBatteryInfo(), isPluggedIn(mBatteryStatus),
499+
mBatteryLevel);
500+
callback.onTimeChanged();
501+
callback.onRingerModeChanged(mRingMode);
502+
callback.onPhoneStateChanged(mPhoneState);
489503
callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
490504
} else {
491505
if (DEBUG) Log.e(TAG, "Object tried to add another INFO callback",
@@ -500,9 +514,7 @@ public void registerInfoCallback(InfoCallback callback) {
500514
public void registerSimStateCallback(SimStateCallback callback) {
501515
if (!mSimStateCallbacks.contains(callback)) {
502516
mSimStateCallbacks.add(callback);
503-
// notify the register the current sim state right away,
504-
// otherwise the register won't receive any state until
505-
// sim state gets changed again.
517+
// Notify listener of the current state
506518
callback.onSimStateChanged(mSimState);
507519
} else {
508520
if (DEBUG) Log.e(TAG, "Object tried to add another SIM callback",

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ public void onReceive(Context context, Intent intent) {
782782
// Don't play lockscreen SFX if the screen went off due to
783783
// timeout.
784784
mSuppressNextLockSound = true;
785-
785+
786786
doKeyguardLocked();
787787
}
788788
}
@@ -793,7 +793,7 @@ public void onReceive(Context context, Intent intent) {
793793
if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState) // call ending
794794
&& !mScreenOn // screen off
795795
&& mExternallyEnabled) { // not disabled by any app
796-
796+
797797
// note: this is a way to gracefully reenable the keyguard when the call
798798
// ends and the screen is off without always reenabling the keyguard
799799
// each time the screen turns off while in call (and having an occasional ugly
@@ -1297,7 +1297,7 @@ public void onClockVisibilityChanged() {
12971297
}
12981298

12991299
/** {@inheritDoc} */
1300-
public void onPhoneStateChanged(String newState) {
1300+
public void onPhoneStateChanged(int phoneState) {
13011301
// ignored
13021302
}
13031303

0 commit comments

Comments
 (0)