OSDN Git Service

1c6dc2cfef8f1aa19f03c9100c60acb5ff78cb1a
[android-x86/frameworks-base.git] / packages / Keyguard / src / com / android / keyguard / KeyguardUpdateMonitor.java
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
17 package com.android.keyguard;
18
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;
33
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;
41
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;
52
53 import com.android.internal.telephony.IccCardConstants;
54 import com.android.internal.telephony.TelephonyIntents;
55
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;
62
63 import com.google.android.collect.Lists;
64
65 import java.lang.ref.WeakReference;
66 import java.util.ArrayList;
67
68 /**
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
71  * to be updated.
72  *
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'...
77  */
78 public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
79
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;
85
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";
90
91     // Callback messages
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;
116
117     private static KeyguardUpdateMonitor sInstance;
118
119     private final Context mContext;
120
121     // Telephony state
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;
130
131     // Device provisioning state
132     private boolean mDeviceProvisioned;
133
134     // Battery status
135     private BatteryStatus mBatteryStatus;
136
137     // Password attempts
138     private int mFailedAttempts = 0;
139     private int mFailedBiometricUnlockAttempts = 0;
140
141     private boolean mAlternateUnlockEnabled;
142
143     private boolean mClockVisible;
144
145     private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
146             mCallbacks = Lists.newArrayList();
147     private ContentObserver mDeviceProvisionedObserver;
148
149     private boolean mSwitchingUser;
150
151     private boolean mScreenOn;
152
153     private final Handler mHandler = new Handler() {
154         @Override
155         public void handleMessage(Message msg) {
156             switch (msg.what) {
157                 case MSG_TIME_UPDATE:
158                     handleTimeUpdate();
159                     break;
160                 case MSG_BATTERY_UPDATE:
161                     handleBatteryUpdate((BatteryStatus) msg.obj);
162                     break;
163                 case MSG_CARRIER_INFO_UPDATE:
164                     handleCarrierInfoUpdate();
165                     break;
166                 case MSG_SIM_STATE_CHANGE:
167                     handleSimStateChange((SimArgs) msg.obj);
168                     break;
169                 case MSG_RINGER_MODE_CHANGED:
170                     handleRingerModeChange(msg.arg1);
171                     break;
172                 case MSG_PHONE_STATE_CHANGED:
173                     handlePhoneStateChanged((String) msg.obj);
174                     break;
175                 case MSG_CLOCK_VISIBILITY_CHANGED:
176                     handleClockVisibilityChanged();
177                     break;
178                 case MSG_DEVICE_PROVISIONED:
179                     handleDeviceProvisioned();
180                     break;
181                 case MSG_DPM_STATE_CHANGED:
182                     handleDevicePolicyManagerStateChanged();
183                     break;
184                 case MSG_USER_SWITCHING:
185                     handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
186                     break;
187                 case MSG_USER_SWITCH_COMPLETE:
188                     handleUserSwitchComplete(msg.arg1);
189                     break;
190                 case MSG_USER_REMOVED:
191                     handleUserRemoved(msg.arg1);
192                     break;
193                 case MSG_KEYGUARD_VISIBILITY_CHANGED:
194                     handleKeyguardVisibilityChanged(msg.arg1);
195                     break;
196                 case MSG_KEYGUARD_BOUNCER_CHANGED:
197                     handleKeyguardBouncerChanged(msg.arg1);
198                     break;
199                 case MSG_BOOT_COMPLETED:
200                     handleBootCompleted();
201                     break;
202                 case MSG_USER_INFO_CHANGED:
203                     handleUserInfoChanged(msg.arg1);
204                     break;
205                 case MSG_REPORT_EMERGENCY_CALL_ACTION:
206                     handleReportEmergencyCallAction();
207                     break;
208                 case MSG_SCREEN_TURNED_OFF:
209                     handleScreenTurnedOff(msg.arg1);
210                     break;
211                 case MSG_SCREEN_TURNED_ON:
212                     handleScreenTurnedOn();
213                     break;
214                 case MSG_FINGERPRINT_ACQUIRED:
215                     handleFingerprintAcquired(msg.arg1);
216                     break;
217                 case MSG_FINGERPRINT_PROCESSED:
218                     handleFingerprintProcessed(msg.arg1);
219                     break;
220                 case MSG_FACE_UNLOCK_STATE_CHANGED:
221                     handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2);
222                     break;
223             }
224         }
225     };
226
227     private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
228     private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
229     private SparseBooleanArray mUserFingerprintRecognized = new SparseBooleanArray();
230     private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
231
232     @Override
233     public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
234         mUserHasTrust.put(userId, enabled);
235
236         for (int i = 0; i < mCallbacks.size(); i++) {
237             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
238             if (cb != null) {
239                 cb.onTrustChanged(userId);
240                 if (enabled && initiatedByUser) {
241                     cb.onTrustInitiatedByUser(userId);
242                 }
243             }
244         }
245     }
246
247     @Override
248     public void onTrustManagedChanged(boolean managed, int userId) {
249         mUserTrustIsManaged.put(userId, managed);
250
251         for (int i = 0; i < mCallbacks.size(); i++) {
252             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
253             if (cb != null) {
254                 cb.onTrustManagedChanged(userId);
255             }
256         }
257     }
258
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();
263             if (cb != null) {
264                 cb.onFingerprintRecognized(userId);
265             }
266         }
267     }
268
269     private void handleFingerprintProcessed(int fingerprintId) {
270         if (fingerprintId == 0) return; // not a valid fingerprint
271
272         final int userId;
273         try {
274             userId = ActivityManagerNative.getDefault().getCurrentUser().id;
275         } catch (RemoteException e) {
276             Log.e(TAG, "Failed to get current user id: ", e);
277             return;
278         }
279         if (isFingerprintDisabled(userId)) {
280             Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
281             return;
282         }
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);
288             }
289         }
290     }
291
292     private void handleFingerprintAcquired(int info) {
293         for (int i = 0; i < mCallbacks.size(); i++) {
294             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
295             if (cb != null) {
296                 cb.onFingerprintAcquired(info);
297             }
298         }
299     }
300
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();
305             if (cb != null) {
306                 cb.onFaceUnlockStateChanged(running, userId);
307             }
308         }
309     }
310
311     public boolean isFaceUnlockRunning(int userId) {
312         return mUserFaceUnlockRunning.get(userId);
313     }
314
315     private boolean isTrustDisabled(int userId) {
316         final DevicePolicyManager dpm =
317                 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
318         if (dpm != null) {
319                 // TODO once UI is finalized
320                 final boolean disabledByGlobalActions = false;
321                 final boolean disabledBySettings = false;
322
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();
327
328                 final boolean disabledByDpm = (dpm.getKeyguardDisabledFeatures(null, userId)
329                         & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
330                 return disabledByDpm || disabledByGlobalActions || disabledBySettings
331                         || disabledBySimPin;
332         }
333         return false;
334     }
335
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;
341     }
342
343     public boolean getUserHasTrust(int userId) {
344         return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
345                 || mUserFingerprintRecognized.get(userId);
346     }
347
348     public boolean getUserTrustIsManaged(int userId) {
349         return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
350     }
351
352     static class DisplayClientState {
353         public int clientGeneration;
354         public boolean clearing;
355         public PendingIntent intent;
356         public int playbackState;
357         public long playbackEventTime;
358     }
359
360     private DisplayClientState mDisplayClientState = new DisplayClientState();
361
362     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
363
364         public void onReceive(Context context, Intent intent) {
365             final String action = intent.getAction();
366             if (DEBUG) Log.d(TAG, "received broadcast " + action);
367
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));
388                 }
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();
402             }
403         }
404     };
405
406     private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
407
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
422                     .equals(action)) {
423                 mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED);
424             }
425         }
426     };
427     private FingerprintManagerReceiver mFingerprintManagerReceiver =
428             new FingerprintManagerReceiver() {
429         @Override
430         public void onProcessed(int fingerprintId) {
431             mHandler.obtainMessage(MSG_FINGERPRINT_PROCESSED, fingerprintId, 0).sendToTarget();
432         };
433
434         @Override
435         public void onAcquired(int info) {
436             mHandler.obtainMessage(MSG_FINGERPRINT_ACQUIRED, info, 0).sendToTarget();
437         }
438
439         @Override
440         public void onError(int error) {
441             if (DEBUG) Log.w(TAG, "FingerprintManager reported error: " + error);
442         }
443     };
444
445     /**
446      * When we receive a
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.
451      */
452     private static class SimArgs {
453         public final IccCardConstants.State simState;
454
455         SimArgs(IccCardConstants.State state) {
456             simState = state;
457         }
458
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");
463             }
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);
468
469                 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
470                         absentReason)) {
471                     state = IccCardConstants.State.PERM_DISABLED;
472                 } else {
473                     state = IccCardConstants.State.ABSENT;
474                 }
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;
484                 } else {
485                     state = IccCardConstants.State.UNKNOWN;
486                 }
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;
494             } else {
495                 state = IccCardConstants.State.UNKNOWN;
496             }
497             return new SimArgs(state);
498         }
499
500         public String toString() {
501             return simState.toString();
502         }
503     }
504
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;
512             this.level = level;
513             this.plugged = plugged;
514             this.health = health;
515         }
516
517         /**
518          * Determine whether the device is plugged in (USB, power, or wireless).
519          * @return true if the device is plugged in.
520          */
521         boolean isPluggedIn() {
522             return plugged == BatteryManager.BATTERY_PLUGGED_AC
523                     || plugged == BatteryManager.BATTERY_PLUGGED_USB
524                     || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
525         }
526
527         /**
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
532          */
533         public boolean isCharged() {
534             return status == BATTERY_STATUS_FULL || level >= 100;
535         }
536
537         /**
538          * Whether battery is low and needs to be charged.
539          * @return true if battery is low
540          */
541         public boolean isBatteryLow() {
542             return level < LOW_BATTERY_THRESHOLD;
543         }
544
545     }
546
547     public static KeyguardUpdateMonitor getInstance(Context context) {
548         if (sInstance == null) {
549             sInstance = new KeyguardUpdateMonitor(context);
550         }
551         return sInstance;
552     }
553
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();
558             if (cb != null) {
559                 cb.onScreenTurnedOn();
560             }
561         }
562     }
563
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();
569             if (cb != null) {
570                 cb.onScreenTurnedOff(arg1);
571             }
572         }
573     }
574
575     /**
576      * IMPORTANT: Must be called from UI thread.
577      */
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();
583             if (cb != null) {
584                 cb.onSetBackground(bmp);
585             }
586         }
587     }
588
589     private void handleUserInfoChanged(int userId) {
590         for (int i = 0; i < mCallbacks.size(); i++) {
591             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
592             if (cb != null) {
593                 cb.onUserInfoChanged(userId);
594             }
595         }
596     }
597
598     private KeyguardUpdateMonitor(Context context) {
599         mContext = 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();
605         }
606
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();
611
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);
624
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);
629
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,
637                 null, null);
638
639         try {
640             ActivityManagerNative.getDefault().registerUserSwitchObserver(
641                     new IUserSwitchObserver.Stub() {
642                         @Override
643                         public void onUserSwitching(int newUserId, IRemoteCallback reply) {
644                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
645                                     newUserId, 0, reply));
646                             mSwitchingUser = true;
647                         }
648                         @Override
649                         public void onUserSwitchComplete(int newUserId) throws RemoteException {
650                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
651                                     newUserId, 0));
652                             mSwitchingUser = false;
653                         }
654                     });
655         } catch (RemoteException e) {
656             // TODO Auto-generated catch block
657             e.printStackTrace();
658         }
659
660         TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
661         trustManager.registerTrustListener(this);
662
663         FingerprintManager fpm;
664         fpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
665         fpm.startListening(mFingerprintManagerReceiver);
666     }
667
668     private boolean isDeviceProvisionedInSettingsDb() {
669         return Settings.Global.getInt(mContext.getContentResolver(),
670                 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
671     }
672
673     private void watchForDeviceProvisioning() {
674         mDeviceProvisionedObserver = new ContentObserver(mHandler) {
675             @Override
676             public void onChange(boolean selfChange) {
677                 super.onChange(selfChange);
678                 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
679                 if (mDeviceProvisioned) {
680                     mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
681                 }
682                 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
683             }
684         };
685
686         mContext.getContentResolver().registerContentObserver(
687                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
688                 false, mDeviceProvisionedObserver);
689
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);
697             }
698         }
699     }
700
701     /**
702      * Handle {@link #MSG_DPM_STATE_CHANGED}
703      */
704     protected void handleDevicePolicyManagerStateChanged() {
705         for (int i = mCallbacks.size() - 1; i >= 0; i--) {
706             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
707             if (cb != null) {
708                 cb.onDevicePolicyManagerStateChanged();
709             }
710         }
711     }
712
713     /**
714      * Handle {@link #MSG_USER_SWITCHING}
715      */
716     protected void handleUserSwitching(int userId, IRemoteCallback reply) {
717         for (int i = 0; i < mCallbacks.size(); i++) {
718             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
719             if (cb != null) {
720                 cb.onUserSwitching(userId);
721             }
722         }
723         try {
724             reply.sendResult(null);
725         } catch (RemoteException e) {
726         }
727     }
728
729     /**
730      * Handle {@link #MSG_USER_SWITCH_COMPLETE}
731      */
732     protected void handleUserSwitchComplete(int userId) {
733         for (int i = 0; i < mCallbacks.size(); i++) {
734             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
735             if (cb != null) {
736                 cb.onUserSwitchComplete(userId);
737             }
738         }
739     }
740
741     /**
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.
746      */
747     public void dispatchBootCompleted() {
748         mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
749     }
750
751     /**
752      * Handle {@link #MSG_BOOT_COMPLETED}
753      */
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();
759             if (cb != null) {
760                 cb.onBootCompleted();
761             }
762         }
763     }
764
765     /**
766      * We need to store this state in the KeyguardUpdateMonitor since this class will not be
767      * destroyed.
768      */
769     public boolean hasBootCompleted() {
770         return mBootCompleted;
771     }
772
773     /**
774      * Handle {@link #MSG_USER_REMOVED}
775      */
776     protected void handleUserRemoved(int userId) {
777         for (int i = 0; i < mCallbacks.size(); i++) {
778             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
779             if (cb != null) {
780                 cb.onUserRemoved(userId);
781             }
782         }
783     }
784
785     /**
786      * Handle {@link #MSG_DEVICE_PROVISIONED}
787      */
788     protected void handleDeviceProvisioned() {
789         for (int i = 0; i < mCallbacks.size(); i++) {
790             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
791             if (cb != null) {
792                 cb.onDeviceProvisioned();
793             }
794         }
795         if (mDeviceProvisionedObserver != null) {
796             // We don't need the observer anymore...
797             mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
798             mDeviceProvisionedObserver = null;
799         }
800     }
801
802     /**
803      * Handle {@link #MSG_PHONE_STATE_CHANGED}
804      */
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;
813         }
814         for (int i = 0; i < mCallbacks.size(); i++) {
815             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
816             if (cb != null) {
817                 cb.onPhoneStateChanged(mPhoneState);
818             }
819         }
820     }
821
822     /**
823      * Handle {@link #MSG_RINGER_MODE_CHANGED}
824      */
825     protected void handleRingerModeChange(int mode) {
826         if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
827         mRingMode = mode;
828         for (int i = 0; i < mCallbacks.size(); i++) {
829             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
830             if (cb != null) {
831                 cb.onRingerModeChanged(mode);
832             }
833         }
834     }
835
836     /**
837      * Handle {@link #MSG_TIME_UPDATE}
838      */
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();
843             if (cb != null) {
844                 cb.onTimeChanged();
845             }
846         }
847     }
848
849     /**
850      * Handle {@link #MSG_BATTERY_UPDATE}
851      */
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();
859                 if (cb != null) {
860                     cb.onRefreshBatteryInfo(status);
861                 }
862             }
863         }
864     }
865
866     /**
867      * Handle {@link #MSG_CARRIER_INFO_UPDATE}
868      */
869     private void handleCarrierInfoUpdate() {
870         if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
871             + ", spn = " + mTelephonySpn);
872
873         for (int i = 0; i < mCallbacks.size(); i++) {
874             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
875             if (cb != null) {
876                 cb.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
877             }
878         }
879     }
880
881     /**
882      * Handle {@link #MSG_SIM_STATE_CHANGE}
883      */
884     private void handleSimStateChange(SimArgs simArgs) {
885         final IccCardConstants.State state = simArgs.simState;
886
887         if (DEBUG) {
888             Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
889                     + "state resolved to " + state.toString());
890         }
891
892         if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
893             mSimState = state;
894             for (int i = 0; i < mCallbacks.size(); i++) {
895                 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
896                 if (cb != null) {
897                     cb.onSimStateChanged(state);
898                 }
899             }
900         }
901     }
902
903     /**
904      * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
905      */
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();
910             if (cb != null) {
911                 cb.onClockVisibilityChanged();
912             }
913         }
914     }
915
916     /**
917      * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
918      */
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();
925             if (cb != null) {
926                 cb.onKeyguardVisibilityChangedRaw(isShowing);
927             }
928         }
929     }
930
931     /**
932      * Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED}
933      * @see #sendKeyguardBouncerChanged(boolean)
934      */
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();
941             if (cb != null) {
942                 cb.onKeyguardBouncerChanged(isBouncer);
943             }
944         }
945     }
946
947     /**
948      * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
949      */
950     private void handleReportEmergencyCallAction() {
951         for (int i = 0; i < mCallbacks.size(); i++) {
952             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
953             if (cb != null) {
954                 cb.onEmergencyCallAction();
955             }
956         }
957     }
958
959     public boolean isKeyguardVisible() {
960         return mKeyguardIsVisible;
961     }
962
963     /**
964      * @return if the keyguard is currently in bouncer mode.
965      */
966     public boolean isKeyguardBouncer() {
967         return mBouncer;
968     }
969
970     public boolean isSwitchingUser() {
971         return mSwitchingUser;
972     }
973
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);
980
981         // change in plug state is always interesting
982         if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
983             return true;
984         }
985
986         // change in battery level while plugged in
987         if (nowPluggedIn && old.level != current.level) {
988             return true;
989         }
990
991         // change where battery needs charging
992         if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
993             return true;
994         }
995         return false;
996     }
997
998     /**
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.
1001      */
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();
1006         }
1007         return null;
1008     }
1009
1010     /**
1011      * @return The default plmn (no service)
1012      */
1013     private CharSequence getDefaultPlmn() {
1014         return mContext.getResources().getText(R.string.keyguard_carrier_default);
1015     }
1016
1017     /**
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.
1020      */
1021     private CharSequence getTelephonySpnFrom(Intent intent) {
1022         if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
1023             final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
1024             if (spn != null) {
1025                 return spn;
1026             }
1027         }
1028         return null;
1029     }
1030
1031     /**
1032      * Remove the given observer's callback.
1033      *
1034      * @param callback The callback to remove
1035      */
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);
1041             }
1042         }
1043     }
1044
1045     /**
1046      * Register to receive notifications about general keyguard information
1047      * (see {@link InfoCallback}.
1048      * @param callback The callback to register
1049      */
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"));
1057                 return;
1058             }
1059         }
1060         mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
1061         removeCallback(null); // remove unused references
1062         sendUpdates(callback);
1063     }
1064
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);
1074     }
1075
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();
1081     }
1082
1083     /**
1084      * @see #handleKeyguardBouncerChanged(int)
1085      */
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();
1091     }
1092
1093     public void reportClockVisible(boolean visible) {
1094         mClockVisible = visible;
1095         mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
1096     }
1097
1098     public IccCardConstants.State getSimState() {
1099         return mSimState;
1100     }
1101
1102     /**
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.
1106      *
1107      * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
1108      * through mHandler, this *must* be called from the UI thread.
1109      */
1110     public void reportSimUnlocked() {
1111         handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
1112     }
1113
1114     /**
1115      * Report that the emergency call button has been pressed and the emergency dialer is
1116      * about to be displayed.
1117      *
1118      * @param bypassHandler runs immediately.
1119      *
1120      * NOTE: Must be called from UI thread if bypassHandler == true.
1121      */
1122     public void reportEmergencyCallAction(boolean bypassHandler) {
1123         if (!bypassHandler) {
1124             mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
1125         } else {
1126             handleReportEmergencyCallAction();
1127         }
1128     }
1129
1130     public CharSequence getTelephonyPlmn() {
1131         return mTelephonyPlmn;
1132     }
1133
1134     public CharSequence getTelephonySpn() {
1135         return mTelephonySpn;
1136     }
1137
1138     /**
1139      * @return Whether the device is provisioned (whether they have gone through
1140      *   the setup wizard)
1141      */
1142     public boolean isDeviceProvisioned() {
1143         return mDeviceProvisioned;
1144     }
1145
1146     public int getFailedUnlockAttempts() {
1147         return mFailedAttempts;
1148     }
1149
1150     public void clearFailedUnlockAttempts() {
1151         mFailedAttempts = 0;
1152         mFailedBiometricUnlockAttempts = 0;
1153     }
1154
1155     public void clearFingerprintRecognized() {
1156         mUserFingerprintRecognized.clear();
1157     }
1158
1159     public void reportFailedUnlockAttempt() {
1160         mFailedAttempts++;
1161     }
1162
1163     public boolean isClockVisible() {
1164         return mClockVisible;
1165     }
1166
1167     public int getPhoneState() {
1168         return mPhoneState;
1169     }
1170
1171     public void reportFailedBiometricUnlockAttempt() {
1172         mFailedBiometricUnlockAttempts++;
1173     }
1174
1175     public boolean getMaxBiometricUnlockAttemptsReached() {
1176         return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
1177     }
1178
1179     public boolean isAlternateUnlockEnabled() {
1180         return mAlternateUnlockEnabled;
1181     }
1182
1183     public void setAlternateUnlockEnabled(boolean enabled) {
1184         mAlternateUnlockEnabled = enabled;
1185     }
1186
1187     public boolean isSimLocked() {
1188         return isSimLocked(mSimState);
1189     }
1190
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;
1195     }
1196
1197     public boolean isSimPinSecure() {
1198         return isSimPinSecure(mSimState);
1199     }
1200
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);
1206     }
1207
1208     public DisplayClientState getCachedDisplayClientState() {
1209         return mDisplayClientState;
1210     }
1211
1212     // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1213     // (KeyguardViewMediator, KeyguardHostView)
1214     public void dispatchScreenTurnedOn() {
1215         synchronized (this) {
1216             mScreenOn = true;
1217         }
1218         mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
1219     }
1220
1221     public void dispatchScreenTurndOff(int why) {
1222         synchronized(this) {
1223             mScreenOn = false;
1224         }
1225         mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0));
1226     }
1227
1228     public boolean isScreenOn() {
1229         return mScreenOn;
1230     }
1231 }