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