FileDocCategorySizeDatePackage
KeyguardUpdateMonitor.javaAPI DocAndroid 5.1 API52456Thu Mar 12 22:22:42 GMT 2015com.android.keyguard

KeyguardUpdateMonitor

public class KeyguardUpdateMonitor extends Object implements TrustManager.TrustListener
Watches for updates that may be interesting to the keyguard, and provides the up to date information as well as a registration for callbacks that care to be updated. Note: under time crunch, this has been extended to include some stuff that doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()} and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'...

Fields Summary
private static final String
TAG
private static final boolean
DEBUG
private static final boolean
DEBUG_SIM_STATES
private static final int
FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP
private static final int
LOW_BATTERY_THRESHOLD
private static final String
ACTION_FACE_UNLOCK_STARTED
private static final String
ACTION_FACE_UNLOCK_STOPPED
private static final int
MSG_TIME_UPDATE
private static final int
MSG_BATTERY_UPDATE
private static final int
MSG_SIM_STATE_CHANGE
private static final int
MSG_RINGER_MODE_CHANGED
private static final int
MSG_PHONE_STATE_CHANGED
private static final int
MSG_CLOCK_VISIBILITY_CHANGED
private static final int
MSG_DEVICE_PROVISIONED
private static final int
MSG_DPM_STATE_CHANGED
private static final int
MSG_USER_SWITCHING
private static final int
MSG_USER_REMOVED
private static final int
MSG_KEYGUARD_VISIBILITY_CHANGED
private static final int
MSG_BOOT_COMPLETED
private static final int
MSG_USER_SWITCH_COMPLETE
private static final int
MSG_SET_CURRENT_CLIENT_ID
private static final int
MSG_SET_PLAYBACK_STATE
private static final int
MSG_USER_INFO_CHANGED
private static final int
MSG_REPORT_EMERGENCY_CALL_ACTION
private static final int
MSG_SCREEN_TURNED_ON
private static final int
MSG_SCREEN_TURNED_OFF
private static final int
MSG_KEYGUARD_BOUNCER_CHANGED
private static final int
MSG_FINGERPRINT_PROCESSED
private static final int
MSG_FINGERPRINT_ACQUIRED
private static final int
MSG_FACE_UNLOCK_STATE_CHANGED
private static final int
MSG_SIM_SUBSCRIPTION_INFO_CHANGED
private static KeyguardUpdateMonitor
sInstance
private final android.content.Context
mContext
HashMap
mSimDatas
private int
mRingMode
private int
mPhoneState
private boolean
mKeyguardIsVisible
private boolean
mBouncer
private boolean
mBootCompleted
private boolean
mDeviceProvisioned
private BatteryStatus
mBatteryStatus
private int
mFailedAttempts
private int
mFailedBiometricUnlockAttempts
private boolean
mAlternateUnlockEnabled
private boolean
mClockVisible
private final ArrayList
mCallbacks
private android.database.ContentObserver
mDeviceProvisionedObserver
private boolean
mSwitchingUser
private boolean
mScreenOn
private android.telephony.SubscriptionManager
mSubscriptionManager
private List
mSubscriptionInfo
private final android.os.Handler
mHandler
private android.telephony.SubscriptionManager.OnSubscriptionsChangedListener
mSubscriptionListener
private android.util.SparseBooleanArray
mUserHasTrust
private android.util.SparseBooleanArray
mUserTrustIsManaged
private android.util.SparseBooleanArray
mUserFingerprintRecognized
private android.util.SparseBooleanArray
mUserFaceUnlockRunning
private DisplayClientState
mDisplayClientState
private final android.content.BroadcastReceiver
mBroadcastReceiver
private final android.content.BroadcastReceiver
mBroadcastAllReceiver
private android.service.fingerprint.FingerprintManagerReceiver
mFingerprintManagerReceiver
Constructors Summary
private KeyguardUpdateMonitor(android.content.Context context)

        mContext = context;
        mSubscriptionManager = SubscriptionManager.from(context);
        mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
        // Since device can't be un-provisioned, we only need to register a content observer
        // to update mDeviceProvisioned when we are...
        if (!mDeviceProvisioned) {
            watchForDeviceProvisioning();
        }

        // Take a guess at initial SIM state, battery status and PLMN until we get an update
        mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);

        // Watch for interesting updates
        final IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_TIME_TICK);
        filter.addAction(Intent.ACTION_TIME_CHANGED);
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
        filter.addAction(Intent.ACTION_USER_REMOVED);
        context.registerReceiver(mBroadcastReceiver, filter);

        final IntentFilter bootCompleteFilter = new IntentFilter();
        bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
        context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);

        final IntentFilter allUserFilter = new IntentFilter();
        allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
        allUserFilter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
        allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED);
        allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED);
        allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
        context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
                null, null);

        mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
        try {
            ActivityManagerNative.getDefault().registerUserSwitchObserver(
                    new IUserSwitchObserver.Stub() {
                        @Override
                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
                            mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
                                    newUserId, 0, reply));
                            mSwitchingUser = true;
                        }
                        @Override
                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
                            mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
                                    newUserId, 0));
                            mSwitchingUser = false;
                        }
                    });
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
        trustManager.registerTrustListener(this);

        FingerprintManager fpm;
        fpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
        fpm.startListening(mFingerprintManagerReceiver);
    
