OSDN Git Service

Explicitly specify user for public mode
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / statusbar / phone / StatusBarKeyguardViewManager.java
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
17 package com.android.systemui.statusbar.phone;
18
19 import android.content.ComponentCallbacks2;
20 import android.content.Context;
21 import android.os.Bundle;
22 import android.os.RemoteException;
23 import android.os.SystemClock;
24 import android.util.Slog;
25 import android.view.KeyEvent;
26 import android.view.View;
27 import android.view.ViewGroup;
28 import android.view.WindowManagerGlobal;
29
30 import com.android.internal.policy.IKeyguardShowCallback;
31 import com.android.internal.widget.LockPatternUtils;
32 import com.android.keyguard.KeyguardUpdateMonitor;
33 import com.android.keyguard.ViewMediatorCallback;
34
35 import static com.android.keyguard.KeyguardHostView.OnDismissAction;
36
37 /**
38  * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
39  * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
40  * which is in turn, reported to this class by the current
41  * {@link com.android.keyguard.KeyguardViewBase}.
42  */
43 public class StatusBarKeyguardViewManager {
44
45     // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
46     private static final long HIDE_TIMING_CORRECTION_MS = -3 * 16;
47
48     // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync
49     // with the appear animations of the PIN/pattern/password views.
50     private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320;
51
52     private static String TAG = "StatusBarKeyguardViewManager";
53
54     private final Context mContext;
55
56     private LockPatternUtils mLockPatternUtils;
57     private ViewMediatorCallback mViewMediatorCallback;
58     private PhoneStatusBar mPhoneStatusBar;
59     private ScrimController mScrimController;
60
61     private ViewGroup mContainer;
62     private StatusBarWindowManager mStatusBarWindowManager;
63
64     private boolean mScreenOn = false;
65     private KeyguardBouncer mBouncer;
66     private boolean mShowing;
67     private boolean mOccluded;
68
69     private boolean mFirstUpdate = true;
70     private boolean mLastShowing;
71     private boolean mLastOccluded;
72     private boolean mLastBouncerShowing;
73     private boolean mLastBouncerDismissible;
74     private OnDismissAction mAfterKeyguardGoneAction;
75
76     public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
77             LockPatternUtils lockPatternUtils) {
78         mContext = context;
79         mViewMediatorCallback = callback;
80         mLockPatternUtils = lockPatternUtils;
81     }
82
83     public void registerStatusBar(PhoneStatusBar phoneStatusBar,
84             ViewGroup container, StatusBarWindowManager statusBarWindowManager,
85             ScrimController scrimController) {
86         mPhoneStatusBar = phoneStatusBar;
87         mContainer = container;
88         mStatusBarWindowManager = statusBarWindowManager;
89         mScrimController = scrimController;
90         mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
91                 mStatusBarWindowManager, container);
92     }
93
94     /**
95      * Show the keyguard.  Will handle creating and attaching to the view manager
96      * lazily.
97      */
98     public void show(Bundle options) {
99         mShowing = true;
100         mStatusBarWindowManager.setKeyguardShowing(true);
101         reset();
102     }
103
104     /**
105      * Shows the notification keyguard or the bouncer depending on
106      * {@link KeyguardBouncer#needsFullscreenBouncer()}.
107      */
108     private void showBouncerOrKeyguard() {
109         if (mBouncer.needsFullscreenBouncer()) {
110
111             // The keyguard might be showing (already). So we need to hide it.
112             mPhoneStatusBar.hideKeyguard();
113             mBouncer.show();
114         } else {
115             mPhoneStatusBar.showKeyguard();
116             mBouncer.hide(false /* destroyView */);
117             mBouncer.prepare();
118         }
119     }
120
121     private void showBouncer() {
122         if (mShowing) {
123             mBouncer.show();
124         }
125         updateStates();
126     }
127
128     public void dismissWithAction(OnDismissAction r, boolean afterKeyguardGone) {
129         if (mShowing) {
130             if (!afterKeyguardGone) {
131                 mBouncer.showWithDismissAction(r);
132             } else {
133                 mBouncer.show();
134                 mAfterKeyguardGoneAction = r;
135             }
136         }
137         updateStates();
138     }
139
140     /**
141      * Reset the state of the view.
142      */
143     public void reset() {
144         if (mShowing) {
145             if (mOccluded) {
146                 mPhoneStatusBar.hideKeyguard();
147                 mBouncer.hide(false /* destroyView */);
148             } else {
149                 showBouncerOrKeyguard();
150             }
151             updateStates();
152         }
153     }
154
155     public void onScreenTurnedOff() {
156         mScreenOn = false;
157         mPhoneStatusBar.onScreenTurnedOff();
158         mBouncer.onScreenTurnedOff();
159     }
160
161     public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
162         mScreenOn = true;
163         mPhoneStatusBar.onScreenTurnedOn();
164         if (callback != null) {
165             callbackAfterDraw(callback);
166         }
167     }
168
169     private void callbackAfterDraw(final IKeyguardShowCallback callback) {
170         mContainer.post(new Runnable() {
171             @Override
172             public void run() {
173                 try {
174                     callback.onShown(mContainer.getWindowToken());
175                 } catch (RemoteException e) {
176                     Slog.w(TAG, "Exception calling onShown():", e);
177                 }
178             }
179         });
180     }
181
182     public void verifyUnlock() {
183         dismiss();
184     }
185
186     public void setNeedsInput(boolean needsInput) {
187         mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
188     }
189
190     public void updateUserActivityTimeout() {
191         mStatusBarWindowManager.setKeyguardUserActivityTimeout(mBouncer.getUserActivityTimeout());
192     }
193
194     public void setOccluded(boolean occluded) {
195         if (occluded && !mOccluded && mShowing) {
196             if (mPhoneStatusBar.isInLaunchTransition()) {
197                 mOccluded = true;
198                 mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */,
199                         new Runnable() {
200                             @Override
201                             public void run() {
202                                 mStatusBarWindowManager.setKeyguardOccluded(true);
203                                 reset();
204                             }
205                         });
206                 return;
207             }
208         }
209         mOccluded = occluded;
210         mStatusBarWindowManager.setKeyguardOccluded(occluded);
211         reset();
212     }
213
214     public boolean isOccluded() {
215         return mOccluded;
216     }
217
218     /**
219      * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
220      * security view of the bouncer.
221      *
222      * @param finishRunnable the runnable to be run after the animation finished, or {@code null} if
223      *                       no action should be run
224      */
225     public void startPreHideAnimation(Runnable finishRunnable) {
226         if (mBouncer.isShowing()) {
227             mBouncer.startPreHideAnimation(finishRunnable);
228         } else if (finishRunnable != null) {
229             finishRunnable.run();
230         }
231     }
232
233     /**
234      * Hides the keyguard view
235      */
236     public void hide(long startTime, final long fadeoutDuration) {
237         mShowing = false;
238
239         long uptimeMillis = SystemClock.uptimeMillis();
240         long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
241
242         if (mPhoneStatusBar.isInLaunchTransition() ) {
243             mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
244                 @Override
245                 public void run() {
246                     mStatusBarWindowManager.setKeyguardShowing(false);
247                     mStatusBarWindowManager.setKeyguardFadingAway(true);
248                     mBouncer.hide(true /* destroyView */);
249                     updateStates();
250                     mScrimController.animateKeyguardFadingOut(
251                             PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
252                             PhoneStatusBar.FADE_KEYGUARD_DURATION, null);
253                 }
254             }, new Runnable() {
255                 @Override
256                 public void run() {
257                     mPhoneStatusBar.hideKeyguard();
258                     mStatusBarWindowManager.setKeyguardFadingAway(false);
259                     mViewMediatorCallback.keyguardGone();
260                     executeAfterKeyguardGoneAction();
261                 }
262             });
263         } else {
264             mPhoneStatusBar.setKeyguardFadingAway(delay, fadeoutDuration);
265             boolean staying = mPhoneStatusBar.hideKeyguard();
266             if (!staying) {
267                 mStatusBarWindowManager.setKeyguardFadingAway(true);
268                 mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
269                     @Override
270                     public void run() {
271                         mStatusBarWindowManager.setKeyguardFadingAway(false);
272                         mPhoneStatusBar.finishKeyguardFadingAway();
273                         WindowManagerGlobal.getInstance().trimMemory(
274                                 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
275                     }
276                 });
277             } else {
278                 mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
279                 mPhoneStatusBar.finishKeyguardFadingAway();
280             }
281             mStatusBarWindowManager.setKeyguardShowing(false);
282             mBouncer.hide(true /* destroyView */);
283             mViewMediatorCallback.keyguardGone();
284             executeAfterKeyguardGoneAction();
285             updateStates();
286         }
287
288     }
289
290     private void executeAfterKeyguardGoneAction() {
291         if (mAfterKeyguardGoneAction != null) {
292             mAfterKeyguardGoneAction.onDismiss();
293             mAfterKeyguardGoneAction = null;
294         }
295     }
296
297     /**
298      * Dismisses the keyguard by going to the next screen or making it gone.
299      */
300     public void dismiss() {
301         if (mScreenOn) {
302             showBouncer();
303         }
304     }
305
306     public boolean isSecure() {
307         return mBouncer.isSecure();
308     }
309
310     /**
311      * @return Whether the keyguard is showing
312      */
313     public boolean isShowing() {
314         return mShowing;
315     }
316
317     /**
318      * Notifies this manager that the back button has been pressed.
319      *
320      * @return whether the back press has been handled
321      */
322     public boolean onBackPressed() {
323         if (mBouncer.isShowing()) {
324             reset();
325             return true;
326         }
327         return false;
328     }
329
330     public boolean isBouncerShowing() {
331         return mBouncer.isShowing();
332     }
333
334     private long getNavBarShowDelay() {
335         if (mPhoneStatusBar.isKeyguardFadingAway()) {
336             return mPhoneStatusBar.getKeyguardFadingAwayDelay();
337         } else {
338
339             // Keyguard is not going away, thus we are showing the navigation bar because the
340             // bouncer is appearing.
341             return NAV_BAR_SHOW_DELAY_BOUNCER;
342         }
343     }
344
345     private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
346         @Override
347         public void run() {
348             mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
349         }
350     };
351
352     private void updateStates() {
353         int vis = mContainer.getSystemUiVisibility();
354         boolean showing = mShowing;
355         boolean occluded = mOccluded;
356         boolean bouncerShowing = mBouncer.isShowing();
357         boolean bouncerDismissible = !mBouncer.needsFullscreenBouncer();
358
359         if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
360                 || mFirstUpdate) {
361             if (bouncerDismissible || !showing) {
362                 mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
363             } else {
364                 mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
365             }
366         }
367         if ((!(showing && !occluded) || bouncerShowing)
368                 != (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing) || mFirstUpdate) {
369             if (mPhoneStatusBar.getNavigationBarView() != null) {
370                 if (!(showing && !occluded) || bouncerShowing) {
371                     mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable,
372                             getNavBarShowDelay());
373                 } else {
374                     mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
375                     mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
376                 }
377             }
378         }
379
380         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
381             mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
382             mPhoneStatusBar.setBouncerShowing(bouncerShowing);
383             mScrimController.setBouncerShowing(bouncerShowing);
384         }
385
386         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
387         if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
388             updateMonitor.sendKeyguardVisibilityChanged(showing && !occluded);
389         }
390         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
391             updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
392         }
393
394         mFirstUpdate = false;
395         mLastShowing = showing;
396         mLastOccluded = occluded;
397         mLastBouncerShowing = bouncerShowing;
398         mLastBouncerDismissible = bouncerDismissible;
399     }
400
401     public boolean onMenuPressed() {
402         return mBouncer.onMenuPressed();
403     }
404
405     public boolean interceptMediaKey(KeyEvent event) {
406         return mBouncer.interceptMediaKey(event);
407     }
408
409     public void onActivityDrawn() {
410         if (mPhoneStatusBar.isCollapsing()) {
411             mPhoneStatusBar.addPostCollapseAction(new Runnable() {
412                 @Override
413                 public void run() {
414                     mViewMediatorCallback.readyForKeyguardDone();
415                 }
416             });
417         } else {
418             mViewMediatorCallback.readyForKeyguardDone();
419         }
420     }
421
422     public boolean shouldDisableWindowAnimationsForUnlock() {
423         return mPhoneStatusBar.isInLaunchTransition();
424     }
425
426     public boolean isGoingToNotificationShade() {
427         return mPhoneStatusBar.isGoingToNotificationShade();
428     }
429
430     public boolean isSecure(int userId) {
431         return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);
432     }
433 }