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