Methods Summary
public voidclearFailedUnlockAttempts()

        mFailedAttempts = 0;
        mFailedBiometricUnlockAttempts = 0;
    
public voidclearFingerprintRecognized()

        mUserFingerprintRecognized.clear();
    
public voiddispatchBootCompleted()
This is exposed since {@link Intent#ACTION_BOOT_COMPLETED} is not sticky. If keyguard crashes sometime after boot, then it will never receive this broadcast and hence not handle the event. This method is ultimately called by PhoneWindowManager in this case.

        mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
    
public voiddispatchScreenTurndOff(int why)

        synchronized(this) {
            mScreenOn = false;
        }
        mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0));
    
public voiddispatchScreenTurnedOn()

        synchronized (this) {
            mScreenOn = true;
        }
        mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON);
    
public voiddispatchSetBackground(android.graphics.Bitmap bmp)
IMPORTANT: Must be called from UI thread.

        if (DEBUG) Log.d(TAG, "dispatchSetBackground");
        final int count = mCallbacks.size();
        for (int i = 0; i < count; i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onSetBackground(bmp);
            }
        }
    
public com.android.keyguard.KeyguardUpdateMonitor$DisplayClientStategetCachedDisplayClientState()

        return mDisplayClientState;
    
private java.lang.CharSequencegetDefaultPlmn()

return
The default plmn (no service)

        return mContext.getResources().getText(R.string.keyguard_carrier_default);
    
public intgetFailedUnlockAttempts()

        return mFailedAttempts;
    
public static com.android.keyguard.KeyguardUpdateMonitorgetInstance(android.content.Context context)

        if (sInstance == null) {
            sInstance = new KeyguardUpdateMonitor(context);
        }
        return sInstance;
    
public booleangetMaxBiometricUnlockAttemptsReached()

        return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
    
public intgetNextSubIdForState(com.android.internal.telephony.IccCardConstants.State state)
Find the next SubscriptionId for a SIM in the given state, favoring lower slot numbers first.

