Home | History | Annotate | Download | only in keyguard
      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 }
   1232