blob: 8c7e071e0d3ea0fe821d6e087c21b8468f6f7f56 [file] [log] [blame]
Adrian Roos12c1ef52014-06-04 13:54:08 +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;
18
Jeff DeCewa87cddb2020-06-12 12:13:52 -040019import static com.android.systemui.DejankUtils.whitelistIpcs;
20
Beverly8c785892018-01-31 17:25:52 -050021import android.animation.Animator;
22import android.animation.AnimatorListenerAdapter;
Jeff DeCewa87cddb2020-06-12 12:13:52 -040023import android.app.admin.DevicePolicyManager;
24import android.content.BroadcastReceiver;
Adrian Roos12c1ef52014-06-04 13:54:08 +020025import android.content.Context;
Jeff DeCewa87cddb2020-06-12 12:13:52 -040026import android.content.Intent;
27import android.content.IntentFilter;
Jason Chang2386a372018-04-24 16:05:30 +080028import android.content.res.ColorStateList;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070029import android.graphics.Color;
Lucas Dupinff6628d2018-10-15 10:12:37 -070030import android.hardware.biometrics.BiometricSourceType;
Gilad Brettercb51b8b2018-03-22 17:04:51 +020031import android.hardware.face.FaceManager;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070032import android.hardware.fingerprint.FingerprintManager;
Adrian Roos12c1ef52014-06-04 13:54:08 +020033import android.os.BatteryManager;
Adrian Roos12c1ef52014-06-04 13:54:08 +020034import android.os.Handler;
35import android.os.Message;
36import android.os.RemoteException;
Adrian Roos12c1ef52014-06-04 13:54:08 +020037import android.text.TextUtils;
38import android.text.format.Formatter;
39import android.util.Log;
40import android.view.View;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +010041import android.view.ViewGroup;
Adrian Roos12c1ef52014-06-04 13:54:08 +020042
Adrian Roosc1b50322017-02-27 21:07:58 +010043import com.android.internal.annotations.VisibleForTesting;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070044import com.android.internal.app.IBatteryStats;
Lucas Dupineff8ef02019-06-06 11:14:01 -070045import com.android.internal.widget.ViewClippingUtil;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070046import com.android.keyguard.KeyguardUpdateMonitor;
47import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jason Monk58be7a62017-02-01 20:17:51 -050048import com.android.settingslib.Utils;
Raff Tsaif4ea5622019-06-26 16:15:21 +080049import com.android.settingslib.fuelgauge.BatteryStatus;
Beverly8c785892018-01-31 17:25:52 -050050import com.android.systemui.Interpolators;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070051import com.android.systemui.R;
Jeff DeCewa87cddb2020-06-12 12:13:52 -040052import com.android.systemui.broadcast.BroadcastDispatcher;
Jerry Chang6a8fb022019-11-15 06:52:54 +080053import com.android.systemui.dock.DockManager;
Beverly8fdb5332019-02-04 14:29:49 -050054import com.android.systemui.plugins.statusbar.StatusBarStateController;
55import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070056import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -050057import com.android.systemui.statusbar.phone.LockscreenLockIconController;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070058import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040059import com.android.systemui.statusbar.policy.KeyguardStateController;
Adrian Roosc1b50322017-02-27 21:07:58 +010060import com.android.systemui.util.wakelock.SettableWakeLock;
61import com.android.systemui.util.wakelock.WakeLock;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070062
Lucas Dupin3fcdd472018-01-19 19:06:45 -080063import java.io.FileDescriptor;
64import java.io.PrintWriter;
Lucas Dupin4272f442018-01-13 22:00:35 -080065import java.text.NumberFormat;
Lucas Dupin8d595d22018-03-08 10:34:58 -080066import java.util.IllegalFormatConversionException;
Lucas Dupin4272f442018-01-13 22:00:35 -080067
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -050068import javax.inject.Inject;
69import javax.inject.Singleton;
70
Adrian Roos12c1ef52014-06-04 13:54:08 +020071/**
Selim Cinekcfafe4e2015-08-11 14:58:44 -070072 * Controls the indications and error messages shown on the Keyguard
Adrian Roos12c1ef52014-06-04 13:54:08 +020073 */
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -050074@Singleton
Lucas Dupin8e2fd012019-04-25 16:40:54 -070075public class KeyguardIndicationController implements StateListener,
Lucas Dupinc8f16e82019-09-17 18:24:50 -040076 KeyguardStateController.Callback {
Adrian Roos12c1ef52014-06-04 13:54:08 +020077
Adrian Roos0c859ae2015-11-23 16:47:50 -080078 private static final String TAG = "KeyguardIndication";
79 private static final boolean DEBUG_CHARGING_SPEED = false;
Adrian Roos12c1ef52014-06-04 13:54:08 +020080
81 private static final int MSG_HIDE_TRANSIENT = 1;
Gilad Brettercb51b8b2018-03-22 17:04:51 +020082 private static final int MSG_CLEAR_BIOMETRIC_MSG = 2;
Lucas Dupin51996bb2019-05-16 17:56:43 -070083 private static final int MSG_SWIPE_UP_TO_UNLOCK = 3;
Gilad Brettercb51b8b2018-03-22 17:04:51 +020084 private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300;
Robert Snoebergerddfb0652019-06-21 16:41:46 -040085 private static final float BOUNCE_ANIMATION_FINAL_Y = 0f;
Adrian Roos12c1ef52014-06-04 13:54:08 +020086
87 private final Context mContext;
Jeff DeCewa87cddb2020-06-12 12:13:52 -040088 private final BroadcastDispatcher mBroadcastDispatcher;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040089 private final KeyguardStateController mKeyguardStateController;
Lucas Dupin8e2fd012019-04-25 16:40:54 -070090 private final StatusBarStateController mStatusBarStateController;
91 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
Lucas Dupin987f1932017-05-13 21:02:52 -070092 private ViewGroup mIndicationArea;
93 private KeyguardIndicationTextView mTextView;
Jeff DeCewa87cddb2020-06-12 12:13:52 -040094 private KeyguardIndicationTextView mDisclosure;
Adrian Roos12c1ef52014-06-04 13:54:08 +020095 private final IBatteryStats mBatteryInfo;
Adrian Roosc1b50322017-02-27 21:07:58 +010096 private final SettableWakeLock mWakeLock;
Jerry Chang6a8fb022019-11-15 06:52:54 +080097 private final DockManager mDockManager;
Jeff DeCewa87cddb2020-06-12 12:13:52 -040098 private final DevicePolicyManager mDevicePolicyManager;
Adrian Roos12c1ef52014-06-04 13:54:08 +020099
Jeff DeCewa87cddb2020-06-12 12:13:52 -0400100 private BroadcastReceiver mBroadcastReceiver;
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500101 private LockscreenLockIconController mLockIconController;
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700102 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Adrian Roos7b043112015-07-10 13:00:33 -0700103
Adrian Roos12c1ef52014-06-04 13:54:08 +0200104 private String mRestingIndication;
Jerry Chang6a8fb022019-11-15 06:52:54 +0800105 private String mAlignmentIndication;
Lucas Dupinef886542018-01-03 16:03:07 -0800106 private CharSequence mTransientIndication;
Lucas Dupinaff42362020-03-27 16:28:20 -0700107 private boolean mTransientTextIsError;
Jason Chang2386a372018-04-24 16:05:30 +0800108 private ColorStateList mInitialTextColorState;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200109 private boolean mVisible;
Lucas Dupin85ea4202019-11-04 16:01:51 -0800110 private boolean mHideTransientMessageOnScreenOff;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200111
112 private boolean mPowerPluggedIn;
Beverly2034c832018-03-19 11:18:51 -0400113 private boolean mPowerPluggedInWired;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200114 private boolean mPowerCharged;
Adrian Roos7b043112015-07-10 13:00:33 -0700115 private int mChargingSpeed;
Adrian Roos0c859ae2015-11-23 16:47:50 -0800116 private int mChargingWattage;
Lucas Dupin4272f442018-01-13 22:00:35 -0800117 private int mBatteryLevel;
Lucas Dupin9131b282019-11-19 16:25:03 -0800118 private long mChargingTimeRemaining;
Jeff DeCewa87cddb2020-06-12 12:13:52 -0400119 private float mDisclosureMaxAlpha;
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700120 private String mMessageToShowOnScreenOn;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200121
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700122 private KeyguardUpdateMonitorCallback mUpdateMonitorCallback;
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800123
Adrian Roos91ba3072017-02-14 16:50:46 +0100124 private boolean mDozing;
Lucas Dupineff8ef02019-06-06 11:14:01 -0700125 private final ViewClippingUtil.ClippingParameters mClippingParams =
126 new ViewClippingUtil.ClippingParameters() {
127 @Override
128 public boolean shouldFinish(View view) {
129 return view == mIndicationArea;
130 }
131 };
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100132
Adrian Roosaf45b602017-03-14 13:10:25 -0700133 /**
134 * Creates a new KeyguardIndicationController and registers callbacks.
135 */
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500136 @Inject
137 KeyguardIndicationController(Context context,
138 WakeLock.Builder wakeLockBuilder,
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400139 KeyguardStateController keyguardStateController,
Lucas Dupin8e2fd012019-04-25 16:40:54 -0700140 StatusBarStateController statusBarStateController,
Jerry Chang6a8fb022019-11-15 06:52:54 +0800141 KeyguardUpdateMonitor keyguardUpdateMonitor,
Lucas Dupin9131b282019-11-19 16:25:03 -0800142 DockManager dockManager,
Jeff DeCewa87cddb2020-06-12 12:13:52 -0400143 BroadcastDispatcher broadcastDispatcher,
144 DevicePolicyManager devicePolicyManager,
Lucas Dupin9131b282019-11-19 16:25:03 -0800145 IBatteryStats iBatteryStats) {
Adrian Roos12c1ef52014-06-04 13:54:08 +0200146 mContext = context;
Jeff DeCewa87cddb2020-06-12 12:13:52 -0400147 mBroadcastDispatcher = broadcastDispatcher;
148 mDevicePolicyManager = devicePolicyManager;
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400149 mKeyguardStateController = keyguardStateController;
Lucas Dupin8e2fd012019-04-25 16:40:54 -0700150 mStatusBarStateController = statusBarStateController;
151 mKeyguardUpdateMonitor = keyguardUpdateMonitor;
Jerry Chang6a8fb022019-11-15 06:52:54 +0800152 mDockManager = dockManager;
Wilson Wu0e727132019-12-26 16:17:56 +0800153 mDockManager.addAlignmentStateListener(
154 alignState -> mHandler.post(() -> handleAlignStateChanged(alignState)));
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500155 mWakeLock = new SettableWakeLock(
156 wakeLockBuilder.setTag("Doze:KeyguardIndication").build(), TAG);
Lucas Dupin9131b282019-11-19 16:25:03 -0800157 mBatteryInfo = iBatteryStats;
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600158
Lucas Dupin8e2fd012019-04-25 16:40:54 -0700159 mKeyguardUpdateMonitor.registerCallback(getKeyguardCallback());
160 mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
161 mStatusBarStateController.addCallback(this);
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400162 mKeyguardStateController.addCallback(this);
Evan Laird878c8532018-10-15 15:54:29 -0400163 }
164
Lucas Dupin00ebe132019-04-26 16:17:56 -0700165 public void setIndicationArea(ViewGroup indicationArea) {
166 mIndicationArea = indicationArea;
167 mTextView = indicationArea.findViewById(R.id.keyguard_indication_text);
168 mInitialTextColorState = mTextView != null ?
169 mTextView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
Jeff DeCewa87cddb2020-06-12 12:13:52 -0400170 mDisclosure = indicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure);
171 mDisclosureMaxAlpha = mDisclosure.getAlpha();
Lucas Dupin00ebe132019-04-26 16:17:56 -0700172 updateIndication(false /* animate */);
Jeff DeCewa87cddb2020-06-12 12:13:52 -0400173 updateDisclosure();
174
175 if (mBroadcastReceiver == null) {
176 // Update the disclosure proactively to avoid IPC on the critical path.
177 mBroadcastReceiver = new BroadcastReceiver() {
178 @Override
179 public void onReceive(Context context, Intent intent) {
180 updateDisclosure();
181 }
182 };
183 mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, new IntentFilter(
184 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED));
185 }
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100186 }
187
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500188 public void setLockIconController(LockscreenLockIconController lockIconController) {
189 mLockIconController = lockIconController;
Lucas Dupin0df60fe2019-04-23 10:19:27 -0700190 }
191
Jerry Chang6a8fb022019-11-15 06:52:54 +0800192 private void handleAlignStateChanged(int alignState) {
193 String alignmentIndication = "";
194 if (alignState == DockManager.ALIGN_STATE_POOR) {
195 alignmentIndication =
196 mContext.getResources().getString(R.string.dock_alignment_slow_charging);
197 } else if (alignState == DockManager.ALIGN_STATE_TERRIBLE) {
198 alignmentIndication =
199 mContext.getResources().getString(R.string.dock_alignment_not_charging);
200 }
201 if (!alignmentIndication.equals(mAlignmentIndication)) {
202 mAlignmentIndication = alignmentIndication;
203 updateIndication(false);
204 }
205 }
206
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800207 /**
208 * Gets the {@link KeyguardUpdateMonitorCallback} instance associated with this
209 * {@link KeyguardIndicationController}.
210 *
211 * <p>Subclasses may override this method to extend or change the callback behavior by extending
212 * the {@link BaseKeyguardCallback}.
213 *
214 * @return A KeyguardUpdateMonitorCallback. Multiple calls to this method <b>must</b> return the
215 * same instance.
216 */
217 protected KeyguardUpdateMonitorCallback getKeyguardCallback() {
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700218 if (mUpdateMonitorCallback == null) {
219 mUpdateMonitorCallback = new BaseKeyguardCallback();
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800220 }
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700221 return mUpdateMonitorCallback;
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800222 }
223
Jeff DeCewa87cddb2020-06-12 12:13:52 -0400224 private void updateDisclosure() {
225 // NOTE: Because this uses IPC, avoid calling updateDisclosure() on a critical path.
226 if (whitelistIpcs(mDevicePolicyManager::isDeviceManaged)) {
227 final CharSequence organizationName =
228 mDevicePolicyManager.getDeviceOwnerOrganizationName();
229 if (organizationName != null) {
230 mDisclosure.switchIndication(mContext.getResources().getString(
231 R.string.do_disclosure_with_name, organizationName));
232 } else {
233 mDisclosure.switchIndication(R.string.do_disclosure_generic);
234 }
235 mDisclosure.setVisibility(View.VISIBLE);
236 } else {
237 mDisclosure.setVisibility(View.GONE);
238 }
239 }
240
Adrian Roos12c1ef52014-06-04 13:54:08 +0200241 public void setVisible(boolean visible) {
242 mVisible = visible;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100243 mIndicationArea.setVisibility(visible ? View.VISIBLE : View.GONE);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200244 if (visible) {
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700245 // If this is called after an error message was already shown, we should not clear it.
246 // Otherwise the error message won't be shown
Jerry Chang6a8fb022019-11-15 06:52:54 +0800247 if (!mHandler.hasMessages(MSG_HIDE_TRANSIENT)) {
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700248 hideTransientIndication();
249 }
Beverly8c785892018-01-31 17:25:52 -0500250 updateIndication(false);
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700251 } else if (!visible) {
252 // If we unlock and return to keyguard quickly, previous error should not be shown
253 hideTransientIndication();
Adrian Roos12c1ef52014-06-04 13:54:08 +0200254 }
255 }
256
257 /**
258 * Sets the indication that is shown if nothing else is showing.
259 */
260 public void setRestingIndication(String restingIndication) {
261 mRestingIndication = restingIndication;
Beverly8c785892018-01-31 17:25:52 -0500262 updateIndication(false);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200263 }
264
265 /**
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700266 * Returns the indication text indicating that trust has been granted.
267 *
268 * @return {@code null} or an empty string if a trust indication text should not be shown.
269 */
Lucas Dupin8e2fd012019-04-25 16:40:54 -0700270 @VisibleForTesting
271 String getTrustGrantedIndication() {
Lucas Dupin859f2c82019-04-17 18:30:00 -0700272 return mContext.getString(R.string.keyguard_indication_trust_unlocked);
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700273 }
274
275 /**
Scott Warner778db332020-01-21 09:45:56 -0500276 * Sets if the device is plugged in
277 */
278 @VisibleForTesting
279 void setPowerPluggedIn(boolean plugged) {
280 mPowerPluggedIn = plugged;
281 }
282
283 /**
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700284 * Returns the indication text indicating that trust is currently being managed.
285 *
286 * @return {@code null} or an empty string if a trust managed text should not be shown.
287 */
Lucas Dupin859f2c82019-04-17 18:30:00 -0700288 private String getTrustManagedIndication() {
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700289 return null;
290 }
291
292 /**
Adrian Roos12c1ef52014-06-04 13:54:08 +0200293 * Hides transient indication in {@param delayMs}.
294 */
295 public void hideTransientIndicationDelayed(long delayMs) {
296 mHandler.sendMessageDelayed(
297 mHandler.obtainMessage(MSG_HIDE_TRANSIENT), delayMs);
298 }
299
300 /**
301 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
302 */
303 public void showTransientIndication(int transientIndication) {
304 showTransientIndication(mContext.getResources().getString(transientIndication));
305 }
306
307 /**
308 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
309 */
Lucas Dupinef886542018-01-03 16:03:07 -0800310 public void showTransientIndication(CharSequence transientIndication) {
Lucas Dupinaff42362020-03-27 16:28:20 -0700311 showTransientIndication(transientIndication, false /* isError */,
Lucas Dupin85ea4202019-11-04 16:01:51 -0800312 false /* hideOnScreenOff */);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700313 }
314
315 /**
316 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
317 */
Lucas Dupin85ea4202019-11-04 16:01:51 -0800318 private void showTransientIndication(CharSequence transientIndication,
Lucas Dupinaff42362020-03-27 16:28:20 -0700319 boolean isError, boolean hideOnScreenOff) {
Adrian Roos12c1ef52014-06-04 13:54:08 +0200320 mTransientIndication = transientIndication;
Lucas Dupin85ea4202019-11-04 16:01:51 -0800321 mHideTransientMessageOnScreenOff = hideOnScreenOff && transientIndication != null;
Lucas Dupinaff42362020-03-27 16:28:20 -0700322 mTransientTextIsError = isError;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200323 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
Lucas Dupin51996bb2019-05-16 17:56:43 -0700324 mHandler.removeMessages(MSG_SWIPE_UP_TO_UNLOCK);
Adrian Roosc1b50322017-02-27 21:07:58 +0100325 if (mDozing && !TextUtils.isEmpty(mTransientIndication)) {
326 // Make sure this doesn't get stuck and burns in. Acquire wakelock until its cleared.
327 mWakeLock.setAcquired(true);
328 hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
329 }
Beverly8c785892018-01-31 17:25:52 -0500330
331 updateIndication(false);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200332 }
333
334 /**
335 * Hides transient indication.
336 */
337 public void hideTransientIndication() {
338 if (mTransientIndication != null) {
339 mTransientIndication = null;
Lucas Dupin85ea4202019-11-04 16:01:51 -0800340 mHideTransientMessageOnScreenOff = false;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200341 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
Beverly8c785892018-01-31 17:25:52 -0500342 updateIndication(false);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200343 }
344 }
345
Beverly8c785892018-01-31 17:25:52 -0500346 protected final void updateIndication(boolean animate) {
Adrian Roosc1b50322017-02-27 21:07:58 +0100347 if (TextUtils.isEmpty(mTransientIndication)) {
348 mWakeLock.setAcquired(false);
349 }
350
Adrian Roos12c1ef52014-06-04 13:54:08 +0200351 if (mVisible) {
Lucas Dupin53d50622017-05-13 15:54:14 -0700352 // Walk down a precedence-ordered list of what indication
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600353 // should be shown based on user or device state
Lucas Dupinff6628d2018-10-15 10:12:37 -0700354 if (mDozing) {
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700355 // When dozing we ignore any text color and use white instead, because
356 // colors can be hard to read in low brightness.
357 mTextView.setTextColor(Color.WHITE);
Lucas Dupinff6628d2018-10-15 10:12:37 -0700358 if (!TextUtils.isEmpty(mTransientIndication)) {
Lucas Dupinff6628d2018-10-15 10:12:37 -0700359 mTextView.switchIndication(mTransientIndication);
Jerry Chang6a8fb022019-11-15 06:52:54 +0800360 } else if (!TextUtils.isEmpty(mAlignmentIndication)) {
361 mTextView.switchIndication(mAlignmentIndication);
Wilson Wubb51d092020-04-21 16:00:59 +0800362 mTextView.setTextColor(mContext.getColor(R.color.misalignment_text_color));
Lucas Dupin07ed3df2019-03-26 21:23:59 -0700363 } else if (mPowerPluggedIn) {
364 String indication = computePowerIndication();
365 if (animate) {
366 animateText(mTextView, indication);
367 } else {
368 mTextView.switchIndication(indication);
369 }
370 } else {
371 String percentage = NumberFormat.getPercentInstance()
372 .format(mBatteryLevel / 100f);
373 mTextView.switchIndication(percentage);
Lucas Dupinff6628d2018-10-15 10:12:37 -0700374 }
Lucas Dupinff6628d2018-10-15 10:12:37 -0700375 return;
376 }
377
Jorim Jaggifabc7432017-05-15 02:40:05 +0200378 int userId = KeyguardUpdateMonitor.getCurrentUser();
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700379 String trustGrantedIndication = getTrustGrantedIndication();
380 String trustManagedIndication = getTrustManagedIndication();
Scott Warner778db332020-01-21 09:45:56 -0500381
382 String powerIndication = null;
383 if (mPowerPluggedIn) {
384 powerIndication = computePowerIndication();
385 }
386
Lucas Dupinaff42362020-03-27 16:28:20 -0700387 boolean isError = false;
Lucas Dupin6c6d5732019-08-27 17:36:05 -0700388 if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600389 mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600390 } else if (!TextUtils.isEmpty(mTransientIndication)) {
Lucas Dupind9af6312020-03-23 17:30:15 -0700391 if (powerIndication != null && !mTransientIndication.equals(powerIndication)) {
Scott Warner778db332020-01-21 09:45:56 -0500392 String indication = mContext.getResources().getString(
393 R.string.keyguard_indication_trust_unlocked_plugged_in,
394 mTransientIndication, powerIndication);
395 mTextView.switchIndication(indication);
396 } else {
397 mTextView.switchIndication(mTransientIndication);
398 }
Lucas Dupinaff42362020-03-27 16:28:20 -0700399 isError = mTransientTextIsError;
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700400 } else if (!TextUtils.isEmpty(trustGrantedIndication)
Lucas Dupin8e2fd012019-04-25 16:40:54 -0700401 && mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
Scott Warner778db332020-01-21 09:45:56 -0500402 if (powerIndication != null) {
403 String indication = mContext.getResources().getString(
404 R.string.keyguard_indication_trust_unlocked_plugged_in,
405 trustGrantedIndication, powerIndication);
406 mTextView.switchIndication(indication);
407 } else {
408 mTextView.switchIndication(trustGrantedIndication);
409 }
Jerry Chang6a8fb022019-11-15 06:52:54 +0800410 } else if (!TextUtils.isEmpty(mAlignmentIndication)) {
411 mTextView.switchIndication(mAlignmentIndication);
Lucas Dupinaff42362020-03-27 16:28:20 -0700412 isError = true;
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600413 } else if (mPowerPluggedIn) {
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600414 if (DEBUG_CHARGING_SPEED) {
Scott Warner778db332020-01-21 09:45:56 -0500415 powerIndication += ", " + (mChargingWattage / 1000) + " mW";
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600416 }
Beverly85499d92018-02-14 15:55:16 -0500417 if (animate) {
Scott Warner778db332020-01-21 09:45:56 -0500418 animateText(mTextView, powerIndication);
Beverly85499d92018-02-14 15:55:16 -0500419 } else {
Scott Warner778db332020-01-21 09:45:56 -0500420 mTextView.switchIndication(powerIndication);
Beverly85499d92018-02-14 15:55:16 -0500421 }
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700422 } else if (!TextUtils.isEmpty(trustManagedIndication)
Lucas Dupin8e2fd012019-04-25 16:40:54 -0700423 && mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
424 && !mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700425 mTextView.switchIndication(trustManagedIndication);
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600426 } else {
427 mTextView.switchIndication(mRestingIndication);
Adrian Roos7b043112015-07-10 13:00:33 -0700428 }
Lucas Dupinaff42362020-03-27 16:28:20 -0700429 mTextView.setTextColor(isError ? Utils.getColorError(mContext)
430 : mInitialTextColorState);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200431 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200432 }
433
Beverly85499d92018-02-14 15:55:16 -0500434 // animates textView - textView moves up and bounces down
435 private void animateText(KeyguardIndicationTextView textView, String indication) {
436 int yTranslation = mContext.getResources().getInteger(
437 R.integer.wired_charging_keyguard_text_animation_distance);
438 int animateUpDuration = mContext.getResources().getInteger(
439 R.integer.wired_charging_keyguard_text_animation_duration_up);
440 int animateDownDuration = mContext.getResources().getInteger(
441 R.integer.wired_charging_keyguard_text_animation_duration_down);
Lucas Dupindef43692018-07-02 15:22:58 -0700442 textView.animate().cancel();
Lucas Dupineff8ef02019-06-06 11:14:01 -0700443 ViewClippingUtil.setClippingDeactivated(textView, true, mClippingParams);
Beverly85499d92018-02-14 15:55:16 -0500444 textView.animate()
445 .translationYBy(yTranslation)
446 .setInterpolator(Interpolators.LINEAR)
447 .setDuration(animateUpDuration)
448 .setListener(new AnimatorListenerAdapter() {
Lucas Dupindef43692018-07-02 15:22:58 -0700449 private boolean mCancelled;
450
Beverly85499d92018-02-14 15:55:16 -0500451 @Override
452 public void onAnimationStart(Animator animation) {
453 textView.switchIndication(indication);
454 }
Lucas Dupindef43692018-07-02 15:22:58 -0700455
456 @Override
457 public void onAnimationCancel(Animator animation) {
Robert Snoebergerddfb0652019-06-21 16:41:46 -0400458 textView.setTranslationY(BOUNCE_ANIMATION_FINAL_Y);
Lucas Dupindef43692018-07-02 15:22:58 -0700459 mCancelled = true;
460 }
461
Beverly85499d92018-02-14 15:55:16 -0500462 @Override
463 public void onAnimationEnd(Animator animation) {
Lucas Dupindef43692018-07-02 15:22:58 -0700464 if (mCancelled) {
Lucas Dupineff8ef02019-06-06 11:14:01 -0700465 ViewClippingUtil.setClippingDeactivated(textView, false,
466 mClippingParams);
Lucas Dupindef43692018-07-02 15:22:58 -0700467 return;
468 }
Beverly85499d92018-02-14 15:55:16 -0500469 textView.animate()
470 .setDuration(animateDownDuration)
471 .setInterpolator(Interpolators.BOUNCE)
Robert Snoebergerddfb0652019-06-21 16:41:46 -0400472 .translationY(BOUNCE_ANIMATION_FINAL_Y)
Lucas Dupindef43692018-07-02 15:22:58 -0700473 .setListener(new AnimatorListenerAdapter() {
474 @Override
Lucas Dupineff8ef02019-06-06 11:14:01 -0700475 public void onAnimationEnd(Animator animation) {
Robert Snoebergerddfb0652019-06-21 16:41:46 -0400476 textView.setTranslationY(BOUNCE_ANIMATION_FINAL_Y);
Lucas Dupineff8ef02019-06-06 11:14:01 -0700477 ViewClippingUtil.setClippingDeactivated(textView, false,
478 mClippingParams);
479 }
Lucas Dupindef43692018-07-02 15:22:58 -0700480 });
Beverly85499d92018-02-14 15:55:16 -0500481 }
482 });
483 }
484
Scott Warner778db332020-01-21 09:45:56 -0500485 @VisibleForTesting
486 String computePowerIndication() {
Adrian Roos12c1ef52014-06-04 13:54:08 +0200487 if (mPowerCharged) {
488 return mContext.getResources().getString(R.string.keyguard_charged);
489 }
490
Lucas Dupin9131b282019-11-19 16:25:03 -0800491 final boolean hasChargingTime = mChargingTimeRemaining > 0;
Adrian Roos7b043112015-07-10 13:00:33 -0700492 int chargingId;
Beverly7d7f6992019-02-11 13:58:27 -0500493 if (mPowerPluggedInWired) {
494 switch (mChargingSpeed) {
Raff Tsaif4ea5622019-06-26 16:15:21 +0800495 case BatteryStatus.CHARGING_FAST:
Beverly7d7f6992019-02-11 13:58:27 -0500496 chargingId = hasChargingTime
497 ? R.string.keyguard_indication_charging_time_fast
498 : R.string.keyguard_plugged_in_charging_fast;
499 break;
Raff Tsaif4ea5622019-06-26 16:15:21 +0800500 case BatteryStatus.CHARGING_SLOWLY:
Beverly7d7f6992019-02-11 13:58:27 -0500501 chargingId = hasChargingTime
502 ? R.string.keyguard_indication_charging_time_slowly
503 : R.string.keyguard_plugged_in_charging_slowly;
504 break;
505 default:
506 chargingId = hasChargingTime
507 ? R.string.keyguard_indication_charging_time
508 : R.string.keyguard_plugged_in;
509 break;
510 }
511 } else {
512 chargingId = hasChargingTime
513 ? R.string.keyguard_indication_charging_time_wireless
514 : R.string.keyguard_plugged_in_wireless;
Adrian Roos7b043112015-07-10 13:00:33 -0700515 }
Adrian Roos7e39e592015-09-23 17:03:47 -0700516
Lucas Dupin8d595d22018-03-08 10:34:58 -0800517 String percentage = NumberFormat.getPercentInstance()
518 .format(mBatteryLevel / 100f);
Adrian Roos7e39e592015-09-23 17:03:47 -0700519 if (hasChargingTime) {
Lucas Dupin8d595d22018-03-08 10:34:58 -0800520 // We now have battery percentage in these strings and it's expected that all
521 // locales will also have it in the future. For now, we still have to support the old
522 // format until all languages get the new translations.
Adrian Roos7e39e592015-09-23 17:03:47 -0700523 String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
Lucas Dupin9131b282019-11-19 16:25:03 -0800524 mContext, mChargingTimeRemaining);
Lucas Dupin8d595d22018-03-08 10:34:58 -0800525 try {
526 return mContext.getResources().getString(chargingId, chargingTimeFormatted,
527 percentage);
528 } catch (IllegalFormatConversionException e) {
529 return mContext.getResources().getString(chargingId, chargingTimeFormatted);
530 }
Adrian Roos7e39e592015-09-23 17:03:47 -0700531 } else {
Lucas Dupin8d595d22018-03-08 10:34:58 -0800532 // Same as above
533 try {
534 return mContext.getResources().getString(chargingId, percentage);
535 } catch (IllegalFormatConversionException e) {
536 return mContext.getResources().getString(chargingId);
537 }
Adrian Roos7e39e592015-09-23 17:03:47 -0700538 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200539 }
540
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800541 public void setStatusBarKeyguardViewManager(
542 StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
543 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
544 }
545
Lucas Dupin7e171e22018-12-20 11:29:35 -0800546 private final KeyguardUpdateMonitorCallback mTickReceiver =
547 new KeyguardUpdateMonitorCallback() {
548 @Override
549 public void onTimeChanged() {
550 if (mVisible) {
551 updateIndication(false /* animate */);
552 }
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800553 }
Lucas Dupin7e171e22018-12-20 11:29:35 -0800554 };
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800555
556 private final Handler mHandler = new Handler() {
557 @Override
558 public void handleMessage(Message msg) {
Adrian Roosc1b50322017-02-27 21:07:58 +0100559 if (msg.what == MSG_HIDE_TRANSIENT) {
560 hideTransientIndication();
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200561 } else if (msg.what == MSG_CLEAR_BIOMETRIC_MSG) {
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500562 if (mLockIconController != null) {
563 mLockIconController.setTransientBiometricsError(false);
564 }
Lucas Dupin51996bb2019-05-16 17:56:43 -0700565 } else if (msg.what == MSG_SWIPE_UP_TO_UNLOCK) {
566 showSwipeUpToUnlock();
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800567 }
568 }
569 };
570
Lucas Dupin51996bb2019-05-16 17:56:43 -0700571 private void showSwipeUpToUnlock() {
572 if (mDozing) {
573 return;
574 }
575
Lucas Dupin51996bb2019-05-16 17:56:43 -0700576 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
Lucas Dupinadce3532019-08-02 11:17:39 -0700577 String message = mContext.getString(R.string.keyguard_retry);
Lucas Dupin51996bb2019-05-16 17:56:43 -0700578 mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
579 } else if (mKeyguardUpdateMonitor.isScreenOn()) {
Lucas Dupin85ea4202019-11-04 16:01:51 -0800580 showTransientIndication(mContext.getString(R.string.keyguard_unlock),
Lucas Dupinaff42362020-03-27 16:28:20 -0700581 false /* isError */, true /* hideOnScreenOff */);
Lucas Dupin51996bb2019-05-16 17:56:43 -0700582 hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
583 }
584 }
585
Adrian Roos91ba3072017-02-14 16:50:46 +0100586 public void setDozing(boolean dozing) {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200587 if (mDozing == dozing) {
588 return;
589 }
Adrian Roos91ba3072017-02-14 16:50:46 +0100590 mDozing = dozing;
Lucas Dupin85ea4202019-11-04 16:01:51 -0800591 if (mHideTransientMessageOnScreenOff && mDozing) {
592 hideTransientIndication();
593 } else {
594 updateIndication(false);
595 }
Adrian Roos91ba3072017-02-14 16:50:46 +0100596 }
597
Lucas Dupin3fcdd472018-01-19 19:06:45 -0800598 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
599 pw.println("KeyguardIndicationController:");
Lucas Dupinaff42362020-03-27 16:28:20 -0700600 pw.println(" mTransientTextIsError: " + mTransientTextIsError);
Jason Chang2386a372018-04-24 16:05:30 +0800601 pw.println(" mInitialTextColorState: " + mInitialTextColorState);
Beverly2034c832018-03-19 11:18:51 -0400602 pw.println(" mPowerPluggedInWired: " + mPowerPluggedInWired);
Lucas Dupin3fcdd472018-01-19 19:06:45 -0800603 pw.println(" mPowerPluggedIn: " + mPowerPluggedIn);
604 pw.println(" mPowerCharged: " + mPowerCharged);
605 pw.println(" mChargingSpeed: " + mChargingSpeed);
606 pw.println(" mChargingWattage: " + mChargingWattage);
607 pw.println(" mMessageToShowOnScreenOn: " + mMessageToShowOnScreenOn);
608 pw.println(" mDozing: " + mDozing);
609 pw.println(" mBatteryLevel: " + mBatteryLevel);
610 pw.println(" mTextView.getText(): " + (mTextView == null ? null : mTextView.getText()));
611 pw.println(" computePowerIndication(): " + computePowerIndication());
612 }
613
Evan Laird878c8532018-10-15 15:54:29 -0400614 @Override
615 public void onStateChanged(int newState) {
616 // don't care
617 }
618
619 @Override
620 public void onDozingChanged(boolean isDozing) {
621 setDozing(isDozing);
622 }
623
Lucas Dupin8e2fd012019-04-25 16:40:54 -0700624 @Override
Jeff DeCewa87cddb2020-06-12 12:13:52 -0400625 public void onDozeAmountChanged(float linear, float eased) {
626 mDisclosure.setAlpha((1 - linear) * mDisclosureMaxAlpha);
627 }
628
629 @Override
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400630 public void onUnlockedChanged() {
Lucas Dupin8e2fd012019-04-25 16:40:54 -0700631 updateIndication(!mDozing);
632 }
633
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800634 protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
Adrian Roos56021892017-02-27 20:25:09 +0100635 public static final int HIDE_DELAY_MS = 5000;
Selim Cinek3e451942016-07-14 18:07:53 -0700636
Adrian Roos12c1ef52014-06-04 13:54:08 +0200637 @Override
Raff Tsaif4ea5622019-06-26 16:15:21 +0800638 public void onRefreshBatteryInfo(BatteryStatus status) {
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100639 boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
Adrian Roos12c1ef52014-06-04 13:54:08 +0200640 || status.status == BatteryManager.BATTERY_STATUS_FULL;
Adrian Roos56021892017-02-27 20:25:09 +0100641 boolean wasPluggedIn = mPowerPluggedIn;
Beverly2034c832018-03-19 11:18:51 -0400642 mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull;
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100643 mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200644 mPowerCharged = status.isCharged();
Adrian Roos0c859ae2015-11-23 16:47:50 -0800645 mChargingWattage = status.maxChargingWattage;
Raff Tsaif4ea5622019-06-26 16:15:21 +0800646 mChargingSpeed = status.getChargingSpeed(mContext);
Lucas Dupin4272f442018-01-13 22:00:35 -0800647 mBatteryLevel = status.level;
Lucas Dupin9131b282019-11-19 16:25:03 -0800648 try {
649 mChargingTimeRemaining = mPowerPluggedIn
650 ? mBatteryInfo.computeChargeTimeRemaining() : -1;
651 } catch (RemoteException e) {
652 Log.e(TAG, "Error calling IBatteryStats: ", e);
653 mChargingTimeRemaining = -1;
654 }
Beverly2034c832018-03-19 11:18:51 -0400655 updateIndication(!wasPluggedIn && mPowerPluggedInWired);
Adrian Roosc1b50322017-02-27 21:07:58 +0100656 if (mDozing) {
657 if (!wasPluggedIn && mPowerPluggedIn) {
658 showTransientIndication(computePowerIndication());
659 hideTransientIndicationDelayed(HIDE_DELAY_MS);
660 } else if (wasPluggedIn && !mPowerPluggedIn) {
661 hideTransientIndication();
662 }
Adrian Roos56021892017-02-27 20:25:09 +0100663 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200664 }
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700665
666 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200667 public void onBiometricHelp(int msgId, String helpString,
668 BiometricSourceType biometricSourceType) {
Haining Chenc06c4812020-01-13 20:38:53 -0800669 // TODO(b/141025588): refactor to reduce repetition of code/comments
670 // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
671 // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
672 // pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
673 // check of whether non-strong biometric is allowed
674 if (!mKeyguardUpdateMonitor
675 .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)) {
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700676 return;
677 }
Lucas Dupin51996bb2019-05-16 17:56:43 -0700678 boolean showSwipeToUnlock =
679 msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700680 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
Jason Chang2386a372018-04-24 16:05:30 +0800681 mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800682 mInitialTextColorState);
Lucas Dupin85ea4202019-11-04 16:01:51 -0800683 } else if (mKeyguardUpdateMonitor.isScreenOn()) {
Lucas Dupinaff42362020-03-27 16:28:20 -0700684 showTransientIndication(helpString, false /* isError */, showSwipeToUnlock);
Lucas Dupin51996bb2019-05-16 17:56:43 -0700685 if (!showSwipeToUnlock) {
686 hideTransientIndicationDelayed(TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
687 }
688 }
689 if (showSwipeToUnlock) {
690 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWIPE_UP_TO_UNLOCK),
691 TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700692 }
693 }
694
695 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200696 public void onBiometricError(int msgId, String errString,
697 BiometricSourceType biometricSourceType) {
Lucas Dupin85ea4202019-11-04 16:01:51 -0800698 if (shouldSuppressBiometricError(msgId, biometricSourceType, mKeyguardUpdateMonitor)) {
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700699 return;
700 }
Lucas Dupine54ad1d2019-04-09 17:08:46 -0700701 animatePadlockError();
Lucas Dupinadce3532019-08-02 11:17:39 -0700702 if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
703 // The face timeout message is not very actionable, let's ask the user to
704 // manually retry.
705 showSwipeUpToUnlock();
706 } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
Lucas Dupine54ad1d2019-04-09 17:08:46 -0700707 mStatusBarKeyguardViewManager.showBouncerMessage(errString, mInitialTextColorState);
Lucas Dupin85ea4202019-11-04 16:01:51 -0800708 } else if (mKeyguardUpdateMonitor.isScreenOn()) {
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800709 showTransientIndication(errString);
Selim Cinek3e451942016-07-14 18:07:53 -0700710 // We want to keep this message around in case the screen was off
Adrian Roos56021892017-02-27 20:25:09 +0100711 hideTransientIndicationDelayed(HIDE_DELAY_MS);
Selim Cinek3e451942016-07-14 18:07:53 -0700712 } else {
713 mMessageToShowOnScreenOn = errString;
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700714 }
Lucas Dupine54ad1d2019-04-09 17:08:46 -0700715 }
716
717 private void animatePadlockError() {
Dave Mankoffc0d9a7d2020-02-27 17:15:52 -0500718 if (mLockIconController != null) {
719 mLockIconController.setTransientBiometricsError(true);
720 }
Lucas Dupine54ad1d2019-04-09 17:08:46 -0700721 mHandler.removeMessages(MSG_CLEAR_BIOMETRIC_MSG);
722 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_BIOMETRIC_MSG),
723 TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700724 }
725
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200726 private boolean shouldSuppressBiometricError(int msgId,
727 BiometricSourceType biometricSourceType, KeyguardUpdateMonitor updateMonitor) {
728 if (biometricSourceType == BiometricSourceType.FINGERPRINT)
729 return shouldSuppressFingerprintError(msgId, updateMonitor);
730 if (biometricSourceType == BiometricSourceType.FACE)
731 return shouldSuppressFaceError(msgId, updateMonitor);
732 return false;
733 }
734
735 private boolean shouldSuppressFingerprintError(int msgId,
736 KeyguardUpdateMonitor updateMonitor) {
Haining Chenc06c4812020-01-13 20:38:53 -0800737 // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
738 // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
739 // pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
740 // check of whether non-strong biometric is allowed
741 return ((!updateMonitor.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200742 && msgId != FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
743 || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED);
744 }
745
746 private boolean shouldSuppressFaceError(int msgId, KeyguardUpdateMonitor updateMonitor) {
Haining Chenc06c4812020-01-13 20:38:53 -0800747 // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
748 // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
749 // pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
750 // check of whether non-strong biometric is allowed
751 return ((!updateMonitor.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200752 && msgId != FaceManager.FACE_ERROR_LOCKOUT_PERMANENT)
753 || msgId == FaceManager.FACE_ERROR_CANCELED);
754 }
755
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700756 @Override
Lucas Dupinef886542018-01-03 16:03:07 -0800757 public void onTrustAgentErrorMessage(CharSequence message) {
Lucas Dupinaff42362020-03-27 16:28:20 -0700758 showTransientIndication(message, true /* isError */, false /* hideOnScreenOff */);
Lucas Dupinef886542018-01-03 16:03:07 -0800759 }
760
761 @Override
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700762 public void onScreenTurnedOn() {
763 if (mMessageToShowOnScreenOn != null) {
Lucas Dupinaff42362020-03-27 16:28:20 -0700764 showTransientIndication(mMessageToShowOnScreenOn, true /* isError */,
Lucas Dupin85ea4202019-11-04 16:01:51 -0800765 false /* hideOnScreenOff */);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700766 // We want to keep this message around in case the screen was off
Adrian Roos56021892017-02-27 20:25:09 +0100767 hideTransientIndicationDelayed(HIDE_DELAY_MS);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700768 mMessageToShowOnScreenOn = null;
769 }
770 }
771
772 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200773 public void onBiometricRunningStateChanged(boolean running,
774 BiometricSourceType biometricSourceType) {
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700775 if (running) {
Lucas Dupin8f3faac2019-03-12 15:28:49 -0700776 // Let's hide any previous messages when authentication starts, otherwise
777 // multiple auth attempts would overlap.
778 hideTransientIndication();
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700779 mMessageToShowOnScreenOn = null;
780 }
781 }
Selim Cinek3e451942016-07-14 18:07:53 -0700782
783 @Override
Haining Chenc06c4812020-01-13 20:38:53 -0800784 public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
785 boolean isStrongBiometric) {
786 super.onBiometricAuthenticated(userId, biometricSourceType, isStrongBiometric);
Kevin Chyn6d793bd2019-03-27 15:36:13 -0700787 mHandler.sendEmptyMessage(MSG_HIDE_TRANSIENT);
Selim Cinek3e451942016-07-14 18:07:53 -0700788 }
789
790 @Override
Lucas Dupin6c6d5732019-08-27 17:36:05 -0700791 public void onUserSwitchComplete(int userId) {
792 if (mVisible) {
793 updateIndication(false);
794 }
795 }
796
797 @Override
Jorim Jaggidadafd42016-09-30 07:20:25 -0700798 public void onUserUnlocked() {
799 if (mVisible) {
Beverly8c785892018-01-31 17:25:52 -0500800 updateIndication(false);
Jorim Jaggidadafd42016-09-30 07:20:25 -0700801 }
802 }
Lucas Dupin71d2fb22019-05-30 18:26:54 -0700803 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200804}