param
state
return
subid or {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if none found

        List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
        int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first
        for (int i = 0; i < list.size(); i++) {
            final SubscriptionInfo info = list.get(i);
            final int id = info.getSubscriptionId();
            int slotId = SubscriptionManager.getSlotId(id);
            if (state == getSimState(id) && bestSlotId > slotId ) {
                resultId = id;
                bestSlotId = slotId;
            }
        }
        return resultId;
    
public intgetPhoneState()

        return mPhoneState;
    
public com.android.internal.telephony.IccCardConstants.StategetSimState(int subId)

        if (mSimDatas.containsKey(subId)) {
            return mSimDatas.get(subId).simState;
        } else {
            return State.UNKNOWN;
        }
    
java.util.ListgetSubscriptionInfo(boolean forceReload)

return
List of SubscriptionInfo records, maybe empty but never null

        List<SubscriptionInfo> sil = mSubscriptionInfo;
        if (sil == null || forceReload) {
            sil = mSubscriptionManager.getActiveSubscriptionInfoList();
        }
        if (sil == null) {
            // getActiveSubscriptionInfoList was null callers expect an empty list.
            mSubscriptionInfo = new ArrayList<SubscriptionInfo>();
        } else {
            mSubscriptionInfo = sil;
        }
        return mSubscriptionInfo;
    
public android.telephony.SubscriptionInfogetSubscriptionInfoForSubId(int subId)

        List<SubscriptionInfo> list = getSubscriptionInfo(false /* forceReload */);
        for (int i = 0; i < list.size(); i++) {
            SubscriptionInfo info = list.get(i);
            if (subId == info.getSubscriptionId()) return info;
        }
        return null; // not found
    
public booleangetUserHasTrust(int userId)

        return !isTrustDisabled(userId) && mUserHasTrust.get(userId)
                || mUserFingerprintRecognized.get(userId);
    
public booleangetUserTrustIsManaged(int userId)

        return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
    
private voidhandleBatteryUpdate(com.android.keyguard.KeyguardUpdateMonitor$BatteryStatus status)
Handle {@link #MSG_BATTERY_UPDATE}

        if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
        final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
        mBatteryStatus = status;
        if (batteryUpdateInteresting) {
            for (int i = 0; i < mCallbacks.size(); i++) {
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
                if (cb != null) {
                    cb.onRefreshBatteryInfo(status);
                }
            }
        }
    
protected voidhandleBootCompleted()
Handle {@link #MSG_BOOT_COMPLETED}

        if (mBootCompleted) return;
        mBootCompleted = true;
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onBootCompleted();
            }
        }
    
private voidhandleClockVisibilityChanged()
Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}

        if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onClockVisibilityChanged();
            }
        }
    
protected voidhandleDevicePolicyManagerStateChanged()
Handle {@link #MSG_DPM_STATE_CHANGED}

        for (int i = mCallbacks.size() - 1; i >= 0; i--) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onDevicePolicyManagerStateChanged();
            }
        }
    
protected voidhandleDeviceProvisioned()
Handle {@link #MSG_DEVICE_PROVISIONED}

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onDeviceProvisioned();
            }
        }
        if (mDeviceProvisionedObserver != null) {
            // We don't need the observer anymore...
            mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
            mDeviceProvisionedObserver = null;
        }
    
private voidhandleFaceUnlockStateChanged(boolean running, int userId)

        mUserFaceUnlockRunning.put(userId, running);
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onFaceUnlockStateChanged(running, userId);
            }
        }
    
private voidhandleFingerprintAcquired(int info)

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onFingerprintAcquired(info);
            }
        }
    
private voidhandleFingerprintProcessed(int fingerprintId)

        if (fingerprintId == 0) return; // not a valid fingerprint

        final int userId;
        try {
            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to get current user id: ", e);
            return;
        }
        if (isFingerprintDisabled(userId)) {
            Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
            return;
        }
        final ContentResolver res = mContext.getContentResolver();
        final int ids[] = FingerprintUtils.getFingerprintIdsForUser(res, userId);
        for (int i = 0; i < ids.length; i++) {
            if (ids[i] == fingerprintId) {
                onFingerprintRecognized(userId);
            }
        }
    
private voidhandleKeyguardBouncerChanged(int bouncer)
Handle {@link #MSG_KEYGUARD_BOUNCER_CHANGED}

see
#sendKeyguardBouncerChanged(boolean)

        if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
        boolean isBouncer = (bouncer == 1);
        mBouncer = isBouncer;
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onKeyguardBouncerChanged(isBouncer);
            }
        }
    
private voidhandleKeyguardVisibilityChanged(int showing)
Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}

        if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
        boolean isShowing = (showing == 1);
        mKeyguardIsVisible = isShowing;
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onKeyguardVisibilityChangedRaw(isShowing);
            }
        }
    
protected voidhandlePhoneStateChanged(java.lang.String newState)
Handle {@link #MSG_PHONE_STATE_CHANGED}

        if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
        if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
            mPhoneState = TelephonyManager.CALL_STATE_IDLE;
        } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
            mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
        } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
            mPhoneState = TelephonyManager.CALL_STATE_RINGING;
        }
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onPhoneStateChanged(mPhoneState);
            }
        }
    
private voidhandleReportEmergencyCallAction()
Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onEmergencyCallAction();
            }
        }
    
