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