blob: 3e01aec85139a57dea20d98c0b8f05d04b888f3e [file] [log] [blame]
Jorim Jaggi03c701e2014-04-02 12:39:51 +02001/*
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.statusbar.phone;
18
Lucas Dupin0df9b7a2018-03-15 17:53:17 -070019import static com.android.keyguard.KeyguardHostView.OnDismissAction;
20import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
21
Jorim Jaggi03c701e2014-04-02 12:39:51 +020022import android.content.Context;
Jorim Jaggifabc7432017-05-15 02:40:05 +020023import android.os.Handler;
Toni Barzic657f8852016-02-04 15:14:49 -080024import android.os.UserHandle;
Toni Barzicb799d3f2016-02-17 15:09:10 -080025import android.os.UserManager;
Lucas Dupin0df9b7a2018-03-15 17:53:17 -070026import android.util.Log;
Lucas Dupinbc9aac12018-03-04 20:18:15 -080027import android.util.MathUtils;
Toni Barzic657f8852016-02-04 15:14:49 -080028import android.util.Slog;
Tej Singhdd7bd352018-02-09 19:33:15 -080029import android.util.StatsLog;
Jorim Jaggidf993512014-05-13 23:06:35 +020030import android.view.KeyEvent;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020031import android.view.LayoutInflater;
32import android.view.View;
33import android.view.ViewGroup;
Adrian Roosedfa96f2016-01-29 12:46:35 -080034import android.view.ViewTreeObserver;
Lucas Dupin6865b712017-09-11 12:28:03 -070035import android.view.WindowInsets;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020036
Jorim Jaggi03c701e2014-04-02 12:39:51 +020037import com.android.internal.widget.LockPatternUtils;
Jorim Jaggi6b88cdf2014-12-22 20:56:50 +010038import com.android.keyguard.KeyguardHostView;
Selim Cinek3122fa82015-06-18 01:38:59 -070039import com.android.keyguard.KeyguardSecurityView;
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070040import com.android.keyguard.KeyguardUpdateMonitor;
41import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020042import com.android.keyguard.R;
43import com.android.keyguard.ViewMediatorCallback;
Jorim Jaggi86b273f2015-07-14 18:08:43 -070044import com.android.systemui.DejankUtils;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070045import com.android.systemui.classifier.FalsingManager;
Jorim Jaggi241ae102016-11-02 21:57:33 -070046import com.android.systemui.keyguard.DismissCallbackRegistry;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020047
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080048import java.io.PrintWriter;
49
Jorim Jaggi03c701e2014-04-02 12:39:51 +020050/**
51 * A class which manages the bouncer on the lockscreen.
52 */
53public class KeyguardBouncer {
54
Lucas Dupinbc9aac12018-03-04 20:18:15 -080055 private static final String TAG = "KeyguardBouncer";
56 static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
Toni Barzic657f8852016-02-04 15:14:49 -080057
Jorim Jaggi241ae102016-11-02 21:57:33 -070058 protected final Context mContext;
59 protected final ViewMediatorCallback mCallback;
60 protected final LockPatternUtils mLockPatternUtils;
61 protected final ViewGroup mContainer;
62 private final FalsingManager mFalsingManager;
63 private final DismissCallbackRegistry mDismissCallbackRegistry;
Jorim Jaggifabc7432017-05-15 02:40:05 +020064 private final Handler mHandler;
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080065 private final BouncerExpansionCallback mExpansionCallback;
Jorim Jaggi241ae102016-11-02 21:57:33 -070066 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070067 new KeyguardUpdateMonitorCallback() {
68 @Override
Adrian Roos1de8bcb2015-08-19 16:52:52 -070069 public void onStrongAuthStateChanged(int userId) {
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070070 mBouncerPromptReason = mCallback.getBouncerPromptReason();
71 }
72 };
Jorim Jaggifabc7432017-05-15 02:40:05 +020073 private final Runnable mRemoveViewRunnable = this::removeView;
Lucas Dupin3d565fa2018-03-20 15:40:14 -070074
Selim Cinekcb3d45a2017-09-08 18:00:18 -070075 private int mStatusBarHeight;
Lucas Dupin3d565fa2018-03-20 15:40:14 -070076 private float mExpansion;
77 protected KeyguardHostView mKeyguardView;
78 protected ViewGroup mRoot;
79 private boolean mShowingSoon;
80 private int mBouncerPromptReason;
Lucas Dupin28dc9d72018-03-21 15:59:15 -070081 private boolean mIsAnimatingAway;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020082
83 public KeyguardBouncer(Context context, ViewMediatorCallback callback,
Jorim Jaggi241ae102016-11-02 21:57:33 -070084 LockPatternUtils lockPatternUtils, ViewGroup container,
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080085 DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
86 BouncerExpansionCallback expansionCallback) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +020087 mContext = context;
88 mCallback = callback;
89 mLockPatternUtils = lockPatternUtils;
90 mContainer = container;
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070091 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
Lucas Dupin0df9b7a2018-03-15 17:53:17 -070092 mFalsingManager = falsingManager;
Jorim Jaggi241ae102016-11-02 21:57:33 -070093 mDismissCallbackRegistry = dismissCallbackRegistry;
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080094 mExpansionCallback = expansionCallback;
Jorim Jaggifabc7432017-05-15 02:40:05 +020095 mHandler = new Handler();
Jorim Jaggi03c701e2014-04-02 12:39:51 +020096 }
97
Jorim Jaggi95e89ca2014-11-24 20:12:50 +010098 public void show(boolean resetSecuritySelection) {
Lucas Dupinbc9aac12018-03-04 20:18:15 -080099 show(resetSecuritySelection, true /* notifyFalsing */);
100 }
101
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700102 /**
103 * Shows the bouncer.
104 *
105 * @param resetSecuritySelection Cleans keyguard view
106 * @param animated true when the bouncer show show animated, false when the user will be
107 * dragging it and animation should be deferred.
108 */
109 public void show(boolean resetSecuritySelection, boolean animated) {
Vadim Tryshevec018432016-02-10 14:11:03 -0800110 final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
111 if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
112 // In split system user mode, we never unlock system user.
113 return;
114 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200115 ensureView();
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800116
117 // On the keyguard, we want to show the bouncer when the user drags up, but it's
118 // not correct to end the falsing session. We still need to verify if those touches
119 // are valid.
120 // Later, at the end of the animation, when the bouncer is at the top of the screen,
121 // onFullyShown() will be called and FalsingManager will stop recording touches.
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700122 if (animated) {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800123 mFalsingManager.onBouncerShown();
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700124 setExpansion(0);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800125 }
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700126
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100127 if (resetSecuritySelection) {
128 // showPrimarySecurityScreen() updates the current security method. This is needed in
129 // case we are already showing and the current security method changed.
130 mKeyguardView.showPrimarySecurityScreen();
131 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200132 if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200133 return;
134 }
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200135
Selim Cinek1a891a92017-12-04 17:41:27 +0100136 final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
Xiaohui Chend743cef2016-10-03 09:55:53 -0700137 final boolean isSystemUser =
138 UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
139 final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
140
Toni Barzic657f8852016-02-04 15:14:49 -0800141 // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
142 // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700143 if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) {
Toni Barzic657f8852016-02-04 15:14:49 -0800144 return;
Jorim Jaggi416493b2014-09-13 03:57:32 +0200145 }
Toni Barzic657f8852016-02-04 15:14:49 -0800146
147 // This condition may indicate an error on Android, so log it.
148 if (!allowDismissKeyguard) {
149 Slog.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
150 }
151
152 mShowingSoon = true;
153
154 // Split up the work over multiple frames.
155 DejankUtils.postAfterTraversal(mShowRunnable);
Matthew Ng66f0b702017-12-08 12:58:42 -0800156
157 mCallback.onBouncerVisiblityChanged(true /* shown */);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200158 }
159
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800160 /**
161 * This method must be called at the end of the bouncer animation when
162 * the translation is performed manually by the user, otherwise FalsingManager
163 * will never be notified and its internal state will be out of sync.
164 */
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800165 private void onFullyShown() {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800166 mFalsingManager.onBouncerShown();
Lucas Dupind2ce46d2018-04-04 17:00:29 -0700167 if (mKeyguardView == null) {
168 Log.wtf(TAG, "onFullyShown when view was null");
169 } else {
170 mKeyguardView.onResume();
171 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800172 }
173
174 /**
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800175 * @see #onFullyShown()
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800176 */
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800177 private void onFullyHidden() {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800178 if (!mShowingSoon) {
179 cancelShowRunnable();
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700180 if (mRoot != null) {
181 mRoot.setVisibility(View.INVISIBLE);
182 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800183 mFalsingManager.onBouncerHidden();
184 }
185 }
186
Jorim Jaggi416493b2014-09-13 03:57:32 +0200187 private final Runnable mShowRunnable = new Runnable() {
188 @Override
189 public void run() {
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200190 mRoot.setVisibility(View.VISIBLE);
Selim Cinek3122fa82015-06-18 01:38:59 -0700191 showPromptReason(mBouncerPromptReason);
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800192 final CharSequence customMessage = mCallback.consumeCustomMessage();
193 if (customMessage != null) {
194 mKeyguardView.showErrorMessage(customMessage);
195 }
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700196 // We might still be collapsed and the view didn't have time to layout yet or still
197 // be small, let's wait on the predraw to do the animation in that case.
198 if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) {
Adrian Roosedfa96f2016-01-29 12:46:35 -0800199 mKeyguardView.startAppearAnimation();
200 } else {
201 mKeyguardView.getViewTreeObserver().addOnPreDrawListener(
202 new ViewTreeObserver.OnPreDrawListener() {
203 @Override
204 public boolean onPreDraw() {
205 mKeyguardView.getViewTreeObserver().removeOnPreDrawListener(this);
206 mKeyguardView.startAppearAnimation();
207 return true;
208 }
209 });
210 mKeyguardView.requestLayout();
211 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200212 mShowingSoon = false;
Tej Singhdd7bd352018-02-09 19:33:15 -0800213 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
214 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200215 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200216 };
217
Selim Cinek3122fa82015-06-18 01:38:59 -0700218 /**
219 * Show a string explaining why the security view needs to be solved.
220 *
221 * @param reason a flag indicating which string should be shown, see
222 * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
223 * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
224 */
225 public void showPromptReason(int reason) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700226 if (mKeyguardView != null) {
227 mKeyguardView.showPromptReason(reason);
228 } else {
229 Log.w(TAG, "Trying to show prompt reason on empty bouncer");
230 }
Selim Cinek3122fa82015-06-18 01:38:59 -0700231 }
232
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700233 public void showMessage(String message, int color) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700234 if (mKeyguardView != null) {
235 mKeyguardView.showMessage(message, color);
236 } else {
237 Log.w(TAG, "Trying to show message on empty bouncer");
238 }
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700239 }
240
Jorim Jaggi416493b2014-09-13 03:57:32 +0200241 private void cancelShowRunnable() {
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700242 DejankUtils.removeCallbacks(mShowRunnable);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200243 mShowingSoon = false;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200244 }
245
Jorim Jaggid9449862015-05-29 14:49:08 -0700246 public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200247 ensureView();
Jorim Jaggid9449862015-05-29 14:49:08 -0700248 mKeyguardView.setOnDismissAction(r, cancelAction);
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100249 show(false /* resetSecuritySelection */);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200250 }
251
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200252 public void hide(boolean destroyView) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700253 if (isShowing()) {
Tej Singhdd7bd352018-02-09 19:33:15 -0800254 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
255 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700256 mDismissCallbackRegistry.notifyDismissCancelled();
257 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700258 mFalsingManager.onBouncerHidden();
Matthew Ng66f0b702017-12-08 12:58:42 -0800259 mCallback.onBouncerVisiblityChanged(false /* shown */);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200260 cancelShowRunnable();
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800261 if (mKeyguardView != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700262 mKeyguardView.cancelDismissAction();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200263 mKeyguardView.cleanUp();
264 }
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700265 mIsAnimatingAway = false;
Jorim Jaggifabc7432017-05-15 02:40:05 +0200266 if (mRoot != null) {
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200267 mRoot.setVisibility(View.INVISIBLE);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200268 if (destroyView) {
269
270 // We have a ViewFlipper that unregisters a broadcast when being detached, which may
271 // be slow because of AM lock contention during unlocking. We can delay it a bit.
272 mHandler.postDelayed(mRemoveViewRunnable, 50);
273 }
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200274 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200275 }
276
Jorim Jaggi76a16232014-08-08 17:00:47 +0200277 /**
278 * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
279 */
280 public void startPreHideAnimation(Runnable runnable) {
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700281 mIsAnimatingAway = true;
Jorim Jaggi76a16232014-08-08 17:00:47 +0200282 if (mKeyguardView != null) {
283 mKeyguardView.startDisappearAnimation(runnable);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200284 } else if (runnable != null) {
Jorim Jaggi76a16232014-08-08 17:00:47 +0200285 runnable.run();
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200286 }
287 }
288
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200289 /**
290 * Reset the state of the view.
291 */
292 public void reset() {
Jorim Jaggi416493b2014-09-13 03:57:32 +0200293 cancelShowRunnable();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200294 inflateView();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700295 mFalsingManager.onBouncerHidden();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200296 }
297
298 public void onScreenTurnedOff() {
Dan Sandler9ee256d2014-04-21 12:05:00 -0400299 if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200300 mKeyguardView.onPause();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200301 }
302 }
303
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200304 public boolean isShowing() {
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700305 return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
Lucas Dupind2ce46d2018-04-04 17:00:29 -0700306 && mExpansion == 0 && !isAnimatingAway();
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200307 }
308
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700309 /**
310 * @return {@code true} when bouncer's pre-hide animation already started but isn't completely
311 * hidden yet, {@code false} otherwise.
312 */
313 public boolean isAnimatingAway() {
314 return mIsAnimatingAway;
315 }
316
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200317 public void prepare() {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100318 boolean wasInitialized = mRoot != null;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200319 ensureView();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100320 if (wasInitialized) {
321 mKeyguardView.showPrimarySecurityScreen();
322 }
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700323 mBouncerPromptReason = mCallback.getBouncerPromptReason();
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200324 }
325
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800326 /**
327 * Current notification panel expansion
328 * @param fraction 0 when notification panel is collapsed and 1 when expanded.
329 * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
330 */
331 public void setExpansion(float fraction) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800332 float oldExpansion = mExpansion;
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700333 mExpansion = fraction;
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700334 if (mKeyguardView != null && !mIsAnimatingAway) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700335 float alpha = MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
336 mKeyguardView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800337 mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
338 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800339
340 if (fraction == 0 && oldExpansion != 0) {
341 onFullyShown();
342 mExpansionCallback.onFullyShown();
343 } else if (fraction == 1 && oldExpansion != 0) {
344 onFullyHidden();
345 mExpansionCallback.onFullyHidden();
346 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800347 }
348
Lucas Dupin6f0d71f2018-03-23 17:26:06 -0700349 public boolean willDismissWithAction() {
350 return mKeyguardView != null && mKeyguardView.hasDismissActions();
351 }
352
Lucas Dupin4c2aa392018-03-28 18:00:45 -0700353 public int getTop() {
354 if (mKeyguardView == null) {
355 return 0;
356 }
357
358 int top = mKeyguardView.getTop();
359 // The password view has an extra top padding that should be ignored.
360 if (mKeyguardView.getCurrentSecurityMode() == SecurityMode.Password) {
361 View messageArea = mKeyguardView.findViewById(R.id.keyguard_message_area);
362 top += messageArea.getTop();
363 }
364 return top;
365 }
366
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800367 protected void ensureView() {
Lucas Dupinf190a852017-07-31 17:11:26 -0700368 // Removal of the view might be deferred to reduce unlock latency,
369 // in this case we need to force the removal, otherwise we'll
370 // end up in an unpredictable state.
371 boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
372 if (mRoot == null || forceRemoval) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200373 inflateView();
374 }
375 }
376
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800377 protected void inflateView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200378 removeView();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200379 mHandler.removeCallbacks(mRemoveViewRunnable);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200380 mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
Lucas Dupin6865b712017-09-11 12:28:03 -0700381 mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200382 mKeyguardView.setLockPatternUtils(mLockPatternUtils);
383 mKeyguardView.setViewMediatorCallback(mCallback);
384 mContainer.addView(mRoot, mContainer.getChildCount());
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700385 mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
386 com.android.systemui.R.dimen.status_bar_height);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200387 mRoot.setVisibility(View.INVISIBLE);
Phil Weaver7d847b02018-02-13 16:02:35 -0800388 mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
Lucas Dupin6865b712017-09-11 12:28:03 -0700389
390 final WindowInsets rootInsets = mRoot.getRootWindowInsets();
391 if (rootInsets != null) {
392 mRoot.dispatchApplyWindowInsets(rootInsets);
393 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200394 }
395
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800396 protected void removeView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200397 if (mRoot != null && mRoot.getParent() == mContainer) {
398 mContainer.removeView(mRoot);
399 mRoot = null;
400 }
401 }
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200402
403 public boolean onBackPressed() {
404 return mKeyguardView != null && mKeyguardView.handleBackKey();
405 }
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200406
407 /**
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100408 * @return True if and only if the security method should be shown before showing the
409 * notifications on Keyguard, like SIM PIN/PUK.
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200410 */
411 public boolean needsFullscreenBouncer() {
Selim Cinekedd32b82015-06-23 22:05:58 -0400412 ensureView();
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200413 if (mKeyguardView != null) {
414 SecurityMode mode = mKeyguardView.getSecurityMode();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100415 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
416 }
417 return false;
418 }
419
420 /**
421 * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
422 * makes this method much faster.
423 */
424 public boolean isFullscreenBouncer() {
425 if (mKeyguardView != null) {
426 SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
427 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200428 }
429 return false;
430 }
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200431
Christoph Studer2231c6e2014-12-19 12:40:13 +0100432 /**
433 * WARNING: This method might cause Binder calls.
434 */
Jorim Jaggi15682502014-04-23 12:01:36 +0200435 public boolean isSecure() {
436 return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
437 }
438
Selim Cinek28540192016-02-19 17:25:08 -0800439 public boolean shouldDismissOnMenuPressed() {
440 return mKeyguardView.shouldEnableMenuKey();
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200441 }
Jorim Jaggidf993512014-05-13 23:06:35 +0200442
443 public boolean interceptMediaKey(KeyEvent event) {
444 ensureView();
445 return mKeyguardView.interceptMediaKey(event);
446 }
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700447
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700448 public void notifyKeyguardAuthenticated(boolean strongAuth) {
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700449 ensureView();
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700450 mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700451 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800452
453 public void dump(PrintWriter pw) {
454 pw.println("KeyguardBouncer");
455 pw.println(" isShowing(): " + isShowing());
456 pw.println(" mStatusBarHeight: " + mStatusBarHeight);
457 pw.println(" mExpansion: " + mExpansion);
458 pw.println(" mKeyguardView; " + mKeyguardView);
459 pw.println(" mShowingSoon: " + mKeyguardView);
460 pw.println(" mBouncerPromptReason: " + mBouncerPromptReason);
461 pw.println(" mIsAnimatingAway: " + mIsAnimatingAway);
462 }
463
464 public interface BouncerExpansionCallback {
465 void onFullyShown();
466 void onFullyHidden();
467 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200468}