protected voidhandleRingerModeChange(int mode)
Handle {@link #MSG_RINGER_MODE_CHANGED}

        if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
        mRingMode = mode;
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onRingerModeChanged(mode);
            }
        }
    
protected voidhandleScreenTurnedOff(int arg1)

        clearFingerprintRecognized();
        final int count = mCallbacks.size();
        for (int i = 0; i < count; i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onScreenTurnedOff(arg1);
            }
        }
    
protected voidhandleScreenTurnedOn()

        final int count = mCallbacks.size();
        for (int i = 0; i < count; i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onScreenTurnedOn();
            }
        }
    
private voidhandleSimStateChange(int subId, int slotId, com.android.internal.telephony.IccCardConstants.State state)
Handle {@link #MSG_SIM_STATE_CHANGE}


        if (DEBUG_SIM_STATES) {
            Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
                    + slotId + ", state=" + state +")");
        }

        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
            Log.w(TAG, "invalid subId in handleSimStateChange()");
            return;
        }

        SimData data = mSimDatas.get(subId);
        final boolean changed;
        if (data == null) {
            data = new SimData(state, slotId, subId);
            mSimDatas.put(subId, data);
            changed = true; // no data yet; force update
        } else {
            changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
            data.simState = state;
            data.subId = subId;
            data.slotId = slotId;
        }
        if (changed && state != State.UNKNOWN) {
            for (int i = 0; i < mCallbacks.size(); i++) {
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
                if (cb != null) {
                    cb.onSimStateChanged(subId, slotId, state);
                }
            }
        }
    
protected voidhandleSimSubscriptionInfoChanged()

        if (DEBUG_SIM_STATES) {
            Log.v(TAG, "onSubscriptionInfoChanged()");
            List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
            if (sil != null) {
                for (SubscriptionInfo subInfo : sil) {
                    Log.v(TAG, "SubInfo:" + subInfo);
                }
            } else {
                Log.v(TAG, "onSubscriptionInfoChanged: list is null");
            }
        }
        List<SubscriptionInfo> subscriptionInfos = getSubscriptionInfo(true /* forceReload */);

        // Hack level over 9000: Because the subscription id is not yet valid when we see the
        // first update in handleSimStateChange, we need to force refresh all all SIM states
        // so the subscription id for them is consistent.
        ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>();
        for (int i = 0; i < subscriptionInfos.size(); i++) {
            SubscriptionInfo info = subscriptionInfos.get(i);
            boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex());
            if (changed) {
                changedSubscriptions.add(info);
            }
        }
        for (int i = 0; i < changedSubscriptions.size(); i++) {
            SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
            for (int j = 0; j < mCallbacks.size(); j++) {
                KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
                if (cb != null) {
                    cb.onSimStateChanged(data.subId, data.slotId, data.simState);
                }
            }
        }
        for (int j = 0; j < mCallbacks.size(); j++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
            if (cb != null) {
                cb.onRefreshCarrierInfo();
            }
        }
    
private voidhandleTimeUpdate()
Handle {@link #MSG_TIME_UPDATE}

        if (DEBUG) Log.d(TAG, "handleTimeUpdate");
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onTimeChanged();
            }
        }
    
private voidhandleUserInfoChanged(int userId)

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onUserInfoChanged(userId);
            }
        }
    
protected voidhandleUserRemoved(int userId)
Handle {@link #MSG_USER_REMOVED}

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onUserRemoved(userId);
            }
        }
    
protected voidhandleUserSwitchComplete(int userId)
Handle {@link #MSG_USER_SWITCH_COMPLETE}

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onUserSwitchComplete(userId);
            }
        }
    
protected voidhandleUserSwitching(int userId, android.os.IRemoteCallback reply)
Handle {@link #MSG_USER_SWITCHING}

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onUserSwitching(userId);
            }
        }
        try {
            reply.sendResult(null);
        } catch (RemoteException e) {
        }
    
public booleanhasBootCompleted()
We need to store this state in the KeyguardUpdateMonitor since this class will not be destroyed.

        return mBootCompleted;
    
public booleanisAlternateUnlockEnabled()

        return mAlternateUnlockEnabled;
    
