KeyguardUpdateMonitor.java revision 20daffd91e4a53054f8c4d7a66c2a68100abee03
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.keyguard; 18 19import android.app.ActivityManagerNative; 20import android.app.IUserSwitchObserver; 21import android.app.PendingIntent; 22import android.app.admin.DevicePolicyManager; 23import android.content.BroadcastReceiver; 24import android.content.Context; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.database.ContentObserver; 28import android.graphics.Bitmap; 29 30import static android.os.BatteryManager.BATTERY_STATUS_FULL; 31import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; 32import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; 33import static android.os.BatteryManager.EXTRA_STATUS; 34import static android.os.BatteryManager.EXTRA_PLUGGED; 35import static android.os.BatteryManager.EXTRA_LEVEL; 36import static android.os.BatteryManager.EXTRA_HEALTH; 37import android.media.AudioManager; 38import android.media.IRemoteControlDisplay; 39import android.os.BatteryManager; 40import android.os.Bundle; 41import android.os.Handler; 42import android.os.IRemoteCallback; 43import android.os.Message; 44import android.os.RemoteException; 45import android.os.UserHandle; 46import android.provider.Settings; 47 48import com.android.internal.telephony.IccCardConstants; 49import com.android.internal.telephony.TelephonyIntents; 50 51import android.telephony.TelephonyManager; 52import android.util.Log; 53import com.google.android.collect.Lists; 54 55import java.lang.ref.WeakReference; 56import 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 */ 68public 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 if (!mBootCompleted) { 639 mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED); 640 } 641 } 642 643 /** 644 * Handle {@link #MSG_BOOT_COMPLETED} 645 */ 646 protected void handleBootCompleted() { 647 mBootCompleted = true; 648 mAudioManager = new AudioManager(mContext); 649 mAudioManager.registerRemoteControlDisplay(mRemoteControlDisplay); 650 for (int i = 0; i < mCallbacks.size(); i++) { 651 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 652 if (cb != null) { 653 cb.onBootCompleted(); 654 } 655 } 656 } 657 658 /** 659 * We need to store this state in the KeyguardUpdateMonitor since this class will not be 660 * destroyed. 661 */ 662 public boolean hasBootCompleted() { 663 return mBootCompleted; 664 } 665 666 /** 667 * Handle {@link #MSG_USER_REMOVED} 668 */ 669 protected void handleUserRemoved(int userId) { 670 for (int i = 0; i < mCallbacks.size(); i++) { 671 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 672 if (cb != null) { 673 cb.onUserRemoved(userId); 674 } 675 } 676 } 677 678 /** 679 * Handle {@link #MSG_DEVICE_PROVISIONED} 680 */ 681 protected void handleDeviceProvisioned() { 682 for (int i = 0; i < mCallbacks.size(); i++) { 683 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 684 if (cb != null) { 685 cb.onDeviceProvisioned(); 686 } 687 } 688 if (mDeviceProvisionedObserver != null) { 689 // We don't need the observer anymore... 690 mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver); 691 mDeviceProvisionedObserver = null; 692 } 693 } 694 695 /** 696 * Handle {@link #MSG_PHONE_STATE_CHANGED} 697 */ 698 protected void handlePhoneStateChanged(String newState) { 699 if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")"); 700 if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) { 701 mPhoneState = TelephonyManager.CALL_STATE_IDLE; 702 } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) { 703 mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK; 704 } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) { 705 mPhoneState = TelephonyManager.CALL_STATE_RINGING; 706 } 707 for (int i = 0; i < mCallbacks.size(); i++) { 708 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 709 if (cb != null) { 710 cb.onPhoneStateChanged(mPhoneState); 711 } 712 } 713 } 714 715 /** 716 * Handle {@link #MSG_RINGER_MODE_CHANGED} 717 */ 718 protected void handleRingerModeChange(int mode) { 719 if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")"); 720 mRingMode = mode; 721 for (int i = 0; i < mCallbacks.size(); i++) { 722 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 723 if (cb != null) { 724 cb.onRingerModeChanged(mode); 725 } 726 } 727 } 728 729 /** 730 * Handle {@link #MSG_TIME_UPDATE} 731 */ 732 private void handleTimeUpdate() { 733 if (DEBUG) Log.d(TAG, "handleTimeUpdate"); 734 for (int i = 0; i < mCallbacks.size(); i++) { 735 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 736 if (cb != null) { 737 cb.onTimeChanged(); 738 } 739 } 740 } 741 742 /** 743 * Handle {@link #MSG_BATTERY_UPDATE} 744 */ 745 private void handleBatteryUpdate(BatteryStatus status) { 746 if (DEBUG) Log.d(TAG, "handleBatteryUpdate"); 747 final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status); 748 mBatteryStatus = status; 749 if (batteryUpdateInteresting) { 750 for (int i = 0; i < mCallbacks.size(); i++) { 751 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 752 if (cb != null) { 753 cb.onRefreshBatteryInfo(status); 754 } 755 } 756 } 757 } 758 759 /** 760 * Handle {@link #MSG_CARRIER_INFO_UPDATE} 761 */ 762 private void handleCarrierInfoUpdate() { 763 if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn 764 + ", spn = " + mTelephonySpn); 765 766 for (int i = 0; i < mCallbacks.size(); i++) { 767 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 768 if (cb != null) { 769 cb.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn); 770 } 771 } 772 } 773 774 /** 775 * Handle {@link #MSG_SIM_STATE_CHANGE} 776 */ 777 private void handleSimStateChange(SimArgs simArgs) { 778 final IccCardConstants.State state = simArgs.simState; 779 780 if (DEBUG) { 781 Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " " 782 + "state resolved to " + state.toString()); 783 } 784 785 if (state != IccCardConstants.State.UNKNOWN && state != mSimState) { 786 mSimState = state; 787 for (int i = 0; i < mCallbacks.size(); i++) { 788 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 789 if (cb != null) { 790 cb.onSimStateChanged(state); 791 } 792 } 793 } 794 } 795 796 /** 797 * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED} 798 */ 799 private void handleClockVisibilityChanged() { 800 if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()"); 801 for (int i = 0; i < mCallbacks.size(); i++) { 802 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 803 if (cb != null) { 804 cb.onClockVisibilityChanged(); 805 } 806 } 807 } 808 809 /** 810 * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED} 811 */ 812 private void handleKeyguardVisibilityChanged(int showing) { 813 if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")"); 814 boolean isShowing = (showing == 1); 815 mKeyguardIsVisible = isShowing; 816 for (int i = 0; i < mCallbacks.size(); i++) { 817 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 818 if (cb != null) { 819 cb.onKeyguardVisibilityChanged(isShowing); 820 } 821 } 822 } 823 824 /** 825 * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION} 826 */ 827 private void handleReportEmergencyCallAction() { 828 for (int i = 0; i < mCallbacks.size(); i++) { 829 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); 830 if (cb != null) { 831 cb.onEmergencyCallAction(); 832 } 833 } 834 } 835 836 public boolean isKeyguardVisible() { 837 return mKeyguardIsVisible; 838 } 839 840 public boolean isSwitchingUser() { 841 return mSwitchingUser; 842 } 843 844 private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) { 845 final boolean nowPluggedIn = current.isPluggedIn(); 846 final boolean wasPluggedIn = old.isPluggedIn(); 847 final boolean stateChangedWhilePluggedIn = 848 wasPluggedIn == true && nowPluggedIn == true 849 && (old.status != current.status); 850 851 // change in plug state is always interesting 852 if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) { 853 return true; 854 } 855 856 // change in battery level while plugged in 857 if (nowPluggedIn && old.level != current.level) { 858 return true; 859 } 860 861 // change where battery needs charging 862 if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) { 863 return true; 864 } 865 return false; 866 } 867 868 /** 869 * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION} 870 * @return The string to use for the plmn, or null if it should not be shown. 871 */ 872 private CharSequence getTelephonyPlmnFrom(Intent intent) { 873 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) { 874 final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN); 875 return (plmn != null) ? plmn : getDefaultPlmn(); 876 } 877 return null; 878 } 879 880 /** 881 * @return The default plmn (no service) 882 */ 883 private CharSequence getDefaultPlmn() { 884 return mContext.getResources().getText(R.string.keyguard_carrier_default); 885 } 886 887 /** 888 * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION} 889 * @return The string to use for the plmn, or null if it should not be shown. 890 */ 891 private CharSequence getTelephonySpnFrom(Intent intent) { 892 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) { 893 final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN); 894 if (spn != null) { 895 return spn; 896 } 897 } 898 return null; 899 } 900 901 /** 902 * Remove the given observer's callback. 903 * 904 * @param callback The callback to remove 905 */ 906 public void removeCallback(KeyguardUpdateMonitorCallback callback) { 907 if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback); 908 for (int i = mCallbacks.size() - 1; i >= 0; i--) { 909 if (mCallbacks.get(i).get() == callback) { 910 mCallbacks.remove(i); 911 } 912 } 913 } 914 915 /** 916 * Register to receive notifications about general keyguard information 917 * (see {@link InfoCallback}. 918 * @param callback The callback to register 919 */ 920 public void registerCallback(KeyguardUpdateMonitorCallback callback) { 921 if (DEBUG) Log.v(TAG, "*** register callback for " + callback); 922 // Prevent adding duplicate callbacks 923 for (int i = 0; i < mCallbacks.size(); i++) { 924 if (mCallbacks.get(i).get() == callback) { 925 if (DEBUG) Log.e(TAG, "Object tried to add another callback", 926 new Exception("Called by")); 927 return; 928 } 929 } 930 mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback)); 931 removeCallback(null); // remove unused references 932 sendUpdates(callback); 933 } 934 935 private void sendUpdates(KeyguardUpdateMonitorCallback callback) { 936 // Notify listener of the current state 937 callback.onRefreshBatteryInfo(mBatteryStatus); 938 callback.onTimeChanged(); 939 callback.onRingerModeChanged(mRingMode); 940 callback.onPhoneStateChanged(mPhoneState); 941 callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn); 942 callback.onClockVisibilityChanged(); 943 callback.onSimStateChanged(mSimState); 944 callback.onMusicClientIdChanged( 945 mDisplayClientState.clientGeneration, 946 mDisplayClientState.clearing, 947 mDisplayClientState.intent); 948 callback.onMusicPlaybackStateChanged(mDisplayClientState.playbackState, 949 mDisplayClientState.playbackEventTime); 950 } 951 952 public void sendKeyguardVisibilityChanged(boolean showing) { 953 if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")"); 954 Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED); 955 message.arg1 = showing ? 1 : 0; 956 message.sendToTarget(); 957 } 958 959 public void reportClockVisible(boolean visible) { 960 mClockVisible = visible; 961 mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget(); 962 } 963 964 public IccCardConstants.State getSimState() { 965 return mSimState; 966 } 967 968 /** 969 * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we 970 * have the information earlier than waiting for the intent 971 * broadcast from the telephony code. 972 * 973 * NOTE: Because handleSimStateChange() invokes callbacks immediately without going 974 * through mHandler, this *must* be called from the UI thread. 975 */ 976 public void reportSimUnlocked() { 977 handleSimStateChange(new SimArgs(IccCardConstants.State.READY)); 978 } 979 980 /** 981 * Report that the emergency call button has been pressed and the emergency dialer is 982 * about to be displayed. 983 * 984 * @param bypassHandler runs immediately. 985 * 986 * NOTE: Must be called from UI thread if bypassHandler == true. 987 */ 988 public void reportEmergencyCallAction(boolean bypassHandler) { 989 if (!bypassHandler) { 990 mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget(); 991 } else { 992 handleReportEmergencyCallAction(); 993 } 994 } 995 996 public CharSequence getTelephonyPlmn() { 997 return mTelephonyPlmn; 998 } 999 1000 public CharSequence getTelephonySpn() { 1001 return mTelephonySpn; 1002 } 1003 1004 /** 1005 * @return Whether the device is provisioned (whether they have gone through 1006 * the setup wizard) 1007 */ 1008 public boolean isDeviceProvisioned() { 1009 return mDeviceProvisioned; 1010 } 1011 1012 public int getFailedUnlockAttempts() { 1013 return mFailedAttempts; 1014 } 1015 1016 public void clearFailedUnlockAttempts() { 1017 mFailedAttempts = 0; 1018 mFailedBiometricUnlockAttempts = 0; 1019 } 1020 1021 public void reportFailedUnlockAttempt() { 1022 mFailedAttempts++; 1023 } 1024 1025 public boolean isClockVisible() { 1026 return mClockVisible; 1027 } 1028 1029 public int getPhoneState() { 1030 return mPhoneState; 1031 } 1032 1033 public void reportFailedBiometricUnlockAttempt() { 1034 mFailedBiometricUnlockAttempts++; 1035 } 1036 1037 public boolean getMaxBiometricUnlockAttemptsReached() { 1038 return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP; 1039 } 1040 1041 public boolean isAlternateUnlockEnabled() { 1042 return mAlternateUnlockEnabled; 1043 } 1044 1045 public void setAlternateUnlockEnabled(boolean enabled) { 1046 mAlternateUnlockEnabled = enabled; 1047 } 1048 1049 public boolean isSimLocked() { 1050 return isSimLocked(mSimState); 1051 } 1052 1053 public static boolean isSimLocked(IccCardConstants.State state) { 1054 return state == IccCardConstants.State.PIN_REQUIRED 1055 || state == IccCardConstants.State.PUK_REQUIRED 1056 || state == IccCardConstants.State.PERM_DISABLED; 1057 } 1058 1059 public boolean isSimPinSecure() { 1060 return isSimPinSecure(mSimState); 1061 } 1062 1063 public static boolean isSimPinSecure(IccCardConstants.State state) { 1064 final IccCardConstants.State simState = state; 1065 return (simState == IccCardConstants.State.PIN_REQUIRED 1066 || simState == IccCardConstants.State.PUK_REQUIRED 1067 || simState == IccCardConstants.State.PERM_DISABLED); 1068 } 1069 1070 public DisplayClientState getCachedDisplayClientState() { 1071 return mDisplayClientState; 1072 } 1073 1074 // TODO: use these callbacks elsewhere in place of the existing notifyScreen*() 1075 // (KeyguardViewMediator, KeyguardHostView) 1076 public void dispatchScreenTurnedOn() { 1077 synchronized (this) { 1078 mScreenOn = true; 1079 } 1080 mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON); 1081 } 1082 1083 public void dispatchScreenTurndOff(int why) { 1084 synchronized(this) { 1085 mScreenOn = false; 1086 } 1087 mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0)); 1088 } 1089 1090 public boolean isScreenOn() { 1091 return mScreenOn; 1092 } 1093} 1094