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