private static booleanisBatteryUpdateInteresting(com.android.keyguard.KeyguardUpdateMonitor$BatteryStatus old, com.android.keyguard.KeyguardUpdateMonitor$BatteryStatus current)

        final boolean nowPluggedIn = current.isPluggedIn();
        final boolean wasPluggedIn = old.isPluggedIn();
        final boolean stateChangedWhilePluggedIn =
            wasPluggedIn == true && nowPluggedIn == true
            && (old.status != current.status);

        // change in plug state is always interesting
        if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
            return true;
        }

        // change in battery level while plugged in
        if (nowPluggedIn && old.level != current.level) {
            return true;
        }

        // change where battery needs charging
        if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
            return true;
        }
        return false;
    
public booleanisClockVisible()

        return mClockVisible;
    
public booleanisDeviceProvisioned()

return
Whether the device is provisioned (whether they have gone through the setup wizard)

        return mDeviceProvisioned;
    
private booleanisDeviceProvisionedInSettingsDb()

        return Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.DEVICE_PROVISIONED, 0) != 0;
    
public booleanisFaceUnlockRunning(int userId)

        return mUserFaceUnlockRunning.get(userId);
    
private booleanisFingerprintDisabled(int userId)

        final DevicePolicyManager dpm =
                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
        return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
                    & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
    
public booleanisKeyguardBouncer()

return
if the keyguard is currently in bouncer mode.

        return mBouncer;
    
public booleanisKeyguardVisible()

        return mKeyguardIsVisible;
    
public booleanisScreenOn()

        return mScreenOn;
    
public booleanisSimPinSecure()

        // True if any SIM is pin secure
        for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) {
            if (isSimPinSecure(getSimState(info.getSubscriptionId()))) return true;
        }
        return false;
    
public static booleanisSimPinSecure(com.android.internal.telephony.IccCardConstants.State state)

        final IccCardConstants.State simState = state;
        return (simState == IccCardConstants.State.PIN_REQUIRED
                || simState == IccCardConstants.State.PUK_REQUIRED
                || simState == IccCardConstants.State.PERM_DISABLED);
    
public booleanisSimPinVoiceSecure()

        // TODO: only count SIMs that handle voice
        return isSimPinSecure();
    
public booleanisSwitchingUser()

        return mSwitchingUser;
    
private booleanisTrustDisabled(int userId)

        final DevicePolicyManager dpm =
                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
        if (dpm != null) {
                // TODO once UI is finalized
                final boolean disabledByGlobalActions = false;
                final boolean disabledBySettings = false;

                // Don't allow trust agent if device is secured with a SIM PIN. This is here
                // mainly because there's no other way to prompt the user to enter their SIM PIN
                // once they get past the keyguard screen.
                final boolean disabledBySimPin = isSimPinSecure();

                final boolean disabledByDpm = (dpm.getKeyguardDisabledFeatures(null, userId)
                        & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
                return disabledByDpm || disabledByGlobalActions || disabledBySettings
                        || disabledBySimPin;
        }
        return false;
    
private voidonFingerprintRecognized(int userId)

        mUserFingerprintRecognized.put(userId, true);
        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onFingerprintRecognized(userId);
            }
        }
    
public voidonTrustChanged(boolean enabled, int userId, boolean initiatedByUser)


    
            
        mUserHasTrust.put(userId, enabled);

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onTrustChanged(userId);
                if (enabled && initiatedByUser) {
                    cb.onTrustInitiatedByUser(userId);
                }
            }
        }
    
public voidonTrustManagedChanged(boolean managed, int userId)

        mUserTrustIsManaged.put(userId, managed);

        for (int i = 0; i < mCallbacks.size(); i++) {
            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
            if (cb != null) {
                cb.onTrustManagedChanged(userId);
            }
        }
    
private booleanrefreshSimState(int subId, int slotId)

return
true if and only if the state has changed for the specified {@code slotId}


        // This is awful. It exists because there are two APIs for getting the SIM status
        // that don't return the complete set of values and have different types. In Keyguard we
        // need IccCardConstants, but TelephonyManager would only give us
        // TelephonyManager.SIM_STATE*, so we retrieve it manually.
        final TelephonyManager tele = TelephonyManager.from(mContext);
        int simState =  tele.getSimState(slotId);
        State state;
        try {
            state = State.intToState(simState);
        } catch(IllegalArgumentException ex) {
            Log.w(TAG, "Unknown sim state: " + simState);
            state = State.UNKNOWN;
        }
        SimData data = mSimDatas.get(subId);
        final boolean changed;
        if (data == null) {
            data = new SimData(state, slotId, subId);
            mSimDatas.put(subId, data);
            changed = true; // no data yet; force update
        } else {
            changed = data.simState != state;
            data.simState = state;
        }
        return changed;
    
