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