blob: dc9b373de688c053c7edccba1eb3803f9436b2ee [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.KeyguardSecurityModel.SecurityMode;
Gus Prevasab336792018-11-14 13:52:20 -050020import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
Lucas Dupin0df9b7a2018-03-15 17:53:17 -070021
Jorim Jaggi03c701e2014-04-02 12:39:51 +020022import android.content.Context;
Jason Chang1e4a4bd2018-05-22 17:30:19 +080023import android.content.res.ColorStateList;
Jorim Jaggifabc7432017-05-15 02:40:05 +020024import android.os.Handler;
Toni Barzic657f8852016-02-04 15:14:49 -080025import android.os.UserHandle;
Toni Barzicb799d3f2016-02-17 15:09:10 -080026import android.os.UserManager;
Lucas Dupin0df9b7a2018-03-15 17:53:17 -070027import android.util.Log;
Lucas Dupinbc9aac12018-03-04 20:18:15 -080028import android.util.MathUtils;
Toni Barzic657f8852016-02-04 15:14:49 -080029import android.util.Slog;
Tej Singhdd7bd352018-02-09 19:33:15 -080030import android.util.StatsLog;
Jorim Jaggidf993512014-05-13 23:06:35 +020031import android.view.KeyEvent;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020032import android.view.LayoutInflater;
33import android.view.View;
34import android.view.ViewGroup;
Adrian Roosedfa96f2016-01-29 12:46:35 -080035import android.view.ViewTreeObserver;
Lucas Dupin6865b712017-09-11 12:28:03 -070036import android.view.WindowInsets;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020037
Jorim Jaggi03c701e2014-04-02 12:39:51 +020038import com.android.internal.widget.LockPatternUtils;
Jorim Jaggi6b88cdf2014-12-22 20:56:50 +010039import com.android.keyguard.KeyguardHostView;
Selim Cinek3122fa82015-06-18 01:38:59 -070040import com.android.keyguard.KeyguardSecurityView;
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070041import com.android.keyguard.KeyguardUpdateMonitor;
42import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020043import com.android.keyguard.R;
44import com.android.keyguard.ViewMediatorCallback;
Jorim Jaggi86b273f2015-07-14 18:08:43 -070045import com.android.systemui.DejankUtils;
Jorim Jaggi241ae102016-11-02 21:57:33 -070046import com.android.systemui.keyguard.DismissCallbackRegistry;
Dave Mankoff468d4f62019-05-08 14:56:29 -040047import com.android.systemui.plugins.FalsingManager;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020048
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080049import java.io.PrintWriter;
50
Jorim Jaggi03c701e2014-04-02 12:39:51 +020051/**
52 * A class which manages the bouncer on the lockscreen.
53 */
54public class KeyguardBouncer {
55
Lucas Dupinbc9aac12018-03-04 20:18:15 -080056 private static final String TAG = "KeyguardBouncer";
Lucas Dupin7825b942019-06-03 20:22:39 -070057 static final long BOUNCER_FACE_DELAY = 1200;
Lucas Dupinbc9aac12018-03-04 20:18:15 -080058 static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
Lucas Dupinf9ca35e2018-05-16 20:41:35 -070059 static final float EXPANSION_HIDDEN = 1f;
60 static final float EXPANSION_VISIBLE = 0f;
Toni Barzic657f8852016-02-04 15:14:49 -080061
Jorim Jaggi241ae102016-11-02 21:57:33 -070062 protected final Context mContext;
63 protected final ViewMediatorCallback mCallback;
64 protected final LockPatternUtils mLockPatternUtils;
65 protected final ViewGroup mContainer;
66 private final FalsingManager mFalsingManager;
67 private final DismissCallbackRegistry mDismissCallbackRegistry;
Jorim Jaggifabc7432017-05-15 02:40:05 +020068 private final Handler mHandler;
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080069 private final BouncerExpansionCallback mExpansionCallback;
Lucas Dupin787f9a02019-04-24 14:56:52 -070070 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
Lucas Dupin7825b942019-06-03 20:22:39 -070071 private final UnlockMethodCache mUnlockMethodCache;
Jorim Jaggi241ae102016-11-02 21:57:33 -070072 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070073 new KeyguardUpdateMonitorCallback() {
74 @Override
Adrian Roos1de8bcb2015-08-19 16:52:52 -070075 public void onStrongAuthStateChanged(int userId) {
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070076 mBouncerPromptReason = mCallback.getBouncerPromptReason();
77 }
78 };
Jorim Jaggifabc7432017-05-15 02:40:05 +020079 private final Runnable mRemoveViewRunnable = this::removeView;
Lucas Dupin04ec6df2019-08-15 11:41:52 -070080 private final KeyguardBypassController mKeyguardBypassController;
Lucas Dupin70659002018-04-30 15:56:52 -070081 protected KeyguardHostView mKeyguardView;
82 private final Runnable mResetRunnable = ()-> {
83 if (mKeyguardView != null) {
Lucas Dupin80180492018-05-08 17:06:06 -070084 mKeyguardView.resetSecurityContainer();
Lucas Dupin70659002018-04-30 15:56:52 -070085 }
86 };
Lucas Dupin3d565fa2018-03-20 15:40:14 -070087
Selim Cinekcb3d45a2017-09-08 18:00:18 -070088 private int mStatusBarHeight;
Lucas Dupin70659002018-04-30 15:56:52 -070089 private float mExpansion = EXPANSION_HIDDEN;
Lucas Dupin3d565fa2018-03-20 15:40:14 -070090 protected ViewGroup mRoot;
91 private boolean mShowingSoon;
92 private int mBouncerPromptReason;
Lucas Dupin28dc9d72018-03-21 15:59:15 -070093 private boolean mIsAnimatingAway;
Lucas Dupinf9ca35e2018-05-16 20:41:35 -070094 private boolean mIsScrimmed;
Lucas Dupin407cc582019-03-11 21:04:31 -070095 private ViewGroup mLockIconContainer;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020096
97 public KeyguardBouncer(Context context, ViewMediatorCallback callback,
Jorim Jaggi241ae102016-11-02 21:57:33 -070098 LockPatternUtils lockPatternUtils, ViewGroup container,
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080099 DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
Lucas Dupin7825b942019-06-03 20:22:39 -0700100 BouncerExpansionCallback expansionCallback, UnlockMethodCache unlockMethodCache,
Lucas Dupin04ec6df2019-08-15 11:41:52 -0700101 KeyguardUpdateMonitor keyguardUpdateMonitor,
102 KeyguardBypassController keyguardBypassController, Handler handler) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200103 mContext = context;
104 mCallback = callback;
105 mLockPatternUtils = lockPatternUtils;
106 mContainer = container;
Lucas Dupin787f9a02019-04-24 14:56:52 -0700107 mKeyguardUpdateMonitor = keyguardUpdateMonitor;
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700108 mFalsingManager = falsingManager;
Jorim Jaggi241ae102016-11-02 21:57:33 -0700109 mDismissCallbackRegistry = dismissCallbackRegistry;
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800110 mExpansionCallback = expansionCallback;
Lucas Dupin787f9a02019-04-24 14:56:52 -0700111 mHandler = handler;
Lucas Dupin7825b942019-06-03 20:22:39 -0700112 mUnlockMethodCache = unlockMethodCache;
Lucas Dupin787f9a02019-04-24 14:56:52 -0700113 mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
Lucas Dupin04ec6df2019-08-15 11:41:52 -0700114 mKeyguardBypassController = keyguardBypassController;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200115 }
116
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100117 public void show(boolean resetSecuritySelection) {
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700118 show(resetSecuritySelection, true /* scrimmed */);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800119 }
120
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700121 /**
122 * Shows the bouncer.
123 *
124 * @param resetSecuritySelection Cleans keyguard view
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700125 * @param isScrimmed true when the bouncer show show scrimmed, false when the user will be
126 * dragging it and translation should be deferred.
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700127 */
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700128 public void show(boolean resetSecuritySelection, boolean isScrimmed) {
Vadim Tryshevec018432016-02-10 14:11:03 -0800129 final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
130 if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
131 // In split system user mode, we never unlock system user.
132 return;
133 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200134 ensureView();
Lucas Dupin93f714d2019-03-26 16:49:24 -0700135 mIsScrimmed = isScrimmed;
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800136
137 // On the keyguard, we want to show the bouncer when the user drags up, but it's
138 // not correct to end the falsing session. We still need to verify if those touches
139 // are valid.
140 // Later, at the end of the animation, when the bouncer is at the top of the screen,
141 // onFullyShown() will be called and FalsingManager will stop recording touches.
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700142 if (isScrimmed) {
Lucas Dupin70659002018-04-30 15:56:52 -0700143 setExpansion(EXPANSION_VISIBLE);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800144 }
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700145
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100146 if (resetSecuritySelection) {
147 // showPrimarySecurityScreen() updates the current security method. This is needed in
148 // case we are already showing and the current security method changed.
Lucas Dupin27321c42019-03-20 16:22:24 -0700149 showPrimarySecurityScreen();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100150 }
Lucas Dupin93f714d2019-03-26 16:49:24 -0700151
Jorim Jaggi416493b2014-09-13 03:57:32 +0200152 if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200153 return;
154 }
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200155
Selim Cinek1a891a92017-12-04 17:41:27 +0100156 final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
Xiaohui Chend743cef2016-10-03 09:55:53 -0700157 final boolean isSystemUser =
158 UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
159 final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
160
Toni Barzic657f8852016-02-04 15:14:49 -0800161 // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
162 // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700163 if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) {
Toni Barzic657f8852016-02-04 15:14:49 -0800164 return;
Jorim Jaggi416493b2014-09-13 03:57:32 +0200165 }
Toni Barzic657f8852016-02-04 15:14:49 -0800166
167 // This condition may indicate an error on Android, so log it.
168 if (!allowDismissKeyguard) {
169 Slog.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
170 }
171
172 mShowingSoon = true;
173
174 // Split up the work over multiple frames.
Lucas Dupin70659002018-04-30 15:56:52 -0700175 DejankUtils.removeCallbacks(mResetRunnable);
Lucas Dupin4c507042019-07-22 16:47:34 -0700176 if (mUnlockMethodCache.isFaceAuthEnabled() && !needsFullscreenBouncer()
Lucas Dupin04ec6df2019-08-15 11:41:52 -0700177 && !mKeyguardUpdateMonitor.userNeedsStrongAuth()
178 && !mKeyguardBypassController.getBypassEnabled()) {
Lucas Dupin787f9a02019-04-24 14:56:52 -0700179 mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
180 } else {
181 DejankUtils.postAfterTraversal(mShowRunnable);
182 }
Matthew Ng66f0b702017-12-08 12:58:42 -0800183
184 mCallback.onBouncerVisiblityChanged(true /* shown */);
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700185 mExpansionCallback.onStartingToShow();
Jorim Jaggi416493b2014-09-13 03:57:32 +0200186 }
187
Lucas Dupin93f714d2019-03-26 16:49:24 -0700188 public boolean isScrimmed() {
189 return mIsScrimmed;
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700190 }
191
Lucas Dupin407cc582019-03-11 21:04:31 -0700192 public ViewGroup getLockIconContainer() {
193 return mRoot == null || mRoot.getVisibility() != View.VISIBLE ? null : mLockIconContainer;
194 }
195
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800196 /**
197 * This method must be called at the end of the bouncer animation when
198 * the translation is performed manually by the user, otherwise FalsingManager
199 * will never be notified and its internal state will be out of sync.
200 */
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800201 private void onFullyShown() {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800202 mFalsingManager.onBouncerShown();
Lucas Dupind2ce46d2018-04-04 17:00:29 -0700203 if (mKeyguardView == null) {
204 Log.wtf(TAG, "onFullyShown when view was null");
205 } else {
206 mKeyguardView.onResume();
207 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800208 }
209
210 /**
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800211 * @see #onFullyShown()
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800212 */
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800213 private void onFullyHidden() {
Lucas Dupin9b8e5e32019-07-24 16:36:14 -0700214 cancelShowRunnable();
215 if (mRoot != null) {
216 mRoot.setVisibility(View.INVISIBLE);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800217 }
Lucas Dupin9b8e5e32019-07-24 16:36:14 -0700218 mFalsingManager.onBouncerHidden();
219 DejankUtils.postAfterTraversal(mResetRunnable);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800220 }
221
Jorim Jaggi416493b2014-09-13 03:57:32 +0200222 private final Runnable mShowRunnable = new Runnable() {
223 @Override
224 public void run() {
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200225 mRoot.setVisibility(View.VISIBLE);
Selim Cinek3122fa82015-06-18 01:38:59 -0700226 showPromptReason(mBouncerPromptReason);
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800227 final CharSequence customMessage = mCallback.consumeCustomMessage();
228 if (customMessage != null) {
229 mKeyguardView.showErrorMessage(customMessage);
230 }
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700231 // We might still be collapsed and the view didn't have time to layout yet or still
232 // be small, let's wait on the predraw to do the animation in that case.
233 if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) {
Adrian Roosedfa96f2016-01-29 12:46:35 -0800234 mKeyguardView.startAppearAnimation();
235 } else {
236 mKeyguardView.getViewTreeObserver().addOnPreDrawListener(
237 new ViewTreeObserver.OnPreDrawListener() {
238 @Override
239 public boolean onPreDraw() {
240 mKeyguardView.getViewTreeObserver().removeOnPreDrawListener(this);
241 mKeyguardView.startAppearAnimation();
242 return true;
243 }
244 });
245 mKeyguardView.requestLayout();
246 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200247 mShowingSoon = false;
Lucas Dupin70659002018-04-30 15:56:52 -0700248 if (mExpansion == EXPANSION_VISIBLE) {
249 mKeyguardView.onResume();
Wang, ArvinXa2d94c52018-09-12 11:31:32 +0800250 mKeyguardView.resetSecurityContainer();
Lucas Dupin70659002018-04-30 15:56:52 -0700251 }
Tej Singhdd7bd352018-02-09 19:33:15 -0800252 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
253 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200254 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200255 };
256
Selim Cinek3122fa82015-06-18 01:38:59 -0700257 /**
258 * Show a string explaining why the security view needs to be solved.
259 *
260 * @param reason a flag indicating which string should be shown, see
261 * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
262 * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
263 */
264 public void showPromptReason(int reason) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700265 if (mKeyguardView != null) {
266 mKeyguardView.showPromptReason(reason);
267 } else {
268 Log.w(TAG, "Trying to show prompt reason on empty bouncer");
269 }
Selim Cinek3122fa82015-06-18 01:38:59 -0700270 }
271
Jason Chang1e4a4bd2018-05-22 17:30:19 +0800272 public void showMessage(String message, ColorStateList colorState) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700273 if (mKeyguardView != null) {
Jason Chang1e4a4bd2018-05-22 17:30:19 +0800274 mKeyguardView.showMessage(message, colorState);
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700275 } else {
276 Log.w(TAG, "Trying to show message on empty bouncer");
277 }
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700278 }
279
Jorim Jaggi416493b2014-09-13 03:57:32 +0200280 private void cancelShowRunnable() {
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700281 DejankUtils.removeCallbacks(mShowRunnable);
Lucas Dupin787f9a02019-04-24 14:56:52 -0700282 mHandler.removeCallbacks(mShowRunnable);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200283 mShowingSoon = false;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200284 }
285
Jorim Jaggid9449862015-05-29 14:49:08 -0700286 public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200287 ensureView();
Jorim Jaggid9449862015-05-29 14:49:08 -0700288 mKeyguardView.setOnDismissAction(r, cancelAction);
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100289 show(false /* resetSecuritySelection */);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200290 }
291
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200292 public void hide(boolean destroyView) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700293 if (isShowing()) {
Tej Singhdd7bd352018-02-09 19:33:15 -0800294 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
295 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700296 mDismissCallbackRegistry.notifyDismissCancelled();
297 }
Lucas Dupin93f714d2019-03-26 16:49:24 -0700298 mIsScrimmed = false;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700299 mFalsingManager.onBouncerHidden();
Matthew Ng66f0b702017-12-08 12:58:42 -0800300 mCallback.onBouncerVisiblityChanged(false /* shown */);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200301 cancelShowRunnable();
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800302 if (mKeyguardView != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700303 mKeyguardView.cancelDismissAction();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200304 mKeyguardView.cleanUp();
305 }
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700306 mIsAnimatingAway = false;
Jorim Jaggifabc7432017-05-15 02:40:05 +0200307 if (mRoot != null) {
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200308 mRoot.setVisibility(View.INVISIBLE);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200309 if (destroyView) {
310
311 // We have a ViewFlipper that unregisters a broadcast when being detached, which may
312 // be slow because of AM lock contention during unlocking. We can delay it a bit.
313 mHandler.postDelayed(mRemoveViewRunnable, 50);
314 }
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200315 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200316 }
317
Jorim Jaggi76a16232014-08-08 17:00:47 +0200318 /**
319 * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
320 */
321 public void startPreHideAnimation(Runnable runnable) {
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700322 mIsAnimatingAway = true;
Jorim Jaggi76a16232014-08-08 17:00:47 +0200323 if (mKeyguardView != null) {
324 mKeyguardView.startDisappearAnimation(runnable);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200325 } else if (runnable != null) {
Jorim Jaggi76a16232014-08-08 17:00:47 +0200326 runnable.run();
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200327 }
328 }
329
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200330 /**
331 * Reset the state of the view.
332 */
333 public void reset() {
Jorim Jaggi416493b2014-09-13 03:57:32 +0200334 cancelShowRunnable();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200335 inflateView();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700336 mFalsingManager.onBouncerHidden();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200337 }
338
339 public void onScreenTurnedOff() {
Dan Sandler9ee256d2014-04-21 12:05:00 -0400340 if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200341 mKeyguardView.onPause();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200342 }
343 }
344
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200345 public boolean isShowing() {
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700346 return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
Lucas Dupin70659002018-04-30 15:56:52 -0700347 && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200348 }
349
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700350 /**
Lucas Dupinb7d32742019-07-12 17:46:11 +0900351 * {@link #show(boolean)} was called but we're not showing yet, or being dragged.
Lucas Dupinfa817a02019-07-02 15:22:54 -0700352 */
Lucas Dupinb7d32742019-07-12 17:46:11 +0900353 public boolean inTransit() {
Lucas Dupin273832d2019-07-23 13:44:12 -0700354 return mShowingSoon || mExpansion != EXPANSION_HIDDEN && mExpansion != EXPANSION_VISIBLE;
Lucas Dupinfa817a02019-07-02 15:22:54 -0700355 }
356
357 /**
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700358 * @return {@code true} when bouncer's pre-hide animation already started but isn't completely
359 * hidden yet, {@code false} otherwise.
360 */
361 public boolean isAnimatingAway() {
362 return mIsAnimatingAway;
363 }
364
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200365 public void prepare() {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100366 boolean wasInitialized = mRoot != null;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200367 ensureView();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100368 if (wasInitialized) {
Lucas Dupin27321c42019-03-20 16:22:24 -0700369 showPrimarySecurityScreen();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100370 }
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700371 mBouncerPromptReason = mCallback.getBouncerPromptReason();
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200372 }
373
Lucas Dupin27321c42019-03-20 16:22:24 -0700374 private void showPrimarySecurityScreen() {
375 mKeyguardView.showPrimarySecurityScreen();
376 KeyguardSecurityView keyguardSecurityView = mKeyguardView.getCurrentSecurityView();
377 if (keyguardSecurityView != null) {
378 mLockIconContainer = ((ViewGroup) keyguardSecurityView)
379 .findViewById(R.id.lock_icon_container);
380 }
381 }
382
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800383 /**
384 * Current notification panel expansion
385 * @param fraction 0 when notification panel is collapsed and 1 when expanded.
386 * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
387 */
388 public void setExpansion(float fraction) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800389 float oldExpansion = mExpansion;
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700390 mExpansion = fraction;
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700391 if (mKeyguardView != null && !mIsAnimatingAway) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700392 float alpha = MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
393 mKeyguardView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800394 mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
395 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800396
Lucas Dupin70659002018-04-30 15:56:52 -0700397 if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800398 onFullyShown();
399 mExpansionCallback.onFullyShown();
Lucas Dupin70659002018-04-30 15:56:52 -0700400 } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800401 onFullyHidden();
402 mExpansionCallback.onFullyHidden();
Lucas Dupin84993542018-10-11 19:23:45 -0700403 } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
404 mExpansionCallback.onStartingToHide();
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800405 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800406 }
407
Lucas Dupin6f0d71f2018-03-23 17:26:06 -0700408 public boolean willDismissWithAction() {
409 return mKeyguardView != null && mKeyguardView.hasDismissActions();
410 }
411
Lucas Dupin4c2aa392018-03-28 18:00:45 -0700412 public int getTop() {
413 if (mKeyguardView == null) {
414 return 0;
415 }
416
417 int top = mKeyguardView.getTop();
418 // The password view has an extra top padding that should be ignored.
419 if (mKeyguardView.getCurrentSecurityMode() == SecurityMode.Password) {
420 View messageArea = mKeyguardView.findViewById(R.id.keyguard_message_area);
421 top += messageArea.getTop();
422 }
423 return top;
424 }
425
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800426 protected void ensureView() {
Lucas Dupinf190a852017-07-31 17:11:26 -0700427 // Removal of the view might be deferred to reduce unlock latency,
428 // in this case we need to force the removal, otherwise we'll
429 // end up in an unpredictable state.
430 boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
431 if (mRoot == null || forceRemoval) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200432 inflateView();
433 }
434 }
435
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800436 protected void inflateView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200437 removeView();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200438 mHandler.removeCallbacks(mRemoveViewRunnable);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200439 mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
Lucas Dupin6865b712017-09-11 12:28:03 -0700440 mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200441 mKeyguardView.setLockPatternUtils(mLockPatternUtils);
442 mKeyguardView.setViewMediatorCallback(mCallback);
443 mContainer.addView(mRoot, mContainer.getChildCount());
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700444 mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
445 com.android.systemui.R.dimen.status_bar_height);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200446 mRoot.setVisibility(View.INVISIBLE);
Phil Weaver7d847b02018-02-13 16:02:35 -0800447 mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
Lucas Dupin6865b712017-09-11 12:28:03 -0700448
449 final WindowInsets rootInsets = mRoot.getRootWindowInsets();
450 if (rootInsets != null) {
451 mRoot.dispatchApplyWindowInsets(rootInsets);
452 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200453 }
454
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800455 protected void removeView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200456 if (mRoot != null && mRoot.getParent() == mContainer) {
457 mContainer.removeView(mRoot);
458 mRoot = null;
459 }
460 }
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200461
462 public boolean onBackPressed() {
463 return mKeyguardView != null && mKeyguardView.handleBackKey();
464 }
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200465
466 /**
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100467 * @return True if and only if the security method should be shown before showing the
468 * notifications on Keyguard, like SIM PIN/PUK.
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200469 */
470 public boolean needsFullscreenBouncer() {
Selim Cinekedd32b82015-06-23 22:05:58 -0400471 ensureView();
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200472 if (mKeyguardView != null) {
473 SecurityMode mode = mKeyguardView.getSecurityMode();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100474 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
475 }
476 return false;
477 }
478
479 /**
480 * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
481 * makes this method much faster.
482 */
483 public boolean isFullscreenBouncer() {
484 if (mKeyguardView != null) {
485 SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
486 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200487 }
488 return false;
489 }
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200490
Christoph Studer2231c6e2014-12-19 12:40:13 +0100491 /**
492 * WARNING: This method might cause Binder calls.
493 */
Jorim Jaggi15682502014-04-23 12:01:36 +0200494 public boolean isSecure() {
495 return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
496 }
497
Selim Cinek28540192016-02-19 17:25:08 -0800498 public boolean shouldDismissOnMenuPressed() {
499 return mKeyguardView.shouldEnableMenuKey();
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200500 }
Jorim Jaggidf993512014-05-13 23:06:35 +0200501
502 public boolean interceptMediaKey(KeyEvent event) {
503 ensureView();
504 return mKeyguardView.interceptMediaKey(event);
505 }
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700506
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700507 public void notifyKeyguardAuthenticated(boolean strongAuth) {
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700508 ensureView();
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700509 mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700510 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800511
512 public void dump(PrintWriter pw) {
513 pw.println("KeyguardBouncer");
514 pw.println(" isShowing(): " + isShowing());
515 pw.println(" mStatusBarHeight: " + mStatusBarHeight);
516 pw.println(" mExpansion: " + mExpansion);
517 pw.println(" mKeyguardView; " + mKeyguardView);
518 pw.println(" mShowingSoon: " + mKeyguardView);
519 pw.println(" mBouncerPromptReason: " + mBouncerPromptReason);
520 pw.println(" mIsAnimatingAway: " + mIsAnimatingAway);
521 }
522
523 public interface BouncerExpansionCallback {
524 void onFullyShown();
Lucas Dupin84993542018-10-11 19:23:45 -0700525 void onStartingToHide();
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700526 void onStartingToShow();
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800527 void onFullyHidden();
528 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200529}