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