blob: 3d0c9e88ac9e91cc3b2a28a571c8243867e70520 [file] [log] [blame]
Jorim Jaggi27267d62015-04-28 13:27:12 -07001/*
2 * Copyright (C) 2015 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 Dupin1aec88f2019-05-01 22:25:22 -070019import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070020import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
21
Jorim Jaggi27267d62015-04-28 13:27:12 -070022import android.content.Context;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070023import android.content.res.ColorStateList;
Selim Cinek6ebba592016-05-31 15:28:28 -070024import android.content.res.Configuration;
Lucas Dupinc9e5d762019-01-28 09:34:30 -080025import android.content.res.TypedArray;
Lucas Dupinc90a6bf2018-10-10 13:53:20 -070026import android.graphics.Color;
Lucas Dupinf3b26292019-03-14 16:06:22 -070027import android.graphics.drawable.Animatable2;
Jorim Jaggi27267d62015-04-28 13:27:12 -070028import android.graphics.drawable.AnimatedVectorDrawable;
29import android.graphics.drawable.Drawable;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070030import android.hardware.biometrics.BiometricSourceType;
Lucas Dupin1aec88f2019-05-01 22:25:22 -070031import android.os.Handler;
Ianaee1b2a2019-05-10 16:48:22 -070032import android.os.Trace;
Jorim Jaggi27267d62015-04-28 13:27:12 -070033import android.util.AttributeSet;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070034import android.view.ViewGroup;
Selim Cinekc99d9a952015-06-19 18:44:50 -070035import android.view.accessibility.AccessibilityNodeInfo;
Jorim Jaggi27267d62015-04-28 13:27:12 -070036
Lucas Dupind7221352019-04-29 19:43:11 -070037import androidx.annotation.Nullable;
38
Lucas Dupinc90a6bf2018-10-10 13:53:20 -070039import com.android.internal.graphics.ColorUtils;
Lucas Dupinda069d72019-05-04 11:29:47 -070040import com.android.internal.telephony.IccCardConstants;
Jorim Jaggi27267d62015-04-28 13:27:12 -070041import com.android.keyguard.KeyguardUpdateMonitor;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070042import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jorim Jaggi27267d62015-04-28 13:27:12 -070043import com.android.systemui.R;
Lucas Dupind7221352019-04-29 19:43:11 -070044import com.android.systemui.dock.DockManager;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070045import com.android.systemui.plugins.statusbar.StatusBarStateController;
Jorim Jaggi27267d62015-04-28 13:27:12 -070046import com.android.systemui.statusbar.KeyguardAffordanceView;
Lucas Dupincdbb1cb2019-05-16 19:48:30 -070047import com.android.systemui.statusbar.phone.ScrimController.ScrimVisibility;
Jorim Jaggi27267d62015-04-28 13:27:12 -070048import com.android.systemui.statusbar.policy.AccessibilityController;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070049import com.android.systemui.statusbar.policy.ConfigurationController;
Lucas Dupin1cad65e2019-05-15 13:47:05 -070050import com.android.systemui.statusbar.policy.KeyguardMonitor;
Zachary Iqbalf50284c2017-01-22 18:54:46 -080051import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
Jorim Jaggi27267d62015-04-28 13:27:12 -070052
Lucas Dupin2e838ac2019-04-17 16:50:58 -070053import javax.inject.Inject;
54import javax.inject.Named;
55
Jorim Jaggi27267d62015-04-28 13:27:12 -070056/**
57 * Manages the different states and animations of the unlock icon.
58 */
Lucas Dupin2e838ac2019-04-17 16:50:58 -070059public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChangedListener,
60 StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
61 UnlockMethodCache.OnUnlockMethodChangedListener {
Jorim Jaggi27267d62015-04-28 13:27:12 -070062
Jorim Jaggi27267d62015-04-28 13:27:12 -070063 private static final int STATE_LOCKED = 0;
64 private static final int STATE_LOCK_OPEN = 1;
Lucas Dupinc2d11b32019-03-06 16:02:18 -080065 private static final int STATE_SCANNING_FACE = 2;
66 private static final int STATE_BIOMETRICS_ERROR = 3;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070067 private final ConfigurationController mConfigurationController;
68 private final StatusBarStateController mStatusBarStateController;
69 private final UnlockMethodCache mUnlockMethodCache;
70 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
71 private final AccessibilityController mAccessibilityController;
Lucas Dupind7221352019-04-29 19:43:11 -070072 private final DockManager mDockManager;
Lucas Dupin1aec88f2019-05-01 22:25:22 -070073 private final Handler mMainHandler;
Lucas Dupin1cad65e2019-05-15 13:47:05 -070074 private final KeyguardMonitor mKeyguardMonitor;
Jorim Jaggi27267d62015-04-28 13:27:12 -070075
76 private int mLastState = 0;
Lucas Dupinc9e5d762019-01-28 09:34:30 -080077 private boolean mTransientBiometricsError;
Lucas Dupinc9e5d762019-01-28 09:34:30 -080078 private boolean mIsFaceUnlockState;
Lucas Dupinda069d72019-05-04 11:29:47 -070079 private boolean mSimLocked;
Selim Cinek6ebba592016-05-31 15:28:28 -070080 private int mDensity;
Lucas Dupinf22194f2018-12-26 11:43:57 -080081 private boolean mPulsing;
82 private boolean mDozing;
Lucas Dupin05904652019-04-09 16:16:15 -070083 private boolean mBouncerVisible;
Lucas Dupind7221352019-04-29 19:43:11 -070084 private boolean mDocked;
Lucas Dupinc9e5d762019-01-28 09:34:30 -080085 private boolean mLastDozing;
86 private boolean mLastPulsing;
Lucas Dupin05904652019-04-09 16:16:15 -070087 private boolean mLastBouncerVisible;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070088 private int mIconColor;
Lucas Dupind7221352019-04-29 19:43:11 -070089 private float mDozeAmount;
Lucas Dupin1aec88f2019-05-01 22:25:22 -070090 private int mIconRes;
91 private boolean mWasPulsingOnThisFrame;
Lucas Dupin71f38042019-05-10 16:23:04 -070092 private boolean mWakeAndUnlockRunning;
Lucas Dupin1cad65e2019-05-15 13:47:05 -070093 private boolean mKeyguardShowing;
Lucas Dupin23964c72019-05-21 16:12:45 -070094 private boolean mShowingLaunchAffordance;
Jorim Jaggi27267d62015-04-28 13:27:12 -070095
Lucas Dupin1cad65e2019-05-15 13:47:05 -070096 private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
97 new KeyguardMonitor.Callback() {
98 @Override
99 public void onKeyguardShowingChanged() {
100 mKeyguardShowing = mKeyguardMonitor.isShowing();
101 update(false /* force */);
102 }
103 };
Lucas Dupind7221352019-04-29 19:43:11 -0700104 private final DockManager.DockEventListener mDockEventListener =
105 new DockManager.DockEventListener() {
106 @Override
107 public void onEvent(int event) {
108 boolean docked = event == DockManager.STATE_DOCKED
109 || event == DockManager.STATE_DOCKED_HIDE;
110 if (docked != mDocked) {
111 mDocked = docked;
112 update(true /* force */);
113 }
114 }
115 };
Jorim Jaggi8dea48c2016-11-28 14:47:45 +0100116
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700117 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
118 new KeyguardUpdateMonitorCallback() {
119 @Override
Lucas Dupinda069d72019-05-04 11:29:47 -0700120 public void onSimStateChanged(int subId, int slotId,
121 IccCardConstants.State simState) {
122 boolean oldSimLocked = mSimLocked;
123 mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure();
124 update(oldSimLocked != mSimLocked);
125 }
126
127 @Override
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700128 public void onKeyguardVisibilityChanged(boolean showing) {
129 update();
130 }
131
132 @Override
133 public void onBiometricRunningStateChanged(boolean running,
134 BiometricSourceType biometricSourceType) {
135 update();
136 }
137
138 @Override
139 public void onStrongAuthStateChanged(int userId) {
140 update();
141 }
142 };
143
144 @Inject
145 public LockIcon(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
146 StatusBarStateController statusBarStateController,
147 ConfigurationController configurationController,
Lucas Dupind7221352019-04-29 19:43:11 -0700148 AccessibilityController accessibilityController,
Lucas Dupin1cad65e2019-05-15 13:47:05 -0700149 KeyguardMonitor keyguardMonitor,
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700150 @Nullable DockManager dockManager,
151 @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
Jorim Jaggi27267d62015-04-28 13:27:12 -0700152 super(context, attrs);
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700153 mContext = context;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700154 mUnlockMethodCache = UnlockMethodCache.getInstance(context);
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700155 mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
156 mAccessibilityController = accessibilityController;
157 mConfigurationController = configurationController;
158 mStatusBarStateController = statusBarStateController;
Lucas Dupin1cad65e2019-05-15 13:47:05 -0700159 mKeyguardMonitor = keyguardMonitor;
Lucas Dupind7221352019-04-29 19:43:11 -0700160 mDockManager = dockManager;
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700161 mMainHandler = mainHandler;
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700162 }
163
164 @Override
165 protected void onAttachedToWindow() {
166 super.onAttachedToWindow();
167 mStatusBarStateController.addCallback(this);
168 mConfigurationController.addCallback(this);
Lucas Dupin1cad65e2019-05-15 13:47:05 -0700169 mKeyguardMonitor.addCallback(mKeyguardMonitorCallback);
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700170 mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
171 mUnlockMethodCache.addListener(this);
Lucas Dupinda069d72019-05-04 11:29:47 -0700172 mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure();
Lucas Dupind7221352019-04-29 19:43:11 -0700173 if (mDockManager != null) {
174 mDockManager.addListener(mDockEventListener);
175 }
Lucas Dupin12dab902019-04-19 11:10:48 -0700176 onThemeChanged();
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700177 }
178
179 @Override
180 protected void onDetachedFromWindow() {
181 super.onDetachedFromWindow();
182 mStatusBarStateController.removeCallback(this);
183 mConfigurationController.removeCallback(this);
184 mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
Lucas Dupin1cad65e2019-05-15 13:47:05 -0700185 mKeyguardMonitor.removeCallback(mKeyguardMonitorCallback);
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700186 mUnlockMethodCache.removeListener(this);
Lucas Dupind7221352019-04-29 19:43:11 -0700187 if (mDockManager != null) {
188 mDockManager.removeListener(mDockEventListener);
189 }
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700190 }
191
192 @Override
193 public void onThemeChanged() {
194 TypedArray typedArray = mContext.getTheme().obtainStyledAttributes(
195 null, new int[]{ R.attr.wallpaperTextColor }, 0, 0);
196 mIconColor = typedArray.getColor(0, Color.WHITE);
197 typedArray.recycle();
198 updateDarkTint();
Jorim Jaggi27267d62015-04-28 13:27:12 -0700199 }
200
201 @Override
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800202 public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800203 update();
204 }
205
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800206 /**
207 * If we're currently presenting an authentication error message.
208 */
209 public void setTransientBiometricsError(boolean transientBiometricsError) {
210 mTransientBiometricsError = transientBiometricsError;
Jorim Jaggi864e64b2015-05-20 14:13:23 -0700211 update();
212 }
213
Selim Cinek6ebba592016-05-31 15:28:28 -0700214 @Override
215 protected void onConfigurationChanged(Configuration newConfig) {
216 super.onConfigurationChanged(newConfig);
217 final int density = newConfig.densityDpi;
218 if (density != mDensity) {
219 mDensity = density;
Selim Cinek6ebba592016-05-31 15:28:28 -0700220 update();
221 }
222 }
223
Jorim Jaggi27267d62015-04-28 13:27:12 -0700224 public void update() {
Selim Cinek6ebba592016-05-31 15:28:28 -0700225 update(false /* force */);
226 }
227
228 public void update(boolean force) {
Jorim Jaggi27267d62015-04-28 13:27:12 -0700229 int state = getState();
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800230 mIsFaceUnlockState = state == STATE_SCANNING_FACE;
231 if (state != mLastState || mLastDozing != mDozing || mLastPulsing != mPulsing
Lucas Dupine24c0bf2019-06-07 11:44:28 -0700232 || mLastBouncerVisible != mBouncerVisible || force) {
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800233 int iconAnimRes = getAnimationResForTransition(mLastState, state, mLastPulsing,
Lucas Dupin05904652019-04-09 16:16:15 -0700234 mPulsing, mLastDozing, mDozing, mBouncerVisible);
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800235 boolean isAnim = iconAnimRes != -1;
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800236
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700237 int iconRes = isAnim ? iconAnimRes : getIconForState(state);
238 if (iconRes != mIconRes) {
239 mIconRes = iconRes;
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800240
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700241 Drawable icon = mContext.getDrawable(iconRes);
242 final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
243 ? (AnimatedVectorDrawable) icon
244 : null;
245 setImageDrawable(icon, false);
246 if (mIsFaceUnlockState) {
247 announceForAccessibility(getContext().getString(
248 R.string.accessibility_scanning_face));
249 }
Bingyu Zhangbfe6dcf2018-04-25 10:20:36 -0700250
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700251 if (animation != null && isAnim) {
252 animation.forceAnimationOnUI();
253 animation.clearAnimationCallbacks();
254 animation.registerAnimationCallback(new Animatable2.AnimationCallback() {
255 @Override
256 public void onAnimationEnd(Drawable drawable) {
257 if (getDrawable() == animation && state == getState()
258 && doesAnimationLoop(iconAnimRes)) {
259 animation.start();
Ianaee1b2a2019-05-10 16:48:22 -0700260 } else {
261 Trace.endAsyncSection("LockIcon#Animation", state);
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700262 }
Lucas Dupinf3b26292019-03-14 16:06:22 -0700263 }
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700264 });
Ianaee1b2a2019-05-10 16:48:22 -0700265 Trace.beginAsyncSection("LockIcon#Animation", state);
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700266 animation.start();
267 }
Jorim Jaggi27267d62015-04-28 13:27:12 -0700268 }
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700269 updateDarkTint();
Jorim Jaggi8dea48c2016-11-28 14:47:45 +0100270
Jorim Jaggi864e64b2015-05-20 14:13:23 -0700271 mLastState = state;
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800272 mLastDozing = mDozing;
273 mLastPulsing = mPulsing;
Lucas Dupin05904652019-04-09 16:16:15 -0700274 mLastBouncerVisible = mBouncerVisible;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700275 }
276
Lucas Dupin71f38042019-05-10 16:23:04 -0700277 boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
Lucas Dupin23964c72019-05-21 16:12:45 -0700278 boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning
279 || mShowingLaunchAffordance;
Lucas Dupind7221352019-04-29 19:43:11 -0700280 setVisibility(invisible ? INVISIBLE : VISIBLE);
Jorim Jaggi27267d62015-04-28 13:27:12 -0700281 updateClickability();
282 }
283
284 private void updateClickability() {
285 if (mAccessibilityController == null) {
286 return;
287 }
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800288 boolean canLock = mUnlockMethodCache.isMethodSecure()
289 && mUnlockMethodCache.canSkipBouncer();
Adrian Roosa94e9642017-08-17 17:29:19 +0200290 boolean clickToUnlock = mAccessibilityController.isAccessibilityEnabled();
Lucas Dupin0df60fe2019-04-23 10:19:27 -0700291 setClickable(clickToUnlock);
292 setLongClickable(canLock && !clickToUnlock);
Jorim Jaggi27267d62015-04-28 13:27:12 -0700293 setFocusable(mAccessibilityController.isAccessibilityEnabled());
294 }
295
Selim Cinekc99d9a952015-06-19 18:44:50 -0700296 @Override
297 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
298 super.onInitializeAccessibilityNodeInfo(info);
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700299 boolean fingerprintRunning = mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
300 boolean unlockingAllowed = mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed();
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800301 if (fingerprintRunning && unlockingAllowed) {
Selim Cinekc99d9a952015-06-19 18:44:50 -0700302 AccessibilityNodeInfo.AccessibilityAction unlock
303 = new AccessibilityNodeInfo.AccessibilityAction(
304 AccessibilityNodeInfo.ACTION_CLICK,
305 getContext().getString(R.string.accessibility_unlock_without_fingerprint));
306 info.addAction(unlock);
Selim Cinek947c77c2017-03-23 14:20:32 -0700307 info.setHintText(getContext().getString(
308 R.string.accessibility_waiting_for_fingerprint));
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800309 } else if (mIsFaceUnlockState) {
Bingyu Zhangbfe6dcf2018-04-25 10:20:36 -0700310 //Avoid 'button' to be spoken for scanning face
311 info.setClassName(LockIcon.class.getName());
312 info.setContentDescription(getContext().getString(
313 R.string.accessibility_scanning_face));
Selim Cinekc99d9a952015-06-19 18:44:50 -0700314 }
315 }
316
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700317 private int getIconForState(int state) {
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800318 int iconRes;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700319 switch (state) {
320 case STATE_LOCKED:
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800321 // Scanning animation is a pulsing padlock. This means that the resting state is
322 // just a padlock.
323 case STATE_SCANNING_FACE:
324 // Error animation also starts and ands on the padlock.
325 case STATE_BIOMETRICS_ERROR:
Lucas Dupince56d3b2019-03-07 13:02:25 -0800326 iconRes = com.android.internal.R.drawable.ic_lock;
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800327 break;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700328 case STATE_LOCK_OPEN:
Lucas Dupince56d3b2019-03-07 13:02:25 -0800329 iconRes = com.android.internal.R.drawable.ic_lock_open;
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800330 break;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700331 default:
332 throw new IllegalArgumentException();
333 }
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800334
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700335 return iconRes;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700336 }
337
Lucas Dupinf3b26292019-03-14 16:06:22 -0700338 private boolean doesAnimationLoop(int resourceId) {
339 return resourceId == com.android.internal.R.anim.lock_scanning;
340 }
341
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700342 private int getAnimationResForTransition(int oldState, int newState,
Lucas Dupin05904652019-04-09 16:16:15 -0700343 boolean wasPulsing, boolean pulsing, boolean wasDozing, boolean dozing,
344 boolean bouncerVisible) {
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800345
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800346 // Never animate when screen is off
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700347 if (dozing && !pulsing && !mWasPulsingOnThisFrame) {
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800348 return -1;
349 }
350
351 boolean isError = oldState != STATE_BIOMETRICS_ERROR && newState == STATE_BIOMETRICS_ERROR;
352 boolean justUnlocked = oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN;
353 boolean justLocked = oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED;
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700354 boolean nowPulsing = !wasPulsing && pulsing;
355 boolean turningOn = wasDozing && !dozing && !mWasPulsingOnThisFrame;
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800356
357 if (isError) {
358 return com.android.internal.R.anim.lock_to_error;
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800359 } else if (justUnlocked) {
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800360 return com.android.internal.R.anim.lock_unlock;
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800361 } else if (justLocked) {
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800362 return com.android.internal.R.anim.lock_lock;
Lucas Dupin05904652019-04-09 16:16:15 -0700363 } else if (newState == STATE_SCANNING_FACE && bouncerVisible) {
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800364 return com.android.internal.R.anim.lock_scanning;
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700365 } else if ((nowPulsing || turningOn) && newState != STATE_LOCK_OPEN) {
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800366 return com.android.internal.R.anim.lock_in;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700367 }
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800368 return -1;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700369 }
370
371 private int getState() {
Selim Cinek1fcafc42015-07-20 14:39:25 -0700372 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
Lucas Dupinc9e5d762019-01-28 09:34:30 -0800373 if (mTransientBiometricsError) {
374 return STATE_BIOMETRICS_ERROR;
Lucas Dupin1cad65e2019-05-15 13:47:05 -0700375 } else if ((mUnlockMethodCache.canSkipBouncer() || !mKeyguardShowing) && !mSimLocked) {
Selim Cinekc3841982015-08-25 18:34:29 -0700376 return STATE_LOCK_OPEN;
Lucas Dupin61de0cb2019-04-03 10:20:46 -0700377 } else if (updateMonitor.isFaceDetectionRunning()) {
Lucas Dupinc2d11b32019-03-06 16:02:18 -0800378 return STATE_SCANNING_FACE;
Jorim Jaggi27267d62015-04-28 13:27:12 -0700379 } else {
380 return STATE_LOCKED;
381 }
382 }
Lucas Dupinc90a6bf2018-10-10 13:53:20 -0700383
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700384 @Override
385 public void onDozeAmountChanged(float linear, float eased) {
386 mDozeAmount = eased;
Lucas Dupinc90a6bf2018-10-10 13:53:20 -0700387 updateDarkTint();
388 }
389
Lucas Dupinf22194f2018-12-26 11:43:57 -0800390 /**
391 * When keyguard is in pulsing (AOD2) state.
392 * @param pulsing {@code true} when pulsing.
Lucas Dupinf22194f2018-12-26 11:43:57 -0800393 */
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700394 public void setPulsing(boolean pulsing) {
Lucas Dupinf22194f2018-12-26 11:43:57 -0800395 mPulsing = pulsing;
Lucas Dupin1aec88f2019-05-01 22:25:22 -0700396 if (!mPulsing) {
397 mWasPulsingOnThisFrame = true;
398 mMainHandler.post(() -> {
399 mWasPulsingOnThisFrame = false;
400 });
401 }
Lucas Dupinf22194f2018-12-26 11:43:57 -0800402 update();
403 }
404
405 /**
406 * Sets the dozing state of the keyguard.
407 */
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700408 @Override
409 public void onDozingChanged(boolean dozing) {
Lucas Dupinf22194f2018-12-26 11:43:57 -0800410 mDozing = dozing;
411 update();
412 }
413
Lucas Dupinc90a6bf2018-10-10 13:53:20 -0700414 private void updateDarkTint() {
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700415 int color = ColorUtils.blendARGB(mIconColor, Color.WHITE, mDozeAmount);
416 setImageTintList(ColorStateList.valueOf(color));
Lucas Dupinc90a6bf2018-10-10 13:53:20 -0700417 }
Lucas Dupin05904652019-04-09 16:16:15 -0700418
419 /**
420 * If bouncer is visible or not.
421 */
422 public void setBouncerVisible(boolean bouncerVisible) {
423 if (mBouncerVisible == bouncerVisible) {
424 return;
425 }
426 mBouncerVisible = bouncerVisible;
427 update();
428 }
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700429
430 @Override
431 public void onDensityOrFontScaleChanged() {
432 ViewGroup.LayoutParams lp = getLayoutParams();
433 if (lp == null) {
434 return;
435 }
436 lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_lock_width);
437 lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_lock_height);
438 setLayoutParams(lp);
439 update(true /* force */);
440 }
441
442 @Override
443 public void onLocaleListChanged() {
444 setContentDescription(getContext().getText(R.string.accessibility_unlock_button));
445 update(true /* force */);
446 }
447
448 @Override
449 public void onUnlockMethodStateChanged() {
450 update();
451 }
Lucas Dupin71f38042019-05-10 16:23:04 -0700452
453 /**
454 * We need to hide the lock whenever there's a fingerprint unlock, otherwise you'll see the
455 * icon on top of the black front scrim.
456 */
457 public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
458 if (wakeAndUnlock) {
459 mWakeAndUnlockRunning = true;
460 }
461 update();
462 }
463
464 /**
Lucas Dupin23964c72019-05-21 16:12:45 -0700465 * When we're launching an affordance, like double pressing power to open camera.
466 */
467 public void onShowingLaunchAffordanceChanged(boolean showing) {
468 mShowingLaunchAffordance = showing;
469 update();
470 }
471
472 /**
Lucas Dupincdbb1cb2019-05-16 19:48:30 -0700473 * Called whenever the scrims become opaque, transparent or semi-transparent.
Lucas Dupin71f38042019-05-10 16:23:04 -0700474 */
Lucas Dupincdbb1cb2019-05-16 19:48:30 -0700475 public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) {
476 if (mWakeAndUnlockRunning
477 && scrimsVisible == ScrimController.VISIBILITY_FULLY_TRANSPARENT) {
478 mWakeAndUnlockRunning = false;
479 update();
480 }
Lucas Dupin71f38042019-05-10 16:23:04 -0700481 }
Jorim Jaggi27267d62015-04-28 13:27:12 -0700482}