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