blob: f7e6cc080c1070f6d6eeb2986430a56695461922 [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();
Wang, ArvinXa2d94c52018-09-12 11:31:32 +0800229 mKeyguardView.resetSecurityContainer();
Lucas Dupin70659002018-04-30 15:56:52 -0700230 }
Tej Singhdd7bd352018-02-09 19:33:15 -0800231 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
232 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200233 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200234 };
235
Selim Cinek3122fa82015-06-18 01:38:59 -0700236 /**
237 * Show a string explaining why the security view needs to be solved.
238 *
239 * @param reason a flag indicating which string should be shown, see
240 * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
241 * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
242 */
243 public void showPromptReason(int reason) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700244 if (mKeyguardView != null) {
245 mKeyguardView.showPromptReason(reason);
246 } else {
247 Log.w(TAG, "Trying to show prompt reason on empty bouncer");
248 }
Selim Cinek3122fa82015-06-18 01:38:59 -0700249 }
250
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700251 public void showMessage(String message, int color) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700252 if (mKeyguardView != null) {
253 mKeyguardView.showMessage(message, color);
254 } else {
255 Log.w(TAG, "Trying to show message on empty bouncer");
256 }
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700257 }
258
Jorim Jaggi416493b2014-09-13 03:57:32 +0200259 private void cancelShowRunnable() {
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700260 DejankUtils.removeCallbacks(mShowRunnable);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200261 mShowingSoon = false;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200262 }
263
Jorim Jaggid9449862015-05-29 14:49:08 -0700264 public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200265 ensureView();
Jorim Jaggid9449862015-05-29 14:49:08 -0700266 mKeyguardView.setOnDismissAction(r, cancelAction);
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100267 show(false /* resetSecuritySelection */);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200268 }
269
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200270 public void hide(boolean destroyView) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700271 if (isShowing()) {
Tej Singhdd7bd352018-02-09 19:33:15 -0800272 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
273 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700274 mDismissCallbackRegistry.notifyDismissCancelled();
275 }
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700276 mFalsingManager.onBouncerHidden();
Matthew Ng66f0b702017-12-08 12:58:42 -0800277 mCallback.onBouncerVisiblityChanged(false /* shown */);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200278 cancelShowRunnable();
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800279 if (mKeyguardView != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700280 mKeyguardView.cancelDismissAction();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200281 mKeyguardView.cleanUp();
282 }
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700283 mIsAnimatingAway = false;
Jorim Jaggifabc7432017-05-15 02:40:05 +0200284 if (mRoot != null) {
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200285 mRoot.setVisibility(View.INVISIBLE);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200286 if (destroyView) {
287
288 // We have a ViewFlipper that unregisters a broadcast when being detached, which may
289 // be slow because of AM lock contention during unlocking. We can delay it a bit.
290 mHandler.postDelayed(mRemoveViewRunnable, 50);
291 }
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200292 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200293 }
294
Jorim Jaggi76a16232014-08-08 17:00:47 +0200295 /**
296 * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
297 */
298 public void startPreHideAnimation(Runnable runnable) {
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700299 mIsAnimatingAway = true;
Jorim Jaggi76a16232014-08-08 17:00:47 +0200300 if (mKeyguardView != null) {
301 mKeyguardView.startDisappearAnimation(runnable);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200302 } else if (runnable != null) {
Jorim Jaggi76a16232014-08-08 17:00:47 +0200303 runnable.run();
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200304 }
305 }
306
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200307 /**
308 * Reset the state of the view.
309 */
310 public void reset() {
Jorim Jaggi416493b2014-09-13 03:57:32 +0200311 cancelShowRunnable();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200312 inflateView();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700313 mFalsingManager.onBouncerHidden();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200314 }
315
316 public void onScreenTurnedOff() {
Dan Sandler9ee256d2014-04-21 12:05:00 -0400317 if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200318 mKeyguardView.onPause();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200319 }
320 }
321
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200322 public boolean isShowing() {
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700323 return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
Lucas Dupin70659002018-04-30 15:56:52 -0700324 && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200325 }
326
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700327 /**
328 * @return {@code true} when bouncer's pre-hide animation already started but isn't completely
329 * hidden yet, {@code false} otherwise.
330 */
331 public boolean isAnimatingAway() {
332 return mIsAnimatingAway;
333 }
334
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200335 public void prepare() {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100336 boolean wasInitialized = mRoot != null;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200337 ensureView();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100338 if (wasInitialized) {
339 mKeyguardView.showPrimarySecurityScreen();
340 }
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700341 mBouncerPromptReason = mCallback.getBouncerPromptReason();
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200342 }
343
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800344 /**
345 * Current notification panel expansion
346 * @param fraction 0 when notification panel is collapsed and 1 when expanded.
347 * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
348 */
349 public void setExpansion(float fraction) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800350 float oldExpansion = mExpansion;
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700351 mExpansion = fraction;
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700352 if (mKeyguardView != null && !mIsAnimatingAway) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700353 float alpha = MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
354 mKeyguardView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800355 mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
356 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800357
Lucas Dupin70659002018-04-30 15:56:52 -0700358 if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800359 onFullyShown();
360 mExpansionCallback.onFullyShown();
Lucas Dupin70659002018-04-30 15:56:52 -0700361 } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800362 onFullyHidden();
363 mExpansionCallback.onFullyHidden();
364 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800365 }
366
Lucas Dupin6f0d71f2018-03-23 17:26:06 -0700367 public boolean willDismissWithAction() {
368 return mKeyguardView != null && mKeyguardView.hasDismissActions();
369 }
370
Lucas Dupin4c2aa392018-03-28 18:00:45 -0700371 public int getTop() {
372 if (mKeyguardView == null) {
373 return 0;
374 }
375
376 int top = mKeyguardView.getTop();
377 // The password view has an extra top padding that should be ignored.
378 if (mKeyguardView.getCurrentSecurityMode() == SecurityMode.Password) {
379 View messageArea = mKeyguardView.findViewById(R.id.keyguard_message_area);
380 top += messageArea.getTop();
381 }
382 return top;
383 }
384
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800385 protected void ensureView() {
Lucas Dupinf190a852017-07-31 17:11:26 -0700386 // Removal of the view might be deferred to reduce unlock latency,
387 // in this case we need to force the removal, otherwise we'll
388 // end up in an unpredictable state.
389 boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
390 if (mRoot == null || forceRemoval) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200391 inflateView();
392 }
393 }
394
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800395 protected void inflateView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200396 removeView();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200397 mHandler.removeCallbacks(mRemoveViewRunnable);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200398 mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
Lucas Dupin6865b712017-09-11 12:28:03 -0700399 mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200400 mKeyguardView.setLockPatternUtils(mLockPatternUtils);
401 mKeyguardView.setViewMediatorCallback(mCallback);
402 mContainer.addView(mRoot, mContainer.getChildCount());
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700403 mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
404 com.android.systemui.R.dimen.status_bar_height);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200405 mRoot.setVisibility(View.INVISIBLE);
Phil Weaver7d847b02018-02-13 16:02:35 -0800406 mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
Lucas Dupin6865b712017-09-11 12:28:03 -0700407
408 final WindowInsets rootInsets = mRoot.getRootWindowInsets();
409 if (rootInsets != null) {
410 mRoot.dispatchApplyWindowInsets(rootInsets);
411 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200412 }
413
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800414 protected void removeView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200415 if (mRoot != null && mRoot.getParent() == mContainer) {
416 mContainer.removeView(mRoot);
417 mRoot = null;
418 }
419 }
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200420
421 public boolean onBackPressed() {
422 return mKeyguardView != null && mKeyguardView.handleBackKey();
423 }
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200424
425 /**
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100426 * @return True if and only if the security method should be shown before showing the
427 * notifications on Keyguard, like SIM PIN/PUK.
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200428 */
429 public boolean needsFullscreenBouncer() {
Selim Cinekedd32b82015-06-23 22:05:58 -0400430 ensureView();
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200431 if (mKeyguardView != null) {
432 SecurityMode mode = mKeyguardView.getSecurityMode();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100433 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
434 }
435 return false;
436 }
437
438 /**
439 * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
440 * makes this method much faster.
441 */
442 public boolean isFullscreenBouncer() {
443 if (mKeyguardView != null) {
444 SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
445 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200446 }
447 return false;
448 }
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200449
Christoph Studer2231c6e2014-12-19 12:40:13 +0100450 /**
451 * WARNING: This method might cause Binder calls.
452 */
Jorim Jaggi15682502014-04-23 12:01:36 +0200453 public boolean isSecure() {
454 return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
455 }
456
Selim Cinek28540192016-02-19 17:25:08 -0800457 public boolean shouldDismissOnMenuPressed() {
458 return mKeyguardView.shouldEnableMenuKey();
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200459 }
Jorim Jaggidf993512014-05-13 23:06:35 +0200460
461 public boolean interceptMediaKey(KeyEvent event) {
462 ensureView();
463 return mKeyguardView.interceptMediaKey(event);
464 }
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700465
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700466 public void notifyKeyguardAuthenticated(boolean strongAuth) {
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700467 ensureView();
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700468 mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700469 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800470
471 public void dump(PrintWriter pw) {
472 pw.println("KeyguardBouncer");
473 pw.println(" isShowing(): " + isShowing());
474 pw.println(" mStatusBarHeight: " + mStatusBarHeight);
475 pw.println(" mExpansion: " + mExpansion);
476 pw.println(" mKeyguardView; " + mKeyguardView);
477 pw.println(" mShowingSoon: " + mKeyguardView);
478 pw.println(" mBouncerPromptReason: " + mBouncerPromptReason);
479 pw.println(" mIsAnimatingAway: " + mIsAnimatingAway);
480 }
481
482 public interface BouncerExpansionCallback {
483 void onFullyShown();
484 void onFullyHidden();
485 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200486}