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