2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.keyguard;
19 import android.app.ActivityManagerNative;
20 import android.app.AlarmManager;
21 import android.app.IUserSwitchObserver;
22 import android.app.PendingIntent;
23 import android.app.admin.DevicePolicyManager;
24 import android.app.trust.TrustManager;
25 import android.content.BroadcastReceiver;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.pm.UserInfo;
31 import android.database.ContentObserver;
32 import android.graphics.Bitmap;
34 import static android.os.BatteryManager.BATTERY_STATUS_FULL;
35 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
36 import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
37 import static android.os.BatteryManager.EXTRA_STATUS;
38 import static android.os.BatteryManager.EXTRA_PLUGGED;
39 import static android.os.BatteryManager.EXTRA_LEVEL;
40 import static android.os.BatteryManager.EXTRA_HEALTH;
42 import android.media.AudioManager;
43 import android.media.IRemoteControlDisplay;
44 import android.os.BatteryManager;
45 import android.os.Bundle;
46 import android.os.Handler;
47 import android.os.IRemoteCallback;
48 import android.os.Message;
49 import android.os.RemoteException;
50 import android.os.UserHandle;
51 import android.provider.Settings;
53 import com.android.internal.telephony.IccCardConstants;
54 import com.android.internal.telephony.TelephonyIntents;
56 import android.service.fingerprint.FingerprintManager;
57 import android.service.fingerprint.FingerprintManagerReceiver;
58 import android.service.fingerprint.FingerprintUtils;
59 import android.telephony.TelephonyManager;
60 import android.util.Log;
61 import android.util.SparseBooleanArray;
63 import com.google.android.collect.Lists;
65 import java.lang.ref.WeakReference;
66 import java.util.ArrayList;
69 * Watches for updates that may be interesting to the keyguard, and provides
70 * the up to date information as well as a registration for callbacks that care
73 * Note: under time crunch, this has been extended to include some stuff that
74 * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns
75 * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
76 * and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'...
78 public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
80 private static final String TAG = "KeyguardUpdateMonitor";
81 private static final boolean DEBUG = KeyguardConstants.DEBUG;
82 private static final boolean DEBUG_SIM_STATES = DEBUG || false;
83 private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
84 private static final int LOW_BATTERY_THRESHOLD = 20;
86 private static final String ACTION_FACE_UNLOCK_STARTED
87 = "com.android.facelock.FACE_UNLOCK_STARTED";
88 private static final String ACTION_FACE_UNLOCK_STOPPED
89 = "com.android.facelock.FACE_UNLOCK_STOPPED";
92 private static final int MSG_TIME_UPDATE = 301;
93 private static final int MSG_BATTERY_UPDATE = 302;
94 private static final int MSG_CARRIER_INFO_UPDATE = 303;
95 private static final int MSG_SIM_STATE_CHANGE = 304;
96 private static final int MSG_RINGER_MODE_CHANGED = 305;
97 private static final int MSG_PHONE_STATE_CHANGED = 306;
98 private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
99 private static final int MSG_DEVICE_PROVISIONED = 308;
100 private static final int MSG_DPM_STATE_CHANGED = 309;
101 private static final int MSG_USER_SWITCHING = 310;
102 private static final int MSG_USER_REMOVED = 311;
103 private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
104 private static final int MSG_BOOT_COMPLETED = 313;
105 private static final int MSG_USER_SWITCH_COMPLETE = 314;
106 private static final int MSG_SET_CURRENT_CLIENT_ID = 315;
107 private static final int MSG_SET_PLAYBACK_STATE = 316;
108 private static final int MSG_USER_INFO_CHANGED = 317;
109 private static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318;
110 private static final int MSG_SCREEN_TURNED_ON = 319;
111 private static final int MSG_SCREEN_TURNED_OFF = 320;
112 private static final int MSG_KEYGUARD_BOUNCER_CHANGED = 322;
113 private static final int MSG_FINGERPRINT_PROCESSED = 323;
114 private static final int MSG_FINGERPRINT_ACQUIRED = 324;
115 private static final int MSG_FACE_UNLOCK_STATE_CHANGED = 325;
117 private static KeyguardUpdateMonitor sInstance;
119 private final Context mContext;
122 private IccCardConstants.State mSimState = IccCardConstants.State.READY;
123 private CharSequence mTelephonyPlmn;
124 private CharSequence mTelephonySpn;
125 private int mRingMode;
126 private int mPhoneState;
127 private boolean mKeyguardIsVisible;
128 private boolean mBouncer;
129 private boolean mBootCompleted;
131 // Device provisioning state
132 private boolean mDeviceProvisioned;
135 private BatteryStatus mBatteryStatus;
138 private int mFailedAttempts = 0;
139 private int mFailedBiometricUnlockAttempts = 0;
141 private boolean mAlternateUnlockEnabled;
143 private boolean mClockVisible;
145 private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
146 mCallbacks = Lists.newArrayList();
147 private ContentObserver mDeviceProvisionedObserver;
149 private boolean mSwitchingUser;
151 private boolean mScreenOn;
153 private final Handler mHandler = new Handler() {
155 public void handleMessage(Message msg) {
157 case MSG_TIME_UPDATE:
160 case MSG_BATTERY_UPDATE:
161 handleBatteryUpdate((BatteryStatus) msg.obj);
163 case MSG_CARRIER_INFO_UPDATE:
164 handleCarrierInfoUpdate();
166 case MSG_SIM_STATE_CHANGE:
167 handleSimStateChange((SimArgs) msg.obj);
169 case MSG_RINGER_MODE_CHANGED:
170 handleRingerModeChange(msg.arg1);
172 case MSG_PHONE_STATE_CHANGED:
173 handlePhoneStateChanged((String) msg.obj);
175 case MSG_CLOCK_VISIBILITY_CHANGED:
176 handleClockVisibilityChanged();
178 case MSG_DEVICE_PROVISIONED:
179 handleDeviceProvisioned();
181 case MSG_DPM_STATE_CHANGED:
182 handleDevicePolicyManagerStateChanged();
184 case MSG_USER_SWITCHING:
185 handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
187 case MSG_USER_SWITCH_COMPLETE:
188 handleUserSwitchComplete(msg.arg1);
190 case MSG_USER_REMOVED:
191 handleUserRemoved(msg.arg1);
193 case MSG_KEYGUARD_VISIBILITY_CHANGED:
194 handleKeyguardVisibilityChanged(msg.arg1);
196 case MSG_KEYGUARD_BOUNCER_CHANGED:
197 handleKeyguardBouncerChanged(msg.arg1);
199 case MSG_BOOT_COMPLETED:
200 handleBootCompleted();
202 case MSG_USER_INFO_CHANGED:
203 handleUserInfoChanged(msg.arg1);
205 case MSG_REPORT_EMERGENCY_CALL_ACTION:
206 handleReportEmergencyCallAction();
208 case MSG_SCREEN_TURNED_OFF:
209 handleScreenTurnedOff(msg.arg1);
211 case MSG_SCREEN_TURNED_ON:
212 handleScreenTurnedOn();
214 case MSG_FINGERPRINT_ACQUIRED:
215 handleFingerprintAcquired(msg.arg1);
217 case MSG_FINGERPRINT_PROCESSED:
218 handleFingerprintProcessed(msg.arg1);
220 case MSG_FACE_UNLOCK_STATE_CHANGED:
221 handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
227 private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
228 private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
229 private SparseBooleanArray mUserFingerprintRecognized = new SparseBooleanArray();
230 private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
233 public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
234 mUserHasTrust.put(userId, enabled);
236 for (int i = 0; i < mCallbacks.size(); i++) {
237 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
239 cb.onTrustChanged(userId);
240 if (enabled && initiatedByUser) {
241 cb.onTrustInitiatedByUser(userId);
248 public void onTrustManagedChanged(boolean managed, int userId) {
249 mUserTrustIsManaged.put(userId, managed);
251 for (int i = 0; i < mCallbacks.size(); i++) {
252 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
254 cb.onTrustManagedChanged(userId);
259 private void onFingerprintRecognized(int userId) {
260 mUserFingerprintRecognized.put(userId, true);
261 for (int i = 0; i < mCallbacks.size(); i++) {
262 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
264 cb.onFingerprintRecognized(userId);
269 private void handleFingerprintProcessed(int fingerprintId) {
270 if (fingerprintId == 0) return; // not a valid fingerprint
274 userId = ActivityManagerNative.getDefault().getCurrentUser().id;
275 } catch (RemoteException e) {
276 Log.e(TAG, "Failed to get current user id: ", e);
279 if (isFingerprintDisabled(userId)) {
280 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
283 final ContentResolver res = mContext.getContentResolver();
284 final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId);
285 for (int i = 0; i < ids.length; i++) {
286 if (ids[i] == fingerprintId) {
287 onFingerprintRecognized(userId);
292 private void handleFingerprintAcquired(int info) {
293 for (int i = 0; i < mCallbacks.size(); i++) {
294 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
296 cb.onFingerprintAcquired(info);
301 private void handleFaceUnlockStateChanged(boolean running, int userId) {
302 mUserFaceUnlockRunning.put(userId, running);
303 for (int i = 0; i < mCallbacks.size(); i++) {
304 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
306 cb.onFaceUnlockStateChanged(running, userId);
311 public boolean isFaceUnlockRunning(int userId) {
312 return mUserFaceUnlockRunning.get(userId);
315 private boolean isTrustDisabled(int userId) {
316 final DevicePolicyManager dpm =
317 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
319 // TODO once UI is finalized
320 final boolean disabledByGlobalActions = false;
321 final boolean disabledBySettings = false;
323 // Don't allow trust agent if device is secured with a SIM PIN. This is here
324 // mainly because there's no other way to prompt the user to enter their SIM PIN
325 // once they get past the keyguard screen.
326 final boolean disabledBySimPin = isSimPinSecure();
328 final boolean disabledByDpm = (dpm.getKeyguardDisabledFeatures(null, userId)
329 & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
330 return disabledByDpm || disabledByGlobalActions || disabledBySettings
336 private boolean isFingerprintDisabled(int userId) {
337 final DevicePolicyManager dpm =
338 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
339 return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
340 & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
343 public boolean getUserHasTrust(int userId) {
344 return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
345 || mUserFingerprintRecognized.get(userId);
348 public boolean getUserTrustIsManaged(int userId) {
349 return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
352 static class DisplayClientState {
353 public int clientGeneration;
354 public boolean clearing;
355 public PendingIntent intent;
356 public int playbackState;
357 public long playbackEventTime;
360 private DisplayClientState mDisplayClientState = new DisplayClientState();
362 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
364 public void onReceive(Context context, Intent intent) {
365 final String action = intent.getAction();
366 if (DEBUG) Log.d(TAG, "received broadcast " + action);
368 if (Intent.ACTION_TIME_TICK.equals(action)
369 || Intent.ACTION_TIME_CHANGED.equals(action)
370 || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
371 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
372 } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
373 mTelephonyPlmn = getTelephonyPlmnFrom(intent);
374 mTelephonySpn = getTelephonySpnFrom(intent);
375 mHandler.sendEmptyMessage(MSG_CARRIER_INFO_UPDATE);
376 } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
377 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
378 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
379 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
380 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
381 final Message msg = mHandler.obtainMessage(
382 MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
383 mHandler.sendMessage(msg);
384 } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
385 if (DEBUG_SIM_STATES) {
386 Log.v(TAG, "action " + action + " state" +
387 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
389 mHandler.sendMessage(mHandler.obtainMessage(
390 MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
391 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
392 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
393 intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
394 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
395 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
396 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
397 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
398 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
399 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
400 } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
401 dispatchBootCompleted();
406 private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
408 public void onReceive(Context context, Intent intent) {
409 final String action = intent.getAction();
410 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
411 mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
412 } else if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
413 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
414 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
415 } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) {
416 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1,
417 getSendingUserId()));
418 } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) {
419 mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0,
420 getSendingUserId()));
421 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
423 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
427 private FingerprintManagerReceiver mFingerprintManagerReceiver =
428 new FingerprintManagerReceiver() {
430 public void onProcessed(int fingerprintId) {
431 mHandler.obtainMessage(MSG_FINGERPRINT_PROCESSED, fingerprintId, 0).sendToTarget();
435 public void onAcquired(int info) {
436 mHandler.obtainMessage(MSG_FINGERPRINT_ACQUIRED, info, 0).sendToTarget();
440 public void onError(int error) {
441 if (DEBUG) Log.w(TAG, "FingerprintManager reported error: " + error);
447 * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
448 * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
449 * we need a single object to pass to the handler. This class helps decode
450 * the intent and provide a {@link SimCard.State} result.
452 private static class SimArgs {
453 public final IccCardConstants.State simState;
455 SimArgs(IccCardConstants.State state) {
459 static SimArgs fromIntent(Intent intent) {
460 IccCardConstants.State state;
461 if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
462 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
464 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
465 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
466 final String absentReason = intent
467 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
469 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
471 state = IccCardConstants.State.PERM_DISABLED;
473 state = IccCardConstants.State.ABSENT;
475 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
476 state = IccCardConstants.State.READY;
477 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
478 final String lockedReason = intent
479 .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
480 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
481 state = IccCardConstants.State.PIN_REQUIRED;
482 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
483 state = IccCardConstants.State.PUK_REQUIRED;
485 state = IccCardConstants.State.UNKNOWN;
487 } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
488 state = IccCardConstants.State.NETWORK_LOCKED;
489 } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
490 || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
491 // This is required because telephony doesn't return to "READY" after
492 // these state transitions. See bug 7197471.
493 state = IccCardConstants.State.READY;
495 state = IccCardConstants.State.UNKNOWN;
497 return new SimArgs(state);
500 public String toString() {
501 return simState.toString();
505 public static class BatteryStatus {
506 public final int status;
507 public final int level;
508 public final int plugged;
509 public final int health;
510 public BatteryStatus(int status, int level, int plugged, int health) {
511 this.status = status;
513 this.plugged = plugged;
514 this.health = health;
518 * Determine whether the device is plugged in (USB, power, or wireless).
519 * @return true if the device is plugged in.
521 boolean isPluggedIn() {
522 return plugged == BatteryManager.BATTERY_PLUGGED_AC
523 || plugged == BatteryManager.BATTERY_PLUGGED_USB
524 || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
528 * Whether or not the device is charged. Note that some devices never return 100% for
529 * battery level, so this allows either battery level or status to determine if the
530 * battery is charged.
531 * @return true if the device is charged
533 public boolean isCharged() {
534 return status == BATTERY_STATUS_FULL || level >= 100;
538 * Whether battery is low and needs to be charged.
539 * @return true if battery is low
541 public boolean isBatteryLow() {
542 return level < LOW_BATTERY_THRESHOLD;
547 public static KeyguardUpdateMonitor getInstance(Context context) {
548 if (sInstance == null) {
549 sInstance = new KeyguardUpdateMonitor(context);
554 protected void handleScreenTurnedOn() {
555 final int count = mCallbacks.size();
556 for (int i = 0; i < count; i++) {
557 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
559 cb.onScreenTurnedOn();
564 protected void handleScreenTurnedOff(int arg1) {
565 clearFingerprintRecognized();
566 final int count = mCallbacks.size();
567 for (int i = 0; i < count; i++) {
568 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
570 cb.onScreenTurnedOff(arg1);
576 * IMPORTANT: Must be called from UI thread.
578 public void dispatchSetBackground(Bitmap bmp) {
579 if (DEBUG) Log.d(TAG, "dispatchSetBackground");
580 final int count = mCallbacks.size();
581 for (int i = 0; i < count; i++) {
582 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
584 cb.onSetBackground(bmp);
589 private void handleUserInfoChanged(int userId) {
590 for (int i = 0; i < mCallbacks.size(); i++) {
591 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
593 cb.onUserInfoChanged(userId);
598 private KeyguardUpdateMonitor(Context context) {
600 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
601 // Since device can't be un-provisioned, we only need to register a content observer
602 // to update mDeviceProvisioned when we are...
603 if (!mDeviceProvisioned) {
604 watchForDeviceProvisioning();
607 // Take a guess at initial SIM state, battery status and PLMN until we get an update
608 mSimState = IccCardConstants.State.NOT_READY;
609 mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
610 mTelephonyPlmn = getDefaultPlmn();
612 // Watch for interesting updates
613 final IntentFilter filter = new IntentFilter();
614 filter.addAction(Intent.ACTION_TIME_TICK);
615 filter.addAction(Intent.ACTION_TIME_CHANGED);
616 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
617 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
618 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
619 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
620 filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
621 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
622 filter.addAction(Intent.ACTION_USER_REMOVED);
623 context.registerReceiver(mBroadcastReceiver, filter);
625 final IntentFilter bootCompleteFilter = new IntentFilter();
626 bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
627 bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
628 context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
630 final IntentFilter allUserFilter = new IntentFilter();
631 allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
632 allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
633 allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED);
634 allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
635 allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
636 context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
640 ActivityManagerNative.getDefault().registerUserSwitchObserver(
641 new IUserSwitchObserver.Stub() {
643 public void onUserSwitching(int newUserId, IRemoteCallback reply) {
644 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
645 newUserId, 0, reply));
646 mSwitchingUser = true;
649 public void onUserSwitchComplete(int newUserId) throws RemoteException {
650 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
652 mSwitchingUser = false;
655 } catch (RemoteException e) {
656 // TODO Auto-generated catch block
660 TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
661 trustManager.registerTrustListener(this);
663 FingerprintManager fpm;
664 fpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
665 fpm.startListening(mFingerprintManagerReceiver);
668 private boolean isDeviceProvisionedInSettingsDb() {
669 return Settings.Global.getInt(mContext.getContentResolver(),
670 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
673 private void watchForDeviceProvisioning() {
674 mDeviceProvisionedObserver = new ContentObserver(mHandler) {
676 public void onChange(boolean selfChange) {
677 super.onChange(selfChange);
678 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
679 if (mDeviceProvisioned) {
680 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
682 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
686 mContext.getContentResolver().registerContentObserver(
687 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
688 false, mDeviceProvisionedObserver);
690 // prevent a race condition between where we check the flag and where we register the
691 // observer by grabbing the value once again...
692 boolean provisioned = isDeviceProvisionedInSettingsDb();
693 if (provisioned != mDeviceProvisioned) {
694 mDeviceProvisioned = provisioned;
695 if (mDeviceProvisioned) {
696 mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
702 * Handle {@link #MSG_DPM_STATE_CHANGED}
704 protected void handleDevicePolicyManagerStateChanged() {
705 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
706 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
708 cb.onDevicePolicyManagerStateChanged();
714 * Handle {@link #MSG_USER_SWITCHING}
716 protected void handleUserSwitching(int userId, IRemoteCallback reply) {
717 for (int i = 0; i < mCallbacks.size(); i++) {
718 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
720 cb.onUserSwitching(userId);
724 reply.sendResult(null);
725 } catch (RemoteException e) {
730 * Handle {@link #MSG_USER_SWITCH_COMPLETE}
732 protected void handleUserSwitchComplete(int userId) {
733 for (int i = 0; i < mCallbacks.size(); i++) {
734 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
736 cb.onUserSwitchComplete(userId);
742 * This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If
743 * keyguard crashes sometime after boot, then it will never receive this
744 * broadcast and hence not handle the event. This method is ultimately called by
745 * PhoneWindowManager in this case.
747 public void dispatchBootCompleted() {
748 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
752 * Handle {@link #MSG_BOOT_COMPLETED}
754 protected void handleBootCompleted() {
755 if (mBootCompleted) return;
756 mBootCompleted = true;
757 for (int i = 0; i < mCallbacks.size(); i++) {
758 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
760 cb.onBootCompleted();
766 * We need to store this state in the KeyguardUpdateMonitor since this class will not be
769 public boolean hasBootCompleted() {
770 return mBootCompleted;
774 * Handle {@link #MSG_USER_REMOVED}
776 protected void handleUserRemoved(int userId) {
777 for (int i = 0; i < mCallbacks.size(); i++) {
778 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
780 cb.onUserRemoved(userId);
786 * Handle {@link #MSG_DEVICE_PROVISIONED}
788 protected void handleDeviceProvisioned() {
789 for (int i = 0; i < mCallbacks.size(); i++) {
790 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
792 cb.onDeviceProvisioned();
795 if (mDeviceProvisionedObserver != null) {
796 // We don't need the observer anymore...
797 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
798 mDeviceProvisionedObserver = null;
803 * Handle {@link #MSG_PHONE_STATE_CHANGED}
805 protected void handlePhoneStateChanged(String newState) {
806 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
807 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
808 mPhoneState = TelephonyManager.CALL_STATE_IDLE;
809 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
810 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
811 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
812 mPhoneState = TelephonyManager.CALL_STATE_RINGING;
814 for (int i = 0; i < mCallbacks.size(); i++) {
815 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
817 cb.onPhoneStateChanged(mPhoneState);
823 * Handle {@link #MSG_RINGER_MODE_CHANGED}
825 protected void handleRingerModeChange(int mode) {
826 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
828 for (int i = 0; i < mCallbacks.size(); i++) {
829 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
831 cb.onRingerModeChanged(mode);
837 * Handle {@link #MSG_TIME_UPDATE}
839 private void handleTimeUpdate() {
840 if (DEBUG) Log.d(TAG, "handleTimeUpdate");
841 for (int i = 0; i < mCallbacks.size(); i++) {
842 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
850 * Handle {@link #MSG_BATTERY_UPDATE}
852 private void handleBatteryUpdate(BatteryStatus status) {
853 if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
854 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
855 mBatteryStatus = status;
856 if (batteryUpdateInteresting) {
857 for (int i = 0; i < mCallbacks.size(); i++) {
858 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
860 cb.onRefreshBatteryInfo(status);
867 * Handle {@link #MSG_CARRIER_INFO_UPDATE}
869 private void handleCarrierInfoUpdate() {
870 if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
871 + ", spn = " + mTelephonySpn);
873 for (int i = 0; i < mCallbacks.size(); i++) {
874 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
876 cb.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
882 * Handle {@link #MSG_SIM_STATE_CHANGE}
884 private void handleSimStateChange(SimArgs simArgs) {
885 final IccCardConstants.State state = simArgs.simState;
888 Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
889 + "state resolved to " + state.toString());
892 if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
894 for (int i = 0; i < mCallbacks.size(); i++) {
895 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
897 cb.onSimStateChanged(state);
904 * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
906 private void handleClockVisibilityChanged() {
907 if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
908 for (int i = 0; i < mCallbacks.size(); i++) {
909 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
911 cb.onClockVisibilityChanged();
917 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
919 private void handleKeyguardVisibilityChanged(int showing) {
920 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
921 boolean isShowing = (showing == 1);
922 mKeyguardIsVisible = isShowing;
923 for (int i = 0; i < mCallbacks.size(); i++) {
924 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
926 cb.onKeyguardVisibilityChangedRaw(isShowing);
932 * Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED}
933 * @see #sendKeyguardBouncerChanged(boolean)
935 private void handleKeyguardBouncerChanged(int bouncer) {
936 if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
937 boolean isBouncer = (bouncer == 1);
938 mBouncer = isBouncer;
939 for (int i = 0; i < mCallbacks.size(); i++) {
940 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
942 cb.onKeyguardBouncerChanged(isBouncer);
948 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
950 private void handleReportEmergencyCallAction() {
951 for (int i = 0; i < mCallbacks.size(); i++) {
952 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
954 cb.onEmergencyCallAction();
959 public boolean isKeyguardVisible() {
960 return mKeyguardIsVisible;
964 * @return if the keyguard is currently in bouncer mode.
966 public boolean isKeyguardBouncer() {
970 public boolean isSwitchingUser() {
971 return mSwitchingUser;
974 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
975 final boolean nowPluggedIn = current.isPluggedIn();
976 final boolean wasPluggedIn = old.isPluggedIn();
977 final boolean stateChangedWhilePluggedIn =
978 wasPluggedIn == true && nowPluggedIn == true
979 && (old.status != current.status);
981 // change in plug state is always interesting
982 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
986 // change in battery level while plugged in
987 if (nowPluggedIn && old.level != current.level) {
991 // change where battery needs charging
992 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
999 * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
1000 * @return The string to use for the plmn, or null if it should not be shown.
1002 private CharSequence getTelephonyPlmnFrom(Intent intent) {
1003 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
1004 final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
1005 return (plmn != null) ? plmn : getDefaultPlmn();
1011 * @return The default plmn (no service)
1013 private CharSequence getDefaultPlmn() {
1014 return mContext.getResources().getText(R.string.keyguard_carrier_default);
1018 * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
1019 * @return The string to use for the plmn, or null if it should not be shown.
1021 private CharSequence getTelephonySpnFrom(Intent intent) {
1022 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
1023 final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
1032 * Remove the given observer's callback.
1034 * @param callback The callback to remove
1036 public void removeCallback(KeyguardUpdateMonitorCallback callback) {
1037 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
1038 for (int i = mCallbacks.size() - 1; i >= 0; i--) {
1039 if (mCallbacks.get(i).get() == callback) {
1040 mCallbacks.remove(i);
1046 * Register to receive notifications about general keyguard information
1047 * (see {@link InfoCallback}.
1048 * @param callback The callback to register
1050 public void registerCallback(KeyguardUpdateMonitorCallback callback) {
1051 if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
1052 // Prevent adding duplicate callbacks
1053 for (int i = 0; i < mCallbacks.size(); i++) {
1054 if (mCallbacks.get(i).get() == callback) {
1055 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
1056 new Exception("Called by"));
1060 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
1061 removeCallback(null); // remove unused references
1062 sendUpdates(callback);
1065 private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
1066 // Notify listener of the current state
1067 callback.onRefreshBatteryInfo(mBatteryStatus);
1068 callback.onTimeChanged();
1069 callback.onRingerModeChanged(mRingMode);
1070 callback.onPhoneStateChanged(mPhoneState);
1071 callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
1072 callback.onClockVisibilityChanged();
1073 callback.onSimStateChanged(mSimState);
1076 public void sendKeyguardVisibilityChanged(boolean showing) {
1077 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
1078 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
1079 message.arg1 = showing ? 1 : 0;
1080 message.sendToTarget();
1084 * @see #handleKeyguardBouncerChanged(int)
1086 public void sendKeyguardBouncerChanged(boolean showingBouncer) {
1087 if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")");
1088 Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED);
1089 message.arg1 = showingBouncer ? 1 : 0;
1090 message.sendToTarget();
1093 public void reportClockVisible(boolean visible) {
1094 mClockVisible = visible;
1095 mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
1098 public IccCardConstants.State getSimState() {
1103 * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
1104 * have the information earlier than waiting for the intent
1105 * broadcast from the telephony code.
1107 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
1108 * through mHandler, this *must* be called from the UI thread.
1110 public void reportSimUnlocked() {
1111 handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
1115 * Report that the emergency call button has been pressed and the emergency dialer is
1116 * about to be displayed.
1118 * @param bypassHandler runs immediately.
1120 * NOTE: Must be called from UI thread if bypassHandler == true.
1122 public void reportEmergencyCallAction(boolean bypassHandler) {
1123 if (!bypassHandler) {
1124 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
1126 handleReportEmergencyCallAction();
1130 public CharSequence getTelephonyPlmn() {
1131 return mTelephonyPlmn;
1134 public CharSequence getTelephonySpn() {
1135 return mTelephonySpn;
1139 * @return Whether the device is provisioned (whether they have gone through
1142 public boolean isDeviceProvisioned() {
1143 return mDeviceProvisioned;
1146 public int getFailedUnlockAttempts() {
1147 return mFailedAttempts;
1150 public void clearFailedUnlockAttempts() {
1151 mFailedAttempts = 0;
1152 mFailedBiometricUnlockAttempts = 0;
1155 public void clearFingerprintRecognized() {
1156 mUserFingerprintRecognized.clear();
1159 public void reportFailedUnlockAttempt() {
1163 public boolean isClockVisible() {
1164 return mClockVisible;
1167 public int getPhoneState() {
1171 public void reportFailedBiometricUnlockAttempt() {
1172 mFailedBiometricUnlockAttempts++;
1175 public boolean getMaxBiometricUnlockAttemptsReached() {
1176 return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
1179 public boolean isAlternateUnlockEnabled() {
1180 return mAlternateUnlockEnabled;
1183 public void setAlternateUnlockEnabled(boolean enabled) {
1184 mAlternateUnlockEnabled = enabled;
1187 public boolean isSimLocked() {
1188 return isSimLocked(mSimState);
1191 public static boolean isSimLocked(IccCardConstants.State state) {
1192 return state == IccCardConstants.State.PIN_REQUIRED
1193 || state == IccCardConstants.State.PUK_REQUIRED
1194 || state == IccCardConstants.State.PERM_DISABLED;
1197 public boolean isSimPinSecure() {
1198 return isSimPinSecure(mSimState);
1201 public static boolean isSimPinSecure(IccCardConstants.State state) {
1202 final IccCardConstants.State simState = state;
1203 return (simState == IccCardConstants.State.PIN_REQUIRED
1204 || simState == IccCardConstants.State.PUK_REQUIRED
1205 || simState == IccCardConstants.State.PERM_DISABLED);
1208 public DisplayClientState getCachedDisplayClientState() {
1209 return mDisplayClientState;
1212 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1213 // (KeyguardViewMediator, KeyguardHostView)
1214 public void dispatchScreenTurnedOn() {
1215 synchronized (this) {
1218 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
1221 public void dispatchScreenTurndOff(int why) {
1222 synchronized(this) {
1225 mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0));
1228 public boolean isScreenOn() {