[go: nahoru, domu]

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