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