blob: c74d09d93fc412ccc27194374ded35d5b1768613 [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;
Lucas Dupinf9ca35e2018-05-16 20:41:35 -070057 static final float EXPANSION_HIDDEN = 1f;
58 static final float EXPANSION_VISIBLE = 0f;
Toni Barzic657f8852016-02-04 15:14:49 -080059
Jorim Jaggi241ae102016-11-02 21:57:33 -070060 protected final Context mContext;
61 protected final ViewMediatorCallback mCallback;
62 protected final LockPatternUtils mLockPatternUtils;
63 protected final ViewGroup mContainer;
64 private final FalsingManager mFalsingManager;
65 private final DismissCallbackRegistry mDismissCallbackRegistry;
Jorim Jaggifabc7432017-05-15 02:40:05 +020066 private final Handler mHandler;
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080067 private final BouncerExpansionCallback mExpansionCallback;
Jorim Jaggi241ae102016-11-02 21:57:33 -070068 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070069 new KeyguardUpdateMonitorCallback() {
70 @Override
Adrian Roos1de8bcb2015-08-19 16:52:52 -070071 public void onStrongAuthStateChanged(int userId) {
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070072 mBouncerPromptReason = mCallback.getBouncerPromptReason();
73 }
74 };
Jorim Jaggifabc7432017-05-15 02:40:05 +020075 private final Runnable mRemoveViewRunnable = this::removeView;
Lucas Dupin70659002018-04-30 15:56:52 -070076 protected KeyguardHostView mKeyguardView;
77 private final Runnable mResetRunnable = ()-> {
78 if (mKeyguardView != null) {
Lucas Dupin80180492018-05-08 17:06:06 -070079 mKeyguardView.resetSecurityContainer();
Lucas Dupin70659002018-04-30 15:56:52 -070080 }
81 };
Lucas Dupin3d565fa2018-03-20 15:40:14 -070082
Selim Cinekcb3d45a2017-09-08 18:00:18 -070083 private int mStatusBarHeight;
Lucas Dupin70659002018-04-30 15:56:52 -070084 private float mExpansion = EXPANSION_HIDDEN;
Lucas Dupin3d565fa2018-03-20 15:40:14 -070085 protected ViewGroup mRoot;
86 private boolean mShowingSoon;
87 private int mBouncerPromptReason;
Lucas Dupin28dc9d72018-03-21 15:59:15 -070088 private boolean mIsAnimatingAway;
Lucas Dupinf9ca35e2018-05-16 20:41:35 -070089 private boolean mIsScrimmed;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020090
91 public KeyguardBouncer(Context context, ViewMediatorCallback callback,
Jorim Jaggi241ae102016-11-02 21:57:33 -070092 LockPatternUtils lockPatternUtils, ViewGroup container,
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080093 DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
94 BouncerExpansionCallback expansionCallback) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +020095 mContext = context;
96 mCallback = callback;
97 mLockPatternUtils = lockPatternUtils;
98 mContainer = container;
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070099 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700100 mFalsingManager = falsingManager;
Jorim Jaggi241ae102016-11-02 21:57:33 -0700101 mDismissCallbackRegistry = dismissCallbackRegistry;
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800102 mExpansionCallback = expansionCallback;
Jorim Jaggifabc7432017-05-15 02:40:05 +0200103 mHandler = new Handler();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200104 }
105
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100106 public void show(boolean resetSecuritySelection) {
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700107 show(resetSecuritySelection, true /* scrimmed */);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800108 }
109
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700110 /**
111 * Shows the bouncer.
112 *
113 * @param resetSecuritySelection Cleans keyguard view
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700114 * @param isScrimmed true when the bouncer show show scrimmed, false when the user will be
115 * dragging it and translation should be deferred.
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700116 */
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700117 public void show(boolean resetSecuritySelection, boolean isScrimmed) {
Vadim Tryshevec018432016-02-10 14:11:03 -0800118 final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
119 if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
120 // In split system user mode, we never unlock system user.
121 return;
122 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200123 ensureView();
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800124
125 // On the keyguard, we want to show the bouncer when the user drags up, but it's
126 // not correct to end the falsing session. We still need to verify if those touches
127 // are valid.
128 // Later, at the end of the animation, when the bouncer is at the top of the screen,
129 // onFullyShown() will be called and FalsingManager will stop recording touches.
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700130 if (isScrimmed) {
Lucas Dupin70659002018-04-30 15:56:52 -0700131 setExpansion(EXPANSION_VISIBLE);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800132 }
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700133 mIsScrimmed = isScrimmed;
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700134
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100135 if (resetSecuritySelection) {
136 // showPrimarySecurityScreen() updates the current security method. This is needed in
137 // case we are already showing and the current security method changed.
138 mKeyguardView.showPrimarySecurityScreen();
139 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200140 if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200141 return;
142 }
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200143
Selim Cinek1a891a92017-12-04 17:41:27 +0100144 final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
Xiaohui Chend743cef2016-10-03 09:55:53 -0700145 final boolean isSystemUser =
146 UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
147 final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
148
Toni Barzic657f8852016-02-04 15:14:49 -0800149 // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
150 // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700151 if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) {
Toni Barzic657f8852016-02-04 15:14:49 -0800152 return;
Jorim Jaggi416493b2014-09-13 03:57:32 +0200153 }
Toni Barzic657f8852016-02-04 15:14:49 -0800154
155 // This condition may indicate an error on Android, so log it.
156 if (!allowDismissKeyguard) {
157 Slog.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
158 }
159
160 mShowingSoon = true;
161
162 // Split up the work over multiple frames.
Lucas Dupin70659002018-04-30 15:56:52 -0700163 DejankUtils.removeCallbacks(mResetRunnable);
Toni Barzic657f8852016-02-04 15:14:49 -0800164 DejankUtils.postAfterTraversal(mShowRunnable);
Matthew Ng66f0b702017-12-08 12:58:42 -0800165
166 mCallback.onBouncerVisiblityChanged(true /* shown */);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200167 }
168
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700169 public boolean isShowingScrimmed() {
170 return isShowing() && mIsScrimmed;
171 }
172
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800173 /**
174 * This method must be called at the end of the bouncer animation when
175 * the translation is performed manually by the user, otherwise FalsingManager
176 * will never be notified and its internal state will be out of sync.
177 */
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800178 private void onFullyShown() {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800179 mFalsingManager.onBouncerShown();
Lucas Dupind2ce46d2018-04-04 17:00:29 -0700180 if (mKeyguardView == null) {
181 Log.wtf(TAG, "onFullyShown when view was null");
182 } else {
183 mKeyguardView.onResume();
184 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800185 }
186
187 /**
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800188 * @see #onFullyShown()
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800189 */
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800190 private void onFullyHidden() {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800191 if (!mShowingSoon) {
192 cancelShowRunnable();
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700193 if (mRoot != null) {
194 mRoot.setVisibility(View.INVISIBLE);
195 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800196 mFalsingManager.onBouncerHidden();
Lucas Dupin70659002018-04-30 15:56:52 -0700197 DejankUtils.postAfterTraversal(mResetRunnable);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800198 }
199 }
200
Jorim Jaggi416493b2014-09-13 03:57:32 +0200201 private final Runnable mShowRunnable = new Runnable() {
202 @Override
203 public void run() {
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200204 mRoot.setVisibility(View.VISIBLE);
Selim Cinek3122fa82015-06-18 01:38:59 -0700205 showPromptReason(mBouncerPromptReason);
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800206 final CharSequence customMessage = mCallback.consumeCustomMessage();
207 if (customMessage != null) {
208 mKeyguardView.showErrorMessage(customMessage);
209 }
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700210 // We might still be collapsed and the view didn't have time to layout yet or still
211 // be small, let's wait on the predraw to do the animation in that case.
212 if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) {
Adrian Roosedfa96f2016-01-29 12:46:35 -0800213 mKeyguardView.startAppearAnimation();
214 } else {
215 mKeyguardView.getViewTreeObserver().addOnPreDrawListener(
216 new ViewTreeObserver.OnPreDrawListener() {
217 @Override
218 public boolean onPreDraw() {
219 mKeyguardView.getViewTreeObserver().removeOnPreDrawListener(this);
220 mKeyguardView.startAppearAnimation();
221 return true;
222 }
223 });
224 mKeyguardView.requestLayout();
225 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200226 mShowingSoon = false;
Lucas Dupin70659002018-04-30 15:56:52 -0700227 if (mExpansion == EXPANSION_VISIBLE) {
228 mKeyguardView.onResume();
229 }
Tej Singhdd7bd352018-02-09 19:33:15 -0800230 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
231 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200232 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200233 };
234
Selim Cinek3122fa82015-06-18 01:38:59 -0700235 /**
236 * Show a string explaining why the security view needs to be solved.
237 *
238 * @param reason a flag indicating which string should be shown, see
239 * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
240 * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
241 */
242 public void showPromptReason(int reason) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700243 if (mKeyguardView != null) {
244 mKeyguardView.showPromptReason(reason);
245 } else {
246 Log.w(TAG, "Trying to show prompt reason on empty bouncer");
247 }
Selim Cinek3122fa82015-06-18 01:38:59 -0700248 }
249
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700250 public void showMessage(String message, int color) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700251 if (mKeyguardView != null) {
252 mKeyguardView.showMessage(message, color);
253 } else {
254 Log.w(TAG, "Trying to show message on empty bouncer");
255 }
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700256 }
257
Jorim Jaggi416493b2014-09-13 03:57:32 +0200258 private void cancelShowRunnable() {
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700259 DejankUtils.removeCallbacks(mShowRunnable);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200260 mShowingSoon = false;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200261 }
262
Jorim Jaggid9449862015-05-29 14:49:08 -0700263 public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200264 ensureView();
Jorim Jaggid9449862015-05-29 14:49:08 -0700265 mKeyguardView.setOnDismissAction(r, cancelAction);
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100266 show(false /* resetSecuritySelection */);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200267 }
268
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200269 public void hide(boolean destroyView) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700270 if (isShowing()) {
Tej Singhdd7bd352018-02-09 19:33:15 -0800271 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
272 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700273 mDismissCallbackRegistry.notifyDismissCancelled();
274 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700275 mFalsingManager.onBouncerHidden();
Matthew Ng66f0b702017-12-08 12:58:42 -0800276 mCallback.onBouncerVisiblityChanged(false /* shown */);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200277 cancelShowRunnable();
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800278 if (mKeyguardView != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700279 mKeyguardView.cancelDismissAction();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200280 mKeyguardView.cleanUp();
281 }
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700282 mIsAnimatingAway = false;
Jorim Jaggifabc7432017-05-15 02:40:05 +0200283 if (mRoot != null) {
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200284 mRoot.setVisibility(View.INVISIBLE);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200285 if (destroyView) {
286
287 // We have a ViewFlipper that unregisters a broadcast when being detached, which may
288 // be slow because of AM lock contention during unlocking. We can delay it a bit.
289 mHandler.postDelayed(mRemoveViewRunnable, 50);
290 }
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200291 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200292 }
293
Jorim Jaggi76a16232014-08-08 17:00:47 +0200294 /**
295 * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
296 */
297 public void startPreHideAnimation(Runnable runnable) {
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700298 mIsAnimatingAway = true;
Jorim Jaggi76a16232014-08-08 17:00:47 +0200299 if (mKeyguardView != null) {
300 mKeyguardView.startDisappearAnimation(runnable);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200301 } else if (runnable != null) {
Jorim Jaggi76a16232014-08-08 17:00:47 +0200302 runnable.run();
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200303 }
304 }
305
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200306 /**
307 * Reset the state of the view.
308 */
309 public void reset() {
Jorim Jaggi416493b2014-09-13 03:57:32 +0200310 cancelShowRunnable();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200311 inflateView();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700312 mFalsingManager.onBouncerHidden();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200313 }
314
315 public void onScreenTurnedOff() {
Dan Sandler9ee256d2014-04-21 12:05:00 -0400316 if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200317 mKeyguardView.onPause();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200318 }
319 }
320
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200321 public boolean isShowing() {
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700322 return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
Lucas Dupin70659002018-04-30 15:56:52 -0700323 && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200324 }
325
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700326 /**
327 * @return {@code true} when bouncer's pre-hide animation already started but isn't completely
328 * hidden yet, {@code false} otherwise.
329 */
330 public boolean isAnimatingAway() {
331 return mIsAnimatingAway;
332 }
333
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200334 public void prepare() {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100335 boolean wasInitialized = mRoot != null;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200336 ensureView();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100337 if (wasInitialized) {
338 mKeyguardView.showPrimarySecurityScreen();
339 }
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700340 mBouncerPromptReason = mCallback.getBouncerPromptReason();
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200341 }
342
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800343 /**
344 * Current notification panel expansion
345 * @param fraction 0 when notification panel is collapsed and 1 when expanded.
346 * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
347 */
348 public void setExpansion(float fraction) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800349 float oldExpansion = mExpansion;
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700350 mExpansion = fraction;
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700351 if (mKeyguardView != null && !mIsAnimatingAway) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700352 float alpha = MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
353 mKeyguardView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800354 mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
355 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800356
Lucas Dupin70659002018-04-30 15:56:52 -0700357 if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800358 onFullyShown();
359 mExpansionCallback.onFullyShown();
Lucas Dupin70659002018-04-30 15:56:52 -0700360 } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800361 onFullyHidden();
362 mExpansionCallback.onFullyHidden();
363 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800364 }
365
Lucas Dupin6f0d71f2018-03-23 17:26:06 -0700366 public boolean willDismissWithAction() {
367 return mKeyguardView != null && mKeyguardView.hasDismissActions();
368 }
369
Lucas Dupin4c2aa392018-03-28 18:00:45 -0700370 public int getTop() {
371 if (mKeyguardView == null) {
372 return 0;
373 }
374
375 int top = mKeyguardView.getTop();
376 // The password view has an extra top padding that should be ignored.
377 if (mKeyguardView.getCurrentSecurityMode() == SecurityMode.Password) {
378 View messageArea = mKeyguardView.findViewById(R.id.keyguard_message_area);
379 top += messageArea.getTop();
380 }
381 return top;
382 }
383
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800384 protected void ensureView() {
Lucas Dupinf190a852017-07-31 17:11:26 -0700385 // Removal of the view might be deferred to reduce unlock latency,
386 // in this case we need to force the removal, otherwise we'll
387 // end up in an unpredictable state.
388 boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
389 if (mRoot == null || forceRemoval) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200390 inflateView();
391 }
392 }
393
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800394 protected void inflateView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200395 removeView();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200396 mHandler.removeCallbacks(mRemoveViewRunnable);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200397 mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
Lucas Dupin6865b712017-09-11 12:28:03 -0700398 mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200399 mKeyguardView.setLockPatternUtils(mLockPatternUtils);
400 mKeyguardView.setViewMediatorCallback(mCallback);
401 mContainer.addView(mRoot, mContainer.getChildCount());
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700402 mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
403 com.android.systemui.R.dimen.status_bar_height);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200404 mRoot.setVisibility(View.INVISIBLE);
Phil Weaver7d847b02018-02-13 16:02:35 -0800405 mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
Lucas Dupin6865b712017-09-11 12:28:03 -0700406
407 final WindowInsets rootInsets = mRoot.getRootWindowInsets();
408 if (rootInsets != null) {
409 mRoot.dispatchApplyWindowInsets(rootInsets);
410 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200411 }
412
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800413 protected void removeView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200414 if (mRoot != null && mRoot.getParent() == mContainer) {
415 mContainer.removeView(mRoot);
416 mRoot = null;
417 }
418 }
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200419
420 public boolean onBackPressed() {
421 return mKeyguardView != null && mKeyguardView.handleBackKey();
422 }
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200423
424 /**
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100425 * @return True if and only if the security method should be shown before showing the
426 * notifications on Keyguard, like SIM PIN/PUK.
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200427 */
428 public boolean needsFullscreenBouncer() {
Selim Cinekedd32b82015-06-23 22:05:58 -0400429 ensureView();
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200430 if (mKeyguardView != null) {
431 SecurityMode mode = mKeyguardView.getSecurityMode();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100432 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
433 }
434 return false;
435 }
436
437 /**
438 * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
439 * makes this method much faster.
440 */
441 public boolean isFullscreenBouncer() {
442 if (mKeyguardView != null) {
443 SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
444 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200445 }
446 return false;
447 }
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200448
Christoph Studer2231c6e2014-12-19 12:40:13 +0100449 /**
450 * WARNING: This method might cause Binder calls.
451 */
Jorim Jaggi15682502014-04-23 12:01:36 +0200452 public boolean isSecure() {
453 return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
454 }
455
Selim Cinek28540192016-02-19 17:25:08 -0800456 public boolean shouldDismissOnMenuPressed() {
457 return mKeyguardView.shouldEnableMenuKey();
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200458 }
Jorim Jaggidf993512014-05-13 23:06:35 +0200459
460 public boolean interceptMediaKey(KeyEvent event) {
461 ensureView();
462 return mKeyguardView.interceptMediaKey(event);
463 }
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700464
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700465 public void notifyKeyguardAuthenticated(boolean strongAuth) {
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700466 ensureView();
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700467 mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700468 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800469
470 public void dump(PrintWriter pw) {
471 pw.println("KeyguardBouncer");
472 pw.println(" isShowing(): " + isShowing());
473 pw.println(" mStatusBarHeight: " + mStatusBarHeight);
474 pw.println(" mExpansion: " + mExpansion);
475 pw.println(" mKeyguardView; " + mKeyguardView);
476 pw.println(" mShowingSoon: " + mKeyguardView);
477 pw.println(" mBouncerPromptReason: " + mBouncerPromptReason);
478 pw.println(" mIsAnimatingAway: " + mIsAnimatingAway);
479 }
480
481 public interface BouncerExpansionCallback {
482 void onFullyShown();
483 void onFullyHidden();
484 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200485}