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