Home | History | Annotate | Download | only in keyguard
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.policy.impl.keyguard;
     18 
     19 import android.app.ActivityManagerNative;
     20 import android.app.IUserSwitchObserver;
     21 import android.app.PendingIntent;
     22 import android.app.admin.DevicePolicyManager;
     23 import android.content.BroadcastReceiver;
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.content.IntentFilter;
     27 import android.database.ContentObserver;
     28 import android.graphics.Bitmap;
     29 
     30 import static android.os.BatteryManager.BATTERY_STATUS_FULL;
     31 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
     32 import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
     33 import static android.os.BatteryManager.EXTRA_STATUS;
     34 import static android.os.BatteryManager.EXTRA_PLUGGED;
     35 import static android.os.BatteryManager.EXTRA_LEVEL;
     36 import static android.os.BatteryManager.EXTRA_HEALTH;
     37 import android.media.AudioManager;
     38 import android.media.IRemoteControlDisplay;
     39 import android.os.BatteryManager;
     40 import android.os.Bundle;
     41 import android.os.Handler;
     42 import android.os.IRemoteCallback;
     43 import android.os.Message;
     44 import android.os.RemoteException;
     45 import android.os.UserHandle;
     46 import android.provider.Settings;
     47 
     48 import com.android.internal.telephony.IccCardConstants;
     49 import com.android.internal.telephony.TelephonyIntents;
     50 
     51 import android.telephony.TelephonyManager;
     52 import android.util.Log;
     53 import com.android.internal.R;
     54 import com.google.android.collect.Lists;
     55 
     56 import java.lang.ref.WeakReference;
     57 import java.util.ArrayList;
     58 
     59 /**
     60  * Watches for updates that may be interesting to the keyguard, and provides
     61  * the up to date information as well as a registration for callbacks that care
     62  * to be updated.
     63  *
     64  * Note: under time crunch, this has been extended to include some stuff that
     65  * doesn't really belong here.  see {@link #handleBatteryUpdate} where it shutdowns
     66  * the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
     67  * and {@link #clearFailedUnlockAttempts()}.  Maybe we should rename this 'KeyguardContext'...
     68  */
     69 public class KeyguardUpdateMonitor {
     70 
     71     private static final String TAG = "KeyguardUpdateMonitor";
     72     private static final boolean DEBUG = false;
     73     private static final boolean DEBUG_SIM_STATES = DEBUG || false;
     74     private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
     75     private static final int LOW_BATTERY_THRESHOLD = 20;
     76 
     77     // Callback messages
     78     private static final int MSG_TIME_UPDATE = 301;
     79     private static final int MSG_BATTERY_UPDATE = 302;
     80     private static final int MSG_CARRIER_INFO_UPDATE = 303;
     81     private static final int MSG_SIM_STATE_CHANGE = 304;
     82     private static final int MSG_RINGER_MODE_CHANGED = 305;
     83     private static final int MSG_PHONE_STATE_CHANGED = 306;
     84     private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
     85     private static final int MSG_DEVICE_PROVISIONED = 308;
     86     private static final int MSG_DPM_STATE_CHANGED = 309;
     87     private static final int MSG_USER_SWITCHING = 310;
     88     private static final int MSG_USER_REMOVED = 311;
     89     private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
     90     protected static final int MSG_BOOT_COMPLETED = 313;
     91     private static final int MSG_USER_SWITCH_COMPLETE = 314;
     92     private static final int MSG_SET_CURRENT_CLIENT_ID = 315;
     93     protected static final int MSG_SET_PLAYBACK_STATE = 316;
     94     protected static final int MSG_USER_INFO_CHANGED = 317;
     95 
     96 
     97     private static KeyguardUpdateMonitor sInstance;
     98 
     99     private final Context mContext;
    100 
    101     // Telephony state
    102     private IccCardConstants.State mSimState = IccCardConstants.State.READY;
    103     private CharSequence mTelephonyPlmn;
    104     private CharSequence mTelephonySpn;
    105     private int mRingMode;
    106     private int mPhoneState;
    107     private boolean mKeyguardIsVisible;
    108     private boolean mBootCompleted;
    109 
    110     // Device provisioning state
    111     private boolean mDeviceProvisioned;
    112 
    113     // Battery status
    114     private BatteryStatus mBatteryStatus;
    115 
    116     // Password attempts
    117     private int mFailedAttempts = 0;
    118     private int mFailedBiometricUnlockAttempts = 0;
    119 
    120     private boolean mAlternateUnlockEnabled;
    121 
    122     private boolean mClockVisible;
    123 
    124     private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
    125             mCallbacks = Lists.newArrayList();
    126     private ContentObserver mDeviceProvisionedObserver;
    127 
    128     private boolean mSwitchingUser;
    129 
    130     private final Handler mHandler = new Handler() {
    131         @Override
    132         public void handleMessage(Message msg) {
    133             switch (msg.what) {
    134                 case MSG_TIME_UPDATE:
    135                     handleTimeUpdate();
    136                     break;
    137                 case MSG_BATTERY_UPDATE:
    138                     handleBatteryUpdate((BatteryStatus) msg.obj);
    139                     break;
    140                 case MSG_CARRIER_INFO_UPDATE:
    141                     handleCarrierInfoUpdate();
    142                     break;
    143                 case MSG_SIM_STATE_CHANGE:
    144                     handleSimStateChange((SimArgs) msg.obj);
    145                     break;
    146                 case MSG_RINGER_MODE_CHANGED:
    147                     handleRingerModeChange(msg.arg1);
    148                     break;
    149                 case MSG_PHONE_STATE_CHANGED:
    150                     handlePhoneStateChanged((String)msg.obj);
    151                     break;
    152                 case MSG_CLOCK_VISIBILITY_CHANGED:
    153                     handleClockVisibilityChanged();
    154                     break;
    155                 case MSG_DEVICE_PROVISIONED:
    156                     handleDeviceProvisioned();
    157                     break;
    158                 case MSG_DPM_STATE_CHANGED:
    159                     handleDevicePolicyManagerStateChanged();
    160                     break;
    161                 case MSG_USER_SWITCHING:
    162                     handleUserSwitching(msg.arg1, (IRemoteCallback)msg.obj);
    163                     break;
    164                 case MSG_USER_SWITCH_COMPLETE:
    165                     handleUserSwitchComplete(msg.arg1);
    166                     break;
    167                 case MSG_USER_REMOVED:
    168                     handleUserRemoved(msg.arg1);
    169                     break;
    170                 case MSG_KEYGUARD_VISIBILITY_CHANGED:
    171                     handleKeyguardVisibilityChanged(msg.arg1);
    172                     break;
    173                 case MSG_BOOT_COMPLETED:
    174                     handleBootCompleted();
    175                     break;
    176                 case MSG_SET_CURRENT_CLIENT_ID:
    177                     handleSetGenerationId(msg.arg1, msg.arg2 != 0, (PendingIntent) msg.obj);
    178                     break;
    179                 case MSG_SET_PLAYBACK_STATE:
    180                     handleSetPlaybackState(msg.arg1, msg.arg2, (Long) msg.obj);
    181                     break;
    182                 case MSG_USER_INFO_CHANGED:
    183                     handleUserInfoChanged(msg.arg1);
    184                     break;
    185             }
    186         }
    187     };
    188 
    189     private AudioManager mAudioManager;
    190 
    191     static class DisplayClientState {
    192         public int clientGeneration;
    193         public boolean clearing;
    194         public PendingIntent intent;
    195         public int playbackState;
    196         public long playbackEventTime;
    197     }
    198 
    199     private DisplayClientState mDisplayClientState = new DisplayClientState();
    200 
    201     /**
    202      * This currently implements the bare minimum required to enable showing and hiding
    203      * KeyguardTransportControl.  There's a lot of client state to maintain which is why
    204      * KeyguardTransportControl maintains an independent connection while it's showing.
    205      */
    206     private final IRemoteControlDisplay.Stub mRemoteControlDisplay =
    207                 new IRemoteControlDisplay.Stub() {
    208 
    209         public void setPlaybackState(int generationId, int state, long stateChangeTimeMs,
    210                 long currentPosMs, float speed) {
    211             Message msg = mHandler.obtainMessage(MSG_SET_PLAYBACK_STATE,
    212                     generationId, state, stateChangeTimeMs);
    213             mHandler.sendMessage(msg);
    214         }
    215 
    216         public void setMetadata(int generationId, Bundle metadata) {
    217 
    218         }
    219 
    220         public void setTransportControlInfo(int generationId, int flags, int posCapabilities) {
    221 
    222         }
    223 
    224         public void setArtwork(int generationId, Bitmap bitmap) {
    225 
    226         }
    227 
    228         public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) {
    229 
    230         }
    231 
    232         public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent,
    233                 boolean clearing) throws RemoteException {
    234             Message msg = mHandler.obtainMessage(MSG_SET_CURRENT_CLIENT_ID,
    235                         clientGeneration, (clearing ? 1 : 0), mediaIntent);
    236             mHandler.sendMessage(msg);
    237         }
    238     };
    239 
    240     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    241 
    242         public void onReceive(Context context, Intent intent) {
    243             final String action = intent.getAction();
    244             if (DEBUG) Log.d(TAG, "received broadcast " + action);
    245 
    246             if (Intent.ACTION_TIME_TICK.equals(action)
    247                     || Intent.ACTION_TIME_CHANGED.equals(action)
    248                     || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
    249                 mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE));
    250             } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
    251                 mTelephonyPlmn = getTelephonyPlmnFrom(intent);
    252                 mTelephonySpn = getTelephonySpnFrom(intent);
    253                 mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE));
    254             } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
    255                 final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
    256                 final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
    257                 final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
    258                 final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
    259                 final Message msg = mHandler.obtainMessage(
    260                         MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
    261                 mHandler.sendMessage(msg);
    262             } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
    263                 if (DEBUG_SIM_STATES) {
    264                     Log.v(TAG, "action " + action + " state" +
    265                         intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
    266                 }
    267                 mHandler.sendMessage(mHandler.obtainMessage(
    268                         MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
    269             } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
    270                 mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
    271                         intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
    272             } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
    273                 String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
    274                 mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
    275             } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
    276                     .equals(action)) {
    277                 mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
    278             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
    279                 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
    280                        intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
    281             } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
    282                 mHandler.sendMessage(mHandler.obtainMessage(MSG_BOOT_COMPLETED));
    283             }
    284         }
    285     };
    286 
    287     private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
    288 
    289         public void onReceive(Context context, Intent intent) {
    290             final String action = intent.getAction();
    291             if (Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
    292                 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED,
    293                         intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0));
    294             }
    295         }
    296     };
    297 
    298     /**
    299      * When we receive a
    300      * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
    301      * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
    302      * we need a single object to pass to the handler.  This class helps decode
    303      * the intent and provide a {@link SimCard.State} result.
    304      */
    305     private static class SimArgs {
    306         public final IccCardConstants.State simState;
    307 
    308         SimArgs(IccCardConstants.State state) {
    309             simState = state;
    310         }
    311 
    312         static SimArgs fromIntent(Intent intent) {
    313             IccCardConstants.State state;
    314             if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
    315                 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
    316             }
    317             String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
    318             if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
    319                 final String absentReason = intent
    320                     .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
    321 
    322                 if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
    323                         absentReason)) {
    324                     state = IccCardConstants.State.PERM_DISABLED;
    325                 } else {
    326                     state = IccCardConstants.State.ABSENT;
    327                 }
    328             } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
    329                 state = IccCardConstants.State.READY;
    330             } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
    331                 final String lockedReason = intent
    332                         .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
    333                 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
    334                     state = IccCardConstants.State.PIN_REQUIRED;
    335                 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
    336                     state = IccCardConstants.State.PUK_REQUIRED;
    337                 } else {
    338                     state = IccCardConstants.State.UNKNOWN;
    339                 }
    340             } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
    341                 state = IccCardConstants.State.NETWORK_LOCKED;
    342             } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
    343                         || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
    344                 // This is required because telephony doesn't return to "READY" after
    345                 // these state transitions. See bug 7197471.
    346                 state = IccCardConstants.State.READY;
    347             } else {
    348                 state = IccCardConstants.State.UNKNOWN;
    349             }
    350             return new SimArgs(state);
    351         }
    352 
    353         public String toString() {
    354             return simState.toString();
    355         }
    356     }
    357 
    358     /* package */ static class BatteryStatus {
    359         public final int status;
    360         public final int level;
    361         public final int plugged;
    362         public final int health;
    363         public BatteryStatus(int status, int level, int plugged, int health) {
    364             this.status = status;
    365             this.level = level;
    366             this.plugged = plugged;
    367             this.health = health;
    368         }
    369 
    370         /**
    371          * Determine whether the device is plugged in (USB, power, or wireless).
    372          * @return true if the device is plugged in.
    373          */
    374         boolean isPluggedIn() {
    375             return plugged == BatteryManager.BATTERY_PLUGGED_AC
    376                     || plugged == BatteryManager.BATTERY_PLUGGED_USB
    377                     || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
    378         }
    379 
    380         /**
    381          * Whether or not the device is charged. Note that some devices never return 100% for
    382          * battery level, so this allows either battery level or status to determine if the
    383          * battery is charged.
    384          * @return true if the device is charged
    385          */
    386         public boolean isCharged() {
    387             return status == BATTERY_STATUS_FULL || level >= 100;
    388         }
    389 
    390         /**
    391          * Whether battery is low and needs to be charged.
    392          * @return true if battery is low
    393          */
    394         public boolean isBatteryLow() {
    395             return level < LOW_BATTERY_THRESHOLD;
    396         }
    397 
    398     }
    399 
    400     public static KeyguardUpdateMonitor getInstance(Context context) {
    401         if (sInstance == null) {
    402             sInstance = new KeyguardUpdateMonitor(context);
    403         }
    404         return sInstance;
    405     }
    406 
    407     protected void handleSetGenerationId(int clientGeneration, boolean clearing, PendingIntent p) {
    408         mDisplayClientState.clientGeneration = clientGeneration;
    409         mDisplayClientState.clearing = clearing;
    410         mDisplayClientState.intent = p;
    411         if (DEBUG)
    412             Log.v(TAG, "handleSetGenerationId(g=" + clientGeneration + ", clear=" + clearing + ")");
    413         for (int i = 0; i < mCallbacks.size(); i++) {
    414             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    415             if (cb != null) {
    416                 cb.onMusicClientIdChanged(clientGeneration, clearing, p);
    417             }
    418         }
    419     }
    420 
    421     protected void handleSetPlaybackState(int generationId, int playbackState, long eventTime) {
    422         if (DEBUG)
    423             Log.v(TAG, "handleSetPlaybackState(gen=" + generationId
    424                 + ", state=" + playbackState + ", t=" + eventTime + ")");
    425         mDisplayClientState.playbackState = playbackState;
    426         mDisplayClientState.playbackEventTime = eventTime;
    427         if (generationId == mDisplayClientState.clientGeneration) {
    428             for (int i = 0; i < mCallbacks.size(); i++) {
    429                 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    430                 if (cb != null) {
    431                     cb.onMusicPlaybackStateChanged(playbackState, eventTime);
    432                 }
    433             }
    434         } else {
    435             Log.w(TAG, "Ignoring generation id " + generationId + " because it's not current");
    436         }
    437     }
    438 
    439     private void handleUserInfoChanged(int userId) {
    440         for (int i = 0; i < mCallbacks.size(); i++) {
    441             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    442             if (cb != null) {
    443                 cb.onUserInfoChanged(userId);
    444             }
    445         }
    446     }
    447 
    448     private KeyguardUpdateMonitor(Context context) {
    449         mContext = context;
    450 
    451         mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
    452         // Since device can't be un-provisioned, we only need to register a content observer
    453         // to update mDeviceProvisioned when we are...
    454         if (!mDeviceProvisioned) {
    455             watchForDeviceProvisioning();
    456         }
    457 
    458         // Take a guess at initial SIM state, battery status and PLMN until we get an update
    459         mSimState = IccCardConstants.State.NOT_READY;
    460         mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
    461         mTelephonyPlmn = getDefaultPlmn();
    462 
    463         // Watch for interesting updates
    464         final IntentFilter filter = new IntentFilter();
    465         filter.addAction(Intent.ACTION_TIME_TICK);
    466         filter.addAction(Intent.ACTION_TIME_CHANGED);
    467         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
    468         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    469         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    470         filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
    471         filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
    472         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
    473         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
    474         filter.addAction(Intent.ACTION_USER_REMOVED);
    475         context.registerReceiver(mBroadcastReceiver, filter);
    476 
    477         final IntentFilter bootCompleteFilter = new IntentFilter();
    478         bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
    479         bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
    480         context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
    481 
    482         final IntentFilter userInfoFilter = new IntentFilter(Intent.ACTION_USER_INFO_CHANGED);
    483         context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, userInfoFilter,
    484                 null, null);
    485 
    486         try {
    487             ActivityManagerNative.getDefault().registerUserSwitchObserver(
    488                     new IUserSwitchObserver.Stub() {
    489                         @Override
    490                         public void onUserSwitching(int newUserId, IRemoteCallback reply) {
    491                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
    492                                     newUserId, 0, reply));
    493                             mSwitchingUser = true;
    494                         }
    495                         @Override
    496                         public void onUserSwitchComplete(int newUserId) throws RemoteException {
    497                             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
    498                                     newUserId));
    499                             mSwitchingUser = false;
    500                         }
    501                     });
    502         } catch (RemoteException e) {
    503             // TODO Auto-generated catch block
    504             e.printStackTrace();
    505         }
    506     }
    507 
    508     private boolean isDeviceProvisionedInSettingsDb() {
    509         return Settings.Global.getInt(mContext.getContentResolver(),
    510                 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
    511     }
    512 
    513     private void watchForDeviceProvisioning() {
    514         mDeviceProvisionedObserver = new ContentObserver(mHandler) {
    515             @Override
    516             public void onChange(boolean selfChange) {
    517                 super.onChange(selfChange);
    518                 mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
    519                 if (mDeviceProvisioned) {
    520                     mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
    521                 }
    522                 if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
    523             }
    524         };
    525 
    526         mContext.getContentResolver().registerContentObserver(
    527                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
    528                 false, mDeviceProvisionedObserver);
    529 
    530         // prevent a race condition between where we check the flag and where we register the
    531         // observer by grabbing the value once again...
    532         boolean provisioned = isDeviceProvisionedInSettingsDb();
    533         if (provisioned != mDeviceProvisioned) {
    534             mDeviceProvisioned = provisioned;
    535             if (mDeviceProvisioned) {
    536                 mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
    537             }
    538         }
    539     }
    540 
    541     /**
    542      * Handle {@link #MSG_DPM_STATE_CHANGED}
    543      */
    544     protected void handleDevicePolicyManagerStateChanged() {
    545         for (int i = mCallbacks.size() - 1; i >= 0; i--) {
    546             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    547             if (cb != null) {
    548                 cb.onDevicePolicyManagerStateChanged();
    549             }
    550         }
    551     }
    552 
    553     /**
    554      * Handle {@link #MSG_USER_SWITCHING}
    555      */
    556     protected void handleUserSwitching(int userId, IRemoteCallback reply) {
    557         for (int i = 0; i < mCallbacks.size(); i++) {
    558             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    559             if (cb != null) {
    560                 cb.onUserSwitching(userId);
    561             }
    562         }
    563         try {
    564             reply.sendResult(null);
    565         } catch (RemoteException e) {
    566         }
    567     }
    568 
    569     /**
    570      * Handle {@link #MSG_USER_SWITCH_COMPLETE}
    571      */
    572     protected void handleUserSwitchComplete(int userId) {
    573         for (int i = 0; i < mCallbacks.size(); i++) {
    574             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    575             if (cb != null) {
    576                 cb.onUserSwitchComplete(userId);
    577             }
    578         }
    579     }
    580 
    581     /**
    582      * Handle {@link #MSG_BOOT_COMPLETED}
    583      */
    584     protected void handleBootCompleted() {
    585         mBootCompleted = true;
    586         mAudioManager = new AudioManager(mContext);
    587         mAudioManager.registerRemoteControlDisplay(mRemoteControlDisplay);
    588         for (int i = 0; i < mCallbacks.size(); i++) {
    589             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    590             if (cb != null) {
    591                 cb.onBootCompleted();
    592             }
    593         }
    594     }
    595 
    596     /**
    597      * We need to store this state in the KeyguardUpdateMonitor since this class will not be
    598      * destroyed.
    599      */
    600     public boolean hasBootCompleted() {
    601         return mBootCompleted;
    602     }
    603 
    604     /**
    605      * Handle {@link #MSG_USER_REMOVED}
    606      */
    607     protected void handleUserRemoved(int userId) {
    608         for (int i = 0; i < mCallbacks.size(); i++) {
    609             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    610             if (cb != null) {
    611                 cb.onUserRemoved(userId);
    612             }
    613         }
    614     }
    615 
    616     /**
    617      * Handle {@link #MSG_DEVICE_PROVISIONED}
    618      */
    619     protected void handleDeviceProvisioned() {
    620         for (int i = 0; i < mCallbacks.size(); i++) {
    621             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    622             if (cb != null) {
    623                 cb.onDeviceProvisioned();
    624             }
    625         }
    626         if (mDeviceProvisionedObserver != null) {
    627             // We don't need the observer anymore...
    628             mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
    629             mDeviceProvisionedObserver = null;
    630         }
    631     }
    632 
    633     /**
    634      * Handle {@link #MSG_PHONE_STATE_CHANGED}
    635      */
    636     protected void handlePhoneStateChanged(String newState) {
    637         if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
    638         if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
    639             mPhoneState = TelephonyManager.CALL_STATE_IDLE;
    640         } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
    641             mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
    642         } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
    643             mPhoneState = TelephonyManager.CALL_STATE_RINGING;
    644         }
    645         for (int i = 0; i < mCallbacks.size(); i++) {
    646             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    647             if (cb != null) {
    648                 cb.onPhoneStateChanged(mPhoneState);
    649             }
    650         }
    651     }
    652 
    653     /**
    654      * Handle {@link #MSG_RINGER_MODE_CHANGED}
    655      */
    656     protected void handleRingerModeChange(int mode) {
    657         if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
    658         mRingMode = mode;
    659         for (int i = 0; i < mCallbacks.size(); i++) {
    660             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    661             if (cb != null) {
    662                 cb.onRingerModeChanged(mode);
    663             }
    664         }
    665     }
    666 
    667     /**
    668      * Handle {@link #MSG_TIME_UPDATE}
    669      */
    670     private void handleTimeUpdate() {
    671         if (DEBUG) Log.d(TAG, "handleTimeUpdate");
    672         for (int i = 0; i < mCallbacks.size(); i++) {
    673             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    674             if (cb != null) {
    675                 cb.onTimeChanged();
    676             }
    677         }
    678     }
    679 
    680     /**
    681      * Handle {@link #MSG_BATTERY_UPDATE}
    682      */
    683     private void handleBatteryUpdate(BatteryStatus status) {
    684         if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
    685         final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
    686         mBatteryStatus = status;
    687         if (batteryUpdateInteresting) {
    688             for (int i = 0; i < mCallbacks.size(); i++) {
    689                 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    690                 if (cb != null) {
    691                     cb.onRefreshBatteryInfo(status);
    692                 }
    693             }
    694         }
    695     }
    696 
    697     /**
    698      * Handle {@link #MSG_CARRIER_INFO_UPDATE}
    699      */
    700     private void handleCarrierInfoUpdate() {
    701         if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
    702             + ", spn = " + mTelephonySpn);
    703 
    704         for (int i = 0; i < mCallbacks.size(); i++) {
    705             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    706             if (cb != null) {
    707                 cb.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
    708             }
    709         }
    710     }
    711 
    712     /**
    713      * Handle {@link #MSG_SIM_STATE_CHANGE}
    714      */
    715     private void handleSimStateChange(SimArgs simArgs) {
    716         final IccCardConstants.State state = simArgs.simState;
    717 
    718         if (DEBUG) {
    719             Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
    720                     + "state resolved to " + state.toString());
    721         }
    722 
    723         if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
    724             mSimState = state;
    725             for (int i = 0; i < mCallbacks.size(); i++) {
    726                 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    727                 if (cb != null) {
    728                     cb.onSimStateChanged(state);
    729                 }
    730             }
    731         }
    732     }
    733 
    734     /**
    735      * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
    736      */
    737     private void handleClockVisibilityChanged() {
    738         if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
    739         for (int i = 0; i < mCallbacks.size(); i++) {
    740             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    741             if (cb != null) {
    742                 cb.onClockVisibilityChanged();
    743             }
    744         }
    745     }
    746 
    747     /**
    748      * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
    749      */
    750     private void handleKeyguardVisibilityChanged(int showing) {
    751         if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
    752         boolean isShowing = (showing == 1);
    753         mKeyguardIsVisible = isShowing;
    754         for (int i = 0; i < mCallbacks.size(); i++) {
    755             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
    756             if (cb != null) {
    757                 cb.onKeyguardVisibilityChanged(isShowing);
    758             }
    759         }
    760     }
    761 
    762     public boolean isKeyguardVisible() {
    763         return mKeyguardIsVisible;
    764     }
    765 
    766     public boolean isSwitchingUser() {
    767         return mSwitchingUser;
    768     }
    769 
    770     private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
    771         final boolean nowPluggedIn = current.isPluggedIn();
    772         final boolean wasPluggedIn = old.isPluggedIn();
    773         final boolean stateChangedWhilePluggedIn =
    774             wasPluggedIn == true && nowPluggedIn == true
    775             && (old.status != current.status);
    776 
    777         // change in plug state is always interesting
    778         if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
    779             return true;
    780         }
    781 
    782         // change in battery level while plugged in
    783         if (nowPluggedIn && old.level != current.level) {
    784             return true;
    785         }
    786 
    787         // change where battery needs charging
    788         if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
    789             return true;
    790         }
    791         return false;
    792     }
    793 
    794     /**
    795      * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
    796      * @return The string to use for the plmn, or null if it should not be shown.
    797      */
    798     private CharSequence getTelephonyPlmnFrom(Intent intent) {
    799         if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
    800             final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
    801             return (plmn != null) ? plmn : getDefaultPlmn();
    802         }
    803         return null;
    804     }
    805 
    806     /**
    807      * @return The default plmn (no service)
    808      */
    809     private CharSequence getDefaultPlmn() {
    810         return mContext.getResources().getText(R.string.lockscreen_carrier_default);
    811     }
    812 
    813     /**
    814      * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
    815      * @return The string to use for the plmn, or null if it should not be shown.
    816      */
    817     private CharSequence getTelephonySpnFrom(Intent intent) {
    818         if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
    819             final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
    820             if (spn != null) {
    821                 return spn;
    822             }
    823         }
    824         return null;
    825     }
    826 
    827     /**
    828      * Remove the given observer's callback.
    829      *
    830      * @param callback The callback to remove
    831      */
    832     public void removeCallback(KeyguardUpdateMonitorCallback callback) {
    833         if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
    834         for (int i = mCallbacks.size() - 1; i >= 0; i--) {
    835             if (mCallbacks.get(i).get() == callback) {
    836                 mCallbacks.remove(i);
    837             }
    838         }
    839     }
    840 
    841     /**
    842      * Register to receive notifications about general keyguard information
    843      * (see {@link InfoCallback}.
    844      * @param callback The callback to register
    845      */
    846     public void registerCallback(KeyguardUpdateMonitorCallback callback) {
    847         if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
    848         // Prevent adding duplicate callbacks
    849         for (int i = 0; i < mCallbacks.size(); i++) {
    850             if (mCallbacks.get(i).get() == callback) {
    851                 if (DEBUG) Log.e(TAG, "Object tried to add another callback",
    852                         new Exception("Called by"));
    853                 return;
    854             }
    855         }
    856         mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
    857         removeCallback(null); // remove unused references
    858         sendUpdates(callback);
    859     }
    860 
    861     private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
    862         // Notify listener of the current state
    863         callback.onRefreshBatteryInfo(mBatteryStatus);
    864         callback.onTimeChanged();
    865         callback.onRingerModeChanged(mRingMode);
    866         callback.onPhoneStateChanged(mPhoneState);
    867         callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
    868         callback.onClockVisibilityChanged();
    869         callback.onSimStateChanged(mSimState);
    870         callback.onMusicClientIdChanged(
    871                 mDisplayClientState.clientGeneration,
    872                 mDisplayClientState.clearing,
    873                 mDisplayClientState.intent);
    874         callback.onMusicPlaybackStateChanged(mDisplayClientState.playbackState,
    875                 mDisplayClientState.playbackEventTime);
    876     }
    877 
    878     public void sendKeyguardVisibilityChanged(boolean showing) {
    879         if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
    880         Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
    881         message.arg1 = showing ? 1 : 0;
    882         message.sendToTarget();
    883     }
    884 
    885     public void reportClockVisible(boolean visible) {
    886         mClockVisible = visible;
    887         mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
    888     }
    889 
    890     public IccCardConstants.State getSimState() {
    891         return mSimState;
    892     }
    893 
    894     /**
    895      * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
    896      * have the information earlier than waiting for the intent
    897      * broadcast from the telephony code.
    898      *
    899      * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
    900      * through mHandler, this *must* be called from the UI thread.
    901      */
    902     public void reportSimUnlocked() {
    903         handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
    904     }
    905 
    906     public CharSequence getTelephonyPlmn() {
    907         return mTelephonyPlmn;
    908     }
    909 
    910     public CharSequence getTelephonySpn() {
    911         return mTelephonySpn;
    912     }
    913 
    914     /**
    915      * @return Whether the device is provisioned (whether they have gone through
    916      *   the setup wizard)
    917      */
    918     public boolean isDeviceProvisioned() {
    919         return mDeviceProvisioned;
    920     }
    921 
    922     public int getFailedUnlockAttempts() {
    923         return mFailedAttempts;
    924     }
    925 
    926     public void clearFailedUnlockAttempts() {
    927         mFailedAttempts = 0;
    928         mFailedBiometricUnlockAttempts = 0;
    929     }
    930 
    931     public void reportFailedUnlockAttempt() {
    932         mFailedAttempts++;
    933     }
    934 
    935     public boolean isClockVisible() {
    936         return mClockVisible;
    937     }
    938 
    939     public int getPhoneState() {
    940         return mPhoneState;
    941     }
    942 
    943     public void reportFailedBiometricUnlockAttempt() {
    944         mFailedBiometricUnlockAttempts++;
    945     }
    946 
    947     public boolean getMaxBiometricUnlockAttemptsReached() {
    948         return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
    949     }
    950 
    951     public boolean isAlternateUnlockEnabled() {
    952         return mAlternateUnlockEnabled;
    953     }
    954 
    955     public void setAlternateUnlockEnabled(boolean enabled) {
    956         mAlternateUnlockEnabled = enabled;
    957     }
    958 
    959     public boolean isSimLocked() {
    960         return isSimLocked(mSimState);
    961     }
    962 
    963     public static boolean isSimLocked(IccCardConstants.State state) {
    964         return state == IccCardConstants.State.PIN_REQUIRED
    965         || state == IccCardConstants.State.PUK_REQUIRED
    966         || state == IccCardConstants.State.PERM_DISABLED;
    967     }
    968 
    969     public boolean isSimPinSecure() {
    970         return isSimPinSecure(mSimState);
    971     }
    972 
    973     public static boolean isSimPinSecure(IccCardConstants.State state) {
    974         final IccCardConstants.State simState = state;
    975         return (simState == IccCardConstants.State.PIN_REQUIRED
    976                 || simState == IccCardConstants.State.PUK_REQUIRED
    977                 || simState == IccCardConstants.State.PERM_DISABLED);
    978     }
    979 
    980     public DisplayClientState getCachedDisplayClientState() {
    981         return mDisplayClientState;
    982     }
    983 }
    984