1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.keyguard; 18 19import android.app.ActivityManagerNative; 20import android.app.AlarmManager; 21import android.app.IUserSwitchObserver; 22import android.app.PendingIntent; 23import android.app.admin.DevicePolicyManager; 24import android.app.trust.TrustManager; 25import android.content.BroadcastReceiver; 26import android.content.ContentResolver; 27import android.content.Context; 28import android.content.Intent; 29import android.content.IntentFilter; 30import android.database.ContentObserver; 31import android.graphics.Bitmap; 32 33import static android.os.BatteryManager.BATTERY_STATUS_FULL; 34import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; 35import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; 36import static android.os.BatteryManager.EXTRA_STATUS; 37import static android.os.BatteryManager.EXTRA_PLUGGED; 38import static android.os.BatteryManager.EXTRA_LEVEL; 39import static android.os.BatteryManager.EXTRA_HEALTH; 40 41import android.media.AudioManager; 42import android.os.BatteryManager; 43import android.os.Handler; 44import android.os.IRemoteCallback; 45import android.os.Message; 46import android.os.RemoteException; 47import android.os.UserHandle; 48import android.provider.Settings; 49 50import com.android.internal.telephony.IccCardConstants; 51import com.android.internal.telephony.IccCardConstants.State; 52import com.android.internal.telephony.PhoneConstants; 53import com.android.internal.telephony.TelephonyIntents; 54import com.android.internal.telephony.TelephonyProperties; 55 56import android.service.fingerprint.FingerprintManager; 57import android.service.fingerprint.FingerprintManagerReceiver; 58import android.service.fingerprint.FingerprintUtils; 59import android.telephony.SubscriptionInfo; 60import android.telephony.SubscriptionManager; 61import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 62import android.telephony.TelephonyManager; 63import android.util.Log; 64import android.util.SparseBooleanArray; 65 66import com.google.android.collect.Lists; 67 68import java.lang.ref.WeakReference; 69import java.util.ArrayList; 70import java.util.HashMap; 71import java.util.List; 72import java.util.Map.Entry; 73 74/** 75 * Watches for updates that may be interesting to the keyguard, and provides 76 * the up to date information as well as a registration for callbacks that care 77 * to be updated. 78 * 79 * Note: under time crunch, this has been extended to include some stuff that 80 * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns 81 * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()} 82 * and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'... 83 */ 84public class KeyguardUpdateMonitor implements TrustManager.TrustListener { 85 86 private static final String TAG = "KeyguardUpdateMonitor"; 87 private static final boolean DEBUG = KeyguardConstants.DEBUG; 88 private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES; 89 private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3; 90 private static final int LOW_BATTERY_THRESHOLD = 20; 91 92 private static final String ACTION_FACE_UNLOCK_STARTED 93 = "com.android.facelock.FACE_UNLOCK_STARTED"; 94 private static final String ACTION_FACE_UNLOCK_STOPPED 95 = "com.android.facelock.FACE_UNLOCK_STOPPED"; 96 97 // Callback messages 98 private static final int MSG_TIME_UPDATE = 301; 99 private static final int MSG_BATTERY_UPDATE = 302; 100 private static final int MSG_SIM_STATE_CHANGE = 304; 101 private static final int MSG_RINGER_MODE_CHANGED = 305; 102 private static final int MSG_PHONE_STATE_CHANGED = 306; 103 private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307; 104 private static final int MSG_DEVICE_PROVISIONED = 308; 105 private static final int MSG_DPM_STATE_CHANGED = 309; 106 private static final int MSG_USER_SWITCHING = 310; 107 private static final int MSG_USER_REMOVED = 311; 108 private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312; 109 private static final int MSG_BOOT_COMPLETED = 313; 110 private static final int MSG_USER_SWITCH_COMPLETE = 314; 111 private static final int MSG_SET_CURRENT_CLIENT_ID = 315; 112 private static final int MSG_SET_PLAYBACK_STATE = 316; 113 private static final int MSG_USER_INFO_CHANGED = 317; 114 private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318; 115 private static final int MSG_SCREEN_TURNED_ON = 319; 116 private static final int MSG_SCREEN_TURNED_OFF = 320; 117 private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322; 118 private static final int MSG_FINGERPRINT_PROCESSED = 323; 119 private static final int MSG_FINGERPRINT_ACQUIRED = 324; 120 private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 325; 121 private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 326; 122 123 private static KeyguardUpdateMonitor sInstance; 124 125 private final Context mContext; 126 HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>(); 127 128 private int mRingMode; 129 private int mPhoneState; 130 private boolean mKeyguardIsVisible; 131 private boolean mBouncer; 132 private boolean mBootCompleted; 133 134 // Device provisioning state 135 private boolean mDeviceProvisioned; 136 137 // Battery status 138 private BatteryStatus mBatteryStatus; 139 140 // Password attempts 141 private int mFailedAttempts = 0; 142 private int mFailedBiometricUnlockAttempts = 0; 143 144 private boolean mAlternateUnlockEnabled; 145 146 private boolean mClockVisible; 147 148 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>> 149 mCallbacks = Lists.newArrayList(); 150 private ContentObserver mDeviceProvisionedObserver; 151 152 private boolean mSwitchingUser; 153 154 private boolean mScreenOn; 155 private SubscriptionManager mSubscriptionManager; 156 private List<SubscriptionInfo> mSubscriptionInfo; 157 158 private final Handler mHandler = new Handler() { 159 @Override 160 public void handleMessage(Message msg) { 161 switch (msg.what) { 162 case MSG_TIME_UPDATE: 163 handleTimeUpdate(); 164 break; 165 case MSG_BATTERY_UPDATE: 166 handleBatteryUpdate((BatteryStatus) msg.obj); 167 break; 168 case MSG_SIM_STATE_CHANGE: 169 handleSimStateChange(msg.arg1, msg.arg2, (State) msg.obj); 170 break; 171 case MSG_RINGER_MODE_CHANGED: 172 handleRingerModeChange(msg.arg1); 173 break; 174 case MSG_PHONE_STATE_CHANGED: 175 handlePhoneStateChanged((String) msg.obj); 176 break; 177 case MSG_CLOCK_VISIBILITY_CHANGED: 178 handleClockVisibilityChanged(); 179 break; 180 case MSG_DEVICE_PROVISIONED: 181 handleDeviceProvisioned(); 182 break; 183 case MSG_DPM_STATE_CHANGED: 184 handleDevicePolicyManagerStateChanged(); 185 break; 186 case MSG_USER_SWITCHING: 187 handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj); 188 break; 189 case MSG_USER_SWITCH_COMPLETE: 190 handleUserSwitchComplete(msg.arg1); 191 break; 192 case MSG_USER_REMOVED: 193 handleUserRemoved(msg.arg1); 194 break; 195 case MSG_KEYGUARD_VISIBILITY_CHANGED: 196 handleKeyguardVisibilityChanged(msg.arg1); 197 break; 198 case MSG_KEYGUARD_BOUNCER_CHANGED: 199 handleKeyguardBouncerChanged(msg.arg1); 200 break; 201 case MSG_BOOT_COMPLETED: 202 handleBootCompleted(); 203 break; 204 case MSG_USER_INFO_CHANGED: 205 handleUserInfoChanged(msg.arg1); 206 break; 207 case MSG_REPORT_EMERGENCY_CALL_ACTION: 208 handleReportEmergencyCallAction(); 209 break; 210 case MSG_SCREEN_TURNED_OFF: 211 handleScreenTurnedOff(msg.arg1); 212 break; 213 case MSG_SCREEN_TURNED_ON: 214 handleScreenTurnedOn(); 215 break; 216 case MSG_FINGERPRINT_ACQUIRED: 217 handleFingerprintAcquired(msg.arg1); 218 break; 219 case MSG_FINGERPRINT_PROCESSED: 220 handleFingerprintProcessed(msg.arg1); 221 break; 222 case MSG_FACE_UNLOCK_STATE_CHANGED: 223 handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2); 224 break; 225 case MSG_SIM_SUBSCRIPTION_INFO_CHANGED: 226 handleSimSubscriptionInfoChanged(); 227 break; 228 } 229 } 230 }; 231 232 private OnSubscriptionsChangedListener mSubscriptionListener = 233 new OnSubscriptionsChangedListener() { 234 @Override 235 public void onSubscriptionsChanged() { 236 mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED); 237 } 238 }; 239 240 private SparseBooleanArray mUserHasTrust = new SparseBooleanArray(); 241 private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray(); 242 private SparseBooleanArray mUserFingerprintRecognized = new SparseBooleanArray(); 243 private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray(); 244 245 @Override 246 public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) { 247 mUserHasTrust.put(userId, enabled); 248 249 for (int i = 0; i < mCallbacks.size(); i++) { 250 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 251 if (cb != null) { 252 cb.onTrustChanged(userId); 253 if (enabled && initiatedByUser) { 254 cb.onTrustInitiatedByUser(userId); 255 } 256 } 257 } 258 } 259 260 protected void handleSimSubscriptionInfoChanged() { 261 if (DEBUG_SIM_STATES) { 262 Log.v(TAG, "onSubscriptionInfoChanged()"); 263 List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList(); 264 if (sil != null) { 265 for (SubscriptionInfo subInfo : sil) { 266 Log.v(TAG, "SubInfo:" + subInfo); 267 } 268 } else { 269 Log.v(TAG, "onSubscriptionInfoChanged: list is null"); 270 } 271 } 272 List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */); 273 274 // Hack level over 9000: Because the subscription id is not yet valid when we see the 275 // first update in handleSimStateChange, we need to force refresh all all SIM states 276 // so the subscription id for them is consistent. 277 ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>(); 278 for (int i = 0; i < subscriptionInfos.size(); i++) { 279 SubscriptionInfo info = subscriptionInfos.get(i); 280 boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex()); 281 if (changed) { 282 changedSubscriptions.add(info); 283 } 284 } 285 for (int i = 0; i < changedSubscriptions.size(); i++) { 286 SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId()); 287 for (int j = 0; j < mCallbacks.size(); j++) { 288 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); 289 if (cb != null) { 290 cb.onSimStateChanged(data.subId, data.slotId, data.simState); 291 } 292 } 293 } 294 for (int j = 0; j < mCallbacks.size(); j++) { 295 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); 296 if (cb != null) { 297 cb.onRefreshCarrierInfo(); 298 } 299 } 300 } 301 302 /** @return List of SubscriptionInfo records, maybe empty but never null */ 303 List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) { 304 List<SubscriptionInfo> sil = mSubscriptionInfo; 305 if (sil == null || forceReload) { 306 sil = mSubscriptionManager.getActiveSubscriptionInfoList(); 307 } 308 if (sil == null) { 309 // getActiveSubscriptionInfoList was null callers expect an empty list. 310 mSubscriptionInfo = new ArrayList<SubscriptionInfo>(); 311 } else { 312 mSubscriptionInfo = sil; 313 } 314 return mSubscriptionInfo; 315 } 316 317 @Override 318 public void onTrustManagedChanged(boolean managed, int userId) { 319 mUserTrustIsManaged.put(userId, managed); 320 321 for (int i = 0; i < mCallbacks.size(); i++) { 322 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 323 if (cb != null) { 324 cb.onTrustManagedChanged(userId); 325 } 326 } 327 } 328 329 private void onFingerprintRecognized(int userId) { 330 mUserFingerprintRecognized.put(userId, true); 331 for (int i = 0; i < mCallbacks.size(); i++) { 332 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 333 if (cb != null) { 334 cb.onFingerprintRecognized(userId); 335 } 336 } 337 } 338 339 private void handleFingerprintProcessed(int fingerprintId) { 340 if (fingerprintId == 0) return; // not a valid fingerprint 341 342 final int userId; 343 try { 344 userId = ActivityManagerNative.getDefault().getCurrentUser().id; 345 } catch (RemoteException e) { 346 Log.e(TAG, "Failed to get current user id: ", e); 347 return; 348 } 349 if (isFingerprintDisabled(userId)) { 350 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId); 351 return; 352 } 353 final ContentResolver res = mContext.getContentResolver(); 354 final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId); 355 for (int i = 0; i < ids.length; i++) { 356 if (ids[i] == fingerprintId) { 357 onFingerprintRecognized(userId); 358 } 359 } 360 } 361 362 private void handleFingerprintAcquired(int info) { 363 for (int i = 0; i < mCallbacks.size(); i++) { 364 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 365 if (cb != null) { 366 cb.onFingerprintAcquired(info); 367 } 368 } 369 } 370 371 private void handleFaceUnlockStateChanged(boolean running, int userId) { 372 mUserFaceUnlockRunning.put(userId, running); 373 for (int i = 0; i < mCallbacks.size(); i++) { 374 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 375 if (cb != null) { 376 cb.onFaceUnlockStateChanged(running, userId); 377 } 378 } 379 } 380 381 public boolean isFaceUnlockRunning(int userId) { 382 return mUserFaceUnlockRunning.get(userId); 383 } 384 385 private boolean isTrustDisabled(int userId) { 386 final DevicePolicyManager dpm = 387 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 388 if (dpm != null) { 389 // TODO once UI is finalized 390 final boolean disabledByGlobalActions = false; 391 final boolean disabledBySettings = false; 392 393 // Don't allow trust agent if device is secured with a SIM PIN. This is here 394 // mainly because there's no other way to prompt the user to enter their SIM PIN 395 // once they get past the keyguard screen. 396 final boolean disabledBySimPin = isSimPinSecure(); 397 398 final boolean disabledByDpm = (dpm.getKeyguardDisabledFeatures(null, userId) 399 & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0; 400 return disabledByDpm || disabledByGlobalActions || disabledBySettings 401 || disabledBySimPin; 402 } 403 return false; 404 } 405 406 private boolean isFingerprintDisabled(int userId) { 407 final DevicePolicyManager dpm = 408 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 409 return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId) 410 & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0; 411 } 412 413 public boolean getUserHasTrust(int userId) { 414 return !isTrustDisabled(userId) && mUserHasTrust.get(userId) 415 || mUserFingerprintRecognized.get(userId); 416 } 417 418 public boolean getUserTrustIsManaged(int userId) { 419 return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId); 420 } 421 422 static class DisplayClientState { 423 public int clientGeneration; 424 public boolean clearing; 425 public PendingIntent intent; 426 public int playbackState; 427 public long playbackEventTime; 428 } 429 430 private DisplayClientState mDisplayClientState = new DisplayClientState(); 431 432 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 433 434 public void onReceive(Context context, Intent intent) { 435 final String action = intent.getAction(); 436 if (DEBUG) Log.d(TAG, "received broadcast " + action); 437 438 if (Intent.ACTION_TIME_TICK.equals(action) 439 || Intent.ACTION_TIME_CHANGED.equals(action) 440 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) { 441 mHandler.sendEmptyMessage(MSG_TIME_UPDATE); 442 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { 443 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN); 444 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0); 445 final int level = intent.getIntExtra(EXTRA_LEVEL, 0); 446 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN); 447 final Message msg = mHandler.obtainMessage( 448 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health)); 449 mHandler.sendMessage(msg); 450 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) { 451 SimData args = SimData.fromIntent(intent); 452 if (DEBUG_SIM_STATES) { 453 Log.v(TAG, "action " + action 454 + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE) 455 + " slotId: " + args.slotId + " subid: " + args.subId); 456 } 457 mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState) 458 .sendToTarget(); 459 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) { 460 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED, 461 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0)); 462 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) { 463 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 464 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state)); 465 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 466 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED, 467 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); 468 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 469 dispatchBootCompleted(); 470 } 471 } 472 }; 473 474 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() { 475 476 public void onReceive(Context context, Intent intent) { 477 final String action = intent.getAction(); 478 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) { 479 mHandler.sendEmptyMessage(MSG_TIME_UPDATE); 480 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) { 481 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED, 482 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0)); 483 } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) { 484 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1, 485 getSendingUserId())); 486 } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) { 487 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0, 488 getSendingUserId())); 489 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 490 .equals(action)) { 491 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED); 492 } 493 } 494 }; 495 private FingerprintManagerReceiver mFingerprintManagerReceiver = 496 new FingerprintManagerReceiver() { 497 @Override 498 public void onProcessed(int fingerprintId) { 499 mHandler.obtainMessage(MSG_FINGERPRINT_PROCESSED, fingerprintId, 0).sendToTarget(); 500 }; 501 502 @Override 503 public void onAcquired(int info) { 504 mHandler.obtainMessage(MSG_FINGERPRINT_ACQUIRED, info, 0).sendToTarget(); 505 } 506 507 @Override 508 public void onError(int error) { 509 if (DEBUG) Log.w(TAG, "FingerprintManager reported error: " + error); 510 } 511 }; 512 513 /** 514 * When we receive a 515 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast, 516 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange}, 517 * we need a single object to pass to the handler. This class helps decode 518 * the intent and provide a {@link SimCard.State} result. 519 */ 520 private static class SimData { 521 public State simState; 522 public int slotId; 523 public int subId; 524 525 SimData(State state, int slot, int id) { 526 simState = state; 527 slotId = slot; 528 subId = id; 529 } 530 531 static SimData fromIntent(Intent intent) { 532 State state; 533 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) { 534 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED"); 535 } 536 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 537 int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0); 538 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 539 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 540 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { 541 final String absentReason = intent 542 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); 543 544 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals( 545 absentReason)) { 546 state = IccCardConstants.State.PERM_DISABLED; 547 } else { 548 state = IccCardConstants.State.ABSENT; 549 } 550 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { 551 state = IccCardConstants.State.READY; 552 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { 553 final String lockedReason = intent 554 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); 555 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { 556 state = IccCardConstants.State.PIN_REQUIRED; 557 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { 558 state = IccCardConstants.State.PUK_REQUIRED; 559 } else { 560 state = IccCardConstants.State.UNKNOWN; 561 } 562 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) { 563 state = IccCardConstants.State.NETWORK_LOCKED; 564 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra) 565 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) { 566 // This is required because telephony doesn't return to "READY" after 567 // these state transitions. See bug 7197471. 568 state = IccCardConstants.State.READY; 569 } else { 570 state = IccCardConstants.State.UNKNOWN; 571 } 572 return new SimData(state, slotId, subId); 573 } 574 575 public String toString() { 576 return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}"; 577 } 578 } 579 580 public static class BatteryStatus { 581 public final int status; 582 public final int level; 583 public final int plugged; 584 public final int health; 585 public BatteryStatus(int status, int level, int plugged, int health) { 586 this.status = status; 587 this.level = level; 588 this.plugged = plugged; 589 this.health = health; 590 } 591 592 /** 593 * Determine whether the device is plugged in (USB, power, or wireless). 594 * @return true if the device is plugged in. 595 */ 596 public boolean isPluggedIn() { 597 return plugged == BatteryManager.BATTERY_PLUGGED_AC 598 || plugged == BatteryManager.BATTERY_PLUGGED_USB 599 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS; 600 } 601 602 /** 603 * Whether or not the device is charged. Note that some devices never return 100% for 604 * battery level, so this allows either battery level or status to determine if the 605 * battery is charged. 606 * @return true if the device is charged 607 */ 608 public boolean isCharged() { 609 return status == BATTERY_STATUS_FULL || level >= 100; 610 } 611 612 /** 613 * Whether battery is low and needs to be charged. 614 * @return true if battery is low 615 */ 616 public boolean isBatteryLow() { 617 return level < LOW_BATTERY_THRESHOLD; 618 } 619 620 } 621 622 public static KeyguardUpdateMonitor getInstance(Context context) { 623 if (sInstance == null) { 624 sInstance = new KeyguardUpdateMonitor(context); 625 } 626 return sInstance; 627 } 628 629 protected void handleScreenTurnedOn() { 630 final int count = mCallbacks.size(); 631 for (int i = 0; i < count; i++) { 632 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 633 if (cb != null) { 634 cb.onScreenTurnedOn(); 635 } 636 } 637 } 638 639 protected void handleScreenTurnedOff(int arg1) { 640 clearFingerprintRecognized(); 641 final int count = mCallbacks.size(); 642 for (int i = 0; i < count; i++) { 643 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 644 if (cb != null) { 645 cb.onScreenTurnedOff(arg1); 646 } 647 } 648 } 649 650 /** 651 * IMPORTANT: Must be called from UI thread. 652 */ 653 public void dispatchSetBackground(Bitmap bmp) { 654 if (DEBUG) Log.d(TAG, "dispatchSetBackground"); 655 final int count = mCallbacks.size(); 656 for (int i = 0; i < count; i++) { 657 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 658 if (cb != null) { 659 cb.onSetBackground(bmp); 660 } 661 } 662 } 663 664 private void handleUserInfoChanged(int userId) { 665 for (int i = 0; i < mCallbacks.size(); i++) { 666 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 667 if (cb != null) { 668 cb.onUserInfoChanged(userId); 669 } 670 } 671 } 672 673 private KeyguardUpdateMonitor(Context context) { 674 mContext = context; 675 mSubscriptionManager = SubscriptionManager.from(context); 676 mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); 677 // Since device can't be un-provisioned, we only need to register a content observer 678 // to update mDeviceProvisioned when we are... 679 if (!mDeviceProvisioned) { 680 watchForDeviceProvisioning(); 681 } 682 683 // Take a guess at initial SIM state, battery status and PLMN until we get an update 684 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0); 685 686 // Watch for interesting updates 687 final IntentFilter filter = new IntentFilter(); 688 filter.addAction(Intent.ACTION_TIME_TICK); 689 filter.addAction(Intent.ACTION_TIME_CHANGED); 690 filter.addAction(Intent.ACTION_BATTERY_CHANGED); 691 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 692 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 693 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); 694 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 695 filter.addAction(Intent.ACTION_USER_REMOVED); 696 context.registerReceiver(mBroadcastReceiver, filter); 697 698 final IntentFilter bootCompleteFilter = new IntentFilter(); 699 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 700 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 701 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter); 702 703 final IntentFilter allUserFilter = new IntentFilter(); 704 allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED); 705 allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED); 706 allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED); 707 allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED); 708 allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 709 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter, 710 null, null); 711 712 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); 713 try { 714 ActivityManagerNative.getDefault().registerUserSwitchObserver( 715 new IUserSwitchObserver.Stub() { 716 @Override 717 public void onUserSwitching(int newUserId, IRemoteCallback reply) { 718 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING, 719 newUserId, 0, reply)); 720 mSwitchingUser = true; 721 } 722 @Override 723 public void onUserSwitchComplete(int newUserId) throws RemoteException { 724 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE, 725 newUserId, 0)); 726 mSwitchingUser = false; 727 } 728 }); 729 } catch (RemoteException e) { 730 // TODO Auto-generated catch block 731 e.printStackTrace(); 732 } 733 734 TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE); 735 trustManager.registerTrustListener(this); 736 737 FingerprintManager fpm; 738 fpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); 739 fpm.startListening(mFingerprintManagerReceiver); 740 } 741 742 private boolean isDeviceProvisionedInSettingsDb() { 743 return Settings.Global.getInt(mContext.getContentResolver(), 744 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 745 } 746 747 private void watchForDeviceProvisioning() { 748 mDeviceProvisionedObserver = new ContentObserver(mHandler) { 749 @Override 750 public void onChange(boolean selfChange) { 751 super.onChange(selfChange); 752 mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); 753 if (mDeviceProvisioned) { 754 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED); 755 } 756 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned); 757 } 758 }; 759 760 mContext.getContentResolver().registerContentObserver( 761 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), 762 false, mDeviceProvisionedObserver); 763 764 // prevent a race condition between where we check the flag and where we register the 765 // observer by grabbing the value once again... 766 boolean provisioned = isDeviceProvisionedInSettingsDb(); 767 if (provisioned != mDeviceProvisioned) { 768 mDeviceProvisioned = provisioned; 769 if (mDeviceProvisioned) { 770 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED); 771 } 772 } 773 } 774 775 /** 776 * Handle {@link #MSG_DPM_STATE_CHANGED} 777 */ 778 protected void handleDevicePolicyManagerStateChanged() { 779 for (int i = mCallbacks.size() - 1; i >= 0; i--) { 780 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 781 if (cb != null) { 782 cb.onDevicePolicyManagerStateChanged(); 783 } 784 } 785 } 786 787 /** 788 * Handle {@link #MSG_USER_SWITCHING} 789 */ 790 protected void handleUserSwitching(int userId, IRemoteCallback reply) { 791 for (int i = 0; i < mCallbacks.size(); i++) { 792 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 793 if (cb != null) { 794 cb.onUserSwitching(userId); 795 } 796 } 797 try { 798 reply.sendResult(null); 799 } catch (RemoteException e) { 800 } 801 } 802 803 /** 804 * Handle {@link #MSG_USER_SWITCH_COMPLETE} 805 */ 806 protected void handleUserSwitchComplete(int userId) { 807 for (int i = 0; i < mCallbacks.size(); i++) { 808 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 809 if (cb != null) { 810 cb.onUserSwitchComplete(userId); 811 } 812 } 813 } 814 815 /** 816 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If 817 * keyguard crashes sometime after boot, then it will never receive this 818 * broadcast and hence not handle the event. This method is ultimately called by 819 * PhoneWindowManager in this case. 820 */ 821 public void dispatchBootCompleted() { 822 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED); 823 } 824 825 /** 826 * Handle {@link #MSG_BOOT_COMPLETED} 827 */ 828 protected void handleBootCompleted() { 829 if (mBootCompleted) return; 830 mBootCompleted = true; 831 for (int i = 0; i < mCallbacks.size(); i++) { 832 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 833 if (cb != null) { 834 cb.onBootCompleted(); 835 } 836 } 837 } 838 839 /** 840 * We need to store this state in the KeyguardUpdateMonitor since this class will not be 841 * destroyed. 842 */ 843 public boolean hasBootCompleted() { 844 return mBootCompleted; 845 } 846 847 /** 848 * Handle {@link #MSG_USER_REMOVED} 849 */ 850 protected void handleUserRemoved(int userId) { 851 for (int i = 0; i < mCallbacks.size(); i++) { 852 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 853 if (cb != null) { 854 cb.onUserRemoved(userId); 855 } 856 } 857 } 858 859 /** 860 * Handle {@link #MSG_DEVICE_PROVISIONED} 861 */ 862 protected void handleDeviceProvisioned() { 863 for (int i = 0; i < mCallbacks.size(); i++) { 864 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 865 if (cb != null) { 866 cb.onDeviceProvisioned(); 867 } 868 } 869 if (mDeviceProvisionedObserver != null) { 870 // We don't need the observer anymore... 871 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver); 872 mDeviceProvisionedObserver = null; 873 } 874 } 875 876 /** 877 * Handle {@link #MSG_PHONE_STATE_CHANGED} 878 */ 879 protected void handlePhoneStateChanged(String newState) { 880 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")"); 881 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) { 882 mPhoneState = TelephonyManager.CALL_STATE_IDLE; 883 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) { 884 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK; 885 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) { 886 mPhoneState = TelephonyManager.CALL_STATE_RINGING; 887 } 888 for (int i = 0; i < mCallbacks.size(); i++) { 889 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 890 if (cb != null) { 891 cb.onPhoneStateChanged(mPhoneState); 892 } 893 } 894 } 895 896 /** 897 * Handle {@link #MSG_RINGER_MODE_CHANGED} 898 */ 899 protected void handleRingerModeChange(int mode) { 900 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")"); 901 mRingMode = mode; 902 for (int i = 0; i < mCallbacks.size(); i++) { 903 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 904 if (cb != null) { 905 cb.onRingerModeChanged(mode); 906 } 907 } 908 } 909 910 /** 911 * Handle {@link #MSG_TIME_UPDATE} 912 */ 913 private void handleTimeUpdate() { 914 if (DEBUG) Log.d(TAG, "handleTimeUpdate"); 915 for (int i = 0; i < mCallbacks.size(); i++) { 916 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 917 if (cb != null) { 918 cb.onTimeChanged(); 919 } 920 } 921 } 922 923 /** 924 * Handle {@link #MSG_BATTERY_UPDATE} 925 */ 926 private void handleBatteryUpdate(BatteryStatus status) { 927 if (DEBUG) Log.d(TAG, "handleBatteryUpdate"); 928 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status); 929 mBatteryStatus = status; 930 if (batteryUpdateInteresting) { 931 for (int i = 0; i < mCallbacks.size(); i++) { 932 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 933 if (cb != null) { 934 cb.onRefreshBatteryInfo(status); 935 } 936 } 937 } 938 } 939 940 /** 941 * Handle {@link #MSG_SIM_STATE_CHANGE} 942 */ 943 private void handleSimStateChange(int subId, int slotId, State state) { 944 945 if (DEBUG_SIM_STATES) { 946 Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId=" 947 + slotId + ", state=" + state +")"); 948 } 949 950 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 951 Log.w(TAG, "invalid subId in handleSimStateChange()"); 952 return; 953 } 954 955 SimData data = mSimDatas.get(subId); 956 final boolean changed; 957 if (data == null) { 958 data = new SimData(state, slotId, subId); 959 mSimDatas.put(subId, data); 960 changed = true; // no data yet; force update 961 } else { 962 changed = (data.simState != state || data.subId != subId || data.slotId != slotId); 963 data.simState = state; 964 data.subId = subId; 965 data.slotId = slotId; 966 } 967 if (changed && state != State.UNKNOWN) { 968 for (int i = 0; i < mCallbacks.size(); i++) { 969 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 970 if (cb != null) { 971 cb.onSimStateChanged(subId, slotId, state); 972 } 973 } 974 } 975 } 976 977 /** 978 * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED} 979 */ 980 private void handleClockVisibilityChanged() { 981 if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()"); 982 for (int i = 0; i < mCallbacks.size(); i++) { 983 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 984 if (cb != null) { 985 cb.onClockVisibilityChanged(); 986 } 987 } 988 } 989 990 /** 991 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED} 992 */ 993 private void handleKeyguardVisibilityChanged(int showing) { 994 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")"); 995 boolean isShowing = (showing == 1); 996 mKeyguardIsVisible = isShowing; 997 for (int i = 0; i < mCallbacks.size(); i++) { 998 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 999 if (cb != null) { 1000 cb.onKeyguardVisibilityChangedRaw(isShowing); 1001 } 1002 } 1003 } 1004 1005 /** 1006 * Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED} 1007 * @see #sendKeyguardBouncerChanged(boolean) 1008 */ 1009 private void handleKeyguardBouncerChanged(int bouncer) { 1010 if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")"); 1011 boolean isBouncer = (bouncer == 1); 1012 mBouncer = isBouncer; 1013 for (int i = 0; i < mCallbacks.size(); i++) { 1014 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1015 if (cb != null) { 1016 cb.onKeyguardBouncerChanged(isBouncer); 1017 } 1018 } 1019 } 1020 1021 /** 1022 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION} 1023 */ 1024 private void handleReportEmergencyCallAction() { 1025 for (int i = 0; i < mCallbacks.size(); i++) { 1026 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1027 if (cb != null) { 1028 cb.onEmergencyCallAction(); 1029 } 1030 } 1031 } 1032 1033 public boolean isKeyguardVisible() { 1034 return mKeyguardIsVisible; 1035 } 1036 1037 /** 1038 * @return if the keyguard is currently in bouncer mode. 1039 */ 1040 public boolean isKeyguardBouncer() { 1041 return mBouncer; 1042 } 1043 1044 public boolean isSwitchingUser() { 1045 return mSwitchingUser; 1046 } 1047 1048 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) { 1049 final boolean nowPluggedIn = current.isPluggedIn(); 1050 final boolean wasPluggedIn = old.isPluggedIn(); 1051 final boolean stateChangedWhilePluggedIn = 1052 wasPluggedIn == true && nowPluggedIn == true 1053 && (old.status != current.status); 1054 1055 // change in plug state is always interesting 1056 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) { 1057 return true; 1058 } 1059 1060 // change in battery level while plugged in 1061 if (nowPluggedIn && old.level != current.level) { 1062 return true; 1063 } 1064 1065 // change where battery needs charging 1066 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) { 1067 return true; 1068 } 1069 return false; 1070 } 1071 1072 /** 1073 * @return The default plmn (no service) 1074 */ 1075 private CharSequence getDefaultPlmn() { 1076 return mContext.getResources().getText(R.string.keyguard_carrier_default); 1077 } 1078 1079 /** 1080 * Remove the given observer's callback. 1081 * 1082 * @param callback The callback to remove 1083 */ 1084 public void removeCallback(KeyguardUpdateMonitorCallback callback) { 1085 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback); 1086 for (int i = mCallbacks.size() - 1; i >= 0; i--) { 1087 if (mCallbacks.get(i).get() == callback) { 1088 mCallbacks.remove(i); 1089 } 1090 } 1091 } 1092 1093 /** 1094 * Register to receive notifications about general keyguard information 1095 * (see {@link InfoCallback}. 1096 * @param callback The callback to register 1097 */ 1098 public void registerCallback(KeyguardUpdateMonitorCallback callback) { 1099 if (DEBUG) Log.v(TAG, "*** register callback for " + callback); 1100 // Prevent adding duplicate callbacks 1101 for (int i = 0; i < mCallbacks.size(); i++) { 1102 if (mCallbacks.get(i).get() == callback) { 1103 if (DEBUG) Log.e(TAG, "Object tried to add another callback", 1104 new Exception("Called by")); 1105 return; 1106 } 1107 } 1108 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback)); 1109 removeCallback(null); // remove unused references 1110 sendUpdates(callback); 1111 } 1112 1113 private void sendUpdates(KeyguardUpdateMonitorCallback callback) { 1114 // Notify listener of the current state 1115 callback.onRefreshBatteryInfo(mBatteryStatus); 1116 callback.onTimeChanged(); 1117 callback.onRingerModeChanged(mRingMode); 1118 callback.onPhoneStateChanged(mPhoneState); 1119 callback.onRefreshCarrierInfo(); 1120 callback.onClockVisibilityChanged(); 1121 for (Entry<Integer, SimData> data : mSimDatas.entrySet()) { 1122 final SimData state = data.getValue(); 1123 callback.onSimStateChanged(state.subId, state.slotId, state.simState); 1124 } 1125 } 1126 1127 public void sendKeyguardVisibilityChanged(boolean showing) { 1128 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")"); 1129 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED); 1130 message.arg1 = showing ? 1 : 0; 1131 message.sendToTarget(); 1132 } 1133 1134 /** 1135 * @see #handleKeyguardBouncerChanged(int) 1136 */ 1137 public void sendKeyguardBouncerChanged(boolean showingBouncer) { 1138 if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")"); 1139 Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED); 1140 message.arg1 = showingBouncer ? 1 : 0; 1141 message.sendToTarget(); 1142 } 1143 1144 public void reportClockVisible(boolean visible) { 1145 mClockVisible = visible; 1146 mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget(); 1147 } 1148 1149 /** 1150 * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we 1151 * have the information earlier than waiting for the intent 1152 * broadcast from the telephony code. 1153 * 1154 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going 1155 * through mHandler, this *must* be called from the UI thread. 1156 */ 1157 public void reportSimUnlocked(int subId) { 1158 if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")"); 1159 int slotId = SubscriptionManager.getSlotId(subId); 1160 handleSimStateChange(subId, slotId, State.READY); 1161 } 1162 1163 /** 1164 * Report that the emergency call button has been pressed and the emergency dialer is 1165 * about to be displayed. 1166 * 1167 * @param bypassHandler runs immediately. 1168 * 1169 * NOTE: Must be called from UI thread if bypassHandler == true. 1170 */ 1171 public void reportEmergencyCallAction(boolean bypassHandler) { 1172 if (!bypassHandler) { 1173 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget(); 1174 } else { 1175 handleReportEmergencyCallAction(); 1176 } 1177 } 1178 1179 /** 1180 * @return Whether the device is provisioned (whether they have gone through 1181 * the setup wizard) 1182 */ 1183 public boolean isDeviceProvisioned() { 1184 return mDeviceProvisioned; 1185 } 1186 1187 public int getFailedUnlockAttempts() { 1188 return mFailedAttempts; 1189 } 1190 1191 public void clearFailedUnlockAttempts() { 1192 mFailedAttempts = 0; 1193 mFailedBiometricUnlockAttempts = 0; 1194 } 1195 1196 public void clearFingerprintRecognized() { 1197 mUserFingerprintRecognized.clear(); 1198 } 1199 1200 public void reportFailedUnlockAttempt() { 1201 mFailedAttempts++; 1202 } 1203 1204 public boolean isClockVisible() { 1205 return mClockVisible; 1206 } 1207 1208 public int getPhoneState() { 1209 return mPhoneState; 1210 } 1211 1212 public void reportFailedBiometricUnlockAttempt() { 1213 mFailedBiometricUnlockAttempts++; 1214 } 1215 1216 public boolean getMaxBiometricUnlockAttemptsReached() { 1217 return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP; 1218 } 1219 1220 public boolean isAlternateUnlockEnabled() { 1221 return mAlternateUnlockEnabled; 1222 } 1223 1224 public void setAlternateUnlockEnabled(boolean enabled) { 1225 mAlternateUnlockEnabled = enabled; 1226 } 1227 1228 public boolean isSimPinVoiceSecure() { 1229 // TODO: only count SIMs that handle voice 1230 return isSimPinSecure(); 1231 } 1232 1233 public boolean isSimPinSecure() { 1234 // True if any SIM is pin secure 1235 for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) { 1236 if (isSimPinSecure(getSimState(info.getSubscriptionId()))) return true; 1237 } 1238 return false; 1239 } 1240 1241 public State getSimState(int subId) { 1242 if (mSimDatas.containsKey(subId)) { 1243 return mSimDatas.get(subId).simState; 1244 } else { 1245 return State.UNKNOWN; 1246 } 1247 } 1248 1249 /** 1250 * @return true if and only if the state has changed for the specified {@code slotId} 1251 */ 1252 private boolean refreshSimState(int subId, int slotId) { 1253 1254 // This is awful. It exists because there are two APIs for getting the SIM status 1255 // that don't return the complete set of values and have different types. In Keyguard we 1256 // need IccCardConstants, but TelephonyManager would only give us 1257 // TelephonyManager.SIM_STATE*, so we retrieve it manually. 1258 final TelephonyManager tele = TelephonyManager.from(mContext); 1259 int simState = tele.getSimState(slotId); 1260 State state; 1261 try { 1262 state = State.intToState(simState); 1263 } catch(IllegalArgumentException ex) { 1264 Log.w(TAG, "Unknown sim state: " + simState); 1265 state = State.UNKNOWN; 1266 } 1267 SimData data = mSimDatas.get(subId); 1268 final boolean changed; 1269 if (data == null) { 1270 data = new SimData(state, slotId, subId); 1271 mSimDatas.put(subId, data); 1272 changed = true; // no data yet; force update 1273 } else { 1274 changed = data.simState != state; 1275 data.simState = state; 1276 } 1277 return changed; 1278 } 1279 1280 public static boolean isSimPinSecure(IccCardConstants.State state) { 1281 final IccCardConstants.State simState = state; 1282 return (simState == IccCardConstants.State.PIN_REQUIRED 1283 || simState == IccCardConstants.State.PUK_REQUIRED 1284 || simState == IccCardConstants.State.PERM_DISABLED); 1285 } 1286 1287 public DisplayClientState getCachedDisplayClientState() { 1288 return mDisplayClientState; 1289 } 1290 1291 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*() 1292 // (KeyguardViewMediator, KeyguardHostView) 1293 public void dispatchScreenTurnedOn() { 1294 synchronized (this) { 1295 mScreenOn = true; 1296 } 1297 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON); 1298 } 1299 1300 public void dispatchScreenTurndOff(int why) { 1301 synchronized(this) { 1302 mScreenOn = false; 1303 } 1304 mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0)); 1305 } 1306 1307 public boolean isScreenOn() { 1308 return mScreenOn; 1309 } 1310 1311 /** 1312 * Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first. 1313 * @param state 1314 * @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found 1315 */ 1316 public int getNextSubIdForState(State state) { 1317 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */); 1318 int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 1319 int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first 1320 for (int i = 0; i < list.size(); i++) { 1321 final SubscriptionInfo info = list.get(i); 1322 final int id = info.getSubscriptionId(); 1323 int slotId = SubscriptionManager.getSlotId(id); 1324 if (state == getSimState(id) && bestSlotId > slotId ) { 1325 resultId = id; 1326 bestSlotId = slotId; 1327 } 1328 } 1329 return resultId; 1330 } 1331 1332 public SubscriptionInfo getSubscriptionInfoForSubId(int subId) { 1333 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */); 1334 for (int i = 0; i < list.size(); i++) { 1335 SubscriptionInfo info = list.get(i); 1336 if (subId == info.getSubscriptionId()) return info; 1337 } 1338 return null; // not found 1339 } 1340} 1341