blob: 0b994ff46f2907f5799659db0171a5057cb8f72e [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 Dupin787f9a02019-04-24 14:56:52 -070057 static final long BOUNCER_FACE_DELAY = 800;
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;
Jorim Jaggi241ae102016-11-02 21:57:33 -070071 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070072 new KeyguardUpdateMonitorCallback() {
73 @Override
Adrian Roos1de8bcb2015-08-19 16:52:52 -070074 public void onStrongAuthStateChanged(int userId) {
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -070075 mBouncerPromptReason = mCallback.getBouncerPromptReason();
76 }
77 };
Jorim Jaggifabc7432017-05-15 02:40:05 +020078 private final Runnable mRemoveViewRunnable = this::removeView;
Lucas Dupin70659002018-04-30 15:56:52 -070079 protected KeyguardHostView mKeyguardView;
80 private final Runnable mResetRunnable = ()-> {
81 if (mKeyguardView != null) {
Lucas Dupin80180492018-05-08 17:06:06 -070082 mKeyguardView.resetSecurityContainer();
Lucas Dupin70659002018-04-30 15:56:52 -070083 }
84 };
Lucas Dupin3d565fa2018-03-20 15:40:14 -070085
Selim Cinekcb3d45a2017-09-08 18:00:18 -070086 private int mStatusBarHeight;
Lucas Dupin70659002018-04-30 15:56:52 -070087 private float mExpansion = EXPANSION_HIDDEN;
Lucas Dupin3d565fa2018-03-20 15:40:14 -070088 protected ViewGroup mRoot;
89 private boolean mShowingSoon;
90 private int mBouncerPromptReason;
Lucas Dupin28dc9d72018-03-21 15:59:15 -070091 private boolean mIsAnimatingAway;
Lucas Dupinf9ca35e2018-05-16 20:41:35 -070092 private boolean mIsScrimmed;
Lucas Dupin407cc582019-03-11 21:04:31 -070093 private ViewGroup mLockIconContainer;
Jorim Jaggi03c701e2014-04-02 12:39:51 +020094
95 public KeyguardBouncer(Context context, ViewMediatorCallback callback,
Jorim Jaggi241ae102016-11-02 21:57:33 -070096 LockPatternUtils lockPatternUtils, ViewGroup container,
Lucas Dupin15a6b6c2018-04-16 14:50:20 +080097 DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
Lucas Dupin787f9a02019-04-24 14:56:52 -070098 BouncerExpansionCallback expansionCallback,
99 KeyguardUpdateMonitor keyguardUpdateMonitor, Handler handler) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200100 mContext = context;
101 mCallback = callback;
102 mLockPatternUtils = lockPatternUtils;
103 mContainer = container;
Lucas Dupin787f9a02019-04-24 14:56:52 -0700104 mKeyguardUpdateMonitor = keyguardUpdateMonitor;
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700105 mFalsingManager = falsingManager;
Jorim Jaggi241ae102016-11-02 21:57:33 -0700106 mDismissCallbackRegistry = dismissCallbackRegistry;
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800107 mExpansionCallback = expansionCallback;
Lucas Dupin787f9a02019-04-24 14:56:52 -0700108 mHandler = handler;
109 mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200110 }
111
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100112 public void show(boolean resetSecuritySelection) {
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700113 show(resetSecuritySelection, true /* scrimmed */);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800114 }
115
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700116 /**
117 * Shows the bouncer.
118 *
119 * @param resetSecuritySelection Cleans keyguard view
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700120 * @param isScrimmed true when the bouncer show show scrimmed, false when the user will be
121 * dragging it and translation should be deferred.
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700122 */
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700123 public void show(boolean resetSecuritySelection, boolean isScrimmed) {
Vadim Tryshevec018432016-02-10 14:11:03 -0800124 final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
125 if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
126 // In split system user mode, we never unlock system user.
127 return;
128 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200129 ensureView();
Lucas Dupin93f714d2019-03-26 16:49:24 -0700130 mIsScrimmed = isScrimmed;
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800131
132 // On the keyguard, we want to show the bouncer when the user drags up, but it's
133 // not correct to end the falsing session. We still need to verify if those touches
134 // are valid.
135 // Later, at the end of the animation, when the bouncer is at the top of the screen,
136 // onFullyShown() will be called and FalsingManager will stop recording touches.
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700137 if (isScrimmed) {
Lucas Dupin70659002018-04-30 15:56:52 -0700138 setExpansion(EXPANSION_VISIBLE);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800139 }
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700140
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100141 if (resetSecuritySelection) {
142 // showPrimarySecurityScreen() updates the current security method. This is needed in
143 // case we are already showing and the current security method changed.
Lucas Dupin27321c42019-03-20 16:22:24 -0700144 showPrimarySecurityScreen();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100145 }
Lucas Dupin93f714d2019-03-26 16:49:24 -0700146
Jorim Jaggi416493b2014-09-13 03:57:32 +0200147 if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200148 return;
149 }
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200150
Selim Cinek1a891a92017-12-04 17:41:27 +0100151 final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
Xiaohui Chend743cef2016-10-03 09:55:53 -0700152 final boolean isSystemUser =
153 UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
154 final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
155
Toni Barzic657f8852016-02-04 15:14:49 -0800156 // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
157 // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700158 if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) {
Toni Barzic657f8852016-02-04 15:14:49 -0800159 return;
Jorim Jaggi416493b2014-09-13 03:57:32 +0200160 }
Toni Barzic657f8852016-02-04 15:14:49 -0800161
162 // This condition may indicate an error on Android, so log it.
163 if (!allowDismissKeyguard) {
164 Slog.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
165 }
166
167 mShowingSoon = true;
168
169 // Split up the work over multiple frames.
Lucas Dupin70659002018-04-30 15:56:52 -0700170 DejankUtils.removeCallbacks(mResetRunnable);
Lucas Dupin787f9a02019-04-24 14:56:52 -0700171 if (mKeyguardUpdateMonitor.isFaceDetectionRunning()) {
172 mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
173 } else {
174 DejankUtils.postAfterTraversal(mShowRunnable);
175 }
Matthew Ng66f0b702017-12-08 12:58:42 -0800176
177 mCallback.onBouncerVisiblityChanged(true /* shown */);
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700178 mExpansionCallback.onStartingToShow();
Jorim Jaggi416493b2014-09-13 03:57:32 +0200179 }
180
Lucas Dupin93f714d2019-03-26 16:49:24 -0700181 public boolean isScrimmed() {
182 return mIsScrimmed;
Lucas Dupinf9ca35e2018-05-16 20:41:35 -0700183 }
184
Lucas Dupin407cc582019-03-11 21:04:31 -0700185 public ViewGroup getLockIconContainer() {
186 return mRoot == null || mRoot.getVisibility() != View.VISIBLE ? null : mLockIconContainer;
187 }
188
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800189 /**
190 * This method must be called at the end of the bouncer animation when
191 * the translation is performed manually by the user, otherwise FalsingManager
192 * will never be notified and its internal state will be out of sync.
193 */
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800194 private void onFullyShown() {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800195 mFalsingManager.onBouncerShown();
Lucas Dupind2ce46d2018-04-04 17:00:29 -0700196 if (mKeyguardView == null) {
197 Log.wtf(TAG, "onFullyShown when view was null");
198 } else {
199 mKeyguardView.onResume();
200 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800201 }
202
203 /**
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800204 * @see #onFullyShown()
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800205 */
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800206 private void onFullyHidden() {
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800207 if (!mShowingSoon) {
208 cancelShowRunnable();
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700209 if (mRoot != null) {
210 mRoot.setVisibility(View.INVISIBLE);
211 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800212 mFalsingManager.onBouncerHidden();
Lucas Dupin70659002018-04-30 15:56:52 -0700213 DejankUtils.postAfterTraversal(mResetRunnable);
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800214 }
215 }
216
Jorim Jaggi416493b2014-09-13 03:57:32 +0200217 private final Runnable mShowRunnable = new Runnable() {
218 @Override
219 public void run() {
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200220 mRoot.setVisibility(View.VISIBLE);
Selim Cinek3122fa82015-06-18 01:38:59 -0700221 showPromptReason(mBouncerPromptReason);
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800222 final CharSequence customMessage = mCallback.consumeCustomMessage();
223 if (customMessage != null) {
224 mKeyguardView.showErrorMessage(customMessage);
225 }
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700226 // We might still be collapsed and the view didn't have time to layout yet or still
227 // be small, let's wait on the predraw to do the animation in that case.
228 if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) {
Adrian Roosedfa96f2016-01-29 12:46:35 -0800229 mKeyguardView.startAppearAnimation();
230 } else {
231 mKeyguardView.getViewTreeObserver().addOnPreDrawListener(
232 new ViewTreeObserver.OnPreDrawListener() {
233 @Override
234 public boolean onPreDraw() {
235 mKeyguardView.getViewTreeObserver().removeOnPreDrawListener(this);
236 mKeyguardView.startAppearAnimation();
237 return true;
238 }
239 });
240 mKeyguardView.requestLayout();
241 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200242 mShowingSoon = false;
Lucas Dupin70659002018-04-30 15:56:52 -0700243 if (mExpansion == EXPANSION_VISIBLE) {
244 mKeyguardView.onResume();
Wang, ArvinXa2d94c52018-09-12 11:31:32 +0800245 mKeyguardView.resetSecurityContainer();
Lucas Dupin70659002018-04-30 15:56:52 -0700246 }
Tej Singhdd7bd352018-02-09 19:33:15 -0800247 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
248 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
Jorim Jaggi0bed7f22014-04-03 16:12:54 +0200249 }
Jorim Jaggi416493b2014-09-13 03:57:32 +0200250 };
251
Selim Cinek3122fa82015-06-18 01:38:59 -0700252 /**
253 * Show a string explaining why the security view needs to be solved.
254 *
255 * @param reason a flag indicating which string should be shown, see
256 * {@link KeyguardSecurityView#PROMPT_REASON_NONE}
257 * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
258 */
259 public void showPromptReason(int reason) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700260 if (mKeyguardView != null) {
261 mKeyguardView.showPromptReason(reason);
262 } else {
263 Log.w(TAG, "Trying to show prompt reason on empty bouncer");
264 }
Selim Cinek3122fa82015-06-18 01:38:59 -0700265 }
266
Jason Chang1e4a4bd2018-05-22 17:30:19 +0800267 public void showMessage(String message, ColorStateList colorState) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700268 if (mKeyguardView != null) {
Jason Chang1e4a4bd2018-05-22 17:30:19 +0800269 mKeyguardView.showMessage(message, colorState);
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700270 } else {
271 Log.w(TAG, "Trying to show message on empty bouncer");
272 }
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700273 }
274
Jorim Jaggi416493b2014-09-13 03:57:32 +0200275 private void cancelShowRunnable() {
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700276 DejankUtils.removeCallbacks(mShowRunnable);
Lucas Dupin787f9a02019-04-24 14:56:52 -0700277 mHandler.removeCallbacks(mShowRunnable);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200278 mShowingSoon = false;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200279 }
280
Jorim Jaggid9449862015-05-29 14:49:08 -0700281 public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200282 ensureView();
Jorim Jaggid9449862015-05-29 14:49:08 -0700283 mKeyguardView.setOnDismissAction(r, cancelAction);
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100284 show(false /* resetSecuritySelection */);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200285 }
286
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200287 public void hide(boolean destroyView) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700288 if (isShowing()) {
Tej Singhdd7bd352018-02-09 19:33:15 -0800289 StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
290 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700291 mDismissCallbackRegistry.notifyDismissCancelled();
292 }
Lucas Dupin93f714d2019-03-26 16:49:24 -0700293 mIsScrimmed = false;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700294 mFalsingManager.onBouncerHidden();
Matthew Ng66f0b702017-12-08 12:58:42 -0800295 mCallback.onBouncerVisiblityChanged(false /* shown */);
Jorim Jaggi416493b2014-09-13 03:57:32 +0200296 cancelShowRunnable();
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800297 if (mKeyguardView != null) {
Jorim Jaggid9449862015-05-29 14:49:08 -0700298 mKeyguardView.cancelDismissAction();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200299 mKeyguardView.cleanUp();
300 }
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700301 mIsAnimatingAway = false;
Jorim Jaggifabc7432017-05-15 02:40:05 +0200302 if (mRoot != null) {
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200303 mRoot.setVisibility(View.INVISIBLE);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200304 if (destroyView) {
305
306 // We have a ViewFlipper that unregisters a broadcast when being detached, which may
307 // be slow because of AM lock contention during unlocking. We can delay it a bit.
308 mHandler.postDelayed(mRemoveViewRunnable, 50);
309 }
Jorim Jaggia0be6d52014-05-26 03:01:13 +0200310 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200311 }
312
Jorim Jaggi76a16232014-08-08 17:00:47 +0200313 /**
314 * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
315 */
316 public void startPreHideAnimation(Runnable runnable) {
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700317 mIsAnimatingAway = true;
Jorim Jaggi76a16232014-08-08 17:00:47 +0200318 if (mKeyguardView != null) {
319 mKeyguardView.startDisappearAnimation(runnable);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200320 } else if (runnable != null) {
Jorim Jaggi76a16232014-08-08 17:00:47 +0200321 runnable.run();
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200322 }
323 }
324
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200325 /**
326 * Reset the state of the view.
327 */
328 public void reset() {
Jorim Jaggi416493b2014-09-13 03:57:32 +0200329 cancelShowRunnable();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200330 inflateView();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700331 mFalsingManager.onBouncerHidden();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200332 }
333
334 public void onScreenTurnedOff() {
Dan Sandler9ee256d2014-04-21 12:05:00 -0400335 if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200336 mKeyguardView.onPause();
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200337 }
338 }
339
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200340 public boolean isShowing() {
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700341 return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
Lucas Dupin70659002018-04-30 15:56:52 -0700342 && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200343 }
344
Lucas Dupind61974d2019-03-29 16:09:26 -0700345 public boolean isPartiallyVisible() {
346 return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
347 && mExpansion != EXPANSION_HIDDEN && !isAnimatingAway();
348 }
349
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700350 /**
351 * @return {@code true} when bouncer's pre-hide animation already started but isn't completely
352 * hidden yet, {@code false} otherwise.
353 */
354 public boolean isAnimatingAway() {
355 return mIsAnimatingAway;
356 }
357
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200358 public void prepare() {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100359 boolean wasInitialized = mRoot != null;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200360 ensureView();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100361 if (wasInitialized) {
Lucas Dupin27321c42019-03-20 16:22:24 -0700362 showPrimarySecurityScreen();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100363 }
Jorim Jaggi86b273f2015-07-14 18:08:43 -0700364 mBouncerPromptReason = mCallback.getBouncerPromptReason();
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200365 }
366
Lucas Dupin27321c42019-03-20 16:22:24 -0700367 private void showPrimarySecurityScreen() {
368 mKeyguardView.showPrimarySecurityScreen();
369 KeyguardSecurityView keyguardSecurityView = mKeyguardView.getCurrentSecurityView();
370 if (keyguardSecurityView != null) {
371 mLockIconContainer = ((ViewGroup) keyguardSecurityView)
372 .findViewById(R.id.lock_icon_container);
373 }
374 }
375
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800376 /**
377 * Current notification panel expansion
378 * @param fraction 0 when notification panel is collapsed and 1 when expanded.
379 * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
380 */
381 public void setExpansion(float fraction) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800382 float oldExpansion = mExpansion;
Lucas Dupin3d565fa2018-03-20 15:40:14 -0700383 mExpansion = fraction;
Lucas Dupin28dc9d72018-03-21 15:59:15 -0700384 if (mKeyguardView != null && !mIsAnimatingAway) {
Lucas Dupin0df9b7a2018-03-15 17:53:17 -0700385 float alpha = MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction);
386 mKeyguardView.setAlpha(MathUtils.constrain(alpha, 0f, 1f));
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800387 mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight());
388 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800389
Lucas Dupin70659002018-04-30 15:56:52 -0700390 if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800391 onFullyShown();
392 mExpansionCallback.onFullyShown();
Lucas Dupin70659002018-04-30 15:56:52 -0700393 } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800394 onFullyHidden();
395 mExpansionCallback.onFullyHidden();
Lucas Dupin84993542018-10-11 19:23:45 -0700396 } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
397 mExpansionCallback.onStartingToHide();
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800398 }
Lucas Dupinbc9aac12018-03-04 20:18:15 -0800399 }
400
Lucas Dupin6f0d71f2018-03-23 17:26:06 -0700401 public boolean willDismissWithAction() {
402 return mKeyguardView != null && mKeyguardView.hasDismissActions();
403 }
404
Lucas Dupin4c2aa392018-03-28 18:00:45 -0700405 public int getTop() {
406 if (mKeyguardView == null) {
407 return 0;
408 }
409
410 int top = mKeyguardView.getTop();
411 // The password view has an extra top padding that should be ignored.
412 if (mKeyguardView.getCurrentSecurityMode() == SecurityMode.Password) {
413 View messageArea = mKeyguardView.findViewById(R.id.keyguard_message_area);
414 top += messageArea.getTop();
415 }
416 return top;
417 }
418
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800419 protected void ensureView() {
Lucas Dupinf190a852017-07-31 17:11:26 -0700420 // Removal of the view might be deferred to reduce unlock latency,
421 // in this case we need to force the removal, otherwise we'll
422 // end up in an unpredictable state.
423 boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
424 if (mRoot == null || forceRemoval) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200425 inflateView();
426 }
427 }
428
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800429 protected void inflateView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200430 removeView();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200431 mHandler.removeCallbacks(mRemoveViewRunnable);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200432 mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
Lucas Dupin6865b712017-09-11 12:28:03 -0700433 mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200434 mKeyguardView.setLockPatternUtils(mLockPatternUtils);
435 mKeyguardView.setViewMediatorCallback(mCallback);
436 mContainer.addView(mRoot, mContainer.getChildCount());
Selim Cinekcb3d45a2017-09-08 18:00:18 -0700437 mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
438 com.android.systemui.R.dimen.status_bar_height);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200439 mRoot.setVisibility(View.INVISIBLE);
Phil Weaver7d847b02018-02-13 16:02:35 -0800440 mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
Lucas Dupin6865b712017-09-11 12:28:03 -0700441
442 final WindowInsets rootInsets = mRoot.getRootWindowInsets();
443 if (rootInsets != null) {
444 mRoot.dispatchApplyWindowInsets(rootInsets);
445 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200446 }
447
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800448 protected void removeView() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200449 if (mRoot != null && mRoot.getParent() == mContainer) {
450 mContainer.removeView(mRoot);
451 mRoot = null;
452 }
453 }
Jorim Jaggie5c7a892014-04-10 20:37:32 +0200454
455 public boolean onBackPressed() {
456 return mKeyguardView != null && mKeyguardView.handleBackKey();
457 }
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200458
459 /**
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100460 * @return True if and only if the security method should be shown before showing the
461 * notifications on Keyguard, like SIM PIN/PUK.
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200462 */
463 public boolean needsFullscreenBouncer() {
Selim Cinekedd32b82015-06-23 22:05:58 -0400464 ensureView();
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200465 if (mKeyguardView != null) {
466 SecurityMode mode = mKeyguardView.getSecurityMode();
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100467 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
468 }
469 return false;
470 }
471
472 /**
473 * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
474 * makes this method much faster.
475 */
476 public boolean isFullscreenBouncer() {
477 if (mKeyguardView != null) {
478 SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
479 return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200480 }
481 return false;
482 }
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200483
Christoph Studer2231c6e2014-12-19 12:40:13 +0100484 /**
485 * WARNING: This method might cause Binder calls.
486 */
Jorim Jaggi15682502014-04-23 12:01:36 +0200487 public boolean isSecure() {
488 return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
489 }
490
Selim Cinek28540192016-02-19 17:25:08 -0800491 public boolean shouldDismissOnMenuPressed() {
492 return mKeyguardView.shouldEnableMenuKey();
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +0200493 }
Jorim Jaggidf993512014-05-13 23:06:35 +0200494
495 public boolean interceptMediaKey(KeyEvent event) {
496 ensureView();
497 return mKeyguardView.interceptMediaKey(event);
498 }
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700499
Jorim Jaggi25b4d4b2015-08-11 15:54:06 -0700500 public void notifyKeyguardAuthenticated(boolean strongAuth) {
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700501 ensureView();
Vadim Tryshev8702ca72016-04-22 08:14:12 -0700502 mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
Jorim Jaggi5cc86592015-06-08 14:48:28 -0700503 }
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800504
505 public void dump(PrintWriter pw) {
506 pw.println("KeyguardBouncer");
507 pw.println(" isShowing(): " + isShowing());
508 pw.println(" mStatusBarHeight: " + mStatusBarHeight);
509 pw.println(" mExpansion: " + mExpansion);
510 pw.println(" mKeyguardView; " + mKeyguardView);
511 pw.println(" mShowingSoon: " + mKeyguardView);
512 pw.println(" mBouncerPromptReason: " + mBouncerPromptReason);
513 pw.println(" mIsAnimatingAway: " + mIsAnimatingAway);
514 }
515
516 public interface BouncerExpansionCallback {
517 void onFullyShown();
Lucas Dupin84993542018-10-11 19:23:45 -0700518 void onStartingToHide();
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700519 void onStartingToShow();
Lucas Dupin15a6b6c2018-04-16 14:50:20 +0800520 void onFullyHidden();
521 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200522}