public voidregisterCallback(KeyguardUpdateMonitorCallback callback)
Register to receive notifications about general keyguard information (see {@link InfoCallback}.

param
callback The callback to register

        if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
        // Prevent adding duplicate callbacks
        for (int i = 0; i < mCallbacks.size(); i++) {
            if (mCallbacks.get(i).get() == callback) {
                if (DEBUG) Log.e(TAG, "Object tried to add another callback",
                        new Exception("Called by"));
                return;
            }
        }
        mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
        removeCallback(null); // remove unused references
        sendUpdates(callback);
    
public voidremoveCallback(KeyguardUpdateMonitorCallback callback)
Remove the given observer's callback.

param
callback The callback to remove

        if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
        for (int i = mCallbacks.size() - 1; i >= 0; i--) {
            if (mCallbacks.get(i).get() == callback) {
                mCallbacks.remove(i);
            }
        }
    
public voidreportClockVisible(boolean visible)

        mClockVisible = visible;
        mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
    
public voidreportEmergencyCallAction(boolean bypassHandler)
Report that the emergency call button has been pressed and the emergency dialer is about to be displayed.

param
bypassHandler runs immediately. NOTE: Must be called from UI thread if bypassHandler == true.

        if (!bypassHandler) {
            mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
        } else {
            handleReportEmergencyCallAction();
        }
    
public voidreportFailedBiometricUnlockAttempt()

        mFailedBiometricUnlockAttempts++;
    
public voidreportFailedUnlockAttempt()

        mFailedAttempts++;
    
public voidreportSimUnlocked(int subId)
Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we have the information earlier than waiting for the intent broadcast from the telephony code. NOTE: Because handleSimStateChange() invokes callbacks immediately without going through mHandler, this *must* be called from the UI thread.

        if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
        int slotId = SubscriptionManager.getSlotId(subId);
        handleSimStateChange(subId, slotId, State.READY);
    
public voidsendKeyguardBouncerChanged(boolean showingBouncer)

see
#handleKeyguardBouncerChanged(int)

        if (DEBUG) Log.d(TAG, "sendKeyguardBouncerChanged(" + showingBouncer + ")");
        Message message = mHandler.obtainMessage(MSG_KEYGUARD_BOUNCER_CHANGED);
        message.arg1 = showingBouncer ? 1 : 0;
        message.sendToTarget();
    
public voidsendKeyguardVisibilityChanged(boolean showing)

        if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
        Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
        message.arg1 = showing ? 1 : 0;
        message.sendToTarget();
    
private voidsendUpdates(KeyguardUpdateMonitorCallback callback)

        // Notify listener of the current state
        callback.onRefreshBatteryInfo(mBatteryStatus);
        callback.onTimeChanged();
        callback.onRingerModeChanged(mRingMode);
        callback.onPhoneStateChanged(mPhoneState);
        callback.onRefreshCarrierInfo();
        callback.onClockVisibilityChanged();
        for (Entry<Integer, SimData> data : mSimDatas.entrySet()) {
            final SimData state = data.getValue();
            callback.onSimStateChanged(state.subId, state.slotId, state.simState);
        }
    
public voidsetAlternateUnlockEnabled(boolean enabled)

        mAlternateUnlockEnabled = enabled;
    
private voidwatchForDeviceProvisioning()

        mDeviceProvisionedObserver = new ContentObserver(mHandler) {
            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
                if (mDeviceProvisioned) {
                    mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
                }
                if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
            }
        };

        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
                false, mDeviceProvisionedObserver);

        // prevent a race condition between where we check the flag and where we register the
        // observer by grabbing the value once again...
        boolean provisioned = isDeviceProvisionedInSettingsDb();
        if (provisioned != mDeviceProvisioned) {
            mDeviceProvisioned = provisioned;
            if (mDeviceProvisioned) {
                mHandler.sendEmptyMessage(MSG_DEVICE_PROVISIONED);
            }
        }