1 /* 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 17 package com.android.systemui.statusbar.policy; 18 19 import static android.hardware.biometrics.BiometricSourceType.FACE; 20 21 import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE; 22 23 import android.annotation.NonNull; 24 import android.content.BroadcastReceiver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.hardware.biometrics.BiometricSourceType; 29 import android.os.Build; 30 import android.os.SystemProperties; 31 import android.os.Trace; 32 33 import androidx.annotation.VisibleForTesting; 34 35 import com.android.internal.widget.LockPatternUtils; 36 import com.android.keyguard.KeyguardUpdateMonitor; 37 import com.android.keyguard.KeyguardUpdateMonitorCallback; 38 import com.android.keyguard.logging.KeyguardUpdateMonitorLogger; 39 import com.android.systemui.Dumpable; 40 import com.android.systemui.R; 41 import com.android.systemui.dagger.SysUISingleton; 42 import com.android.systemui.dump.DumpManager; 43 import com.android.systemui.flags.FeatureFlags; 44 import com.android.systemui.keyguard.KeyguardUnlockAnimationController; 45 46 import dagger.Lazy; 47 48 import java.io.PrintWriter; 49 import java.util.ArrayList; 50 import java.util.Objects; 51 52 import javax.inject.Inject; 53 54 /** 55 * 56 */ 57 @SysUISingleton 58 public class KeyguardStateControllerImpl implements KeyguardStateController, Dumpable { 59 60 private static final boolean DEBUG_AUTH_WITH_ADB = false; 61 private static final String AUTH_BROADCAST_KEY = "debug_trigger_auth"; 62 63 private final ArrayList<Callback> mCallbacks = new ArrayList<>(); 64 private final Context mContext; 65 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; 66 private final LockPatternUtils mLockPatternUtils; 67 private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = 68 new UpdateMonitorCallback(); 69 private final Lazy<KeyguardUnlockAnimationController> mUnlockAnimationControllerLazy; 70 private final KeyguardUpdateMonitorLogger mLogger; 71 72 private boolean mCanDismissLockScreen; 73 private boolean mShowing; 74 private boolean mPrimaryBouncerShowing; 75 private boolean mSecure; 76 private boolean mOccluded; 77 78 private boolean mKeyguardFadingAway; 79 private long mKeyguardFadingAwayDelay; 80 private long mKeyguardFadingAwayDuration; 81 private boolean mKeyguardGoingAway; 82 private boolean mLaunchTransitionFadingAway; 83 private boolean mTrustManaged; 84 private boolean mTrusted; 85 private boolean mDebugUnlocked = false; 86 private boolean mFaceAuthEnabled; 87 88 private float mDismissAmount = 0f; 89 private boolean mDismissingFromTouch = false; 90 91 /** 92 * Whether the panel is currently flinging to a collapsed state, which means we're dismissing 93 * the keyguard. 94 */ 95 private boolean mFlingingToDismissKeyguard = false; 96 97 /** 98 * Whether the panel is currently flinging to a collapsed state, which means we're dismissing 99 * the keyguard, and the fling started during a swipe gesture. This means that we need to take 100 * over the gesture and animate the rest of the way dismissed. 101 */ 102 private boolean mFlingingToDismissKeyguardDuringSwipeGesture = false; 103 104 /** 105 * Whether the panel is currently flinging to an expanded state, which means we cancelled the 106 * dismiss gesture and are snapping back to the keyguard state. 107 */ 108 private boolean mSnappingKeyguardBackAfterSwipe = false; 109 110 private FeatureFlags mFeatureFlags; 111 112 /** 113 * 114 */ 115 @Inject KeyguardStateControllerImpl( Context context, KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils, Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController, KeyguardUpdateMonitorLogger logger, DumpManager dumpManager, FeatureFlags featureFlags)116 public KeyguardStateControllerImpl( 117 Context context, 118 KeyguardUpdateMonitor keyguardUpdateMonitor, 119 LockPatternUtils lockPatternUtils, 120 Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController, 121 KeyguardUpdateMonitorLogger logger, 122 DumpManager dumpManager, 123 FeatureFlags featureFlags) { 124 mContext = context; 125 mLogger = logger; 126 mKeyguardUpdateMonitor = keyguardUpdateMonitor; 127 mLockPatternUtils = lockPatternUtils; 128 mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); 129 mUnlockAnimationControllerLazy = keyguardUnlockAnimationController; 130 mFeatureFlags = featureFlags; 131 132 dumpManager.registerDumpable(getClass().getSimpleName(), this); 133 134 update(true /* updateAlways */); 135 if (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB) { 136 // Watch for interesting updates 137 final IntentFilter filter = new IntentFilter(); 138 filter.addAction(AUTH_BROADCAST_KEY); 139 context.registerReceiver(new BroadcastReceiver() { 140 @Override 141 public void onReceive(Context context, Intent intent) { 142 if (DEBUG_AUTH_WITH_ADB && AUTH_BROADCAST_KEY.equals(intent.getAction())) { 143 mDebugUnlocked = !mDebugUnlocked; 144 update(true /* updateAlways */); 145 } 146 } 147 }, filter, null, null, Context.RECEIVER_EXPORTED_UNAUDITED); 148 } 149 } 150 151 @Override addCallback(@onNull Callback callback)152 public void addCallback(@NonNull Callback callback) { 153 Objects.requireNonNull(callback, "Callback must not be null. b/128895449"); 154 if (!mCallbacks.contains(callback)) { 155 mCallbacks.add(callback); 156 } 157 } 158 159 @Override removeCallback(@onNull Callback callback)160 public void removeCallback(@NonNull Callback callback) { 161 Objects.requireNonNull(callback, "Callback must not be null. b/128895449"); 162 mCallbacks.remove(callback); 163 } 164 165 @Override isShowing()166 public boolean isShowing() { 167 return mShowing; 168 } 169 170 @Override isPrimaryBouncerShowing()171 public boolean isPrimaryBouncerShowing() { 172 return mPrimaryBouncerShowing; 173 } 174 175 @Override isMethodSecure()176 public boolean isMethodSecure() { 177 return mSecure; 178 } 179 180 @Override isOccluded()181 public boolean isOccluded() { 182 return mOccluded; 183 } 184 185 @Override isTrusted()186 public boolean isTrusted() { 187 return mTrusted; 188 } 189 190 @Override notifyKeyguardState(boolean showing, boolean occluded)191 public void notifyKeyguardState(boolean showing, boolean occluded) { 192 if (mShowing == showing && mOccluded == occluded) return; 193 mShowing = showing; 194 mOccluded = occluded; 195 mKeyguardUpdateMonitor.setKeyguardShowing(showing, occluded); 196 Trace.instantForTrack(Trace.TRACE_TAG_APP, "UI Events", 197 "Keyguard showing: " + showing + " occluded: " + occluded); 198 notifyKeyguardChanged(); 199 200 // Update the dismiss amount to the full 0f/1f if we explicitly show or hide the keyguard. 201 // Otherwise, the dismiss amount could be left at a random value if we show/hide during a 202 // dismiss gesture, canceling the gesture. 203 notifyKeyguardDismissAmountChanged(showing ? 0f : 1f, false); 204 } 205 notifyKeyguardChanged()206 private void notifyKeyguardChanged() { 207 Trace.beginSection("KeyguardStateController#notifyKeyguardChanged"); 208 // Copy the list to allow removal during callback. 209 new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged); 210 Trace.endSection(); 211 } 212 notifyKeyguardFaceAuthEnabledChanged()213 private void notifyKeyguardFaceAuthEnabledChanged() { 214 // Copy the list to allow removal during callback. 215 new ArrayList<>(mCallbacks).forEach(Callback::onFaceAuthEnabledChanged); 216 } 217 notifyUnlockedChanged()218 private void notifyUnlockedChanged() { 219 Trace.beginSection("KeyguardStateController#notifyUnlockedChanged"); 220 // Copy the list to allow removal during callback. 221 new ArrayList<>(mCallbacks).forEach(Callback::onUnlockedChanged); 222 Trace.endSection(); 223 } 224 225 @Override notifyKeyguardFadingAway(long delay, long fadeoutDuration)226 public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) { 227 mKeyguardFadingAwayDelay = delay; 228 mKeyguardFadingAwayDuration = fadeoutDuration; 229 setKeyguardFadingAway(true); 230 } 231 setKeyguardFadingAway(boolean keyguardFadingAway)232 private void setKeyguardFadingAway(boolean keyguardFadingAway) { 233 if (mKeyguardFadingAway != keyguardFadingAway) { 234 Trace.traceCounter(Trace.TRACE_TAG_APP, "keyguardFadingAway", 235 keyguardFadingAway ? 1 : 0); 236 mKeyguardFadingAway = keyguardFadingAway; 237 ArrayList<Callback> callbacks = new ArrayList<>(mCallbacks); 238 for (int i = 0; i < callbacks.size(); i++) { 239 callbacks.get(i).onKeyguardFadingAwayChanged(); 240 } 241 } 242 } 243 244 @Override notifyKeyguardDoneFading()245 public void notifyKeyguardDoneFading() { 246 notifyKeyguardGoingAway(false); 247 setKeyguardFadingAway(false); 248 } 249 250 @VisibleForTesting update(boolean updateAlways)251 void update(boolean updateAlways) { 252 Trace.beginSection("KeyguardStateController#update"); 253 int user = KeyguardUpdateMonitor.getCurrentUser(); 254 boolean secure = mLockPatternUtils.isSecure(user); 255 boolean canDismissLockScreen = !secure || mKeyguardUpdateMonitor.getUserCanSkipBouncer(user) 256 || (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked); 257 boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user); 258 boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user); 259 boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user); 260 boolean changed = secure != mSecure || canDismissLockScreen != mCanDismissLockScreen 261 || trustManaged != mTrustManaged || mTrusted != trusted 262 || mFaceAuthEnabled != faceAuthEnabled; 263 if (changed || updateAlways) { 264 mSecure = secure; 265 mCanDismissLockScreen = canDismissLockScreen; 266 mTrusted = trusted; 267 mTrustManaged = trustManaged; 268 mFaceAuthEnabled = faceAuthEnabled; 269 mLogger.logKeyguardStateUpdate( 270 mSecure, mCanDismissLockScreen, mTrusted, mTrustManaged); 271 notifyUnlockedChanged(); 272 } 273 Trace.endSection(); 274 } 275 276 @Override canDismissLockScreen()277 public boolean canDismissLockScreen() { 278 return mCanDismissLockScreen; 279 } 280 281 @Override isKeyguardScreenRotationAllowed()282 public boolean isKeyguardScreenRotationAllowed() { 283 return SystemProperties.getBoolean("lockscreen.rot_override", false) 284 || mContext.getResources().getBoolean(R.bool.config_enableLockScreenRotation) 285 || mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE); 286 } 287 288 @Override isFaceAuthEnabled()289 public boolean isFaceAuthEnabled() { 290 return mFaceAuthEnabled; 291 } 292 293 @Override isKeyguardFadingAway()294 public boolean isKeyguardFadingAway() { 295 return mKeyguardFadingAway; 296 } 297 298 @Override isKeyguardGoingAway()299 public boolean isKeyguardGoingAway() { 300 return mKeyguardGoingAway; 301 } 302 303 @Override isAnimatingBetweenKeyguardAndSurfaceBehind()304 public boolean isAnimatingBetweenKeyguardAndSurfaceBehind() { 305 return mUnlockAnimationControllerLazy.get().isAnimatingBetweenKeyguardAndSurfaceBehind(); 306 } 307 308 @Override getKeyguardFadingAwayDelay()309 public long getKeyguardFadingAwayDelay() { 310 return mKeyguardFadingAwayDelay; 311 } 312 313 @Override getKeyguardFadingAwayDuration()314 public long getKeyguardFadingAwayDuration() { 315 return mKeyguardFadingAwayDuration; 316 } 317 318 @Override calculateGoingToFullShadeDelay()319 public long calculateGoingToFullShadeDelay() { 320 return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration; 321 } 322 323 @Override isFlingingToDismissKeyguard()324 public boolean isFlingingToDismissKeyguard() { 325 return mFlingingToDismissKeyguard; 326 } 327 328 @Override isFlingingToDismissKeyguardDuringSwipeGesture()329 public boolean isFlingingToDismissKeyguardDuringSwipeGesture() { 330 return mFlingingToDismissKeyguardDuringSwipeGesture; 331 } 332 333 @Override isSnappingKeyguardBackAfterSwipe()334 public boolean isSnappingKeyguardBackAfterSwipe() { 335 return mSnappingKeyguardBackAfterSwipe; 336 } 337 338 @Override getDismissAmount()339 public float getDismissAmount() { 340 return mDismissAmount; 341 } 342 343 @Override isDismissingFromSwipe()344 public boolean isDismissingFromSwipe() { 345 return mDismissingFromTouch; 346 } 347 348 @Override notifyKeyguardGoingAway(boolean keyguardGoingAway)349 public void notifyKeyguardGoingAway(boolean keyguardGoingAway) { 350 if (mKeyguardGoingAway != keyguardGoingAway) { 351 Trace.traceCounter(Trace.TRACE_TAG_APP, "keyguardGoingAway", 352 keyguardGoingAway ? 1 : 0); 353 mKeyguardGoingAway = keyguardGoingAway; 354 new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardGoingAwayChanged); 355 } 356 } 357 358 @Override notifyPrimaryBouncerShowing(boolean showing)359 public void notifyPrimaryBouncerShowing(boolean showing) { 360 if (mPrimaryBouncerShowing != showing) { 361 mPrimaryBouncerShowing = showing; 362 363 new ArrayList<>(mCallbacks).forEach(Callback::onPrimaryBouncerShowingChanged); 364 } 365 } 366 367 @Override notifyPanelFlingEnd()368 public void notifyPanelFlingEnd() { 369 mFlingingToDismissKeyguard = false; 370 mFlingingToDismissKeyguardDuringSwipeGesture = false; 371 mSnappingKeyguardBackAfterSwipe = false; 372 } 373 374 @Override notifyPanelFlingStart(boolean flingToDismiss)375 public void notifyPanelFlingStart(boolean flingToDismiss) { 376 mFlingingToDismissKeyguard = flingToDismiss; 377 mFlingingToDismissKeyguardDuringSwipeGesture = 378 flingToDismiss && mDismissingFromTouch; 379 mSnappingKeyguardBackAfterSwipe = !flingToDismiss; 380 } 381 382 @Override notifyKeyguardDismissAmountChanged(float dismissAmount, boolean dismissingFromTouch)383 public void notifyKeyguardDismissAmountChanged(float dismissAmount, 384 boolean dismissingFromTouch) { 385 mDismissAmount = dismissAmount; 386 mDismissingFromTouch = dismissingFromTouch; 387 new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardDismissAmountChanged); 388 } 389 390 @Override setLaunchTransitionFadingAway(boolean fadingAway)391 public void setLaunchTransitionFadingAway(boolean fadingAway) { 392 mLaunchTransitionFadingAway = fadingAway; 393 new ArrayList<>(mCallbacks).forEach(Callback::onLaunchTransitionFadingAwayChanged); 394 } 395 396 @Override isLaunchTransitionFadingAway()397 public boolean isLaunchTransitionFadingAway() { 398 return mLaunchTransitionFadingAway; 399 } 400 401 /** 402 * Dumps internal state for debugging. 403 * @param pw Where to dump. 404 */ 405 @Override dump(PrintWriter pw, String[] args)406 public void dump(PrintWriter pw, String[] args) { 407 pw.println("KeyguardStateController:"); 408 pw.println(" mShowing: " + mShowing); 409 pw.println(" mOccluded: " + mOccluded); 410 pw.println(" mSecure: " + mSecure); 411 pw.println(" mCanDismissLockScreen: " + mCanDismissLockScreen); 412 pw.println(" mTrustManaged: " + mTrustManaged); 413 pw.println(" mTrusted: " + mTrusted); 414 pw.println(" mDebugUnlocked: " + mDebugUnlocked); 415 pw.println(" mFaceAuthEnabled: " + mFaceAuthEnabled); 416 pw.println(" isKeyguardFadingAway: " + isKeyguardFadingAway()); 417 pw.println(" isKeyguardGoingAway: " + isKeyguardGoingAway()); 418 pw.println(" isLaunchTransitionFadingAway: " + isLaunchTransitionFadingAway()); 419 } 420 421 private class UpdateMonitorCallback extends KeyguardUpdateMonitorCallback { 422 @Override onUserSwitchComplete(int userId)423 public void onUserSwitchComplete(int userId) { 424 update(false /* updateAlways */); 425 } 426 427 @Override onTrustChanged(int userId)428 public void onTrustChanged(int userId) { 429 update(false /* updateAlways */); 430 notifyKeyguardChanged(); 431 } 432 433 @Override onTrustManagedChanged(int userId)434 public void onTrustManagedChanged(int userId) { 435 update(false /* updateAlways */); 436 } 437 438 @Override onBiometricEnrollmentStateChanged(BiometricSourceType biometricSourceType)439 public void onBiometricEnrollmentStateChanged(BiometricSourceType biometricSourceType) { 440 if (biometricSourceType == FACE) { 441 // We only care about enrollment state here. Keyguard face auth enabled is just 442 // same as face auth enrolled 443 update(false); 444 notifyKeyguardFaceAuthEnabledChanged(); 445 } 446 } 447 448 @Override onStartedWakingUp()449 public void onStartedWakingUp() { 450 update(false /* updateAlways */); 451 } 452 453 @Override onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric)454 public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType, 455 boolean isStrongBiometric) { 456 Trace.beginSection("KeyguardUpdateMonitorCallback#onBiometricAuthenticated"); 457 if (mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric)) { 458 update(false /* updateAlways */); 459 } 460 Trace.endSection(); 461 } 462 463 @Override onStrongAuthStateChanged(int userId)464 public void onStrongAuthStateChanged(int userId) { 465 update(false /* updateAlways */); 466 } 467 468 @Override onLockedOutStateChanged(BiometricSourceType biometricSourceType)469 public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) { 470 update(false /* updateAlways */); 471 } 472 473 @Override onKeyguardVisibilityChanged(boolean visible)474 public void onKeyguardVisibilityChanged(boolean visible) { 475 update(false /* updateAlways */); 476 } 477 478 @Override onBiometricsCleared()479 public void onBiometricsCleared() { 480 update(false /* alwaysUpdate */); 481 } 482 483 @Override onEnabledTrustAgentsChanged(int userId)484 public void onEnabledTrustAgentsChanged(int userId) { 485 update(false /* updateAlways */); 486 } 487 } 488 } 489