1/* 2 * Copyright (C) 2007 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; 18 19import com.android.internal.telephony.IccCard; 20import com.android.internal.widget.LockPatternUtils; 21 22import android.app.ActivityManagerNative; 23import android.app.AlarmManager; 24import android.app.PendingIntent; 25import android.app.StatusBarManager; 26import android.content.BroadcastReceiver; 27import android.content.ContentResolver; 28import android.content.Context; 29import android.content.Intent; 30import android.content.IntentFilter; 31import android.media.AudioManager; 32import android.media.Ringtone; 33import android.media.RingtoneManager; 34import android.net.Uri; 35import android.os.Handler; 36import android.os.IBinder; 37import android.os.LocalPowerManager; 38import android.os.Message; 39import android.os.PowerManager; 40import android.os.RemoteException; 41import android.os.SystemClock; 42import android.os.SystemProperties; 43import android.provider.Settings; 44import android.telephony.TelephonyManager; 45import android.util.Config; 46import android.util.EventLog; 47import android.util.Log; 48import android.view.KeyEvent; 49import android.view.WindowManagerImpl; 50import android.view.WindowManagerPolicy; 51 52 53/** 54 * Mediates requests related to the keyguard. This includes queries about the 55 * state of the keyguard, power management events that effect whether the keyguard 56 * should be shown or reset, callbacks to the phone window manager to notify 57 * it of when the keyguard is showing, and events from the keyguard view itself 58 * stating that the keyguard was succesfully unlocked. 59 * 60 * Note that the keyguard view is shown when the screen is off (as appropriate) 61 * so that once the screen comes on, it will be ready immediately. 62 * 63 * Example queries about the keyguard: 64 * - is {movement, key} one that should wake the keygaurd? 65 * - is the keyguard showing? 66 * - are input events restricted due to the state of the keyguard? 67 * 68 * Callbacks to the phone window manager: 69 * - the keyguard is showing 70 * 71 * Example external events that translate to keyguard view changes: 72 * - screen turned off -> reset the keyguard, and show it so it will be ready 73 * next time the screen turns on 74 * - keyboard is slid open -> if the keyguard is not secure, hide it 75 * 76 * Events from the keyguard view: 77 * - user succesfully unlocked keyguard -> hide keyguard view, and no longer 78 * restrict input events. 79 * 80 * Note: in addition to normal power managment events that effect the state of 81 * whether the keyguard should be showing, external apps and services may request 82 * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}. When 83 * false, this will override all other conditions for turning on the keyguard. 84 * 85 * Threading and synchronization: 86 * This class is created by the initialization routine of the {@link WindowManagerPolicy}, 87 * and runs on its thread. The keyguard UI is created from that thread in the 88 * constructor of this class. The apis may be called from other threads, including the 89 * {@link com.android.server.KeyInputQueue}'s and {@link android.view.WindowManager}'s. 90 * Therefore, methods on this class are synchronized, and any action that is pointed 91 * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI 92 * thread of the keyguard. 93 */ 94public class KeyguardViewMediator implements KeyguardViewCallback, 95 KeyguardUpdateMonitor.SimStateCallback { 96 private final static boolean DEBUG = false && Config.LOGD; 97 private final static boolean DBG_WAKE = DEBUG || true; 98 99 private final static String TAG = "KeyguardViewMediator"; 100 101 private static final String DELAYED_KEYGUARD_ACTION = 102 "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD"; 103 104 // used for handler messages 105 private static final int TIMEOUT = 1; 106 private static final int SHOW = 2; 107 private static final int HIDE = 3; 108 private static final int RESET = 4; 109 private static final int VERIFY_UNLOCK = 5; 110 private static final int NOTIFY_SCREEN_OFF = 6; 111 private static final int NOTIFY_SCREEN_ON = 7; 112 private static final int WAKE_WHEN_READY = 8; 113 private static final int KEYGUARD_DONE = 9; 114 private static final int KEYGUARD_DONE_DRAWING = 10; 115 private static final int KEYGUARD_DONE_AUTHENTICATING = 11; 116 private static final int SET_HIDDEN = 12; 117 private static final int KEYGUARD_TIMEOUT = 13; 118 119 /** 120 * The default amount of time we stay awake (used for all key input) 121 */ 122 protected static final int AWAKE_INTERVAL_DEFAULT_MS = 5000; 123 124 125 /** 126 * The default amount of time we stay awake (used for all key input) when 127 * the keyboard is open 128 */ 129 protected static final int AWAKE_INTERVAL_DEFAULT_KEYBOARD_OPEN_MS = 10000; 130 131 /** 132 * How long to wait after the screen turns off due to timeout before 133 * turning on the keyguard (i.e, the user has this much time to turn 134 * the screen back on without having to face the keyguard). 135 */ 136 private static final int KEYGUARD_DELAY_MS = 5000; 137 138 /** 139 * How long we'll wait for the {@link KeyguardViewCallback#keyguardDoneDrawing()} 140 * callback before unblocking a call to {@link #setKeyguardEnabled(boolean)} 141 * that is reenabling the keyguard. 142 */ 143 private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000; 144 145 private Context mContext; 146 private AlarmManager mAlarmManager; 147 private StatusBarManager mStatusBarManager; 148 private boolean mShowLockIcon = false; 149 private IBinder mSecureLockIcon = null; 150 151 private boolean mSystemReady; 152 153 // Whether the next call to playSounds() should be skipped. Defaults to 154 // true because the first lock (on boot) should be silent. 155 private boolean mSuppressNextLockSound = true; 156 157 158 /** Low level access to the power manager for enableUserActivity. Having this 159 * requires that we run in the system process. */ 160 LocalPowerManager mRealPowerManager; 161 162 /** High level access to the power manager for WakeLocks */ 163 private PowerManager mPM; 164 165 /** 166 * Used to keep the device awake while the keyguard is showing, i.e for 167 * calls to {@link #pokeWakelock()} 168 */ 169 private PowerManager.WakeLock mWakeLock; 170 171 /** 172 * Used to keep the device awake while to ensure the keyguard finishes opening before 173 * we sleep. 174 */ 175 private PowerManager.WakeLock mShowKeyguardWakeLock; 176 177 /** 178 * Does not turn on screen, held while a call to {@link KeyguardViewManager#wakeWhenReadyTq(int)} 179 * is called to make sure the device doesn't sleep before it has a chance to poke 180 * the wake lock. 181 * @see #wakeWhenReadyLocked(int) 182 */ 183 private PowerManager.WakeLock mWakeAndHandOff; 184 185 private KeyguardViewManager mKeyguardViewManager; 186 187 // these are protected by synchronized (this) 188 189 /** 190 * External apps (like the phone app) can tell us to disable the keygaurd. 191 */ 192 private boolean mExternallyEnabled = true; 193 194 /** 195 * Remember if an external call to {@link #setKeyguardEnabled} with value 196 * false caused us to hide the keyguard, so that we need to reshow it once 197 * the keygaurd is reenabled with another call with value true. 198 */ 199 private boolean mNeedToReshowWhenReenabled = false; 200 201 // cached value of whether we are showing (need to know this to quickly 202 // answer whether the input should be restricted) 203 private boolean mShowing = false; 204 205 // true if the keyguard is hidden by another window 206 private boolean mHidden = false; 207 208 /** 209 * Helps remember whether the screen has turned on since the last time 210 * it turned off due to timeout. see {@link #onScreenTurnedOff(int)} 211 */ 212 private int mDelayedShowingSequence; 213 214 private int mWakelockSequence; 215 216 private PhoneWindowManager mCallback; 217 218 /** 219 * If the user has disabled the keyguard, then requests to exit, this is 220 * how we'll ultimately let them know whether it was successful. We use this 221 * var being non-null as an indicator that there is an in progress request. 222 */ 223 private WindowManagerPolicy.OnKeyguardExitResult mExitSecureCallback; 224 225 // the properties of the keyguard 226 private KeyguardViewProperties mKeyguardViewProperties; 227 228 private KeyguardUpdateMonitor mUpdateMonitor; 229 230 private boolean mKeyboardOpen = false; 231 232 private boolean mScreenOn = false; 233 234 // last known state of the cellular connection 235 private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE; 236 237 /** 238 * we send this intent when the keyguard is dismissed. 239 */ 240 private Intent mUserPresentIntent; 241 242 /** 243 * {@link #setKeyguardEnabled} waits on this condition when it reenables 244 * the keyguard. 245 */ 246 private boolean mWaitingUntilKeyguardVisible = false; 247 248 public KeyguardViewMediator(Context context, PhoneWindowManager callback, 249 LocalPowerManager powerManager) { 250 mContext = context; 251 252 mRealPowerManager = powerManager; 253 mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 254 mWakeLock = mPM.newWakeLock( 255 PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, 256 "keyguard"); 257 mWakeLock.setReferenceCounted(false); 258 mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard"); 259 mShowKeyguardWakeLock.setReferenceCounted(false); 260 261 mWakeAndHandOff = mPM.newWakeLock( 262 PowerManager.PARTIAL_WAKE_LOCK, 263 "keyguardWakeAndHandOff"); 264 mWakeAndHandOff.setReferenceCounted(false); 265 266 IntentFilter filter = new IntentFilter(); 267 filter.addAction(DELAYED_KEYGUARD_ACTION); 268 filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); 269 context.registerReceiver(mBroadCastReceiver, filter); 270 mAlarmManager = (AlarmManager) context 271 .getSystemService(Context.ALARM_SERVICE); 272 mCallback = callback; 273 274 mUpdateMonitor = new KeyguardUpdateMonitor(context); 275 276 mUpdateMonitor.registerSimStateCallback(this); 277 278 mKeyguardViewProperties = new LockPatternKeyguardViewProperties( 279 new LockPatternUtils(mContext), mUpdateMonitor); 280 281 mKeyguardViewManager = new KeyguardViewManager( 282 context, WindowManagerImpl.getDefault(), this, 283 mKeyguardViewProperties, mUpdateMonitor); 284 285 mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT); 286 mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 287 288 final ContentResolver cr = mContext.getContentResolver(); 289 mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1); 290 } 291 292 /** 293 * Let us know that the system is ready after startup. 294 */ 295 public void onSystemReady() { 296 synchronized (this) { 297 if (DEBUG) Log.d(TAG, "onSystemReady"); 298 mSystemReady = true; 299 doKeyguard(); 300 } 301 } 302 303 /** 304 * Called to let us know the screen was turned off. 305 * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER}, 306 * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or 307 * {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}. 308 */ 309 public void onScreenTurnedOff(int why) { 310 synchronized (this) { 311 mScreenOn = false; 312 if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")"); 313 314 if (mExitSecureCallback != null) { 315 if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled"); 316 mExitSecureCallback.onKeyguardExitResult(false); 317 mExitSecureCallback = null; 318 if (!mExternallyEnabled) { 319 hideLocked(); 320 } 321 } else if (mShowing) { 322 notifyScreenOffLocked(); 323 resetStateLocked(); 324 } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) { 325 // if the screen turned off because of timeout, set an alarm 326 // to enable it a little bit later (i.e, give the user a chance 327 // to turn the screen back on within a certain window without 328 // having to unlock the screen) 329 long when = SystemClock.elapsedRealtime() + KEYGUARD_DELAY_MS; 330 Intent intent = new Intent(DELAYED_KEYGUARD_ACTION); 331 intent.putExtra("seq", mDelayedShowingSequence); 332 PendingIntent sender = PendingIntent.getBroadcast(mContext, 333 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 334 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, 335 sender); 336 if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = " 337 + mDelayedShowingSequence); 338 } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) { 339 // Do not enable the keyguard if the prox sensor forced the screen off. 340 } else { 341 doKeyguard(); 342 } 343 } 344 } 345 346 /** 347 * Let's us know the screen was turned on. 348 */ 349 public void onScreenTurnedOn() { 350 synchronized (this) { 351 mScreenOn = true; 352 mDelayedShowingSequence++; 353 if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence); 354 notifyScreenOnLocked(); 355 } 356 } 357 358 /** 359 * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide 360 * a way for external stuff to override normal keyguard behavior. For instance 361 * the phone app disables the keyguard when it receives incoming calls. 362 */ 363 public void setKeyguardEnabled(boolean enabled) { 364 synchronized (this) { 365 if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")"); 366 367 368 mExternallyEnabled = enabled; 369 370 if (!enabled && mShowing) { 371 if (mExitSecureCallback != null) { 372 if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring"); 373 // we're in the process of handling a request to verify the user 374 // can get past the keyguard. ignore extraneous requests to disable / reenable 375 return; 376 } 377 378 // hiding keyguard that is showing, remember to reshow later 379 if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, " 380 + "disabling status bar expansion"); 381 mNeedToReshowWhenReenabled = true; 382 hideLocked(); 383 } else if (enabled && mNeedToReshowWhenReenabled) { 384 // reenabled after previously hidden, reshow 385 if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling " 386 + "status bar expansion"); 387 mNeedToReshowWhenReenabled = false; 388 389 if (mExitSecureCallback != null) { 390 if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting"); 391 mExitSecureCallback.onKeyguardExitResult(false); 392 mExitSecureCallback = null; 393 resetStateLocked(); 394 } else { 395 showLocked(); 396 397 // block until we know the keygaurd is done drawing (and post a message 398 // to unblock us after a timeout so we don't risk blocking too long 399 // and causing an ANR). 400 mWaitingUntilKeyguardVisible = true; 401 mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS); 402 if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false"); 403 while (mWaitingUntilKeyguardVisible) { 404 try { 405 wait(); 406 } catch (InterruptedException e) { 407 Thread.currentThread().interrupt(); 408 } 409 } 410 if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible"); 411 } 412 } 413 } 414 } 415 416 /** 417 * @see android.app.KeyguardManager#exitKeyguardSecurely 418 */ 419 public void verifyUnlock(WindowManagerPolicy.OnKeyguardExitResult callback) { 420 synchronized (this) { 421 if (DEBUG) Log.d(TAG, "verifyUnlock"); 422 if (!mUpdateMonitor.isDeviceProvisioned()) { 423 // don't allow this api when the device isn't provisioned 424 if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned"); 425 callback.onKeyguardExitResult(false); 426 } else if (mExternallyEnabled) { 427 // this only applies when the user has externally disabled the 428 // keyguard. this is unexpected and means the user is not 429 // using the api properly. 430 Log.w(TAG, "verifyUnlock called when not externally disabled"); 431 callback.onKeyguardExitResult(false); 432 } else if (mExitSecureCallback != null) { 433 // already in progress with someone else 434 callback.onKeyguardExitResult(false); 435 } else { 436 mExitSecureCallback = callback; 437 verifyUnlockLocked(); 438 } 439 } 440 } 441 442 /** 443 * Is the keyguard currently showing? 444 */ 445 public boolean isShowing() { 446 return mShowing; 447 } 448 449 /** 450 * Is the keyguard currently showing and not being force hidden? 451 */ 452 public boolean isShowingAndNotHidden() { 453 return mShowing && !mHidden; 454 } 455 456 /** 457 * Notify us when the keyguard is hidden by another window 458 */ 459 public void setHidden(boolean isHidden) { 460 if (DEBUG) Log.d(TAG, "setHidden " + isHidden); 461 mHandler.removeMessages(SET_HIDDEN); 462 Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0); 463 mHandler.sendMessage(msg); 464 } 465 466 /** 467 * Handles SET_HIDDEN message sent by setHidden() 468 */ 469 private void handleSetHidden(boolean isHidden) { 470 synchronized (KeyguardViewMediator.this) { 471 if (mHidden != isHidden) { 472 mHidden = isHidden; 473 adjustUserActivityLocked(); 474 adjustStatusBarLocked(); 475 } 476 } 477 } 478 479 /** 480 * Used by PhoneWindowManager to enable the keyguard due to a user activity timeout. 481 * This must be safe to call from any thread and with any window manager locks held. 482 */ 483 public void doKeyguardTimeout() { 484 mHandler.removeMessages(KEYGUARD_TIMEOUT); 485 Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT); 486 mHandler.sendMessage(msg); 487 } 488 489 /** 490 * Given the state of the keyguard, is the input restricted? 491 * Input is restricted when the keyguard is showing, or when the keyguard 492 * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet. 493 */ 494 public boolean isInputRestricted() { 495 return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned(); 496 } 497 498 /** 499 * Returns true if the change is resulting in the keyguard beign dismissed, 500 * meaning the screen can turn on immediately. Otherwise returns false. 501 */ 502 public boolean doLidChangeTq(boolean isLidOpen) { 503 mKeyboardOpen = isLidOpen; 504 505 if (mUpdateMonitor.isKeyguardBypassEnabled() && mKeyboardOpen 506 && !mKeyguardViewProperties.isSecure() && mKeyguardViewManager.isShowing()) { 507 if (DEBUG) Log.d(TAG, "bypassing keyguard on sliding open of keyboard with non-secure keyguard"); 508 mHandler.sendEmptyMessage(KEYGUARD_DONE_AUTHENTICATING); 509 return true; 510 } 511 return false; 512 } 513 514 /** 515 * Enable the keyguard if the settings are appropriate. 516 */ 517 private void doKeyguard() { 518 synchronized (this) { 519 // if another app is disabling us, don't show 520 if (!mExternallyEnabled) { 521 if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); 522 523 // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes 524 // for an occasional ugly flicker in this situation: 525 // 1) receive a call with the screen on (no keyguard) or make a call 526 // 2) screen times out 527 // 3) user hits key to turn screen back on 528 // instead, we reenable the keyguard when we know the screen is off and the call 529 // ends (see the broadcast receiver below) 530 // TODO: clean this up when we have better support at the window manager level 531 // for apps that wish to be on top of the keyguard 532 return; 533 } 534 535 // if the keyguard is already showing, don't bother 536 if (mKeyguardViewManager.isShowing()) { 537 if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing"); 538 return; 539 } 540 541 // if the setup wizard hasn't run yet, don't show 542 final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", 543 false); 544 final boolean provisioned = mUpdateMonitor.isDeviceProvisioned(); 545 final IccCard.State state = mUpdateMonitor.getSimState(); 546 final boolean lockedOrMissing = state.isPinLocked() 547 || ((state == IccCard.State.ABSENT) && requireSim); 548 549 if (!lockedOrMissing && !provisioned) { 550 if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned" 551 + " and the sim is not locked or missing"); 552 return; 553 } 554 555 if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen"); 556 showLocked(); 557 } 558 } 559 560 /** 561 * Send message to keyguard telling it to reset its state. 562 * @see #handleReset() 563 */ 564 private void resetStateLocked() { 565 if (DEBUG) Log.d(TAG, "resetStateLocked"); 566 Message msg = mHandler.obtainMessage(RESET); 567 mHandler.sendMessage(msg); 568 } 569 570 /** 571 * Send message to keyguard telling it to verify unlock 572 * @see #handleVerifyUnlock() 573 */ 574 private void verifyUnlockLocked() { 575 if (DEBUG) Log.d(TAG, "verifyUnlockLocked"); 576 mHandler.sendEmptyMessage(VERIFY_UNLOCK); 577 } 578 579 580 /** 581 * Send a message to keyguard telling it the screen just turned on. 582 * @see #onScreenTurnedOff(int) 583 * @see #handleNotifyScreenOff 584 */ 585 private void notifyScreenOffLocked() { 586 if (DEBUG) Log.d(TAG, "notifyScreenOffLocked"); 587 mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF); 588 } 589 590 /** 591 * Send a message to keyguard telling it the screen just turned on. 592 * @see #onScreenTurnedOn() 593 * @see #handleNotifyScreenOn 594 */ 595 private void notifyScreenOnLocked() { 596 if (DEBUG) Log.d(TAG, "notifyScreenOnLocked"); 597 mHandler.sendEmptyMessage(NOTIFY_SCREEN_ON); 598 } 599 600 /** 601 * Send message to keyguard telling it about a wake key so it can adjust 602 * its state accordingly and then poke the wake lock when it is ready. 603 * @param keyCode The wake key. 604 * @see #handleWakeWhenReady 605 * @see #onWakeKeyWhenKeyguardShowingTq(int) 606 */ 607 private void wakeWhenReadyLocked(int keyCode) { 608 if (DBG_WAKE) Log.d(TAG, "wakeWhenReadyLocked(" + keyCode + ")"); 609 610 /** 611 * acquire the handoff lock that will keep the cpu running. this will 612 * be released once the keyguard has set itself up and poked the other wakelock 613 * in {@link #handleWakeWhenReady(int)} 614 */ 615 mWakeAndHandOff.acquire(); 616 617 Message msg = mHandler.obtainMessage(WAKE_WHEN_READY, keyCode, 0); 618 mHandler.sendMessage(msg); 619 } 620 621 /** 622 * Send message to keyguard telling it to show itself 623 * @see #handleShow() 624 */ 625 private void showLocked() { 626 if (DEBUG) Log.d(TAG, "showLocked"); 627 // ensure we stay awake until we are finished displaying the keyguard 628 mShowKeyguardWakeLock.acquire(); 629 Message msg = mHandler.obtainMessage(SHOW); 630 mHandler.sendMessage(msg); 631 } 632 633 /** 634 * Send message to keyguard telling it to hide itself 635 * @see #handleHide() 636 */ 637 private void hideLocked() { 638 if (DEBUG) Log.d(TAG, "hideLocked"); 639 Message msg = mHandler.obtainMessage(HIDE); 640 mHandler.sendMessage(msg); 641 } 642 643 /** {@inheritDoc} */ 644 public void onSimStateChanged(IccCard.State simState) { 645 if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState); 646 647 switch (simState) { 648 case ABSENT: 649 // only force lock screen in case of missing sim if user hasn't 650 // gone through setup wizard 651 if (!mUpdateMonitor.isDeviceProvisioned()) { 652 if (!isShowing()) { 653 if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_ABSENT and keygaurd isn't showing, we need " 654 + "to show the keyguard since the device isn't provisioned yet."); 655 doKeyguard(); 656 } else { 657 resetStateLocked(); 658 } 659 } 660 break; 661 case PIN_REQUIRED: 662 case PUK_REQUIRED: 663 if (!isShowing()) { 664 if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, we need " 665 + "to show the keyguard so the user can enter their sim pin"); 666 doKeyguard(); 667 } else { 668 resetStateLocked(); 669 } 670 671 break; 672 case READY: 673 if (isShowing()) { 674 resetStateLocked(); 675 } 676 break; 677 } 678 } 679 680 public boolean isSecure() { 681 return mKeyguardViewProperties.isSecure(); 682 } 683 684 private BroadcastReceiver mBroadCastReceiver = new BroadcastReceiver() { 685 @Override 686 public void onReceive(Context context, Intent intent) { 687 final String action = intent.getAction(); 688 if (action.equals(DELAYED_KEYGUARD_ACTION)) { 689 690 int sequence = intent.getIntExtra("seq", 0); 691 692 if (false) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = " 693 + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence); 694 695 if (mDelayedShowingSequence == sequence) { 696 // Don't play lockscreen SFX if the screen went off due to 697 // timeout. 698 mSuppressNextLockSound = true; 699 700 doKeyguard(); 701 } 702 } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) { 703 mPhoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 704 705 if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState) // call ending 706 && !mScreenOn // screen off 707 && mExternallyEnabled) { // not disabled by any app 708 709 // note: this is a way to gracefully reenable the keyguard when the call 710 // ends and the screen is off without always reenabling the keyguard 711 // each time the screen turns off while in call (and having an occasional ugly 712 // flicker while turning back on the screen and disabling the keyguard again). 713 if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the " 714 + "keyguard is showing"); 715 doKeyguard(); 716 } 717 } 718 } 719 }; 720 721 722 /** 723 * When a key is received when the screen is off and the keyguard is showing, 724 * we need to decide whether to actually turn on the screen, and if so, tell 725 * the keyguard to prepare itself and poke the wake lock when it is ready. 726 * 727 * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}. 728 * Be sure not to take any action that takes a long time; any significant 729 * action should be posted to a handler. 730 * 731 * @param keyCode The keycode of the key that woke the device 732 * @return Whether we poked the wake lock (and turned the screen on) 733 */ 734 public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode) { 735 if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")"); 736 737 if (isWakeKeyWhenKeyguardShowing(keyCode)) { 738 // give the keyguard view manager a chance to adjust the state of the 739 // keyguard based on the key that woke the device before poking 740 // the wake lock 741 wakeWhenReadyLocked(keyCode); 742 return true; 743 } else { 744 return false; 745 } 746 } 747 748 private boolean isWakeKeyWhenKeyguardShowing(int keyCode) { 749 switch (keyCode) { 750 case KeyEvent.KEYCODE_VOLUME_UP: 751 case KeyEvent.KEYCODE_VOLUME_DOWN: 752 case KeyEvent.KEYCODE_MUTE: 753 case KeyEvent.KEYCODE_HEADSETHOOK: 754 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 755 case KeyEvent.KEYCODE_MEDIA_STOP: 756 case KeyEvent.KEYCODE_MEDIA_NEXT: 757 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 758 case KeyEvent.KEYCODE_MEDIA_REWIND: 759 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 760 case KeyEvent.KEYCODE_CAMERA: 761 return false; 762 } 763 return true; 764 } 765 766 /** 767 * Callbacks from {@link KeyguardViewManager}. 768 */ 769 770 /** {@inheritDoc} */ 771 public void pokeWakelock() { 772 pokeWakelock(mKeyboardOpen ? 773 AWAKE_INTERVAL_DEFAULT_KEYBOARD_OPEN_MS : AWAKE_INTERVAL_DEFAULT_MS); 774 } 775 776 /** {@inheritDoc} */ 777 public void pokeWakelock(int holdMs) { 778 synchronized (this) { 779 if (DBG_WAKE) Log.d(TAG, "pokeWakelock(" + holdMs + ")"); 780 mWakeLock.acquire(); 781 mHandler.removeMessages(TIMEOUT); 782 mWakelockSequence++; 783 Message msg = mHandler.obtainMessage(TIMEOUT, mWakelockSequence, 0); 784 mHandler.sendMessageDelayed(msg, holdMs); 785 } 786 } 787 788 /** 789 * {@inheritDoc} 790 * 791 * @see #handleKeyguardDone 792 */ 793 public void keyguardDone(boolean authenticated) { 794 keyguardDone(authenticated, true); 795 } 796 797 public void keyguardDone(boolean authenticated, boolean wakeup) { 798 synchronized (this) { 799 EventLog.writeEvent(70000, 2); 800 if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")"); 801 Message msg = mHandler.obtainMessage(KEYGUARD_DONE); 802 msg.arg1 = wakeup ? 1 : 0; 803 mHandler.sendMessage(msg); 804 805 if (authenticated) { 806 mUpdateMonitor.clearFailedAttempts(); 807 } 808 809 if (mExitSecureCallback != null) { 810 mExitSecureCallback.onKeyguardExitResult(authenticated); 811 mExitSecureCallback = null; 812 813 if (authenticated) { 814 // after succesfully exiting securely, no need to reshow 815 // the keyguard when they've released the lock 816 mExternallyEnabled = true; 817 mNeedToReshowWhenReenabled = false; 818 } 819 } 820 } 821 } 822 823 /** 824 * {@inheritDoc} 825 * 826 * @see #handleKeyguardDoneDrawing 827 */ 828 public void keyguardDoneDrawing() { 829 mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING); 830 } 831 832 /** 833 * This handler will be associated with the policy thread, which will also 834 * be the UI thread of the keyguard. Since the apis of the policy, and therefore 835 * this class, can be called by other threads, any action that directly 836 * interacts with the keyguard ui should be posted to this handler, rather 837 * than called directly. 838 */ 839 private Handler mHandler = new Handler() { 840 @Override 841 public void handleMessage(Message msg) { 842 switch (msg.what) { 843 case TIMEOUT: 844 handleTimeout(msg.arg1); 845 return ; 846 case SHOW: 847 handleShow(); 848 return ; 849 case HIDE: 850 handleHide(); 851 return ; 852 case RESET: 853 handleReset(); 854 return ; 855 case VERIFY_UNLOCK: 856 handleVerifyUnlock(); 857 return; 858 case NOTIFY_SCREEN_OFF: 859 handleNotifyScreenOff(); 860 return; 861 case NOTIFY_SCREEN_ON: 862 handleNotifyScreenOn(); 863 return; 864 case WAKE_WHEN_READY: 865 handleWakeWhenReady(msg.arg1); 866 return; 867 case KEYGUARD_DONE: 868 handleKeyguardDone(msg.arg1 != 0); 869 return; 870 case KEYGUARD_DONE_DRAWING: 871 handleKeyguardDoneDrawing(); 872 return; 873 case KEYGUARD_DONE_AUTHENTICATING: 874 keyguardDone(true); 875 return; 876 case SET_HIDDEN: 877 handleSetHidden(msg.arg1 != 0); 878 break; 879 case KEYGUARD_TIMEOUT: 880 doKeyguard(); 881 break; 882 } 883 } 884 }; 885 886 /** 887 * @see #keyguardDone 888 * @see #KEYGUARD_DONE 889 */ 890 private void handleKeyguardDone(boolean wakeup) { 891 if (DEBUG) Log.d(TAG, "handleKeyguardDone"); 892 handleHide(); 893 if (wakeup) { 894 mPM.userActivity(SystemClock.uptimeMillis(), true); 895 } 896 mWakeLock.release(); 897 mContext.sendBroadcast(mUserPresentIntent); 898 } 899 900 /** 901 * @see #keyguardDoneDrawing 902 * @see #KEYGUARD_DONE_DRAWING 903 */ 904 private void handleKeyguardDoneDrawing() { 905 synchronized(this) { 906 if (false) Log.d(TAG, "handleKeyguardDoneDrawing"); 907 if (mWaitingUntilKeyguardVisible) { 908 if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible"); 909 mWaitingUntilKeyguardVisible = false; 910 notifyAll(); 911 912 // there will usually be two of these sent, one as a timeout, and one 913 // as a result of the callback, so remove any remaining messages from 914 // the queue 915 mHandler.removeMessages(KEYGUARD_DONE_DRAWING); 916 } 917 } 918 } 919 920 /** 921 * Handles the message sent by {@link #pokeWakelock} 922 * @param seq used to determine if anything has changed since the message 923 * was sent. 924 * @see #TIMEOUT 925 */ 926 private void handleTimeout(int seq) { 927 synchronized (KeyguardViewMediator.this) { 928 if (DEBUG) Log.d(TAG, "handleTimeout"); 929 if (seq == mWakelockSequence) { 930 mWakeLock.release(); 931 } 932 } 933 } 934 935 private void playSounds(boolean locked) { 936 // User feedback for keyguard. 937 938 if (mSuppressNextLockSound) { 939 mSuppressNextLockSound = false; 940 return; 941 } 942 943 final ContentResolver cr = mContext.getContentResolver(); 944 if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) 945 { 946 final String whichSound = locked 947 ? Settings.System.LOCK_SOUND 948 : Settings.System.UNLOCK_SOUND; 949 final String soundPath = Settings.System.getString(cr, whichSound); 950 if (soundPath != null) { 951 final Uri soundUri = Uri.parse("file://" + soundPath); 952 if (soundUri != null) { 953 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); 954 if (sfx != null) { 955 sfx.setStreamType(AudioManager.STREAM_SYSTEM); 956 sfx.play(); 957 } else { 958 Log.d(TAG, "playSounds: failed to load ringtone from uri: " + soundUri); 959 } 960 } else { 961 Log.d(TAG, "playSounds: could not parse Uri: " + soundPath); 962 } 963 } else { 964 Log.d(TAG, "playSounds: whichSound = " + whichSound + "; soundPath was null"); 965 } 966 } 967 } 968 969 /** 970 * Handle message sent by {@link #showLocked}. 971 * @see #SHOW 972 */ 973 private void handleShow() { 974 synchronized (KeyguardViewMediator.this) { 975 if (DEBUG) Log.d(TAG, "handleShow"); 976 if (!mSystemReady) return; 977 978 playSounds(true); 979 980 mKeyguardViewManager.show(); 981 mShowing = true; 982 adjustUserActivityLocked(); 983 adjustStatusBarLocked(); 984 try { 985 ActivityManagerNative.getDefault().closeSystemDialogs("lock"); 986 } catch (RemoteException e) { 987 } 988 mShowKeyguardWakeLock.release(); 989 } 990 } 991 992 /** 993 * Handle message sent by {@link #hideLocked()} 994 * @see #HIDE 995 */ 996 private void handleHide() { 997 synchronized (KeyguardViewMediator.this) { 998 if (DEBUG) Log.d(TAG, "handleHide"); 999 if (mWakeAndHandOff.isHeld()) { 1000 Log.w(TAG, "attempt to hide the keyguard while waking, ignored"); 1001 return; 1002 } 1003 1004 // only play "unlock" noises if not on a call (since the incall UI 1005 // disables the keyguard) 1006 if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) { 1007 playSounds(false); 1008 } 1009 1010 mKeyguardViewManager.hide(); 1011 mShowing = false; 1012 adjustUserActivityLocked(); 1013 adjustStatusBarLocked(); 1014 } 1015 } 1016 1017 private void adjustUserActivityLocked() { 1018 // disable user activity if we are shown and not hidden 1019 if (DEBUG) Log.d(TAG, "adjustUserActivityLocked mShowing: " + mShowing + " mHidden: " + mHidden); 1020 boolean enabled = !mShowing || mHidden; 1021 mRealPowerManager.enableUserActivity(enabled); 1022 if (!enabled && mScreenOn) { 1023 // reinstate our short screen timeout policy 1024 pokeWakelock(); 1025 } 1026 } 1027 1028 private void adjustStatusBarLocked() { 1029 if (mStatusBarManager == null) { 1030 mStatusBarManager = (StatusBarManager) 1031 mContext.getSystemService(Context.STATUS_BAR_SERVICE); 1032 } 1033 if (mStatusBarManager == null) { 1034 Log.w(TAG, "Could not get status bar manager"); 1035 } else { 1036 if (mShowLockIcon) { 1037 // Give feedback to user when secure keyguard is active and engaged 1038 if (mShowing && isSecure()) { 1039 if (mSecureLockIcon == null) { 1040 mSecureLockIcon = mStatusBarManager.addIcon("secure", 1041 com.android.internal.R.drawable.stat_sys_secure, 0); 1042 } 1043 } else { 1044 if (mSecureLockIcon != null) { 1045 mStatusBarManager.removeIcon(mSecureLockIcon); 1046 mSecureLockIcon = null; 1047 } 1048 } 1049 } 1050 1051 // if the keyguard is shown, allow the status bar to open 1052 // only if the keyguard is insecure and is covered by another window 1053 boolean enable = !mShowing || (mHidden && !isSecure()); 1054 mStatusBarManager.disable(enable ? 1055 StatusBarManager.DISABLE_NONE : 1056 StatusBarManager.DISABLE_EXPAND); 1057 } 1058 } 1059 1060 /** 1061 * Handle message sent by {@link #wakeWhenReadyLocked(int)} 1062 * @param keyCode The key that woke the device. 1063 * @see #WAKE_WHEN_READY 1064 */ 1065 private void handleWakeWhenReady(int keyCode) { 1066 synchronized (KeyguardViewMediator.this) { 1067 if (DBG_WAKE) Log.d(TAG, "handleWakeWhenReady(" + keyCode + ")"); 1068 1069 // this should result in a call to 'poke wakelock' which will set a timeout 1070 // on releasing the wakelock 1071 if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) { 1072 // poke wakelock ourselves if keyguard is no longer active 1073 Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves"); 1074 pokeWakelock(); 1075 } 1076 1077 /** 1078 * Now that the keyguard is ready and has poked the wake lock, we can 1079 * release the handoff wakelock 1080 */ 1081 mWakeAndHandOff.release(); 1082 1083 if (!mWakeLock.isHeld()) { 1084 Log.w(TAG, "mWakeLock not held in mKeyguardViewManager.wakeWhenReadyTq"); 1085 } 1086 } 1087 } 1088 1089 /** 1090 * Handle message sent by {@link #resetStateLocked()} 1091 * @see #RESET 1092 */ 1093 private void handleReset() { 1094 synchronized (KeyguardViewMediator.this) { 1095 if (DEBUG) Log.d(TAG, "handleReset"); 1096 mKeyguardViewManager.reset(); 1097 } 1098 } 1099 1100 /** 1101 * Handle message sent by {@link #verifyUnlock} 1102 * @see #RESET 1103 */ 1104 private void handleVerifyUnlock() { 1105 synchronized (KeyguardViewMediator.this) { 1106 if (DEBUG) Log.d(TAG, "handleVerifyUnlock"); 1107 mKeyguardViewManager.verifyUnlock(); 1108 mShowing = true; 1109 } 1110 } 1111 1112 /** 1113 * Handle message sent by {@link #notifyScreenOffLocked()} 1114 * @see #NOTIFY_SCREEN_OFF 1115 */ 1116 private void handleNotifyScreenOff() { 1117 synchronized (KeyguardViewMediator.this) { 1118 if (DEBUG) Log.d(TAG, "handleNotifyScreenOff"); 1119 mKeyguardViewManager.onScreenTurnedOff(); 1120 } 1121 } 1122 1123 /** 1124 * Handle message sent by {@link #notifyScreenOnLocked()} 1125 * @see #NOTIFY_SCREEN_ON 1126 */ 1127 private void handleNotifyScreenOn() { 1128 synchronized (KeyguardViewMediator.this) { 1129 if (DEBUG) Log.d(TAG, "handleNotifyScreenOn"); 1130 mKeyguardViewManager.onScreenTurnedOn(); 1131 } 1132 } 1133} 1134 1135 1136