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