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