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.ActivityManager; 20import android.app.ActivityManagerNative; 21import android.app.AlarmManager; 22import android.app.IUserSwitchObserver; 23import android.app.PendingIntent; 24import android.app.admin.DevicePolicyManager; 25import android.app.trust.TrustManager; 26import android.content.BroadcastReceiver; 27import android.content.Context; 28import android.content.Intent; 29import android.content.IntentFilter; 30import android.database.ContentObserver; 31import android.graphics.Bitmap; 32import android.hardware.fingerprint.Fingerprint; 33import android.hardware.fingerprint.FingerprintManager; 34import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; 35import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; 36import android.media.AudioManager; 37import android.os.BatteryManager; 38import android.os.CancellationSignal; 39import android.os.Handler; 40import android.os.IRemoteCallback; 41import android.os.Message; 42import android.os.RemoteException; 43import android.os.SystemClock; 44import android.os.UserHandle; 45import android.provider.Settings; 46import android.telephony.ServiceState; 47import android.telephony.SubscriptionInfo; 48import android.telephony.SubscriptionManager; 49import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 50import android.telephony.TelephonyManager; 51import android.util.ArraySet; 52import android.util.Log; 53import android.util.SparseBooleanArray; 54import android.util.SparseIntArray; 55 56import com.google.android.collect.Lists; 57 58import com.android.internal.telephony.IccCardConstants; 59import com.android.internal.telephony.IccCardConstants.State; 60import com.android.internal.telephony.PhoneConstants; 61import com.android.internal.telephony.TelephonyIntents; 62import com.android.internal.widget.LockPatternUtils; 63 64import java.io.FileDescriptor; 65import java.io.PrintWriter; 66import java.lang.ref.WeakReference; 67import java.util.ArrayList; 68import java.util.HashMap; 69import java.util.List; 70import java.util.Map.Entry; 71 72import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; 73import static android.os.BatteryManager.BATTERY_STATUS_FULL; 74import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; 75import static android.os.BatteryManager.EXTRA_HEALTH; 76import static android.os.BatteryManager.EXTRA_LEVEL; 77import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT; 78import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE; 79import static android.os.BatteryManager.EXTRA_PLUGGED; 80import static android.os.BatteryManager.EXTRA_STATUS; 81 82/** 83 * Watches for updates that may be interesting to the keyguard, and provides 84 * the up to date information as well as a registration for callbacks that care 85 * to be updated. 86 * 87 * Note: under time crunch, this has been extended to include some stuff that 88 * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns 89 * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()} 90 * and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'... 91 */ 92public class KeyguardUpdateMonitor implements TrustManager.TrustListener { 93 94 private static final String TAG = "KeyguardUpdateMonitor"; 95 private static final boolean DEBUG = KeyguardConstants.DEBUG; 96 private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES; 97 private static final int LOW_BATTERY_THRESHOLD = 20; 98 99 private static final String ACTION_FACE_UNLOCK_STARTED 100 = "com.android.facelock.FACE_UNLOCK_STARTED"; 101 private static final String ACTION_FACE_UNLOCK_STOPPED 102 = "com.android.facelock.FACE_UNLOCK_STOPPED"; 103 104 private static final String ACTION_STRONG_AUTH_TIMEOUT = 105 "com.android.systemui.ACTION_STRONG_AUTH_TIMEOUT"; 106 private static final String USER_ID = "com.android.systemui.USER_ID"; 107 108 private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF"; 109 110 /** 111 * Milliseconds after unlocking with fingerprint times out, i.e. the user has to use a 112 * strong auth method like password, PIN or pattern. 113 */ 114 private static final long FINGERPRINT_UNLOCK_TIMEOUT_MS = 72 * 60 * 60 * 1000; 115 116 // Callback messages 117 private static final int MSG_TIME_UPDATE = 301; 118 private static final int MSG_BATTERY_UPDATE = 302; 119 private static final int MSG_SIM_STATE_CHANGE = 304; 120 private static final int MSG_RINGER_MODE_CHANGED = 305; 121 private static final int MSG_PHONE_STATE_CHANGED = 306; 122 private static final int MSG_DEVICE_PROVISIONED = 308; 123 private static final int MSG_DPM_STATE_CHANGED = 309; 124 private static final int MSG_USER_SWITCHING = 310; 125 private static final int MSG_KEYGUARD_RESET = 312; 126 private static final int MSG_BOOT_COMPLETED = 313; 127 private static final int MSG_USER_SWITCH_COMPLETE = 314; 128 private static final int MSG_USER_INFO_CHANGED = 317; 129 private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318; 130 private static final int MSG_STARTED_WAKING_UP = 319; 131 private static final int MSG_FINISHED_GOING_TO_SLEEP = 320; 132 private static final int MSG_STARTED_GOING_TO_SLEEP = 321; 133 private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322; 134 private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 327; 135 private static final int MSG_SIM_SUBSCRIPTION_INFO_CHANGED = 328; 136 private static final int MSG_AIRPLANE_MODE_CHANGED = 329; 137 private static final int MSG_SERVICE_STATE_CHANGE = 330; 138 private static final int MSG_SCREEN_TURNED_ON = 331; 139 private static final int MSG_SCREEN_TURNED_OFF = 332; 140 141 /** Fingerprint state: Not listening to fingerprint. */ 142 private static final int FINGERPRINT_STATE_STOPPED = 0; 143 144 /** Fingerprint state: Listening. */ 145 private static final int FINGERPRINT_STATE_RUNNING = 1; 146 147 /** 148 * Fingerprint state: Cancelling and waiting for the confirmation from FingerprintService to 149 * send us the confirmation that cancellation has happened. 150 */ 151 private static final int FINGERPRINT_STATE_CANCELLING = 2; 152 153 /** 154 * Fingerprint state: During cancelling we got another request to start listening, so when we 155 * receive the cancellation done signal, we should start listening again. 156 */ 157 private static final int FINGERPRINT_STATE_CANCELLING_RESTARTING = 3; 158 159 private static final int DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT = 5000000; 160 161 private static KeyguardUpdateMonitor sInstance; 162 163 private final Context mContext; 164 HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>(); 165 HashMap<Integer, ServiceState> mServiceStates = new HashMap<Integer, ServiceState>(); 166 167 private int mRingMode; 168 private int mPhoneState; 169 private boolean mKeyguardIsVisible; 170 171 /** 172 * If true, fingerprint was already authenticated and we don't need to start listening again 173 * until the Keyguard has been dismissed. 174 */ 175 private boolean mFingerprintAlreadyAuthenticated; 176 private boolean mGoingToSleep; 177 private boolean mBouncer; 178 private boolean mBootCompleted; 179 180 // Device provisioning state 181 private boolean mDeviceProvisioned; 182 183 // Battery status 184 private BatteryStatus mBatteryStatus; 185 186 // Password attempts 187 private SparseIntArray mFailedAttempts = new SparseIntArray(); 188 189 /** Tracks whether strong authentication hasn't been used since quite some time per user. */ 190 private ArraySet<Integer> mStrongAuthNotTimedOut = new ArraySet<>(); 191 private final StrongAuthTracker mStrongAuthTracker; 192 193 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>> 194 mCallbacks = Lists.newArrayList(); 195 private ContentObserver mDeviceProvisionedObserver; 196 197 private boolean mSwitchingUser; 198 199 private boolean mDeviceInteractive; 200 private boolean mScreenOn; 201 private SubscriptionManager mSubscriptionManager; 202 private AlarmManager mAlarmManager; 203 private List<SubscriptionInfo> mSubscriptionInfo; 204 private TrustManager mTrustManager; 205 private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED; 206 207 private final Handler mHandler = new Handler() { 208 @Override 209 public void handleMessage(Message msg) { 210 switch (msg.what) { 211 case MSG_TIME_UPDATE: 212 handleTimeUpdate(); 213 break; 214 case MSG_BATTERY_UPDATE: 215 handleBatteryUpdate((BatteryStatus) msg.obj); 216 break; 217 case MSG_SIM_STATE_CHANGE: 218 handleSimStateChange(msg.arg1, msg.arg2, (State) msg.obj); 219 break; 220 case MSG_RINGER_MODE_CHANGED: 221 handleRingerModeChange(msg.arg1); 222 break; 223 case MSG_PHONE_STATE_CHANGED: 224 handlePhoneStateChanged((String) msg.obj); 225 break; 226 case MSG_DEVICE_PROVISIONED: 227 handleDeviceProvisioned(); 228 break; 229 case MSG_DPM_STATE_CHANGED: 230 handleDevicePolicyManagerStateChanged(); 231 break; 232 case MSG_USER_SWITCHING: 233 handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj); 234 break; 235 case MSG_USER_SWITCH_COMPLETE: 236 handleUserSwitchComplete(msg.arg1); 237 break; 238 case MSG_KEYGUARD_RESET: 239 handleKeyguardReset(); 240 break; 241 case MSG_KEYGUARD_BOUNCER_CHANGED: 242 handleKeyguardBouncerChanged(msg.arg1); 243 break; 244 case MSG_BOOT_COMPLETED: 245 handleBootCompleted(); 246 break; 247 case MSG_USER_INFO_CHANGED: 248 handleUserInfoChanged(msg.arg1); 249 break; 250 case MSG_REPORT_EMERGENCY_CALL_ACTION: 251 handleReportEmergencyCallAction(); 252 break; 253 case MSG_STARTED_GOING_TO_SLEEP: 254 handleStartedGoingToSleep(msg.arg1); 255 break; 256 case MSG_FINISHED_GOING_TO_SLEEP: 257 handleFinishedGoingToSleep(msg.arg1); 258 break; 259 case MSG_STARTED_WAKING_UP: 260 handleStartedWakingUp(); 261 break; 262 case MSG_FACE_UNLOCK_STATE_CHANGED: 263 handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2); 264 break; 265 case MSG_SIM_SUBSCRIPTION_INFO_CHANGED: 266 handleSimSubscriptionInfoChanged(); 267 break; 268 case MSG_AIRPLANE_MODE_CHANGED: 269 handleAirplaneModeChanged(); 270 break; 271 case MSG_SERVICE_STATE_CHANGE: 272 handleServiceStateChange(msg.arg1, (ServiceState) msg.obj); 273 break; 274 case MSG_SCREEN_TURNED_ON: 275 handleScreenTurnedOn(); 276 break; 277 case MSG_SCREEN_TURNED_OFF: 278 handleScreenTurnedOff(); 279 break; 280 } 281 } 282 }; 283 284 private OnSubscriptionsChangedListener mSubscriptionListener = 285 new OnSubscriptionsChangedListener() { 286 @Override 287 public void onSubscriptionsChanged() { 288 mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED); 289 } 290 }; 291 292 private SparseBooleanArray mUserHasTrust = new SparseBooleanArray(); 293 private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray(); 294 private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray(); 295 private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray(); 296 297 private static int sCurrentUser; 298 299 public synchronized static void setCurrentUser(int currentUser) { 300 sCurrentUser = currentUser; 301 } 302 303 public synchronized static int getCurrentUser() { 304 return sCurrentUser; 305 } 306 307 @Override 308 public void onTrustChanged(boolean enabled, int userId, int flags) { 309 mUserHasTrust.put(userId, enabled); 310 for (int i = 0; i < mCallbacks.size(); i++) { 311 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 312 if (cb != null) { 313 cb.onTrustChanged(userId); 314 if (enabled && flags != 0) { 315 cb.onTrustGrantedWithFlags(flags, userId); 316 } 317 } 318 } 319 } 320 321 protected void handleSimSubscriptionInfoChanged() { 322 if (DEBUG_SIM_STATES) { 323 Log.v(TAG, "onSubscriptionInfoChanged()"); 324 List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList(); 325 if (sil != null) { 326 for (SubscriptionInfo subInfo : sil) { 327 Log.v(TAG, "SubInfo:" + subInfo); 328 } 329 } else { 330 Log.v(TAG, "onSubscriptionInfoChanged: list is null"); 331 } 332 } 333 List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */); 334 335 // Hack level over 9000: Because the subscription id is not yet valid when we see the 336 // first update in handleSimStateChange, we need to force refresh all all SIM states 337 // so the subscription id for them is consistent. 338 ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>(); 339 for (int i = 0; i < subscriptionInfos.size(); i++) { 340 SubscriptionInfo info = subscriptionInfos.get(i); 341 boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex()); 342 if (changed) { 343 changedSubscriptions.add(info); 344 } 345 } 346 for (int i = 0; i < changedSubscriptions.size(); i++) { 347 SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId()); 348 for (int j = 0; j < mCallbacks.size(); j++) { 349 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); 350 if (cb != null) { 351 cb.onSimStateChanged(data.subId, data.slotId, data.simState); 352 } 353 } 354 } 355 for (int j = 0; j < mCallbacks.size(); j++) { 356 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); 357 if (cb != null) { 358 cb.onRefreshCarrierInfo(); 359 } 360 } 361 } 362 363 private void handleAirplaneModeChanged() { 364 for (int j = 0; j < mCallbacks.size(); j++) { 365 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); 366 if (cb != null) { 367 cb.onRefreshCarrierInfo(); 368 } 369 } 370 } 371 372 /** @return List of SubscriptionInfo records, maybe empty but never null */ 373 List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) { 374 List<SubscriptionInfo> sil = mSubscriptionInfo; 375 if (sil == null || forceReload) { 376 sil = mSubscriptionManager.getActiveSubscriptionInfoList(); 377 } 378 if (sil == null) { 379 // getActiveSubscriptionInfoList was null callers expect an empty list. 380 mSubscriptionInfo = new ArrayList<SubscriptionInfo>(); 381 } else { 382 mSubscriptionInfo = sil; 383 } 384 return mSubscriptionInfo; 385 } 386 387 @Override 388 public void onTrustManagedChanged(boolean managed, int userId) { 389 mUserTrustIsManaged.put(userId, managed); 390 391 for (int i = 0; i < mCallbacks.size(); i++) { 392 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 393 if (cb != null) { 394 cb.onTrustManagedChanged(userId); 395 } 396 } 397 } 398 399 private void onFingerprintAuthenticated(int userId) { 400 mUserFingerprintAuthenticated.put(userId, true); 401 402 // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a 403 // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is 404 // fully gone. 405 mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed(); 406 for (int i = 0; i < mCallbacks.size(); i++) { 407 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 408 if (cb != null) { 409 cb.onFingerprintAuthenticated(userId); 410 } 411 } 412 } 413 414 private void handleFingerprintAuthFailed() { 415 for (int i = 0; i < mCallbacks.size(); i++) { 416 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 417 if (cb != null) { 418 cb.onFingerprintAuthFailed(); 419 } 420 } 421 handleFingerprintHelp(-1, mContext.getString(R.string.fingerprint_not_recognized)); 422 } 423 424 private void handleFingerprintAcquired(int acquireInfo) { 425 if (acquireInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) { 426 return; 427 } 428 for (int i = 0; i < mCallbacks.size(); i++) { 429 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 430 if (cb != null) { 431 cb.onFingerprintAcquired(); 432 } 433 } 434 } 435 436 private void handleFingerprintAuthenticated() { 437 try { 438 final int userId; 439 try { 440 userId = ActivityManagerNative.getDefault().getCurrentUser().id; 441 } catch (RemoteException e) { 442 Log.e(TAG, "Failed to get current user id: ", e); 443 return; 444 } 445 if (isFingerprintDisabled(userId)) { 446 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId); 447 return; 448 } 449 onFingerprintAuthenticated(userId); 450 } finally { 451 setFingerprintRunningState(FINGERPRINT_STATE_STOPPED); 452 } 453 } 454 455 private void handleFingerprintHelp(int msgId, String helpString) { 456 for (int i = 0; i < mCallbacks.size(); i++) { 457 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 458 if (cb != null) { 459 cb.onFingerprintHelp(msgId, helpString); 460 } 461 } 462 } 463 464 private void handleFingerprintError(int msgId, String errString) { 465 if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED 466 && mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) { 467 setFingerprintRunningState(FINGERPRINT_STATE_STOPPED); 468 startListeningForFingerprint(); 469 } else { 470 setFingerprintRunningState(FINGERPRINT_STATE_STOPPED); 471 } 472 for (int i = 0; i < mCallbacks.size(); i++) { 473 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 474 if (cb != null) { 475 cb.onFingerprintError(msgId, errString); 476 } 477 } 478 } 479 480 private void handleFingerprintLockoutReset() { 481 updateFingerprintListeningState(); 482 } 483 484 private void setFingerprintRunningState(int fingerprintRunningState) { 485 boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING; 486 boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING; 487 mFingerprintRunningState = fingerprintRunningState; 488 489 // Clients of KeyguardUpdateMonitor don't care about the internal state about the 490 // asynchronousness of the cancel cycle. So only notify them if the actualy running state 491 // has changed. 492 if (wasRunning != isRunning) { 493 notifyFingerprintRunningStateChanged(); 494 } 495 } 496 497 private void notifyFingerprintRunningStateChanged() { 498 for (int i = 0; i < mCallbacks.size(); i++) { 499 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 500 if (cb != null) { 501 cb.onFingerprintRunningStateChanged(isFingerprintDetectionRunning()); 502 } 503 } 504 } 505 private void handleFaceUnlockStateChanged(boolean running, int userId) { 506 mUserFaceUnlockRunning.put(userId, running); 507 for (int i = 0; i < mCallbacks.size(); i++) { 508 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 509 if (cb != null) { 510 cb.onFaceUnlockStateChanged(running, userId); 511 } 512 } 513 } 514 515 public boolean isFaceUnlockRunning(int userId) { 516 return mUserFaceUnlockRunning.get(userId); 517 } 518 519 public boolean isFingerprintDetectionRunning() { 520 return mFingerprintRunningState == FINGERPRINT_STATE_RUNNING; 521 } 522 523 private boolean isTrustDisabled(int userId) { 524 // Don't allow trust agent if device is secured with a SIM PIN. This is here 525 // mainly because there's no other way to prompt the user to enter their SIM PIN 526 // once they get past the keyguard screen. 527 final boolean disabledBySimPin = isSimPinSecure(); 528 return disabledBySimPin; 529 } 530 531 private boolean isFingerprintDisabled(int userId) { 532 final DevicePolicyManager dpm = 533 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 534 return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId) 535 & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0 536 || isSimPinSecure(); 537 } 538 539 public boolean getUserCanSkipBouncer(int userId) { 540 return getUserHasTrust(userId) || (mUserFingerprintAuthenticated.get(userId) 541 && isUnlockingWithFingerprintAllowed()); 542 } 543 544 public boolean getUserHasTrust(int userId) { 545 return !isTrustDisabled(userId) && mUserHasTrust.get(userId); 546 } 547 548 public boolean getUserTrustIsManaged(int userId) { 549 return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId); 550 } 551 552 public boolean isUnlockingWithFingerprintAllowed() { 553 return mStrongAuthTracker.isUnlockingWithFingerprintAllowed() 554 && !hasFingerprintUnlockTimedOut(sCurrentUser); 555 } 556 557 public StrongAuthTracker getStrongAuthTracker() { 558 return mStrongAuthTracker; 559 } 560 561 /** 562 * @return true if the user hasn't use strong authentication (pattern, PIN, password) since a 563 * while and thus can't unlock with fingerprint, false otherwise 564 */ 565 public boolean hasFingerprintUnlockTimedOut(int userId) { 566 return !mStrongAuthNotTimedOut.contains(userId); 567 } 568 569 public void reportSuccessfulStrongAuthUnlockAttempt() { 570 mStrongAuthNotTimedOut.add(sCurrentUser); 571 scheduleStrongAuthTimeout(); 572 if (mFpm != null) { 573 byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */ 574 mFpm.resetTimeout(token); 575 } 576 } 577 578 private void scheduleStrongAuthTimeout() { 579 long when = SystemClock.elapsedRealtime() + FINGERPRINT_UNLOCK_TIMEOUT_MS; 580 Intent intent = new Intent(ACTION_STRONG_AUTH_TIMEOUT); 581 intent.putExtra(USER_ID, sCurrentUser); 582 PendingIntent sender = PendingIntent.getBroadcast(mContext, 583 sCurrentUser, intent, PendingIntent.FLAG_CANCEL_CURRENT); 584 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, sender); 585 notifyStrongAuthStateChanged(sCurrentUser); 586 } 587 588 private void notifyStrongAuthStateChanged(int userId) { 589 for (int i = 0; i < mCallbacks.size(); i++) { 590 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 591 if (cb != null) { 592 cb.onStrongAuthStateChanged(userId); 593 } 594 } 595 } 596 597 static class DisplayClientState { 598 public int clientGeneration; 599 public boolean clearing; 600 public PendingIntent intent; 601 public int playbackState; 602 public long playbackEventTime; 603 } 604 605 private DisplayClientState mDisplayClientState = new DisplayClientState(); 606 607 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 608 609 @Override 610 public void onReceive(Context context, Intent intent) { 611 final String action = intent.getAction(); 612 if (DEBUG) Log.d(TAG, "received broadcast " + action); 613 614 if (Intent.ACTION_TIME_TICK.equals(action) 615 || Intent.ACTION_TIME_CHANGED.equals(action) 616 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) { 617 mHandler.sendEmptyMessage(MSG_TIME_UPDATE); 618 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { 619 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN); 620 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0); 621 final int level = intent.getIntExtra(EXTRA_LEVEL, 0); 622 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN); 623 624 final int maxChargingMicroAmp = intent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT, -1); 625 int maxChargingMicroVolt = intent.getIntExtra(EXTRA_MAX_CHARGING_VOLTAGE, -1); 626 final int maxChargingMicroWatt; 627 628 if (maxChargingMicroVolt <= 0) { 629 maxChargingMicroVolt = DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT; 630 } 631 if (maxChargingMicroAmp > 0) { 632 // Calculating muW = muA * muV / (10^6 mu^2 / mu); splitting up the divisor 633 // to maintain precision equally on both factors. 634 maxChargingMicroWatt = (maxChargingMicroAmp / 1000) 635 * (maxChargingMicroVolt / 1000); 636 } else { 637 maxChargingMicroWatt = -1; 638 } 639 final Message msg = mHandler.obtainMessage( 640 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health, 641 maxChargingMicroWatt)); 642 mHandler.sendMessage(msg); 643 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) { 644 SimData args = SimData.fromIntent(intent); 645 if (DEBUG_SIM_STATES) { 646 Log.v(TAG, "action " + action 647 + " state: " + intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE) 648 + " slotId: " + args.slotId + " subid: " + args.subId); 649 } 650 mHandler.obtainMessage(MSG_SIM_STATE_CHANGE, args.subId, args.slotId, args.simState) 651 .sendToTarget(); 652 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) { 653 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED, 654 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0)); 655 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) { 656 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 657 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state)); 658 } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { 659 mHandler.sendEmptyMessage(MSG_AIRPLANE_MODE_CHANGED); 660 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 661 dispatchBootCompleted(); 662 } else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)) { 663 ServiceState serviceState = ServiceState.newFromBundle(intent.getExtras()); 664 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 665 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 666 if (DEBUG) { 667 Log.v(TAG, "action " + action + " serviceState=" + serviceState + " subId=" 668 + subId); 669 } 670 mHandler.sendMessage( 671 mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState)); 672 } 673 } 674 }; 675 676 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() { 677 678 @Override 679 public void onReceive(Context context, Intent intent) { 680 final String action = intent.getAction(); 681 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) { 682 mHandler.sendEmptyMessage(MSG_TIME_UPDATE); 683 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) { 684 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED, 685 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0)); 686 } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) { 687 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1, 688 getSendingUserId())); 689 } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) { 690 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0, 691 getSendingUserId())); 692 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED 693 .equals(action)) { 694 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED); 695 } 696 } 697 }; 698 699 private final BroadcastReceiver mStrongAuthTimeoutReceiver = new BroadcastReceiver() { 700 @Override 701 public void onReceive(Context context, Intent intent) { 702 if (ACTION_STRONG_AUTH_TIMEOUT.equals(intent.getAction())) { 703 int userId = intent.getIntExtra(USER_ID, -1); 704 mStrongAuthNotTimedOut.remove(userId); 705 notifyStrongAuthStateChanged(userId); 706 } 707 } 708 }; 709 710 private final FingerprintManager.LockoutResetCallback mLockoutResetCallback 711 = new FingerprintManager.LockoutResetCallback() { 712 @Override 713 public void onLockoutReset() { 714 handleFingerprintLockoutReset(); 715 } 716 }; 717 718 private FingerprintManager.AuthenticationCallback mAuthenticationCallback 719 = new AuthenticationCallback() { 720 721 @Override 722 public void onAuthenticationFailed() { 723 handleFingerprintAuthFailed(); 724 }; 725 726 @Override 727 public void onAuthenticationSucceeded(AuthenticationResult result) { 728 handleFingerprintAuthenticated(); 729 } 730 731 @Override 732 public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { 733 handleFingerprintHelp(helpMsgId, helpString.toString()); 734 } 735 736 @Override 737 public void onAuthenticationError(int errMsgId, CharSequence errString) { 738 handleFingerprintError(errMsgId, errString.toString()); 739 } 740 741 @Override 742 public void onAuthenticationAcquired(int acquireInfo) { 743 handleFingerprintAcquired(acquireInfo); 744 } 745 }; 746 private CancellationSignal mFingerprintCancelSignal; 747 private FingerprintManager mFpm; 748 749 /** 750 * When we receive a 751 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast, 752 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange}, 753 * we need a single object to pass to the handler. This class helps decode 754 * the intent and provide a {@link SimCard.State} result. 755 */ 756 private static class SimData { 757 public State simState; 758 public int slotId; 759 public int subId; 760 761 SimData(State state, int slot, int id) { 762 simState = state; 763 slotId = slot; 764 subId = id; 765 } 766 767 static SimData fromIntent(Intent intent) { 768 State state; 769 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) { 770 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED"); 771 } 772 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 773 int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0); 774 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 775 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 776 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { 777 final String absentReason = intent 778 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); 779 780 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals( 781 absentReason)) { 782 state = IccCardConstants.State.PERM_DISABLED; 783 } else { 784 state = IccCardConstants.State.ABSENT; 785 } 786 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { 787 state = IccCardConstants.State.READY; 788 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { 789 final String lockedReason = intent 790 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); 791 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { 792 state = IccCardConstants.State.PIN_REQUIRED; 793 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { 794 state = IccCardConstants.State.PUK_REQUIRED; 795 } else { 796 state = IccCardConstants.State.UNKNOWN; 797 } 798 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) { 799 state = IccCardConstants.State.NETWORK_LOCKED; 800 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra) 801 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) { 802 // This is required because telephony doesn't return to "READY" after 803 // these state transitions. See bug 7197471. 804 state = IccCardConstants.State.READY; 805 } else { 806 state = IccCardConstants.State.UNKNOWN; 807 } 808 return new SimData(state, slotId, subId); 809 } 810 811 @Override 812 public String toString() { 813 return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}"; 814 } 815 } 816 817 public static class BatteryStatus { 818 public static final int CHARGING_UNKNOWN = -1; 819 public static final int CHARGING_SLOWLY = 0; 820 public static final int CHARGING_REGULAR = 1; 821 public static final int CHARGING_FAST = 2; 822 823 public final int status; 824 public final int level; 825 public final int plugged; 826 public final int health; 827 public final int maxChargingWattage; 828 public BatteryStatus(int status, int level, int plugged, int health, 829 int maxChargingWattage) { 830 this.status = status; 831 this.level = level; 832 this.plugged = plugged; 833 this.health = health; 834 this.maxChargingWattage = maxChargingWattage; 835 } 836 837 /** 838 * Determine whether the device is plugged in (USB, power, or wireless). 839 * @return true if the device is plugged in. 840 */ 841 public boolean isPluggedIn() { 842 return plugged == BatteryManager.BATTERY_PLUGGED_AC 843 || plugged == BatteryManager.BATTERY_PLUGGED_USB 844 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS; 845 } 846 847 /** 848 * Whether or not the device is charged. Note that some devices never return 100% for 849 * battery level, so this allows either battery level or status to determine if the 850 * battery is charged. 851 * @return true if the device is charged 852 */ 853 public boolean isCharged() { 854 return status == BATTERY_STATUS_FULL || level >= 100; 855 } 856 857 /** 858 * Whether battery is low and needs to be charged. 859 * @return true if battery is low 860 */ 861 public boolean isBatteryLow() { 862 return level < LOW_BATTERY_THRESHOLD; 863 } 864 865 public final int getChargingSpeed(int slowThreshold, int fastThreshold) { 866 return maxChargingWattage <= 0 ? CHARGING_UNKNOWN : 867 maxChargingWattage < slowThreshold ? CHARGING_SLOWLY : 868 maxChargingWattage > fastThreshold ? CHARGING_FAST : 869 CHARGING_REGULAR; 870 } 871 } 872 873 public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker { 874 public StrongAuthTracker(Context context) { 875 super(context); 876 } 877 878 public boolean isUnlockingWithFingerprintAllowed() { 879 int userId = getCurrentUser(); 880 return isFingerprintAllowedForUser(userId); 881 } 882 883 public boolean hasUserAuthenticatedSinceBoot() { 884 int userId = getCurrentUser(); 885 return (getStrongAuthForUser(userId) 886 & STRONG_AUTH_REQUIRED_AFTER_BOOT) == 0; 887 } 888 889 @Override 890 public void onStrongAuthRequiredChanged(int userId) { 891 notifyStrongAuthStateChanged(userId); 892 } 893 } 894 895 public static KeyguardUpdateMonitor getInstance(Context context) { 896 if (sInstance == null) { 897 sInstance = new KeyguardUpdateMonitor(context); 898 } 899 return sInstance; 900 } 901 902 protected void handleStartedWakingUp() { 903 updateFingerprintListeningState(); 904 final int count = mCallbacks.size(); 905 for (int i = 0; i < count; i++) { 906 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 907 if (cb != null) { 908 cb.onStartedWakingUp(); 909 } 910 } 911 } 912 913 protected void handleStartedGoingToSleep(int arg1) { 914 clearFingerprintRecognized(); 915 final int count = mCallbacks.size(); 916 for (int i = 0; i < count; i++) { 917 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 918 if (cb != null) { 919 cb.onStartedGoingToSleep(arg1); 920 } 921 } 922 mGoingToSleep = true; 923 mFingerprintAlreadyAuthenticated = false; 924 updateFingerprintListeningState(); 925 } 926 927 protected void handleFinishedGoingToSleep(int arg1) { 928 mGoingToSleep = false; 929 final int count = mCallbacks.size(); 930 for (int i = 0; i < count; i++) { 931 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 932 if (cb != null) { 933 cb.onFinishedGoingToSleep(arg1); 934 } 935 } 936 updateFingerprintListeningState(); 937 } 938 939 private void handleScreenTurnedOn() { 940 final int count = mCallbacks.size(); 941 for (int i = 0; i < count; i++) { 942 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 943 if (cb != null) { 944 cb.onScreenTurnedOn(); 945 } 946 } 947 } 948 949 private void handleScreenTurnedOff() { 950 final int count = mCallbacks.size(); 951 for (int i = 0; i < count; i++) { 952 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 953 if (cb != null) { 954 cb.onScreenTurnedOff(); 955 } 956 } 957 } 958 959 /** 960 * IMPORTANT: Must be called from UI thread. 961 */ 962 public void dispatchSetBackground(Bitmap bmp) { 963 if (DEBUG) Log.d(TAG, "dispatchSetBackground"); 964 final int count = mCallbacks.size(); 965 for (int i = 0; i < count; i++) { 966 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 967 if (cb != null) { 968 cb.onSetBackground(bmp); 969 } 970 } 971 } 972 973 private void handleUserInfoChanged(int userId) { 974 for (int i = 0; i < mCallbacks.size(); i++) { 975 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 976 if (cb != null) { 977 cb.onUserInfoChanged(userId); 978 } 979 } 980 } 981 982 private KeyguardUpdateMonitor(Context context) { 983 mContext = context; 984 mSubscriptionManager = SubscriptionManager.from(context); 985 mAlarmManager = context.getSystemService(AlarmManager.class); 986 mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); 987 mStrongAuthTracker = new StrongAuthTracker(context); 988 989 // Since device can't be un-provisioned, we only need to register a content observer 990 // to update mDeviceProvisioned when we are... 991 if (!mDeviceProvisioned) { 992 watchForDeviceProvisioning(); 993 } 994 995 // Take a guess at initial SIM state, battery status and PLMN until we get an update 996 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0, 0); 997 998 // Watch for interesting updates 999 final IntentFilter filter = new IntentFilter(); 1000 filter.addAction(Intent.ACTION_TIME_TICK); 1001 filter.addAction(Intent.ACTION_TIME_CHANGED); 1002 filter.addAction(Intent.ACTION_BATTERY_CHANGED); 1003 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 1004 filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 1005 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 1006 filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); 1007 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); 1008 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 1009 context.registerReceiver(mBroadcastReceiver, filter); 1010 1011 final IntentFilter bootCompleteFilter = new IntentFilter(); 1012 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 1013 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 1014 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter); 1015 1016 final IntentFilter allUserFilter = new IntentFilter(); 1017 allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED); 1018 allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED); 1019 allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED); 1020 allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED); 1021 allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 1022 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter, 1023 null, null); 1024 1025 mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); 1026 try { 1027 ActivityManagerNative.getDefault().registerUserSwitchObserver( 1028 new IUserSwitchObserver.Stub() { 1029 @Override 1030 public void onUserSwitching(int newUserId, IRemoteCallback reply) { 1031 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING, 1032 newUserId, 0, reply)); 1033 } 1034 @Override 1035 public void onUserSwitchComplete(int newUserId) throws RemoteException { 1036 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE, 1037 newUserId, 0)); 1038 } 1039 @Override 1040 public void onForegroundProfileSwitch(int newProfileId) { 1041 // Ignore. 1042 } 1043 }); 1044 } catch (RemoteException e) { 1045 // TODO Auto-generated catch block 1046 e.printStackTrace(); 1047 } 1048 1049 IntentFilter strongAuthTimeoutFilter = new IntentFilter(); 1050 strongAuthTimeoutFilter.addAction(ACTION_STRONG_AUTH_TIMEOUT); 1051 context.registerReceiver(mStrongAuthTimeoutReceiver, strongAuthTimeoutFilter, 1052 PERMISSION_SELF, null /* handler */); 1053 mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE); 1054 mTrustManager.registerTrustListener(this); 1055 new LockPatternUtils(context).registerStrongAuthTracker(mStrongAuthTracker); 1056 1057 mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); 1058 updateFingerprintListeningState(); 1059 if (mFpm != null) { 1060 mFpm.addLockoutResetCallback(mLockoutResetCallback); 1061 } 1062 } 1063 1064 private void updateFingerprintListeningState() { 1065 boolean shouldListenForFingerprint = shouldListenForFingerprint(); 1066 if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) { 1067 stopListeningForFingerprint(); 1068 } else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING 1069 && shouldListenForFingerprint) { 1070 startListeningForFingerprint(); 1071 } 1072 } 1073 1074 private boolean shouldListenForFingerprint() { 1075 return (mKeyguardIsVisible || !mDeviceInteractive || mBouncer || mGoingToSleep) 1076 && !mSwitchingUser && !mFingerprintAlreadyAuthenticated 1077 && !isFingerprintDisabled(getCurrentUser()); 1078 } 1079 1080 private void startListeningForFingerprint() { 1081 if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) { 1082 setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING); 1083 return; 1084 } 1085 if (DEBUG) Log.v(TAG, "startListeningForFingerprint()"); 1086 int userId = ActivityManager.getCurrentUser(); 1087 if (isUnlockWithFingerprintPossible(userId)) { 1088 if (mFingerprintCancelSignal != null) { 1089 mFingerprintCancelSignal.cancel(); 1090 } 1091 mFingerprintCancelSignal = new CancellationSignal(); 1092 mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId); 1093 setFingerprintRunningState(FINGERPRINT_STATE_RUNNING); 1094 } 1095 } 1096 1097 public boolean isUnlockWithFingerprintPossible(int userId) { 1098 return mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId) 1099 && mFpm.getEnrolledFingerprints(userId).size() > 0; 1100 } 1101 1102 private void stopListeningForFingerprint() { 1103 if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()"); 1104 if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING) { 1105 mFingerprintCancelSignal.cancel(); 1106 mFingerprintCancelSignal = null; 1107 setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING); 1108 } 1109 if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING_RESTARTING) { 1110 setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING); 1111 } 1112 } 1113 1114 private boolean isDeviceProvisionedInSettingsDb() { 1115 return Settings.Global.getInt(mContext.getContentResolver(), 1116 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 1117 } 1118 1119 private void watchForDeviceProvisioning() { 1120 mDeviceProvisionedObserver = new ContentObserver(mHandler) { 1121 @Override 1122 public void onChange(boolean selfChange) { 1123 super.onChange(selfChange); 1124 mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); 1125 if (mDeviceProvisioned) { 1126 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED); 1127 } 1128 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned); 1129 } 1130 }; 1131 1132 mContext.getContentResolver().registerContentObserver( 1133 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), 1134 false, mDeviceProvisionedObserver); 1135 1136 // prevent a race condition between where we check the flag and where we register the 1137 // observer by grabbing the value once again... 1138 boolean provisioned = isDeviceProvisionedInSettingsDb(); 1139 if (provisioned != mDeviceProvisioned) { 1140 mDeviceProvisioned = provisioned; 1141 if (mDeviceProvisioned) { 1142 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED); 1143 } 1144 } 1145 } 1146 1147 /** 1148 * Handle {@link #MSG_DPM_STATE_CHANGED} 1149 */ 1150 protected void handleDevicePolicyManagerStateChanged() { 1151 updateFingerprintListeningState(); 1152 for (int i = mCallbacks.size() - 1; i >= 0; i--) { 1153 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1154 if (cb != null) { 1155 cb.onDevicePolicyManagerStateChanged(); 1156 } 1157 } 1158 } 1159 1160 /** 1161 * Handle {@link #MSG_USER_SWITCHING} 1162 */ 1163 protected void handleUserSwitching(int userId, IRemoteCallback reply) { 1164 mSwitchingUser = true; 1165 updateFingerprintListeningState(); 1166 1167 for (int i = 0; i < mCallbacks.size(); i++) { 1168 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1169 if (cb != null) { 1170 cb.onUserSwitching(userId); 1171 } 1172 } 1173 try { 1174 reply.sendResult(null); 1175 } catch (RemoteException e) { 1176 } 1177 } 1178 1179 /** 1180 * Handle {@link #MSG_USER_SWITCH_COMPLETE} 1181 */ 1182 protected void handleUserSwitchComplete(int userId) { 1183 mSwitchingUser = false; 1184 updateFingerprintListeningState(); 1185 1186 for (int i = 0; i < mCallbacks.size(); i++) { 1187 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1188 if (cb != null) { 1189 cb.onUserSwitchComplete(userId); 1190 } 1191 } 1192 } 1193 1194 /** 1195 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If 1196 * keyguard crashes sometime after boot, then it will never receive this 1197 * broadcast and hence not handle the event. This method is ultimately called by 1198 * PhoneWindowManager in this case. 1199 */ 1200 public void dispatchBootCompleted() { 1201 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED); 1202 } 1203 1204 /** 1205 * Handle {@link #MSG_BOOT_COMPLETED} 1206 */ 1207 protected void handleBootCompleted() { 1208 if (mBootCompleted) return; 1209 mBootCompleted = true; 1210 for (int i = 0; i < mCallbacks.size(); i++) { 1211 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1212 if (cb != null) { 1213 cb.onBootCompleted(); 1214 } 1215 } 1216 } 1217 1218 /** 1219 * We need to store this state in the KeyguardUpdateMonitor since this class will not be 1220 * destroyed. 1221 */ 1222 public boolean hasBootCompleted() { 1223 return mBootCompleted; 1224 } 1225 1226 /** 1227 * Handle {@link #MSG_DEVICE_PROVISIONED} 1228 */ 1229 protected void handleDeviceProvisioned() { 1230 for (int i = 0; i < mCallbacks.size(); i++) { 1231 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1232 if (cb != null) { 1233 cb.onDeviceProvisioned(); 1234 } 1235 } 1236 if (mDeviceProvisionedObserver != null) { 1237 // We don't need the observer anymore... 1238 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver); 1239 mDeviceProvisionedObserver = null; 1240 } 1241 } 1242 1243 /** 1244 * Handle {@link #MSG_PHONE_STATE_CHANGED} 1245 */ 1246 protected void handlePhoneStateChanged(String newState) { 1247 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")"); 1248 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) { 1249 mPhoneState = TelephonyManager.CALL_STATE_IDLE; 1250 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) { 1251 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK; 1252 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) { 1253 mPhoneState = TelephonyManager.CALL_STATE_RINGING; 1254 } 1255 for (int i = 0; i < mCallbacks.size(); i++) { 1256 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1257 if (cb != null) { 1258 cb.onPhoneStateChanged(mPhoneState); 1259 } 1260 } 1261 } 1262 1263 /** 1264 * Handle {@link #MSG_RINGER_MODE_CHANGED} 1265 */ 1266 protected void handleRingerModeChange(int mode) { 1267 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")"); 1268 mRingMode = mode; 1269 for (int i = 0; i < mCallbacks.size(); i++) { 1270 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1271 if (cb != null) { 1272 cb.onRingerModeChanged(mode); 1273 } 1274 } 1275 } 1276 1277 /** 1278 * Handle {@link #MSG_TIME_UPDATE} 1279 */ 1280 private void handleTimeUpdate() { 1281 if (DEBUG) Log.d(TAG, "handleTimeUpdate"); 1282 for (int i = 0; i < mCallbacks.size(); i++) { 1283 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1284 if (cb != null) { 1285 cb.onTimeChanged(); 1286 } 1287 } 1288 } 1289 1290 /** 1291 * Handle {@link #MSG_BATTERY_UPDATE} 1292 */ 1293 private void handleBatteryUpdate(BatteryStatus status) { 1294 if (DEBUG) Log.d(TAG, "handleBatteryUpdate"); 1295 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status); 1296 mBatteryStatus = status; 1297 if (batteryUpdateInteresting) { 1298 for (int i = 0; i < mCallbacks.size(); i++) { 1299 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1300 if (cb != null) { 1301 cb.onRefreshBatteryInfo(status); 1302 } 1303 } 1304 } 1305 } 1306 1307 /** 1308 * Handle {@link #MSG_SIM_STATE_CHANGE} 1309 */ 1310 private void handleSimStateChange(int subId, int slotId, State state) { 1311 1312 if (DEBUG_SIM_STATES) { 1313 Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId=" 1314 + slotId + ", state=" + state +")"); 1315 } 1316 1317 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 1318 Log.w(TAG, "invalid subId in handleSimStateChange()"); 1319 return; 1320 } 1321 1322 SimData data = mSimDatas.get(subId); 1323 final boolean changed; 1324 if (data == null) { 1325 data = new SimData(state, slotId, subId); 1326 mSimDatas.put(subId, data); 1327 changed = true; // no data yet; force update 1328 } else { 1329 changed = (data.simState != state || data.subId != subId || data.slotId != slotId); 1330 data.simState = state; 1331 data.subId = subId; 1332 data.slotId = slotId; 1333 } 1334 if (changed && state != State.UNKNOWN) { 1335 for (int i = 0; i < mCallbacks.size(); i++) { 1336 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1337 if (cb != null) { 1338 cb.onSimStateChanged(subId, slotId, state); 1339 } 1340 } 1341 } 1342 } 1343 1344 /** 1345 * Handle {@link #MSG_SERVICE_STATE_CHANGE} 1346 */ 1347 private void handleServiceStateChange(int subId, ServiceState serviceState) { 1348 if (DEBUG) { 1349 Log.d(TAG, 1350 "handleServiceStateChange(subId=" + subId + ", serviceState=" + serviceState); 1351 } 1352 1353 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 1354 Log.w(TAG, "invalid subId in handleServiceStateChange()"); 1355 return; 1356 } 1357 1358 mServiceStates.put(subId, serviceState); 1359 1360 for (int j = 0; j < mCallbacks.size(); j++) { 1361 KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); 1362 if (cb != null) { 1363 cb.onRefreshCarrierInfo(); 1364 } 1365 } 1366 } 1367 1368 /** 1369 * Notifies that the visibility state of Keyguard has changed. 1370 * 1371 * <p>Needs to be called from the main thread. 1372 */ 1373 public void onKeyguardVisibilityChanged(boolean showing) { 1374 if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")"); 1375 mKeyguardIsVisible = showing; 1376 for (int i = 0; i < mCallbacks.size(); i++) { 1377 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1378 if (cb != null) { 1379 cb.onKeyguardVisibilityChangedRaw(showing); 1380 } 1381 } 1382 if (!showing) { 1383 mFingerprintAlreadyAuthenticated = false; 1384 } 1385 updateFingerprintListeningState(); 1386 } 1387 1388 /** 1389 * Handle {@link #MSG_KEYGUARD_RESET} 1390 */ 1391 private void handleKeyguardReset() { 1392 if (DEBUG) Log.d(TAG, "handleKeyguardReset"); 1393 updateFingerprintListeningState(); 1394 } 1395 1396 /** 1397 * Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED} 1398 * @see #sendKeyguardBouncerChanged(boolean) 1399 */ 1400 private void handleKeyguardBouncerChanged(int bouncer) { 1401 if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")"); 1402 boolean isBouncer = (bouncer == 1); 1403 mBouncer = isBouncer; 1404 for (int i = 0; i < mCallbacks.size(); i++) { 1405 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1406 if (cb != null) { 1407 cb.onKeyguardBouncerChanged(isBouncer); 1408 } 1409 } 1410 updateFingerprintListeningState(); 1411 } 1412 1413 /** 1414 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION} 1415 */ 1416 private void handleReportEmergencyCallAction() { 1417 for (int i = 0; i < mCallbacks.size(); i++) { 1418 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 1419 if (cb != null) { 1420 cb.onEmergencyCallAction(); 1421 } 1422 } 1423 } 1424 1425 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) { 1426 final boolean nowPluggedIn = current.isPluggedIn(); 1427 final boolean wasPluggedIn = old.isPluggedIn(); 1428 final boolean stateChangedWhilePluggedIn = 1429 wasPluggedIn == true && nowPluggedIn == true 1430 && (old.status != current.status); 1431 1432 // change in plug state is always interesting 1433 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) { 1434 return true; 1435 } 1436 1437 // change in battery level while plugged in 1438 if (nowPluggedIn && old.level != current.level) { 1439 return true; 1440 } 1441 1442 // change where battery needs charging 1443 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) { 1444 return true; 1445 } 1446 1447 // change in charging current while plugged in 1448 if (nowPluggedIn && current.maxChargingWattage != old.maxChargingWattage) { 1449 return true; 1450 } 1451 1452 return false; 1453 } 1454 1455 /** 1456 * Remove the given observer's callback. 1457 * 1458 * @param callback The callback to remove 1459 */ 1460 public void removeCallback(KeyguardUpdateMonitorCallback callback) { 1461 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback); 1462 for (int i = mCallbacks.size() - 1; i >= 0; i--) { 1463 if (mCallbacks.get(i).get() == callback) { 1464 mCallbacks.remove(i); 1465 } 1466 } 1467 } 1468 1469 /** 1470 * Register to receive notifications about general keyguard information 1471 * (see {@link InfoCallback}. 1472 * @param callback The callback to register 1473 */ 1474 public void registerCallback(KeyguardUpdateMonitorCallback callback) { 1475 if (DEBUG) Log.v(TAG, "*** register callback for " + callback); 1476 // Prevent adding duplicate callbacks 1477 for (int i = 0; i < mCallbacks.size(); i++) { 1478 if (mCallbacks.get(i).get() == callback) { 1479 if (DEBUG) Log.e(TAG, "Object tried to add another callback", 1480 new Exception("Called by")); 1481 return; 1482 } 1483 } 1484 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback)); 1485 removeCallback(null); // remove unused references 1486 sendUpdates(callback); 1487 } 1488 1489 private void sendUpdates(KeyguardUpdateMonitorCallback callback) { 1490 // Notify listener of the current state 1491 callback.onRefreshBatteryInfo(mBatteryStatus); 1492 callback.onTimeChanged(); 1493 callback.onRingerModeChanged(mRingMode); 1494 callback.onPhoneStateChanged(mPhoneState); 1495 callback.onRefreshCarrierInfo(); 1496 callback.onClockVisibilityChanged(); 1497 for (Entry<Integer, SimData> data : mSimDatas.entrySet()) { 1498 final SimData state = data.getValue(); 1499 callback.onSimStateChanged(state.subId, state.slotId, state.simState); 1500 } 1501 } 1502 1503 public void sendKeyguardReset() { 1504 mHandler.obtainMessage(MSG_KEYGUARD_RESET).sendToTarget(); 1505 } 1506 1507 /** 1508 * @see #handleKeyguardBouncerChanged(int) 1509 */ 1510 public void sendKeyguardBouncerChanged(boolean showingBouncer) { 1511 if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")"); 1512 Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED); 1513 message.arg1 = showingBouncer ? 1 : 0; 1514 message.sendToTarget(); 1515 } 1516 1517 /** 1518 * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we 1519 * have the information earlier than waiting for the intent 1520 * broadcast from the telephony code. 1521 * 1522 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going 1523 * through mHandler, this *must* be called from the UI thread. 1524 */ 1525 public void reportSimUnlocked(int subId) { 1526 if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")"); 1527 int slotId = SubscriptionManager.getSlotId(subId); 1528 handleSimStateChange(subId, slotId, State.READY); 1529 } 1530 1531 /** 1532 * Report that the emergency call button has been pressed and the emergency dialer is 1533 * about to be displayed. 1534 * 1535 * @param bypassHandler runs immediately. 1536 * 1537 * NOTE: Must be called from UI thread if bypassHandler == true. 1538 */ 1539 public void reportEmergencyCallAction(boolean bypassHandler) { 1540 if (!bypassHandler) { 1541 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget(); 1542 } else { 1543 handleReportEmergencyCallAction(); 1544 } 1545 } 1546 1547 /** 1548 * @return Whether the device is provisioned (whether they have gone through 1549 * the setup wizard) 1550 */ 1551 public boolean isDeviceProvisioned() { 1552 return mDeviceProvisioned; 1553 } 1554 1555 public void clearFailedUnlockAttempts() { 1556 mFailedAttempts.delete(sCurrentUser); 1557 } 1558 1559 public int getFailedUnlockAttempts(int userId) { 1560 return mFailedAttempts.get(userId, 0); 1561 } 1562 1563 public void reportFailedStrongAuthUnlockAttempt(int userId) { 1564 mFailedAttempts.put(userId, getFailedUnlockAttempts(userId) + 1); 1565 } 1566 1567 public void clearFingerprintRecognized() { 1568 mUserFingerprintAuthenticated.clear(); 1569 } 1570 1571 public boolean isSimPinVoiceSecure() { 1572 // TODO: only count SIMs that handle voice 1573 return isSimPinSecure(); 1574 } 1575 1576 public boolean isSimPinSecure() { 1577 // True if any SIM is pin secure 1578 for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) { 1579 if (isSimPinSecure(getSimState(info.getSubscriptionId()))) return true; 1580 } 1581 return false; 1582 } 1583 1584 public State getSimState(int subId) { 1585 if (mSimDatas.containsKey(subId)) { 1586 return mSimDatas.get(subId).simState; 1587 } else { 1588 return State.UNKNOWN; 1589 } 1590 } 1591 1592 /** 1593 * @return true if and only if the state has changed for the specified {@code slotId} 1594 */ 1595 private boolean refreshSimState(int subId, int slotId) { 1596 1597 // This is awful. It exists because there are two APIs for getting the SIM status 1598 // that don't return the complete set of values and have different types. In Keyguard we 1599 // need IccCardConstants, but TelephonyManager would only give us 1600 // TelephonyManager.SIM_STATE*, so we retrieve it manually. 1601 final TelephonyManager tele = TelephonyManager.from(mContext); 1602 int simState = tele.getSimState(slotId); 1603 State state; 1604 try { 1605 state = State.intToState(simState); 1606 } catch(IllegalArgumentException ex) { 1607 Log.w(TAG, "Unknown sim state: " + simState); 1608 state = State.UNKNOWN; 1609 } 1610 SimData data = mSimDatas.get(subId); 1611 final boolean changed; 1612 if (data == null) { 1613 data = new SimData(state, slotId, subId); 1614 mSimDatas.put(subId, data); 1615 changed = true; // no data yet; force update 1616 } else { 1617 changed = data.simState != state; 1618 data.simState = state; 1619 } 1620 return changed; 1621 } 1622 1623 public static boolean isSimPinSecure(IccCardConstants.State state) { 1624 final IccCardConstants.State simState = state; 1625 return (simState == IccCardConstants.State.PIN_REQUIRED 1626 || simState == IccCardConstants.State.PUK_REQUIRED 1627 || simState == IccCardConstants.State.PERM_DISABLED); 1628 } 1629 1630 public DisplayClientState getCachedDisplayClientState() { 1631 return mDisplayClientState; 1632 } 1633 1634 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*() 1635 // (KeyguardViewMediator, KeyguardHostView) 1636 public void dispatchStartedWakingUp() { 1637 synchronized (this) { 1638 mDeviceInteractive = true; 1639 } 1640 mHandler.sendEmptyMessage(MSG_STARTED_WAKING_UP); 1641 } 1642 1643 public void dispatchStartedGoingToSleep(int why) { 1644 mHandler.sendMessage(mHandler.obtainMessage(MSG_STARTED_GOING_TO_SLEEP, why, 0)); 1645 } 1646 1647 public void dispatchFinishedGoingToSleep(int why) { 1648 synchronized(this) { 1649 mDeviceInteractive = false; 1650 } 1651 mHandler.sendMessage(mHandler.obtainMessage(MSG_FINISHED_GOING_TO_SLEEP, why, 0)); 1652 } 1653 1654 public void dispatchScreenTurnedOn() { 1655 synchronized (this) { 1656 mScreenOn = true; 1657 } 1658 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON); 1659 } 1660 1661 public void dispatchScreenTurnedOff() { 1662 synchronized(this) { 1663 mScreenOn = false; 1664 } 1665 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF); 1666 } 1667 1668 public boolean isDeviceInteractive() { 1669 return mDeviceInteractive; 1670 } 1671 1672 public boolean isGoingToSleep() { 1673 return mGoingToSleep; 1674 } 1675 1676 /** 1677 * Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first. 1678 * @param state 1679 * @return subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found 1680 */ 1681 public int getNextSubIdForState(State state) { 1682 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */); 1683 int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 1684 int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first 1685 for (int i = 0; i < list.size(); i++) { 1686 final SubscriptionInfo info = list.get(i); 1687 final int id = info.getSubscriptionId(); 1688 int slotId = SubscriptionManager.getSlotId(id); 1689 if (state == getSimState(id) && bestSlotId > slotId ) { 1690 resultId = id; 1691 bestSlotId = slotId; 1692 } 1693 } 1694 return resultId; 1695 } 1696 1697 public SubscriptionInfo getSubscriptionInfoForSubId(int subId) { 1698 List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */); 1699 for (int i = 0; i < list.size(); i++) { 1700 SubscriptionInfo info = list.get(i); 1701 if (subId == info.getSubscriptionId()) return info; 1702 } 1703 return null; // not found 1704 } 1705 1706 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1707 pw.println("KeyguardUpdateMonitor state:"); 1708 pw.println(" SIM States:"); 1709 for (SimData data : mSimDatas.values()) { 1710 pw.println(" " + data.toString()); 1711 } 1712 pw.println(" Subs:"); 1713 if (mSubscriptionInfo != null) { 1714 for (int i = 0; i < mSubscriptionInfo.size(); i++) { 1715 pw.println(" " + mSubscriptionInfo.get(i)); 1716 } 1717 } 1718 pw.println(" Service states:"); 1719 for (int subId : mServiceStates.keySet()) { 1720 pw.println(" " + subId + "=" + mServiceStates.get(subId)); 1721 } 1722 if (mFpm != null && mFpm.isHardwareDetected()) { 1723 final int userId = ActivityManager.getCurrentUser(); 1724 final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId); 1725 pw.println(" Fingerprint state (user=" + userId + ")"); 1726 pw.println(" allowed=" + isUnlockingWithFingerprintAllowed()); 1727 pw.println(" auth'd=" + mUserFingerprintAuthenticated.get(userId)); 1728 pw.println(" authSinceBoot=" 1729 + getStrongAuthTracker().hasUserAuthenticatedSinceBoot()); 1730 pw.println(" disabled(DPM)=" + isFingerprintDisabled(userId)); 1731 pw.println(" possible=" + isUnlockWithFingerprintPossible(userId)); 1732 pw.println(" strongAuthFlags=" + Integer.toHexString(strongAuthFlags)); 1733 pw.println(" timedout=" + hasFingerprintUnlockTimedOut(userId)); 1734 pw.println(" trustManaged=" + getUserTrustIsManaged(userId)); 1735 } 1736 } 1737} 1738