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
onTrustChanged(boolean enabled, int userId, boolean initiatedByUser)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 
handleSimSubscriptionInfoChanged()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 */
getSubscriptionInfo(boolean forceReload)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
onTrustManagedChanged(boolean managed, int userId)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 
onFingerprintRecognized(int userId)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 
handleFingerprintProcessed(int fingerprintId)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 
handleFingerprintAcquired(int info)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 
handleFaceUnlockStateChanged(boolean running, int userId)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 
isFaceUnlockRunning(int userId)381     public boolean isFaceUnlockRunning(int userId) {
382         return mUserFaceUnlockRunning.get(userId);
383     }
384 
isTrustDisabled(int userId)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 
isFingerprintDisabled(int userId)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 
getUserHasTrust(int userId)413     public boolean getUserHasTrust(int userId) {
414         return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
415                 || mUserFingerprintRecognized.get(userId);
416     }
417 
getUserTrustIsManaged(int userId)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 
SimData(State state, int slot, int id)525         SimData(State state, int slot, int id) {
526             simState = state;
527             slotId = slot;
528             subId = id;
529         }
530 
fromIntent(Intent intent)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 
toString()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;
BatteryStatus(int status, int level, int plugged, 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          */
isPluggedIn()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          */
isCharged()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          */
isBatteryLow()616         public boolean isBatteryLow() {
617             return level < LOW_BATTERY_THRESHOLD;
618         }
619 
620     }
621 
getInstance(Context context)622     public static KeyguardUpdateMonitor getInstance(Context context) {
623         if (sInstance == null) {
624             sInstance = new KeyguardUpdateMonitor(context);
625         }
626         return sInstance;
627     }
628 
handleScreenTurnedOn()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 
handleScreenTurnedOff(int arg1)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      */
dispatchSetBackground(Bitmap bmp)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 
handleUserInfoChanged(int userId)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 
KeyguardUpdateMonitor(Context context)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 
isDeviceProvisionedInSettingsDb()742     private boolean isDeviceProvisionedInSettingsDb() {
743         return Settings.Global.getInt(mContext.getContentResolver(),
744                 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
745     }
746 
watchForDeviceProvisioning()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      */
handleDevicePolicyManagerStateChanged()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      */
handleUserSwitching(int userId, IRemoteCallback reply)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      */
handleUserSwitchComplete(int userId)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      */
dispatchBootCompleted()821     public void dispatchBootCompleted() {
822         mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
823     }
824 
825     /**
826      * Handle {@link #MSG_BOOT_COMPLETED}
827      */
handleBootCompleted()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      */
hasBootCompleted()843     public boolean hasBootCompleted() {
844         return mBootCompleted;
845     }
846 
847     /**
848      * Handle {@link #MSG_USER_REMOVED}
849      */
handleUserRemoved(int userId)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      */
handleDeviceProvisioned()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      */
handlePhoneStateChanged(String newState)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      */
handleRingerModeChange(int mode)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      */
handleTimeUpdate()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      */
handleBatteryUpdate(BatteryStatus status)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      */
handleSimStateChange(int subId, int slotId, State state)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      */
handleClockVisibilityChanged()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      */
handleKeyguardVisibilityChanged(int showing)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      */
handleKeyguardBouncerChanged(int bouncer)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      */
handleReportEmergencyCallAction()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 
isKeyguardVisible()1033     public boolean isKeyguardVisible() {
1034         return mKeyguardIsVisible;
1035     }
1036 
1037     /**
1038      * @return if the keyguard is currently in bouncer mode.
1039      */
isKeyguardBouncer()1040     public boolean isKeyguardBouncer() {
1041         return mBouncer;
1042     }
1043 
isSwitchingUser()1044     public boolean isSwitchingUser() {
1045         return mSwitchingUser;
1046     }
1047 
isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current)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      */
getDefaultPlmn()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      */
removeCallback(KeyguardUpdateMonitorCallback callback)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      */
registerCallback(KeyguardUpdateMonitorCallback callback)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 
sendUpdates(KeyguardUpdateMonitorCallback callback)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 
sendKeyguardVisibilityChanged(boolean showing)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      */
sendKeyguardBouncerChanged(boolean showingBouncer)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 
reportClockVisible(boolean visible)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      */
reportSimUnlocked(int subId)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      */
reportEmergencyCallAction(boolean bypassHandler)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      */
isDeviceProvisioned()1183     public boolean isDeviceProvisioned() {
1184         return mDeviceProvisioned;
1185     }
1186 
getFailedUnlockAttempts()1187     public int getFailedUnlockAttempts() {
1188         return mFailedAttempts;
1189     }
1190 
clearFailedUnlockAttempts()1191     public void clearFailedUnlockAttempts() {
1192         mFailedAttempts = 0;
1193         mFailedBiometricUnlockAttempts = 0;
1194     }
1195 
clearFingerprintRecognized()1196     public void clearFingerprintRecognized() {
1197         mUserFingerprintRecognized.clear();
1198     }
1199 
reportFailedUnlockAttempt()1200     public void reportFailedUnlockAttempt() {
1201         mFailedAttempts++;
1202     }
1203 
isClockVisible()1204     public boolean isClockVisible() {
1205         return mClockVisible;
1206     }
1207 
getPhoneState()1208     public int getPhoneState() {
1209         return mPhoneState;
1210     }
1211 
reportFailedBiometricUnlockAttempt()1212     public void reportFailedBiometricUnlockAttempt() {
1213         mFailedBiometricUnlockAttempts++;
1214     }
1215 
getMaxBiometricUnlockAttemptsReached()1216     public boolean getMaxBiometricUnlockAttemptsReached() {
1217         return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
1218     }
1219 
isAlternateUnlockEnabled()1220     public boolean isAlternateUnlockEnabled() {
1221         return mAlternateUnlockEnabled;
1222     }
1223 
setAlternateUnlockEnabled(boolean enabled)1224     public void setAlternateUnlockEnabled(boolean enabled) {
1225         mAlternateUnlockEnabled = enabled;
1226     }
1227 
isSimPinVoiceSecure()1228     public boolean isSimPinVoiceSecure() {
1229         // TODO: only count SIMs that handle voice
1230         return isSimPinSecure();
1231     }
1232 
isSimPinSecure()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 
getSimState(int subId)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      */
refreshSimState(int subId, int slotId)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 
isSimPinSecure(IccCardConstants.State state)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 
getCachedDisplayClientState()1287     public DisplayClientState getCachedDisplayClientState() {
1288         return mDisplayClientState;
1289     }
1290 
1291     // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
1292     // (KeyguardViewMediator, KeyguardHostView)
dispatchScreenTurnedOn()1293     public void dispatchScreenTurnedOn() {
1294         synchronized (this) {
1295             mScreenOn = true;
1296         }
1297         mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
1298     }
1299 
dispatchScreenTurndOff(int why)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 
isScreenOn()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      */
getNextSubIdForState(State state)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 
getSubscriptionInfoForSubId(int subId)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