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