KeyguardViewMediator.java revision 17f509aefe98f448f8f0692321415eb0ac0abc2e
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.keyguard;
18
19import com.android.internal.policy.IKeyguardExitCallback;
20import com.android.internal.policy.IKeyguardShowCallback;
21import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
22
23import android.app.Activity;
24import android.app.ActivityManagerNative;
25import android.app.AlarmManager;
26import android.app.PendingIntent;
27import android.app.SearchManager;
28import android.app.StatusBarManager;
29import android.content.BroadcastReceiver;
30import android.content.ContentResolver;
31import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
34import android.media.AudioManager;
35import android.media.SoundPool;
36import android.os.Bundle;
37import android.os.Handler;
38import android.os.Looper;
39import android.os.Message;
40import android.os.PowerManager;
41import android.os.RemoteException;
42import android.os.SystemClock;
43import android.os.SystemProperties;
44import android.os.UserHandle;
45import android.os.UserManager;
46import android.provider.Settings;
47import android.telephony.TelephonyManager;
48import android.util.EventLog;
49import android.util.Log;
50import android.util.Slog;
51import android.view.KeyEvent;
52import android.view.WindowManager;
53import android.view.WindowManagerPolicy;
54
55import com.android.internal.telephony.IccCardConstants;
56import com.android.internal.widget.LockPatternUtils;
57
58
59/**
60 * Mediates requests related to the keyguard.  This includes queries about the
61 * state of the keyguard, power management events that effect whether the keyguard
62 * should be shown or reset, callbacks to the phone window manager to notify
63 * it of when the keyguard is showing, and events from the keyguard view itself
64 * stating that the keyguard was succesfully unlocked.
65 *
66 * Note that the keyguard view is shown when the screen is off (as appropriate)
67 * so that once the screen comes on, it will be ready immediately.
68 *
69 * Example queries about the keyguard:
70 * - is {movement, key} one that should wake the keygaurd?
71 * - is the keyguard showing?
72 * - are input events restricted due to the state of the keyguard?
73 *
74 * Callbacks to the phone window manager:
75 * - the keyguard is showing
76 *
77 * Example external events that translate to keyguard view changes:
78 * - screen turned off -> reset the keyguard, and show it so it will be ready
79 *   next time the screen turns on
80 * - keyboard is slid open -> if the keyguard is not secure, hide it
81 *
82 * Events from the keyguard view:
83 * - user succesfully unlocked keyguard -> hide keyguard view, and no longer
84 *   restrict input events.
85 *
86 * Note: in addition to normal power managment events that effect the state of
87 * whether the keyguard should be showing, external apps and services may request
88 * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}.  When
89 * false, this will override all other conditions for turning on the keyguard.
90 *
91 * Threading and synchronization:
92 * This class is created by the initialization routine of the {@link WindowManagerPolicy},
93 * and runs on its thread.  The keyguard UI is created from that thread in the
94 * constructor of this class.  The apis may be called from other threads, including the
95 * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
96 * Therefore, methods on this class are synchronized, and any action that is pointed
97 * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
98 * thread of the keyguard.
99 */
100public class KeyguardViewMediator {
101    private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
102    final static boolean DEBUG = false;
103    private final static boolean DBG_WAKE = false;
104
105    private final static String TAG = "KeyguardViewMediator";
106
107    private static final String DELAYED_KEYGUARD_ACTION =
108        "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
109
110    // used for handler messages
111    private static final int SHOW = 2;
112    private static final int HIDE = 3;
113    private static final int RESET = 4;
114    private static final int VERIFY_UNLOCK = 5;
115    private static final int NOTIFY_SCREEN_OFF = 6;
116    private static final int NOTIFY_SCREEN_ON = 7;
117    private static final int WAKE_WHEN_READY = 8;
118    private static final int KEYGUARD_DONE = 9;
119    private static final int KEYGUARD_DONE_DRAWING = 10;
120    private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
121    private static final int SET_HIDDEN = 12;
122    private static final int KEYGUARD_TIMEOUT = 13;
123    private static final int SHOW_ASSISTANT = 14;
124
125    /**
126     * The default amount of time we stay awake (used for all key input)
127     */
128    protected static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
129
130    /**
131     * How long to wait after the screen turns off due to timeout before
132     * turning on the keyguard (i.e, the user has this much time to turn
133     * the screen back on without having to face the keyguard).
134     */
135    private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
136
137    /**
138     * How long we'll wait for the {@link ViewMediatorCallback#keyguardDoneDrawing()}
139     * callback before unblocking a call to {@link #setKeyguardEnabled(boolean)}
140     * that is reenabling the keyguard.
141     */
142    private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
143
144    /**
145     * Allow the user to expand the status bar when the keyguard is engaged
146     * (without a pattern or password).
147     */
148    private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
149
150    /** The stream type that the lock sounds are tied to. */
151    private int mMasterStreamType;
152
153    private Context mContext;
154    private AlarmManager mAlarmManager;
155    private AudioManager mAudioManager;
156    private StatusBarManager mStatusBarManager;
157    private boolean mShowLockIcon;
158    private boolean mShowingLockIcon;
159    private boolean mSwitchingUser;
160
161    private boolean mSystemReady;
162
163    // Whether the next call to playSounds() should be skipped.  Defaults to
164    // true because the first lock (on boot) should be silent.
165    private boolean mSuppressNextLockSound = true;
166
167
168    /** High level access to the power manager for WakeLocks */
169    private PowerManager mPM;
170
171    /** UserManager for querying number of users */
172    private UserManager mUserManager;
173
174    /** SearchManager for determining whether or not search assistant is available */
175    private SearchManager mSearchManager;
176
177    /**
178     * Used to keep the device awake while to ensure the keyguard finishes opening before
179     * we sleep.
180     */
181    private PowerManager.WakeLock mShowKeyguardWakeLock;
182
183    /**
184     * Does not turn on screen, held while a call to {@link KeyguardViewManager#wakeWhenReadyTq(int)}
185     * is called to make sure the device doesn't sleep before it has a chance to poke
186     * the wake lock.
187     * @see #wakeWhenReady(int)
188     */
189    private PowerManager.WakeLock mWakeAndHandOff;
190
191    private KeyguardViewManager mKeyguardViewManager;
192
193    // these are protected by synchronized (this)
194
195    /**
196     * External apps (like the phone app) can tell us to disable the keygaurd.
197     */
198    private boolean mExternallyEnabled = true;
199
200    /**
201     * Remember if an external call to {@link #setKeyguardEnabled} with value
202     * false caused us to hide the keyguard, so that we need to reshow it once
203     * the keygaurd is reenabled with another call with value true.
204     */
205    private boolean mNeedToReshowWhenReenabled = false;
206
207    // cached value of whether we are showing (need to know this to quickly
208    // answer whether the input should be restricted)
209    private boolean mShowing = false;
210
211    // true if the keyguard is hidden by another window
212    private boolean mHidden = false;
213
214    /**
215     * Helps remember whether the screen has turned on since the last time
216     * it turned off due to timeout. see {@link #onScreenTurnedOff(int)}
217     */
218    private int mDelayedShowingSequence;
219
220    /**
221     * If the user has disabled the keyguard, then requests to exit, this is
222     * how we'll ultimately let them know whether it was successful.  We use this
223     * var being non-null as an indicator that there is an in progress request.
224     */
225    private IKeyguardExitCallback mExitSecureCallback;
226
227    // the properties of the keyguard
228
229    private KeyguardUpdateMonitor mUpdateMonitor;
230
231    private boolean mScreenOn;
232
233    // last known state of the cellular connection
234    private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
235
236    /**
237     * we send this intent when the keyguard is dismissed.
238     */
239    private static final Intent USER_PRESENT_INTENT = new Intent(Intent.ACTION_USER_PRESENT)
240            .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
241                    | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
242
243    /**
244     * {@link #setKeyguardEnabled} waits on this condition when it reenables
245     * the keyguard.
246     */
247    private boolean mWaitingUntilKeyguardVisible = false;
248    private LockPatternUtils mLockPatternUtils;
249    private boolean mKeyguardDonePending = false;
250
251    private SoundPool mLockSounds;
252    private int mLockSoundId;
253    private int mUnlockSoundId;
254    private int mLockSoundStreamId;
255
256    /**
257     * The volume applied to the lock/unlock sounds.
258     */
259    private final float mLockSoundVolume;
260
261    /**
262     * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
263     * various things.
264     */
265    public interface ViewMediatorCallback {
266
267        /**
268         * Wake the device immediately.
269         */
270        void wakeUp();
271
272        /**
273         * Reports user activity and requests that the screen stay on.
274         */
275        void userActivity();
276
277        /**
278         * Reports user activity and requests that the screen stay on for at least
279         * the specified amount of time.
280         * @param millis The amount of time in millis.  This value is currently ignored.
281         */
282        void userActivity(long millis);
283
284        /**
285         * Report that the keyguard is done.
286         * @param authenticated Whether the user securely got past the keyguard.
287         *   the only reason for this to be false is if the keyguard was instructed
288         *   to appear temporarily to verify the user is supposed to get past the
289         *   keyguard, and the user fails to do so.
290         */
291        void keyguardDone(boolean authenticated);
292
293        /**
294         * Report that the keyguard is done drawing.
295         */
296        void keyguardDoneDrawing();
297
298        /**
299         * Tell ViewMediator that the current view needs IME input
300         * @param needsInput
301         */
302        void setNeedsInput(boolean needsInput);
303
304        /**
305         * Tell view mediator that the keyguard view's desired user activity timeout
306         * has changed and needs to be reapplied to the window.
307         */
308        void onUserActivityTimeoutChanged();
309
310        /**
311         * Report that the keyguard is dismissable, pending the next keyguardDone call.
312         */
313        void keyguardDonePending();
314    }
315
316    KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
317
318        @Override
319        public void onUserSwitching(int userId) {
320            // Note that the mLockPatternUtils user has already been updated from setCurrentUser.
321            // We need to force a reset of the views, since lockNow (called by
322            // ActivityManagerService) will not reconstruct the keyguard if it is already showing.
323            synchronized (KeyguardViewMediator.this) {
324                mSwitchingUser = true;
325                resetStateLocked(null);
326                adjustStatusBarLocked();
327                // Disable face unlock when the user switches.
328                KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
329            }
330        }
331
332        @Override
333        public void onUserSwitchComplete(int userId) {
334            mSwitchingUser = false;
335        }
336
337        @Override
338        public void onUserRemoved(int userId) {
339            mLockPatternUtils.removeUser(userId);
340        }
341
342        @Override
343        void onPhoneStateChanged(int phoneState) {
344            synchronized (KeyguardViewMediator.this) {
345                if (TelephonyManager.CALL_STATE_IDLE == phoneState  // call ending
346                        && !mScreenOn                           // screen off
347                        && mExternallyEnabled) {                // not disabled by any app
348
349                    // note: this is a way to gracefully reenable the keyguard when the call
350                    // ends and the screen is off without always reenabling the keyguard
351                    // each time the screen turns off while in call (and having an occasional ugly
352                    // flicker while turning back on the screen and disabling the keyguard again).
353                    if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
354                            + "keyguard is showing");
355                    doKeyguardLocked(null);
356                }
357            }
358        };
359
360        @Override
361        public void onClockVisibilityChanged() {
362            adjustStatusBarLocked();
363        }
364
365        @Override
366        public void onDeviceProvisioned() {
367            sendUserPresentBroadcast();
368        }
369
370        @Override
371        public void onSimStateChanged(IccCardConstants.State simState) {
372            if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
373
374            switch (simState) {
375                case NOT_READY:
376                case ABSENT:
377                    // only force lock screen in case of missing sim if user hasn't
378                    // gone through setup wizard
379                    synchronized (this) {
380                        if (!mUpdateMonitor.isDeviceProvisioned()) {
381                            if (!isShowing()) {
382                                if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
383                                        + " we need to show the keyguard since the "
384                                        + "device isn't provisioned yet.");
385                                doKeyguardLocked(null);
386                            } else {
387                                resetStateLocked(null);
388                            }
389                        }
390                    }
391                    break;
392                case PIN_REQUIRED:
393                case PUK_REQUIRED:
394                    synchronized (this) {
395                        if (!isShowing()) {
396                            if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
397                                    + "showing; need to show keyguard so user can enter sim pin");
398                            doKeyguardLocked(null);
399                        } else {
400                            resetStateLocked(null);
401                        }
402                    }
403                    break;
404                case PERM_DISABLED:
405                    synchronized (this) {
406                        if (!isShowing()) {
407                            if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
408                                  + "keygaurd isn't showing.");
409                            doKeyguardLocked(null);
410                        } else {
411                            if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
412                                  + "show permanently disabled message in lockscreen.");
413                            resetStateLocked(null);
414                        }
415                    }
416                    break;
417                case READY:
418                    synchronized (this) {
419                        if (isShowing()) {
420                            resetStateLocked(null);
421                        }
422                    }
423                    break;
424            }
425        }
426
427    };
428
429    ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
430        public void wakeUp() {
431            KeyguardViewMediator.this.wakeUp();
432        }
433
434        public void userActivity() {
435            KeyguardViewMediator.this.userActivity();
436        }
437
438        public void userActivity(long holdMs) {
439            KeyguardViewMediator.this.userActivity(holdMs);
440        }
441
442        public void keyguardDone(boolean authenticated) {
443            KeyguardViewMediator.this.keyguardDone(authenticated, true);
444        }
445
446        public void keyguardDoneDrawing() {
447            mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
448        }
449
450        @Override
451        public void setNeedsInput(boolean needsInput) {
452            mKeyguardViewManager.setNeedsInput(needsInput);
453        }
454
455        @Override
456        public void onUserActivityTimeoutChanged() {
457            mKeyguardViewManager.updateUserActivityTimeout();
458        }
459
460        @Override
461        public void keyguardDonePending() {
462            mKeyguardDonePending = true;
463        }
464    };
465
466    public void wakeUp() {
467        mPM.wakeUp(SystemClock.uptimeMillis());
468    }
469
470    private void userActivity() {
471        userActivity(AWAKE_INTERVAL_DEFAULT_MS);
472    }
473
474    public void userActivity(long holdMs) {
475        // We ignore the hold time.  Eventually we should remove it.
476        // Instead, the keyguard window has an explicit user activity timeout set on it.
477        mPM.userActivity(SystemClock.uptimeMillis(), false);
478    }
479
480    /**
481     * Construct a KeyguardViewMediator
482     * @param context
483     * @param lockPatternUtils optional mock interface for LockPatternUtils
484     */
485    public KeyguardViewMediator(Context context, LockPatternUtils lockPatternUtils) {
486        mContext = context;
487        mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
488        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
489        mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
490        mShowKeyguardWakeLock.setReferenceCounted(false);
491
492        mWakeAndHandOff = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "keyguardWakeAndHandOff");
493        mWakeAndHandOff.setReferenceCounted(false);
494
495        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
496
497        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
498
499        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
500
501        mLockPatternUtils = lockPatternUtils != null
502                ? lockPatternUtils : new LockPatternUtils(mContext);
503        mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
504
505        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
506
507        mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
508                mLockPatternUtils);
509
510        final ContentResolver cr = mContext.getContentResolver();
511        mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1);
512
513        mScreenOn = mPM.isScreenOn();
514
515        mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
516        String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);
517        if (soundPath != null) {
518            mLockSoundId = mLockSounds.load(soundPath, 1);
519        }
520        if (soundPath == null || mLockSoundId == 0) {
521            Log.w(TAG, "failed to load lock sound from " + soundPath);
522        }
523        soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);
524        if (soundPath != null) {
525            mUnlockSoundId = mLockSounds.load(soundPath, 1);
526        }
527        if (soundPath == null || mUnlockSoundId == 0) {
528            Log.w(TAG, "failed to load unlock sound from " + soundPath);
529        }
530        int lockSoundDefaultAttenuation = context.getResources().getInteger(
531                com.android.internal.R.integer.config_lockSoundVolumeDb);
532        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
533    }
534
535    /**
536     * Let us know that the system is ready after startup.
537     */
538    public void onSystemReady() {
539        mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
540        synchronized (this) {
541            if (DEBUG) Log.d(TAG, "onSystemReady");
542            mSystemReady = true;
543            mUpdateMonitor.registerCallback(mUpdateCallback);
544
545            // Suppress biometric unlock right after boot until things have settled if it is the
546            // selected security method, otherwise unsuppress it.  It must be unsuppressed if it is
547            // not the selected security method for the following reason:  if the user starts
548            // without a screen lock selected, the biometric unlock would be suppressed the first
549            // time they try to use it.
550            //
551            // Note that the biometric unlock will still not show if it is not the selected method.
552            // Calling setAlternateUnlockEnabled(true) simply says don't suppress it if it is the
553            // selected method.
554            if (mLockPatternUtils.usingBiometricWeak()
555                    && mLockPatternUtils.isBiometricWeakInstalled()) {
556                if (DEBUG) Log.d(TAG, "suppressing biometric unlock during boot");
557                mUpdateMonitor.setAlternateUnlockEnabled(false);
558            } else {
559                mUpdateMonitor.setAlternateUnlockEnabled(true);
560            }
561
562            doKeyguardLocked(null);
563        }
564        // Most services aren't available until the system reaches the ready state, so we
565        // send it here when the device first boots.
566        maybeSendUserPresentBroadcast();
567    }
568
569    /**
570     * Called to let us know the screen was turned off.
571     * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
572     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
573     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
574     */
575    public void onScreenTurnedOff(int why) {
576        synchronized (this) {
577            mScreenOn = false;
578            if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")");
579
580            mKeyguardDonePending = false;
581
582            // Lock immediately based on setting if secure (user has a pin/pattern/password).
583            // This also "locks" the device when not secure to provide easy access to the
584            // camera while preventing unwanted input.
585            final boolean lockImmediately =
586                mLockPatternUtils.getPowerButtonInstantlyLocks() || !mLockPatternUtils.isSecure();
587
588            if (mExitSecureCallback != null) {
589                if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
590                try {
591                    mExitSecureCallback.onKeyguardExitResult(false);
592                } catch (RemoteException e) {
593                    Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
594                }
595                mExitSecureCallback = null;
596                if (!mExternallyEnabled) {
597                    hideLocked();
598                }
599            } else if (mShowing) {
600                notifyScreenOffLocked();
601                resetStateLocked(null);
602            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
603                   || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
604                doKeyguardLaterLocked();
605            } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
606                // Do not enable the keyguard if the prox sensor forced the screen off.
607            } else {
608                doKeyguardLocked(null);
609            }
610        }
611    }
612
613    private void doKeyguardLaterLocked() {
614        // if the screen turned off because of timeout or the user hit the power button
615        // and we don't need to lock immediately, set an alarm
616        // to enable it a little bit later (i.e, give the user a chance
617        // to turn the screen back on within a certain window without
618        // having to unlock the screen)
619        final ContentResolver cr = mContext.getContentResolver();
620
621        // From DisplaySettings
622        long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT,
623                KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT);
624
625        // From SecuritySettings
626        final long lockAfterTimeout = Settings.Secure.getInt(cr,
627                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
628                KEYGUARD_LOCK_AFTER_DELAY_DEFAULT);
629
630        // From DevicePolicyAdmin
631        final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
632                .getMaximumTimeToLock(null, mLockPatternUtils.getCurrentUser());
633
634        long timeout;
635        if (policyTimeout > 0) {
636            // policy in effect. Make sure we don't go beyond policy limit.
637            displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
638            timeout = Math.min(policyTimeout - displayTimeout, lockAfterTimeout);
639        } else {
640            timeout = lockAfterTimeout;
641        }
642
643        if (timeout <= 0) {
644            // Lock now
645            mSuppressNextLockSound = true;
646            doKeyguardLocked(null);
647        } else {
648            // Lock in the future
649            long when = SystemClock.elapsedRealtime() + timeout;
650            Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
651            intent.putExtra("seq", mDelayedShowingSequence);
652            PendingIntent sender = PendingIntent.getBroadcast(mContext,
653                    0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
654            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
655            if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
656                             + mDelayedShowingSequence);
657        }
658    }
659
660    private void cancelDoKeyguardLaterLocked() {
661        mDelayedShowingSequence++;
662    }
663
664    /**
665     * Let's us know the screen was turned on.
666     */
667    public void onScreenTurnedOn(IKeyguardShowCallback callback) {
668        synchronized (this) {
669            mScreenOn = true;
670            cancelDoKeyguardLaterLocked();
671            if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
672            if (callback != null) {
673                notifyScreenOnLocked(callback);
674            }
675        }
676        maybeSendUserPresentBroadcast();
677    }
678
679    private void maybeSendUserPresentBroadcast() {
680        if (mSystemReady && mLockPatternUtils.isLockScreenDisabled()
681                && mUserManager.getUsers(true).size() == 1) {
682            // Lock screen is disabled because the user has set the preference to "None".
683            // In this case, send out ACTION_USER_PRESENT here instead of in
684            // handleKeyguardDone()
685            sendUserPresentBroadcast();
686        }
687    }
688
689    /**
690     * A dream started.  We should lock after the usual screen-off lock timeout but only
691     * if there is a secure lock pattern.
692     */
693    public void onDreamingStarted() {
694        synchronized (this) {
695            if (mScreenOn && mLockPatternUtils.isSecure()) {
696                doKeyguardLaterLocked();
697            }
698        }
699    }
700
701    /**
702     * A dream stopped.
703     */
704    public void onDreamingStopped() {
705        synchronized (this) {
706            if (mScreenOn) {
707                cancelDoKeyguardLaterLocked();
708            }
709        }
710    }
711
712    /**
713     * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
714     * a way for external stuff to override normal keyguard behavior.  For instance
715     * the phone app disables the keyguard when it receives incoming calls.
716     */
717    public void setKeyguardEnabled(boolean enabled) {
718        synchronized (this) {
719            if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
720
721            mExternallyEnabled = enabled;
722
723            if (!enabled && mShowing) {
724                if (mExitSecureCallback != null) {
725                    if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
726                    // we're in the process of handling a request to verify the user
727                    // can get past the keyguard. ignore extraneous requests to disable / reenable
728                    return;
729                }
730
731                // hiding keyguard that is showing, remember to reshow later
732                if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
733                        + "disabling status bar expansion");
734                mNeedToReshowWhenReenabled = true;
735                hideLocked();
736            } else if (enabled && mNeedToReshowWhenReenabled) {
737                // reenabled after previously hidden, reshow
738                if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
739                        + "status bar expansion");
740                mNeedToReshowWhenReenabled = false;
741
742                if (mExitSecureCallback != null) {
743                    if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
744                    try {
745                        mExitSecureCallback.onKeyguardExitResult(false);
746                    } catch (RemoteException e) {
747                        Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
748                    }
749                    mExitSecureCallback = null;
750                    resetStateLocked(null);
751                } else {
752                    showLocked(null);
753
754                    // block until we know the keygaurd is done drawing (and post a message
755                    // to unblock us after a timeout so we don't risk blocking too long
756                    // and causing an ANR).
757                    mWaitingUntilKeyguardVisible = true;
758                    mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
759                    if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false");
760                    while (mWaitingUntilKeyguardVisible) {
761                        try {
762                            wait();
763                        } catch (InterruptedException e) {
764                            Thread.currentThread().interrupt();
765                        }
766                    }
767                    if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible");
768                }
769            }
770        }
771    }
772
773    /**
774     * @see android.app.KeyguardManager#exitKeyguardSecurely
775     */
776    public void verifyUnlock(IKeyguardExitCallback callback) {
777        synchronized (this) {
778            if (DEBUG) Log.d(TAG, "verifyUnlock");
779            if (!mUpdateMonitor.isDeviceProvisioned()) {
780                // don't allow this api when the device isn't provisioned
781                if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned");
782                try {
783                    callback.onKeyguardExitResult(false);
784                } catch (RemoteException e) {
785                    Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
786                }
787            } else if (mExternallyEnabled) {
788                // this only applies when the user has externally disabled the
789                // keyguard.  this is unexpected and means the user is not
790                // using the api properly.
791                Log.w(TAG, "verifyUnlock called when not externally disabled");
792                try {
793                    callback.onKeyguardExitResult(false);
794                } catch (RemoteException e) {
795                    Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
796                }
797            } else if (mExitSecureCallback != null) {
798                // already in progress with someone else
799                try {
800                    callback.onKeyguardExitResult(false);
801                } catch (RemoteException e) {
802                    Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
803                }
804            } else {
805                mExitSecureCallback = callback;
806                verifyUnlockLocked();
807            }
808        }
809    }
810
811    /**
812     * Is the keyguard currently showing?
813     */
814    public boolean isShowing() {
815        return mShowing;
816    }
817
818    /**
819     * Is the keyguard currently showing and not being force hidden?
820     */
821    public boolean isShowingAndNotHidden() {
822        return mShowing && !mHidden;
823    }
824
825    /**
826     * Notify us when the keyguard is hidden by another window
827     */
828    public void setHidden(boolean isHidden) {
829        if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
830        mUpdateMonitor.sendKeyguardVisibilityChanged(!isHidden);
831        mHandler.removeMessages(SET_HIDDEN);
832        Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0);
833        mHandler.sendMessage(msg);
834    }
835
836    /**
837     * Handles SET_HIDDEN message sent by setHidden()
838     */
839    private void handleSetHidden(boolean isHidden) {
840        synchronized (KeyguardViewMediator.this) {
841            if (mHidden != isHidden) {
842                mHidden = isHidden;
843                updateActivityLockScreenState();
844                adjustStatusBarLocked();
845            }
846        }
847    }
848
849    /**
850     * Used by PhoneWindowManager to enable the keyguard due to a user activity timeout.
851     * This must be safe to call from any thread and with any window manager locks held.
852     */
853    public void doKeyguardTimeout(Bundle options) {
854        mHandler.removeMessages(KEYGUARD_TIMEOUT);
855        Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT, options);
856        mHandler.sendMessage(msg);
857    }
858
859    /**
860     * Given the state of the keyguard, is the input restricted?
861     * Input is restricted when the keyguard is showing, or when the keyguard
862     * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.
863     */
864    public boolean isInputRestricted() {
865        return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();
866    }
867
868    /**
869     * Enable the keyguard if the settings are appropriate.
870     */
871    private void doKeyguardLocked(Bundle options) {
872        // if another app is disabling us, don't show
873        if (!mExternallyEnabled) {
874            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
875
876            // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
877            // for an occasional ugly flicker in this situation:
878            // 1) receive a call with the screen on (no keyguard) or make a call
879            // 2) screen times out
880            // 3) user hits key to turn screen back on
881            // instead, we reenable the keyguard when we know the screen is off and the call
882            // ends (see the broadcast receiver below)
883            // TODO: clean this up when we have better support at the window manager level
884            // for apps that wish to be on top of the keyguard
885            return;
886        }
887
888        // if the keyguard is already showing, don't bother
889        if (mKeyguardViewManager.isShowing()) {
890            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
891            return;
892        }
893
894        // if the setup wizard hasn't run yet, don't show
895        final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
896                false);
897        final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
898        final IccCardConstants.State state = mUpdateMonitor.getSimState();
899        final boolean lockedOrMissing = state.isPinLocked()
900                || ((state == IccCardConstants.State.ABSENT
901                || state == IccCardConstants.State.PERM_DISABLED)
902                && requireSim);
903
904        if (!lockedOrMissing && !provisioned) {
905            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
906                    + " and the sim is not locked or missing");
907            return;
908        }
909
910        if (mUserManager.getUsers(true).size() < 2
911                && mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {
912            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
913            return;
914        }
915
916        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
917        showLocked(options);
918    }
919
920    /**
921     * Dismiss the keyguard through the security layers.
922     */
923    public void dismiss() {
924        if (mShowing && !mHidden) {
925            mKeyguardViewManager.dismiss();
926        }
927    }
928
929    /**
930     * Send message to keyguard telling it to reset its state.
931     * @param options options about how to show the keyguard
932     * @see #handleReset()
933     */
934    private void resetStateLocked(Bundle options) {
935        if (DEBUG) Log.d(TAG, "resetStateLocked");
936        Message msg = mHandler.obtainMessage(RESET, options);
937        mHandler.sendMessage(msg);
938    }
939
940    /**
941     * Send message to keyguard telling it to verify unlock
942     * @see #handleVerifyUnlock()
943     */
944    private void verifyUnlockLocked() {
945        if (DEBUG) Log.d(TAG, "verifyUnlockLocked");
946        mHandler.sendEmptyMessage(VERIFY_UNLOCK);
947    }
948
949
950    /**
951     * Send a message to keyguard telling it the screen just turned on.
952     * @see #onScreenTurnedOff(int)
953     * @see #handleNotifyScreenOff
954     */
955    private void notifyScreenOffLocked() {
956        if (DEBUG) Log.d(TAG, "notifyScreenOffLocked");
957        mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF);
958    }
959
960    /**
961     * Send a message to keyguard telling it the screen just turned on.
962     * @see #onScreenTurnedOn()
963     * @see #handleNotifyScreenOn
964     */
965    private void notifyScreenOnLocked(IKeyguardShowCallback result) {
966        if (DEBUG) Log.d(TAG, "notifyScreenOnLocked");
967        Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, result);
968        mHandler.sendMessage(msg);
969    }
970
971    /**
972     * Send message to keyguard telling it about a wake key so it can adjust
973     * its state accordingly and then poke the wake lock when it is ready.
974     * @param keyCode The wake key.
975     * @see #handleWakeWhenReady
976     * @see #onWakeKeyWhenKeyguardShowing(int)
977     */
978    private void wakeWhenReady(int keyCode) {
979        if (DBG_WAKE) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
980
981        /**
982         * acquire the handoff lock that will keep the cpu running.  this will
983         * be released once the keyguard has set itself up and poked the other wakelock
984         * in {@link #handleWakeWhenReady(int)}
985         */
986        mWakeAndHandOff.acquire();
987
988        Message msg = mHandler.obtainMessage(WAKE_WHEN_READY, keyCode, 0);
989        mHandler.sendMessage(msg);
990    }
991
992    /**
993     * Send message to keyguard telling it to show itself
994     * @see #handleShow()
995     */
996    private void showLocked(Bundle options) {
997        if (DEBUG) Log.d(TAG, "showLocked");
998        // ensure we stay awake until we are finished displaying the keyguard
999        mShowKeyguardWakeLock.acquire();
1000        Message msg = mHandler.obtainMessage(SHOW, options);
1001        mHandler.sendMessage(msg);
1002    }
1003
1004    /**
1005     * Send message to keyguard telling it to hide itself
1006     * @see #handleHide()
1007     */
1008    private void hideLocked() {
1009        if (DEBUG) Log.d(TAG, "hideLocked");
1010        Message msg = mHandler.obtainMessage(HIDE);
1011        mHandler.sendMessage(msg);
1012    }
1013
1014    public boolean isSecure() {
1015        return mLockPatternUtils.isSecure()
1016            || KeyguardUpdateMonitor.getInstance(mContext).isSimPinSecure();
1017    }
1018
1019    /**
1020     * Update the newUserId. Call while holding WindowManagerService lock.
1021     * NOTE: Should only be called by KeyguardViewMediator in response to the user id changing.
1022     *
1023     * @param newUserId The id of the incoming user.
1024     */
1025    public void setCurrentUser(int newUserId) {
1026        mLockPatternUtils.setCurrentUser(newUserId);
1027    }
1028
1029    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
1030        @Override
1031        public void onReceive(Context context, Intent intent) {
1032            if (DELAYED_KEYGUARD_ACTION.equals(intent.getAction())) {
1033                final int sequence = intent.getIntExtra("seq", 0);
1034                if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
1035                        + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
1036                synchronized (KeyguardViewMediator.this) {
1037                    if (mDelayedShowingSequence == sequence) {
1038                        // Don't play lockscreen SFX if the screen went off due to timeout.
1039                        mSuppressNextLockSound = true;
1040                        doKeyguardLocked(null);
1041                    }
1042                }
1043            }
1044        }
1045    };
1046
1047    /**
1048     * When a key is received when the screen is off and the keyguard is showing,
1049     * we need to decide whether to actually turn on the screen, and if so, tell
1050     * the keyguard to prepare itself and poke the wake lock when it is ready.
1051     *
1052     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
1053     * Be sure not to take any action that takes a long time; any significant
1054     * action should be posted to a handler.
1055     *
1056     * @param keyCode The keycode of the key that woke the device
1057     */
1058    public void onWakeKeyWhenKeyguardShowing(int keyCode) {
1059        if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")");
1060
1061        // give the keyguard view manager a chance to adjust the state of the
1062        // keyguard based on the key that woke the device before poking
1063        // the wake lock
1064        wakeWhenReady(keyCode);
1065    }
1066
1067    /**
1068     * When a wake motion such as an external mouse movement is received when the screen
1069     * is off and the keyguard is showing, we need to decide whether to actually turn
1070     * on the screen, and if so, tell the keyguard to prepare itself and poke the wake
1071     * lock when it is ready.
1072     *
1073     * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
1074     * Be sure not to take any action that takes a long time; any significant
1075     * action should be posted to a handler.
1076     */
1077    public void onWakeMotionWhenKeyguardShowing() {
1078        if (DEBUG) Log.d(TAG, "onWakeMotionWhenKeyguardShowing()");
1079
1080        // give the keyguard view manager a chance to adjust the state of the
1081        // keyguard based on the key that woke the device before poking
1082        // the wake lock
1083        wakeWhenReady(KeyEvent.KEYCODE_UNKNOWN);
1084    }
1085
1086    public void keyguardDone(boolean authenticated, boolean wakeup) {
1087        mKeyguardDonePending = false;
1088        synchronized (this) {
1089            EventLog.writeEvent(70000, 2);
1090            if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")");
1091            Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
1092            msg.arg1 = wakeup ? 1 : 0;
1093            mHandler.sendMessage(msg);
1094
1095            if (authenticated) {
1096                mUpdateMonitor.clearFailedUnlockAttempts();
1097            }
1098
1099            if (mExitSecureCallback != null) {
1100                try {
1101                    mExitSecureCallback.onKeyguardExitResult(authenticated);
1102                } catch (RemoteException e) {
1103                    Slog.w(TAG, "Failed to call onKeyguardExitResult(" + authenticated + ")", e);
1104                }
1105
1106                mExitSecureCallback = null;
1107
1108                if (authenticated) {
1109                    // after succesfully exiting securely, no need to reshow
1110                    // the keyguard when they've released the lock
1111                    mExternallyEnabled = true;
1112                    mNeedToReshowWhenReenabled = false;
1113                }
1114            }
1115        }
1116    }
1117
1118    /**
1119     * This handler will be associated with the policy thread, which will also
1120     * be the UI thread of the keyguard.  Since the apis of the policy, and therefore
1121     * this class, can be called by other threads, any action that directly
1122     * interacts with the keyguard ui should be posted to this handler, rather
1123     * than called directly.
1124     */
1125    private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
1126        @Override
1127        public void handleMessage(Message msg) {
1128            switch (msg.what) {
1129                case SHOW:
1130                    handleShow((Bundle) msg.obj);
1131                    return ;
1132                case HIDE:
1133                    handleHide();
1134                    return ;
1135                case RESET:
1136                    handleReset((Bundle) msg.obj);
1137                    return ;
1138                case VERIFY_UNLOCK:
1139                    handleVerifyUnlock();
1140                    return;
1141                case NOTIFY_SCREEN_OFF:
1142                    handleNotifyScreenOff();
1143                    return;
1144                case NOTIFY_SCREEN_ON:
1145                    handleNotifyScreenOn((IKeyguardShowCallback) msg.obj);
1146                    return;
1147                case WAKE_WHEN_READY:
1148                    handleWakeWhenReady(msg.arg1);
1149                    return;
1150                case KEYGUARD_DONE:
1151                    handleKeyguardDone(msg.arg1 != 0);
1152                    return;
1153                case KEYGUARD_DONE_DRAWING:
1154                    handleKeyguardDoneDrawing();
1155                    return;
1156                case KEYGUARD_DONE_AUTHENTICATING:
1157                    keyguardDone(true, true);
1158                    return;
1159                case SET_HIDDEN:
1160                    handleSetHidden(msg.arg1 != 0);
1161                    break;
1162                case KEYGUARD_TIMEOUT:
1163                    synchronized (KeyguardViewMediator.this) {
1164                        doKeyguardLocked((Bundle) msg.obj);
1165                    }
1166                    break;
1167                case SHOW_ASSISTANT:
1168                    handleShowAssistant();
1169                    break;
1170            }
1171        }
1172    };
1173
1174    /**
1175     * @see #keyguardDone
1176     * @see #KEYGUARD_DONE
1177     */
1178    private void handleKeyguardDone(boolean wakeup) {
1179        if (DEBUG) Log.d(TAG, "handleKeyguardDone");
1180        handleHide();
1181        if (wakeup) {
1182            wakeUp();
1183        }
1184
1185        sendUserPresentBroadcast();
1186    }
1187
1188    private void sendUserPresentBroadcast() {
1189        final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
1190        mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, currentUser);
1191    }
1192
1193    /**
1194     * @see #keyguardDoneDrawing
1195     * @see #KEYGUARD_DONE_DRAWING
1196     */
1197    private void handleKeyguardDoneDrawing() {
1198        synchronized(this) {
1199            if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing");
1200            if (mWaitingUntilKeyguardVisible) {
1201                if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible");
1202                mWaitingUntilKeyguardVisible = false;
1203                notifyAll();
1204
1205                // there will usually be two of these sent, one as a timeout, and one
1206                // as a result of the callback, so remove any remaining messages from
1207                // the queue
1208                mHandler.removeMessages(KEYGUARD_DONE_DRAWING);
1209            }
1210        }
1211    }
1212
1213    private void playSounds(boolean locked) {
1214        // User feedback for keyguard.
1215
1216        if (mSuppressNextLockSound) {
1217            mSuppressNextLockSound = false;
1218            return;
1219        }
1220
1221        final ContentResolver cr = mContext.getContentResolver();
1222        if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
1223            final int whichSound = locked
1224                ? mLockSoundId
1225                : mUnlockSoundId;
1226            mLockSounds.stop(mLockSoundStreamId);
1227            // Init mAudioManager
1228            if (mAudioManager == null) {
1229                mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1230                if (mAudioManager == null) return;
1231                mMasterStreamType = mAudioManager.getMasterStreamType();
1232            }
1233            // If the stream is muted, don't play the sound
1234            if (mAudioManager.isStreamMute(mMasterStreamType)) return;
1235
1236            mLockSoundStreamId = mLockSounds.play(whichSound,
1237                    mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
1238        }
1239    }
1240
1241    private void updateActivityLockScreenState() {
1242        try {
1243            ActivityManagerNative.getDefault().setLockScreenShown(
1244                    mShowing && !mHidden);
1245        } catch (RemoteException e) {
1246        }
1247    }
1248
1249    /**
1250     * Handle message sent by {@link #showLocked}.
1251     * @see #SHOW
1252     */
1253    private void handleShow(Bundle options) {
1254        synchronized (KeyguardViewMediator.this) {
1255            if (!mSystemReady) {
1256                if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
1257                return;
1258            } else {
1259                if (DEBUG) Log.d(TAG, "handleShow");
1260            }
1261
1262            mKeyguardViewManager.show(options);
1263            mShowing = true;
1264            mKeyguardDonePending = false;
1265            updateActivityLockScreenState();
1266            adjustStatusBarLocked();
1267            userActivity();
1268            try {
1269                ActivityManagerNative.getDefault().closeSystemDialogs("lock");
1270            } catch (RemoteException e) {
1271            }
1272
1273            // Do this at the end to not slow down display of the keyguard.
1274            playSounds(true);
1275
1276            mShowKeyguardWakeLock.release();
1277        }
1278    }
1279
1280    /**
1281     * Handle message sent by {@link #hideLocked()}
1282     * @see #HIDE
1283     */
1284    private void handleHide() {
1285        synchronized (KeyguardViewMediator.this) {
1286            if (DEBUG) Log.d(TAG, "handleHide");
1287            if (mWakeAndHandOff.isHeld()) {
1288                Log.w(TAG, "attempt to hide the keyguard while waking, ignored");
1289                return;
1290            }
1291
1292            // only play "unlock" noises if not on a call (since the incall UI
1293            // disables the keyguard)
1294            if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
1295                playSounds(false);
1296            }
1297
1298            mKeyguardViewManager.hide();
1299            mShowing = false;
1300            mKeyguardDonePending = false;
1301            updateActivityLockScreenState();
1302            adjustStatusBarLocked();
1303        }
1304    }
1305
1306    private void adjustStatusBarLocked() {
1307        if (mStatusBarManager == null) {
1308            mStatusBarManager = (StatusBarManager)
1309                    mContext.getSystemService(Context.STATUS_BAR_SERVICE);
1310        }
1311        if (mStatusBarManager == null) {
1312            Log.w(TAG, "Could not get status bar manager");
1313        } else {
1314            if (mShowLockIcon) {
1315                // Give feedback to user when secure keyguard is active and engaged
1316                if (mShowing && isSecure()) {
1317                    if (!mShowingLockIcon) {
1318                        String contentDescription = mContext.getString(
1319                                com.android.internal.R.string.status_bar_device_locked);
1320                        mStatusBarManager.setIcon("secure",
1321                                com.android.internal.R.drawable.stat_sys_secure, 0,
1322                                contentDescription);
1323                        mShowingLockIcon = true;
1324                    }
1325                } else {
1326                    if (mShowingLockIcon) {
1327                        mStatusBarManager.removeIcon("secure");
1328                        mShowingLockIcon = false;
1329                    }
1330                }
1331            }
1332
1333            // Disable aspects of the system/status/navigation bars that must not be re-enabled by
1334            // windows that appear on top, ever
1335            int flags = StatusBarManager.DISABLE_NONE;
1336            if (mShowing) {
1337                // Permanently disable components not available when keyguard is enabled
1338                // (like recents). Temporary enable/disable (e.g. the "back" button) are
1339                // done in KeyguardHostView.
1340                flags |= StatusBarManager.DISABLE_RECENT;
1341                if (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
1342                    // showing secure lockscreen; disable expanding.
1343                    flags |= StatusBarManager.DISABLE_EXPAND;
1344                }
1345                if (isSecure()) {
1346                    // showing secure lockscreen; disable ticker.
1347                    flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER;
1348                }
1349                if (!isAssistantAvailable()) {
1350                    flags |= StatusBarManager.DISABLE_SEARCH;
1351                }
1352            }
1353
1354            if (DEBUG) {
1355                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
1356                        + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
1357            }
1358
1359            if (!(mContext instanceof Activity)) {
1360                mStatusBarManager.disable(flags);
1361            }
1362        }
1363    }
1364
1365    /**
1366     * Handle message sent by {@link #wakeWhenReady(int)}
1367     * @param keyCode The key that woke the device.
1368     * @see #WAKE_WHEN_READY
1369     */
1370    private void handleWakeWhenReady(int keyCode) {
1371        synchronized (KeyguardViewMediator.this) {
1372            if (DBG_WAKE) Log.d(TAG, "handleWakeWhenReady(" + keyCode + ")");
1373
1374            // this should result in a call to 'poke wakelock' which will set a timeout
1375            // on releasing the wakelock
1376            if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) {
1377                // poke wakelock ourselves if keyguard is no longer active
1378                Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves");
1379                userActivity();
1380            }
1381
1382            /**
1383             * Now that the keyguard is ready and has poked the wake lock, we can
1384             * release the handoff wakelock
1385             */
1386            mWakeAndHandOff.release();
1387        }
1388    }
1389
1390    /**
1391     * Handle message sent by {@link #resetStateLocked(Bundle)}
1392     * @see #RESET
1393     */
1394    private void handleReset(Bundle options) {
1395        if (options == null) {
1396            options = new Bundle();
1397        }
1398        options.putBoolean(KeyguardViewManager.IS_SWITCHING_USER, mSwitchingUser);
1399        synchronized (KeyguardViewMediator.this) {
1400            if (DEBUG) Log.d(TAG, "handleReset");
1401            mKeyguardViewManager.reset(options);
1402        }
1403    }
1404
1405    /**
1406     * Handle message sent by {@link #verifyUnlock}
1407     * @see #VERIFY_UNLOCK
1408     */
1409    private void handleVerifyUnlock() {
1410        synchronized (KeyguardViewMediator.this) {
1411            if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
1412            mKeyguardViewManager.verifyUnlock();
1413            mShowing = true;
1414            updateActivityLockScreenState();
1415        }
1416    }
1417
1418    /**
1419     * Handle message sent by {@link #notifyScreenOffLocked()}
1420     * @see #NOTIFY_SCREEN_OFF
1421     */
1422    private void handleNotifyScreenOff() {
1423        synchronized (KeyguardViewMediator.this) {
1424            if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
1425            mKeyguardViewManager.onScreenTurnedOff();
1426        }
1427    }
1428
1429    /**
1430     * Handle message sent by {@link #notifyScreenOnLocked()}
1431     * @see #NOTIFY_SCREEN_ON
1432     */
1433    private void handleNotifyScreenOn(IKeyguardShowCallback callback) {
1434        synchronized (KeyguardViewMediator.this) {
1435            if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
1436            mKeyguardViewManager.onScreenTurnedOn(callback);
1437        }
1438    }
1439
1440    public boolean isDismissable() {
1441        return mKeyguardDonePending || !isSecure();
1442    }
1443
1444    public void showAssistant() {
1445        Message msg = mHandler.obtainMessage(SHOW_ASSISTANT);
1446        mHandler.sendMessage(msg);
1447    }
1448
1449    public void handleShowAssistant() {
1450        mKeyguardViewManager.showAssistant();
1451    }
1452
1453    private boolean isAssistantAvailable() {
1454        return mSearchManager != null
1455                && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
1456    }
1457}
1458