1 /* 2 * Copyright (C) 2020 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.keyguard; 18 19 import static android.app.StatusBarManager.SESSION_KEYGUARD; 20 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 21 22 import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISSIBLE_KEYGUARD; 23 import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC; 24 import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS; 25 import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_NONE_SECURITY; 26 import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_PASSWORD; 27 import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_SIM; 28 import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_PRIMARY; 29 import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_SECONDARY_USER; 30 import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE; 31 import static com.android.keyguard.KeyguardSecurityModel.SecurityMode.SimPin; 32 import static com.android.keyguard.KeyguardSecurityModel.SecurityMode.SimPuk; 33 import static com.android.systemui.DejankUtils.whitelistIpcs; 34 import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE; 35 36 import android.app.ActivityManager; 37 import android.app.admin.DevicePolicyManager; 38 import android.app.admin.flags.Flags; 39 import android.content.Intent; 40 import android.content.res.ColorStateList; 41 import android.content.res.Configuration; 42 import android.content.res.Resources; 43 import android.media.AudioManager; 44 import android.metrics.LogMaker; 45 import android.os.SystemClock; 46 import android.os.UserHandle; 47 import android.telephony.TelephonyManager; 48 import android.text.TextUtils; 49 import android.util.Log; 50 import android.util.MathUtils; 51 import android.util.Slog; 52 import android.view.KeyEvent; 53 import android.view.MotionEvent; 54 import android.view.View; 55 import android.view.ViewTreeObserver; 56 import android.widget.FrameLayout; 57 import android.window.OnBackAnimationCallback; 58 59 import androidx.annotation.NonNull; 60 import androidx.annotation.Nullable; 61 62 import com.android.internal.annotations.VisibleForTesting; 63 import com.android.internal.logging.InstanceId; 64 import com.android.internal.logging.MetricsLogger; 65 import com.android.internal.logging.UiEventLogger; 66 import com.android.internal.logging.nano.MetricsProto; 67 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 68 import com.android.internal.widget.LockPatternUtils; 69 import com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent; 70 import com.android.keyguard.KeyguardSecurityContainer.SwipeListener; 71 import com.android.keyguard.KeyguardSecurityModel.SecurityMode; 72 import com.android.keyguard.dagger.KeyguardBouncerScope; 73 import com.android.settingslib.utils.ThreadUtils; 74 import com.android.systemui.Gefingerpoken; 75 import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate; 76 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor; 77 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; 78 import com.android.systemui.classifier.FalsingA11yDelegate; 79 import com.android.systemui.classifier.FalsingCollector; 80 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor; 81 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor; 82 import com.android.systemui.flags.FeatureFlags; 83 import com.android.systemui.keyguard.KeyguardWmStateRefactor; 84 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; 85 import com.android.systemui.log.SessionTracker; 86 import com.android.systemui.plugins.ActivityStarter; 87 import com.android.systemui.plugins.FalsingManager; 88 import com.android.systemui.res.R; 89 import com.android.systemui.scene.shared.flag.SceneContainerFlag; 90 import com.android.systemui.shared.system.SysUiStatsLog; 91 import com.android.systemui.statusbar.policy.ConfigurationController; 92 import com.android.systemui.statusbar.policy.DeviceProvisionedController; 93 import com.android.systemui.statusbar.policy.KeyguardStateController; 94 import com.android.systemui.statusbar.policy.UserSwitcherController; 95 import com.android.systemui.user.domain.interactor.SelectedUserInteractor; 96 import com.android.systemui.util.ViewController; 97 import com.android.systemui.util.kotlin.JavaAdapter; 98 import com.android.systemui.util.settings.GlobalSettings; 99 100 import dagger.Lazy; 101 102 import kotlinx.coroutines.Job; 103 104 import java.io.File; 105 import java.util.Arrays; 106 107 import javax.inject.Inject; 108 import javax.inject.Provider; 109 110 /** Controller for {@link KeyguardSecurityContainer} */ 111 @KeyguardBouncerScope 112 public class KeyguardSecurityContainerController extends ViewController<KeyguardSecurityContainer> 113 implements KeyguardSecurityView { 114 115 private static final boolean DEBUG = KeyguardConstants.DEBUG; 116 private static final String TAG = "KeyguardSecurityView"; 117 118 private final AdminSecondaryLockScreenController mAdminSecondaryLockScreenController; 119 private final LockPatternUtils mLockPatternUtils; 120 private final KeyguardUpdateMonitor mUpdateMonitor; 121 private final KeyguardSecurityModel mSecurityModel; 122 private final MetricsLogger mMetricsLogger; 123 private final UiEventLogger mUiEventLogger; 124 private final KeyguardStateController mKeyguardStateController; 125 private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController; 126 private final ConfigurationController mConfigurationController; 127 private final FalsingCollector mFalsingCollector; 128 private final FalsingManager mFalsingManager; 129 private final UserSwitcherController mUserSwitcherController; 130 private final GlobalSettings mGlobalSettings; 131 private final FeatureFlags mFeatureFlags; 132 private final SessionTracker mSessionTracker; 133 private final FalsingA11yDelegate mFalsingA11yDelegate; 134 private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor; 135 private final BouncerMessageInteractor mBouncerMessageInteractor; 136 private int mTranslationY; 137 private final KeyguardTransitionInteractor mKeyguardTransitionInteractor; 138 private final DevicePolicyManager mDevicePolicyManager; 139 // Whether the volume keys should be handled by keyguard. If true, then 140 // they will be handled here for specific media types such as music, otherwise 141 // the audio service will bring up the volume dialog. 142 private static final boolean KEYGUARD_MANAGES_VOLUME = false; 143 144 private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key"; 145 146 private final TelephonyManager mTelephonyManager; 147 private final ViewMediatorCallback mViewMediatorCallback; 148 private final AudioManager mAudioManager; 149 private View.OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event); 150 private ActivityStarter.OnDismissAction mDismissAction; 151 private Runnable mCancelAction; 152 private boolean mWillRunDismissFromKeyguard; 153 154 private int mLastOrientation; 155 156 private SecurityMode mCurrentSecurityMode = SecurityMode.Invalid; 157 private int mCurrentUser = UserHandle.USER_NULL; 158 private UserSwitcherController.UserSwitchCallback mUserSwitchCallback = 159 new UserSwitcherController.UserSwitchCallback() { 160 @Override 161 public void onUserSwitched() { 162 if (mCurrentUser == mSelectedUserInteractor.getSelectedUserId()) { 163 return; 164 } 165 mCurrentUser = mSelectedUserInteractor.getSelectedUserId(); 166 showPrimarySecurityScreen(false); 167 if (mCurrentSecurityMode != SimPin 168 && mCurrentSecurityMode != SimPuk) { 169 reinflateViewFlipper((l) -> { 170 }); 171 } 172 } 173 }; 174 175 @VisibleForTesting 176 final Gefingerpoken mGlobalTouchListener = new Gefingerpoken() { 177 private MotionEvent mTouchDown; 178 179 @Override 180 public boolean onInterceptTouchEvent(MotionEvent ev) { 181 return false; 182 } 183 184 @Override 185 public boolean onTouchEvent(MotionEvent ev) { 186 // Do just a bit of our own falsing. People should only be tapping on the input, not 187 // swiping. 188 if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { 189 // If we're in one handed mode, the user can tap on the opposite side of the screen 190 // to move the bouncer across. In that case, inhibit the falsing (otherwise the taps 191 // to move the bouncer to each screen side can end up closing it instead). 192 if (mView.isTouchOnTheOtherSideOfSecurity(ev)) { 193 mFalsingCollector.avoidGesture(); 194 } 195 196 if (mTouchDown != null) { 197 mTouchDown.recycle(); 198 mTouchDown = null; 199 } 200 mTouchDown = MotionEvent.obtain(ev); 201 } else if (mTouchDown != null) { 202 if (ev.getActionMasked() == MotionEvent.ACTION_UP 203 || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) { 204 mTouchDown.recycle(); 205 mTouchDown = null; 206 } 207 } 208 return false; 209 } 210 }; 211 212 private KeyguardSecurityCallback mKeyguardSecurityCallback = new KeyguardSecurityCallback() { 213 @Override 214 public void onUserInput() { 215 mBouncerMessageInteractor.onPrimaryBouncerUserInput(); 216 mDeviceEntryFaceAuthInteractor.onPrimaryBouncerUserInput(); 217 } 218 219 @Override 220 public void dismiss(boolean authenticated, int targetId, 221 SecurityMode expectedSecurityMode) { 222 dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false, 223 expectedSecurityMode); 224 } 225 226 @Override 227 public boolean dismiss(boolean authenticated, int targetId, 228 boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { 229 return showNextSecurityScreenOrFinish( 230 authenticated, targetId, bypassSecondaryLockScreen, expectedSecurityMode); 231 } 232 233 @Override 234 public void userActivity() { 235 mViewMediatorCallback.userActivity(); 236 } 237 238 @Override 239 public boolean isVerifyUnlockOnly() { 240 return false; 241 } 242 243 @Override 244 public void onAttemptLockoutStart(long seconds) { 245 mBouncerMessageInteractor.onPrimaryAuthLockedOut(seconds); 246 } 247 248 @Override 249 public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { 250 if (timeoutMs == 0 && !success) { 251 mBouncerMessageInteractor.onPrimaryAuthIncorrectAttempt(); 252 } 253 int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT; 254 if (mView.isSidedSecurityMode()) { 255 bouncerSide = mView.isSecurityLeftAligned() 256 ? SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__LEFT 257 : SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__RIGHT; 258 } 259 260 if (success) { 261 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED, 262 SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__SUCCESS, 263 bouncerSide); 264 mLockPatternUtils.reportSuccessfulPasswordAttempt(userId); 265 // Force a garbage collection in an attempt to erase any lockscreen password left in 266 // memory. Do it asynchronously with a 5-sec delay to avoid making the keyguard 267 // dismiss animation janky. 268 ThreadUtils.postOnBackgroundThread(() -> { 269 try { 270 Thread.sleep(5000); 271 } catch (InterruptedException ignored) { 272 } 273 System.gc(); 274 System.runFinalization(); 275 System.gc(); 276 }); 277 } else { 278 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED, 279 SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__FAILURE, 280 bouncerSide); 281 reportFailedUnlockAttempt(userId, timeoutMs); 282 } 283 mMetricsLogger.write(new LogMaker(MetricsEvent.BOUNCER) 284 .setType(success ? MetricsEvent.TYPE_SUCCESS : MetricsEvent.TYPE_FAILURE)); 285 mUiEventLogger.log(success ? BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS 286 : BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, getSessionId()); 287 } 288 289 @Override 290 public void reset() { 291 mViewMediatorCallback.resetKeyguard(); 292 } 293 294 @Override 295 public void onCancelClicked() { 296 mViewMediatorCallback.onCancelClicked(); 297 } 298 299 /** 300 * Authentication has happened and it's time to dismiss keyguard. This function 301 * should clean up and inform KeyguardViewMediator. 302 * 303 * @param targetUserId a user that needs to be the foreground user at the dismissal 304 * completion. 305 */ 306 @Override 307 public void finish(int targetUserId) { 308 if (!SceneContainerFlag.isEnabled()) { 309 // If there's a pending runnable because the user interacted with a widget 310 // and we're leaving keyguard, then run it. 311 boolean deferKeyguardDone = false; 312 mWillRunDismissFromKeyguard = false; 313 if (mDismissAction != null) { 314 deferKeyguardDone = mDismissAction.onDismiss(); 315 mWillRunDismissFromKeyguard = mDismissAction.willRunAnimationOnKeyguard(); 316 mDismissAction = null; 317 mCancelAction = null; 318 } 319 if (mViewMediatorCallback != null) { 320 if (deferKeyguardDone) { 321 mViewMediatorCallback.keyguardDonePending(targetUserId); 322 } else { 323 mViewMediatorCallback.keyguardDone(targetUserId); 324 } 325 } 326 } 327 328 if (KeyguardWmStateRefactor.isEnabled()) { 329 mKeyguardTransitionInteractor.startDismissKeyguardTransition( 330 "KeyguardSecurityContainerController#finish"); 331 } 332 } 333 334 @Override 335 public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) { 336 mViewMediatorCallback.setNeedsInput(needsInput); 337 } 338 339 @Override 340 public void showCurrentSecurityScreen() { 341 showPrimarySecurityScreen(false); 342 } 343 }; 344 345 private final SwipeListener mSwipeListener = new SwipeListener() { 346 @Override 347 public void onSwipeUp() { 348 if (mDeviceEntryFaceAuthInteractor.canFaceAuthRun()) { 349 mKeyguardSecurityCallback.userActivity(); 350 } 351 mDeviceEntryFaceAuthInteractor.onSwipeUpOnBouncer(); 352 if (mDeviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()) { 353 mUpdateMonitor.requestActiveUnlock( 354 ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT_LEGACY, 355 "swipeUpOnBouncer"); 356 } 357 } 358 359 @Override 360 public void onSwipeDown() { 361 mViewMediatorCallback.onBouncerSwipeDown(); 362 } 363 }; 364 private final ConfigurationController.ConfigurationListener mConfigurationListener = 365 new ConfigurationController.ConfigurationListener() { 366 @Override 367 public void onThemeChanged() { 368 reloadColors(); 369 } 370 371 @Override 372 public void onUiModeChanged() { 373 reloadColors(); 374 } 375 376 @Override 377 public void onDensityOrFontScaleChanged() { 378 KeyguardSecurityContainerController.this 379 .onDensityOrFontScaleOrOrientationChanged(); 380 } 381 382 @Override 383 public void onOrientationChanged(int orientation) { 384 if (mFeatureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE) 385 && getResources().getBoolean(R.bool.update_bouncer_constraints)) { 386 boolean useSplitBouncer = orientation == ORIENTATION_LANDSCAPE; 387 mSecurityViewFlipperController.updateConstraints(useSplitBouncer); 388 } 389 } 390 391 @Override 392 public void onConfigChanged(Configuration newConfig) { 393 configureMode(); 394 } 395 }; 396 private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = 397 new KeyguardUpdateMonitorCallback() { 398 @Override 399 public void onTrustGrantedForCurrentUser( 400 boolean dismissKeyguard, 401 boolean newlyUnlocked, 402 TrustGrantFlags flags, 403 String message 404 ) { 405 if (dismissKeyguard) { 406 if (!mView.isVisibleToUser()) { 407 // The trust agent dismissed the keyguard without the user proving 408 // that they are present (by swiping up to show the bouncer). That's 409 // fine if the user proved presence via some other way to the trust 410 // agent. 411 Log.i(TAG, "TrustAgent dismissed Keyguard."); 412 } 413 mKeyguardSecurityCallback.dismiss( 414 false /* authenticated */, 415 mSelectedUserInteractor.getSelectedUserId(), 416 /* bypassSecondaryLockScreen */ false, 417 SecurityMode.Invalid 418 ); 419 } else { 420 if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) { 421 mViewMediatorCallback.playTrustedSound(); 422 } 423 } 424 } 425 426 @Override 427 public void onDevicePolicyManagerStateChanged() { 428 showPrimarySecurityScreen(false); 429 } 430 }; 431 private final SelectedUserInteractor mSelectedUserInteractor; 432 private final Provider<DeviceEntryInteractor> mDeviceEntryInteractor; 433 private final Provider<JavaAdapter> mJavaAdapter; 434 private final DeviceProvisionedController mDeviceProvisionedController; 435 private final Lazy<PrimaryBouncerInteractor> mPrimaryBouncerInteractor; 436 @Nullable 437 private Job mSceneTransitionCollectionJob; 438 439 @Inject KeyguardSecurityContainerController(KeyguardSecurityContainer view, AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory, LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor keyguardUpdateMonitor, KeyguardSecurityModel keyguardSecurityModel, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, KeyguardStateController keyguardStateController, KeyguardSecurityViewFlipperController securityViewFlipperController, ConfigurationController configurationController, FalsingCollector falsingCollector, FalsingManager falsingManager, UserSwitcherController userSwitcherController, FeatureFlags featureFlags, GlobalSettings globalSettings, SessionTracker sessionTracker, FalsingA11yDelegate falsingA11yDelegate, TelephonyManager telephonyManager, ViewMediatorCallback viewMediatorCallback, AudioManager audioManager, DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor, BouncerMessageInteractor bouncerMessageInteractor, Provider<JavaAdapter> javaAdapter, SelectedUserInteractor selectedUserInteractor, DeviceProvisionedController deviceProvisionedController, FaceAuthAccessibilityDelegate faceAuthAccessibilityDelegate, DevicePolicyManager devicePolicyManager, KeyguardTransitionInteractor keyguardTransitionInteractor, Lazy<PrimaryBouncerInteractor> primaryBouncerInteractor, Provider<DeviceEntryInteractor> deviceEntryInteractor )440 public KeyguardSecurityContainerController(KeyguardSecurityContainer view, 441 AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory, 442 LockPatternUtils lockPatternUtils, 443 KeyguardUpdateMonitor keyguardUpdateMonitor, 444 KeyguardSecurityModel keyguardSecurityModel, 445 MetricsLogger metricsLogger, 446 UiEventLogger uiEventLogger, 447 KeyguardStateController keyguardStateController, 448 KeyguardSecurityViewFlipperController securityViewFlipperController, 449 ConfigurationController configurationController, 450 FalsingCollector falsingCollector, 451 FalsingManager falsingManager, 452 UserSwitcherController userSwitcherController, 453 FeatureFlags featureFlags, 454 GlobalSettings globalSettings, 455 SessionTracker sessionTracker, 456 FalsingA11yDelegate falsingA11yDelegate, 457 TelephonyManager telephonyManager, 458 ViewMediatorCallback viewMediatorCallback, 459 AudioManager audioManager, 460 DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor, 461 BouncerMessageInteractor bouncerMessageInteractor, 462 Provider<JavaAdapter> javaAdapter, 463 SelectedUserInteractor selectedUserInteractor, 464 DeviceProvisionedController deviceProvisionedController, 465 FaceAuthAccessibilityDelegate faceAuthAccessibilityDelegate, 466 DevicePolicyManager devicePolicyManager, 467 KeyguardTransitionInteractor keyguardTransitionInteractor, 468 Lazy<PrimaryBouncerInteractor> primaryBouncerInteractor, 469 Provider<DeviceEntryInteractor> deviceEntryInteractor 470 ) { 471 super(view); 472 view.setAccessibilityDelegate(faceAuthAccessibilityDelegate); 473 mLockPatternUtils = lockPatternUtils; 474 mUpdateMonitor = keyguardUpdateMonitor; 475 mSecurityModel = keyguardSecurityModel; 476 mMetricsLogger = metricsLogger; 477 mUiEventLogger = uiEventLogger; 478 mKeyguardStateController = keyguardStateController; 479 mSecurityViewFlipperController = securityViewFlipperController; 480 mAdminSecondaryLockScreenController = adminSecondaryLockScreenControllerFactory.create( 481 mKeyguardSecurityCallback); 482 mConfigurationController = configurationController; 483 mLastOrientation = getResources().getConfiguration().orientation; 484 mFalsingCollector = falsingCollector; 485 mFalsingManager = falsingManager; 486 mUserSwitcherController = userSwitcherController; 487 mFeatureFlags = featureFlags; 488 mGlobalSettings = globalSettings; 489 mSessionTracker = sessionTracker; 490 mFalsingA11yDelegate = falsingA11yDelegate; 491 mTelephonyManager = telephonyManager; 492 mViewMediatorCallback = viewMediatorCallback; 493 mAudioManager = audioManager; 494 mDeviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor; 495 mBouncerMessageInteractor = bouncerMessageInteractor; 496 mSelectedUserInteractor = selectedUserInteractor; 497 mDeviceEntryInteractor = deviceEntryInteractor; 498 mJavaAdapter = javaAdapter; 499 mKeyguardTransitionInteractor = keyguardTransitionInteractor; 500 mDeviceProvisionedController = deviceProvisionedController; 501 mPrimaryBouncerInteractor = primaryBouncerInteractor; 502 mDevicePolicyManager = devicePolicyManager; 503 } 504 505 @Override onInit()506 public void onInit() { 507 mSecurityViewFlipperController.init(); 508 updateResources(); 509 configureMode(); 510 } 511 512 @Override onViewAttached()513 protected void onViewAttached() { 514 mUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); 515 mView.setSwipeListener(mSwipeListener); 516 mView.addMotionEventListener(mGlobalTouchListener); 517 mConfigurationController.addCallback(mConfigurationListener); 518 mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback); 519 mView.setViewMediatorCallback(mViewMediatorCallback); 520 // Update ViewMediator with the current input method requirements 521 mViewMediatorCallback.setNeedsInput(needsInput()); 522 mView.setOnKeyListener(mOnKeyListener); 523 524 showPrimarySecurityScreen(false); 525 526 if (SceneContainerFlag.isEnabled()) { 527 // When the scene framework says that the lockscreen has been dismissed, dismiss the 528 // keyguard here, revealing the underlying app or launcher: 529 mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow( 530 mDeviceEntryInteractor.get().isDeviceEntered(), 531 isDeviceEntered -> { 532 if (isDeviceEntered) { 533 final int selectedUserId = mSelectedUserInteractor.getSelectedUserId(); 534 showNextSecurityScreenOrFinish( 535 /* authenticated= */ true, 536 selectedUserId, 537 /* bypassSecondaryLockScreen= */ true, 538 mSecurityModel.getSecurityMode(selectedUserId)); 539 } 540 } 541 ); 542 } 543 } 544 545 @Override onViewDetached()546 protected void onViewDetached() { 547 mUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback); 548 mConfigurationController.removeCallback(mConfigurationListener); 549 mView.removeMotionEventListener(mGlobalTouchListener); 550 mUserSwitcherController.removeUserSwitchCallback(mUserSwitchCallback); 551 552 if (mSceneTransitionCollectionJob != null) { 553 mSceneTransitionCollectionJob.cancel(null); 554 mSceneTransitionCollectionJob = null; 555 } 556 } 557 558 /** */ onPause()559 public void onPause() { 560 if (DEBUG) { 561 Log.d(TAG, String.format("screen off, instance %s at %s", 562 Integer.toHexString(hashCode()), SystemClock.uptimeMillis())); 563 } 564 showPrimarySecurityScreen(true); 565 mAdminSecondaryLockScreenController.hide(); 566 if (mCurrentSecurityMode != SecurityMode.None) { 567 getCurrentSecurityController(controller -> controller.onPause()); 568 } 569 mView.onPause(); 570 mView.clearFocus(); 571 } 572 573 /** 574 * Shows the primary security screen for the user. This will be either the multi-selector 575 * or the user's security method. 576 * 577 * @param turningOff true if the device is being turned off 578 */ showPrimarySecurityScreen(boolean turningOff)579 public void showPrimarySecurityScreen(boolean turningOff) { 580 if (DEBUG) Log.d(TAG, "show()"); 581 SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode( 582 mSelectedUserInteractor.getSelectedUserId())); 583 if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")"); 584 mPrimaryBouncerInteractor.get().setLastShownPrimarySecurityScreen(securityMode); 585 showSecurityScreen(securityMode); 586 } 587 588 /** 589 * Show a string explaining why the security view needs to be solved. 590 * 591 * @param reason a flag indicating which string should be shown, see 592 * {@link KeyguardSecurityView#PROMPT_REASON_NONE}, 593 * {@link KeyguardSecurityView#PROMPT_REASON_RESTART}, 594 * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and 595 * {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}. 596 */ 597 @Override showPromptReason(int reason)598 public void showPromptReason(int reason) { 599 if (mCurrentSecurityMode != SecurityMode.None) { 600 if (reason != PROMPT_REASON_NONE) { 601 Log.i(TAG, "Strong auth required, reason: " + reason); 602 } 603 getCurrentSecurityController(controller -> controller.showPromptReason(reason)); 604 } 605 } 606 607 /** Set message of bouncer title. */ showMessage(CharSequence message, ColorStateList colorState, boolean animated)608 public void showMessage(CharSequence message, ColorStateList colorState, boolean animated) { 609 if (mCurrentSecurityMode != SecurityMode.None) { 610 getCurrentSecurityController( 611 controller -> controller.showMessage(message, colorState, animated)); 612 } 613 } 614 615 /** 616 * Sets an action to run when keyguard finishes. 617 * 618 * @param action callback to be invoked when keyguard disappear animation completes. 619 */ setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction)620 public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) { 621 if (SceneContainerFlag.isEnabled()) { 622 return; 623 } 624 if (mCancelAction != null) { 625 mCancelAction.run(); 626 } 627 mDismissAction = action; 628 mCancelAction = cancelAction; 629 } 630 631 /** 632 * @return whether dismiss action or cancel action has been set. 633 */ hasDismissActions()634 public boolean hasDismissActions() { 635 return mDismissAction != null || mCancelAction != null; 636 } 637 638 /** 639 * @return will the dismissal run from the keyguard layout (instead of from bouncer) 640 */ willRunDismissFromKeyguard()641 public boolean willRunDismissFromKeyguard() { 642 return mWillRunDismissFromKeyguard; 643 } 644 645 /** 646 * Remove any dismiss action or cancel action that was set. 647 */ cancelDismissAction()648 public void cancelDismissAction() { 649 setOnDismissAction(null, null); 650 } 651 652 /** 653 * Potentially dismiss the current security screen, after validating that all device 654 * security has been unlocked. Otherwise show the next screen. 655 */ dismiss(boolean authenticated, int targetUserId, SecurityMode expectedSecurityMode)656 public void dismiss(boolean authenticated, int targetUserId, 657 SecurityMode expectedSecurityMode) { 658 mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode); 659 } 660 661 /** 662 * Dismisses the keyguard by going to the next screen or making it gone. 663 * 664 * @param targetUserId a user that needs to be the foreground user at the dismissal completion. 665 * @return True if the keyguard is done. 666 */ dismiss(int targetUserId)667 public boolean dismiss(int targetUserId) { 668 return mKeyguardSecurityCallback.dismiss(false, targetUserId, false, 669 getCurrentSecurityMode()); 670 } 671 getCurrentSecurityMode()672 public SecurityMode getCurrentSecurityMode() { 673 return mCurrentSecurityMode; 674 } 675 676 /** 677 * @return the top of the corresponding view. 678 */ getTop()679 public int getTop() { 680 int top = mView.getTop(); 681 // The password view has an extra top padding that should be ignored. 682 if (getCurrentSecurityMode() == SecurityMode.Password) { 683 View messageArea = mView.findViewById(R.id.keyguard_message_area); 684 top += messageArea.getTop(); 685 } 686 return top; 687 } 688 689 /** Set true if the view can be interacted with */ setInteractable(boolean isInteractable)690 public void setInteractable(boolean isInteractable) { 691 mView.setInteractable(isInteractable); 692 } 693 694 /** 695 * Dismiss keyguard due to a user unlock event. 696 */ finish(int currentUser)697 public void finish(int currentUser) { 698 mKeyguardSecurityCallback.finish(currentUser); 699 } 700 701 /** 702 * @return the text of the KeyguardMessageArea. 703 */ getTitle()704 public CharSequence getTitle() { 705 return mView.getTitle(); 706 } 707 708 /** 709 * Resets the state of the views. 710 */ reset()711 public void reset() { 712 mView.reset(); 713 mSecurityViewFlipperController.reset(); 714 } 715 716 /** Prepares views in the bouncer before starting appear animation. */ prepareToShow()717 public void prepareToShow() { 718 View bouncerUserSwitcher = mView.findViewById(R.id.keyguard_bouncer_user_switcher); 719 if (bouncerUserSwitcher != null) { 720 bouncerUserSwitcher.setAlpha(0f); 721 } 722 } 723 724 @Override onResume(int reason)725 public void onResume(int reason) { 726 if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode())); 727 mView.requestFocus(); 728 if (mCurrentSecurityMode != SecurityMode.None) { 729 int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN; 730 if (mView.isSidedSecurityMode()) { 731 state = mView.isSecurityLeftAligned() 732 ? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_LEFT 733 : SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_RIGHT; 734 } 735 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, state); 736 737 738 getCurrentSecurityController(controller -> controller.onResume(reason)); 739 } 740 mView.onResume( 741 mSecurityModel.getSecurityMode(mSelectedUserInteractor.getSelectedUserId()), 742 mKeyguardStateController.isFaceEnrolledAndEnabled()); 743 } 744 745 /** Sets an initial message that would override the default message */ setInitialMessage()746 public void setInitialMessage() { 747 CharSequence customMessage = mViewMediatorCallback.consumeCustomMessage(); 748 if (!TextUtils.isEmpty(customMessage)) { 749 showMessage(customMessage, /* colorState= */ null, /* animated= */ false); 750 return; 751 } 752 showPromptReason(mViewMediatorCallback.getBouncerPromptReason()); 753 } 754 755 /** 756 * Show the bouncer and start appear animations. 757 */ appear()758 public void appear() { 759 // We might still be collapsed and the view didn't have time to layout yet or still 760 // be small, let's wait on the predraw to do the animation in that case. 761 mView.getViewTreeObserver().addOnPreDrawListener( 762 new ViewTreeObserver.OnPreDrawListener() { 763 @Override 764 public boolean onPreDraw() { 765 mView.getViewTreeObserver().removeOnPreDrawListener(this); 766 startAppearAnimation(); 767 return true; 768 } 769 }); 770 mView.requestLayout(); 771 } 772 startAppearAnimation()773 public void startAppearAnimation() { 774 if (mCurrentSecurityMode != SecurityMode.None) { 775 mView.startAppearAnimation(mCurrentSecurityMode); 776 getCurrentSecurityController(controller -> controller.startAppearAnimation()); 777 } 778 } 779 780 /** Set the alpha of the security container view */ setAlpha(float alpha)781 public void setAlpha(float alpha) { 782 mView.setAlpha(alpha); 783 } 784 startDisappearAnimation(Runnable onFinishRunnable)785 public boolean startDisappearAnimation(Runnable onFinishRunnable) { 786 if (mCurrentSecurityMode != SecurityMode.None) { 787 mView.startDisappearAnimation(mCurrentSecurityMode); 788 getCurrentSecurityController( 789 controller -> { 790 boolean didRunAnimation = controller.startDisappearAnimation( 791 onFinishRunnable); 792 if (!didRunAnimation && onFinishRunnable != null) { 793 onFinishRunnable.run(); 794 } 795 }); 796 } 797 return true; 798 } 799 onStartingToHide()800 public void onStartingToHide() { 801 if (mCurrentSecurityMode != SecurityMode.None) { 802 getCurrentSecurityController(controller -> controller.onStartingToHide()); 803 } 804 } 805 806 /** Called when the bouncer changes visibility. */ onBouncerVisibilityChanged(boolean isVisible)807 public void onBouncerVisibilityChanged(boolean isVisible) { 808 if (!isVisible) { 809 mView.resetScale(); 810 } 811 } 812 813 /** 814 * Shows the next security screen if there is one. 815 * 816 * @param authenticated true if the user entered the correct authentication 817 * @param targetUserId a user that needs to be the foreground user at the finish 818 * (if called) 819 * completion. 820 * @param bypassSecondaryLockScreen true if the user is allowed to bypass the secondary 821 * secondary lock screen requirement, if any. 822 * @param expectedSecurityMode SecurityMode that is invoking this request. 823 * SecurityMode.Invalid 824 * indicates that no check should be done 825 * @return true if keyguard is done 826 */ showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode)827 public boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId, 828 boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { 829 if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")"); 830 if (expectedSecurityMode != SecurityMode.Invalid 831 && expectedSecurityMode != getCurrentSecurityMode()) { 832 Log.w(TAG, "Attempted to invoke showNextSecurityScreenOrFinish with securityMode " 833 + expectedSecurityMode + ", but current mode is " + getCurrentSecurityMode()); 834 return false; 835 } 836 837 boolean authenticatedWithPrimaryAuth = false; 838 boolean finish = false; 839 int eventSubtype = -1; 840 BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN; 841 if (mUpdateMonitor.forceIsDismissibleIsKeepingDeviceUnlocked()) { 842 finish = true; 843 eventSubtype = BOUNCER_DISMISSIBLE_KEYGUARD; 844 // TODO: b/308417021 add UI event 845 } else if (mUpdateMonitor.getUserHasTrust(targetUserId)) { 846 finish = true; 847 eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS; 848 uiEvent = BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS; 849 } else if (mUpdateMonitor.getUserUnlockedWithBiometric(targetUserId)) { 850 finish = true; 851 eventSubtype = BOUNCER_DISMISS_BIOMETRIC; 852 uiEvent = BouncerUiEvent.BOUNCER_DISMISS_BIOMETRIC; 853 } else if (SecurityMode.None == getCurrentSecurityMode()) { 854 SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId); 855 if (SecurityMode.None == securityMode) { 856 finish = true; // no security required 857 eventSubtype = BOUNCER_DISMISS_NONE_SECURITY; 858 uiEvent = BouncerUiEvent.BOUNCER_DISMISS_NONE_SECURITY; 859 } else { 860 showSecurityScreen(securityMode); // switch to the alternate security view 861 } 862 } else if (authenticated) { 863 switch (getCurrentSecurityMode()) { 864 case Pattern: 865 case Password: 866 case PIN: 867 authenticatedWithPrimaryAuth = true; 868 finish = true; 869 eventSubtype = BOUNCER_DISMISS_PASSWORD; 870 uiEvent = BouncerUiEvent.BOUNCER_DISMISS_PASSWORD; 871 break; 872 873 case SimPin: 874 case SimPuk: 875 // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home 876 SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId); 877 boolean isLockscreenDisabled = mLockPatternUtils.isLockScreenDisabled( 878 mSelectedUserInteractor.getSelectedUserId()) 879 || !mDeviceProvisionedController.isUserSetup(targetUserId); 880 881 if (securityMode == SecurityMode.None && isLockscreenDisabled) { 882 finish = true; 883 eventSubtype = BOUNCER_DISMISS_SIM; 884 uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM; 885 } else if (Arrays.asList(SimPin, SimPuk).contains(securityMode)) { 886 // There are additional screens to the sim pin/puk flow. 887 showSecurityScreen(securityMode); 888 } 889 break; 890 891 default: 892 Log.v(TAG, "Bad security screen " + getCurrentSecurityMode() 893 + ", fail safe"); 894 showPrimarySecurityScreen(false); 895 break; 896 } 897 } 898 // Check for device admin specified additional security measures. 899 if (finish && !bypassSecondaryLockScreen) { 900 Intent secondaryLockscreenIntent = 901 mUpdateMonitor.getSecondaryLockscreenRequirement(targetUserId); 902 if (secondaryLockscreenIntent != null) { 903 mAdminSecondaryLockScreenController.show(secondaryLockscreenIntent); 904 return false; 905 } 906 } 907 if (eventSubtype != -1) { 908 mMetricsLogger.write(new LogMaker(MetricsProto.MetricsEvent.BOUNCER) 909 .setType(MetricsProto.MetricsEvent.TYPE_DISMISS).setSubtype(eventSubtype)); 910 } 911 if (uiEvent != BouncerUiEvent.UNKNOWN) { 912 mUiEventLogger.log(uiEvent, getSessionId()); 913 } 914 915 if (SceneContainerFlag.isEnabled()) { 916 if (authenticatedWithPrimaryAuth) { 917 mPrimaryBouncerInteractor.get() 918 .notifyKeyguardAuthenticatedPrimaryAuth(targetUserId); 919 } else if (finish) { 920 mPrimaryBouncerInteractor.get().notifyUserRequestedBouncerWhenAlreadyAuthenticated( 921 targetUserId); 922 } 923 } 924 925 if (finish) { 926 mKeyguardSecurityCallback.finish(targetUserId); 927 } 928 return finish; 929 } 930 931 @Override needsInput()932 public boolean needsInput() { 933 return false; 934 } 935 936 /** 937 * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture. 938 */ 939 @NonNull getBackCallback()940 public OnBackAnimationCallback getBackCallback() { 941 return mView.getBackCallback(); 942 } 943 944 /** 945 * @return whether we should dispatch the back key event before Ime. 946 */ dispatchBackKeyEventPreIme()947 public boolean dispatchBackKeyEventPreIme() { 948 return getCurrentSecurityMode() == SecurityMode.Password; 949 } 950 951 /** 952 * Allows the media keys to work when the keyguard is showing. 953 * The media keys should be of no interest to the actual keyguard view(s), 954 * so intercepting them here should not be of any harm. 955 * 956 * @param event The key event 957 * @return whether the event was consumed as a media key. 958 */ interceptMediaKey(KeyEvent event)959 public boolean interceptMediaKey(KeyEvent event) { 960 int keyCode = event.getKeyCode(); 961 if (event.getAction() == KeyEvent.ACTION_DOWN) { 962 switch (keyCode) { 963 case KeyEvent.KEYCODE_MEDIA_PLAY: 964 case KeyEvent.KEYCODE_MEDIA_PAUSE: 965 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 966 /* Suppress PLAY/PAUSE toggle when phone is ringing or 967 * in-call to avoid music playback */ 968 if (mTelephonyManager != null 969 && mTelephonyManager.getCallState() 970 != TelephonyManager.CALL_STATE_IDLE) { 971 return true; // suppress key event 972 } 973 return false; 974 case KeyEvent.KEYCODE_MUTE: 975 case KeyEvent.KEYCODE_HEADSETHOOK: 976 case KeyEvent.KEYCODE_MEDIA_STOP: 977 case KeyEvent.KEYCODE_MEDIA_NEXT: 978 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 979 case KeyEvent.KEYCODE_MEDIA_REWIND: 980 case KeyEvent.KEYCODE_MEDIA_RECORD: 981 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 982 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 983 handleMediaKeyEvent(event); 984 return true; 985 } 986 987 case KeyEvent.KEYCODE_VOLUME_UP: 988 case KeyEvent.KEYCODE_VOLUME_DOWN: 989 case KeyEvent.KEYCODE_VOLUME_MUTE: { 990 if (KEYGUARD_MANAGES_VOLUME) { 991 // Volume buttons should only function for music (local or remote). 992 // TODO: Actually handle MUTE. 993 mAudioManager.adjustSuggestedStreamVolume( 994 keyCode == KeyEvent.KEYCODE_VOLUME_UP 995 ? AudioManager.ADJUST_RAISE 996 : AudioManager.ADJUST_LOWER /* direction */, 997 AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */); 998 // Don't execute default volume behavior 999 return true; 1000 } else { 1001 return false; 1002 } 1003 } 1004 } 1005 } else if (event.getAction() == KeyEvent.ACTION_UP) { 1006 switch (keyCode) { 1007 case KeyEvent.KEYCODE_MUTE: 1008 case KeyEvent.KEYCODE_HEADSETHOOK: 1009 case KeyEvent.KEYCODE_MEDIA_PLAY: 1010 case KeyEvent.KEYCODE_MEDIA_PAUSE: 1011 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 1012 case KeyEvent.KEYCODE_MEDIA_STOP: 1013 case KeyEvent.KEYCODE_MEDIA_NEXT: 1014 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 1015 case KeyEvent.KEYCODE_MEDIA_REWIND: 1016 case KeyEvent.KEYCODE_MEDIA_RECORD: 1017 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 1018 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 1019 handleMediaKeyEvent(event); 1020 return true; 1021 } 1022 } 1023 } 1024 return false; 1025 } 1026 1027 handleMediaKeyEvent(KeyEvent keyEvent)1028 private void handleMediaKeyEvent(KeyEvent keyEvent) { 1029 mAudioManager.dispatchMediaKeyEvent(keyEvent); 1030 } 1031 1032 /** 1033 * In general, we enable unlocking the insecure keyguard with the menu key. However, there are 1034 * some cases where we wish to disable it, notably when the menu button placement or technology 1035 * is prone to false positives. 1036 * 1037 * @return true if the menu key should be enabled 1038 */ shouldEnableMenuKey()1039 public boolean shouldEnableMenuKey() { 1040 final Resources res = mView.getResources(); 1041 final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen); 1042 final boolean isTestHarness = ActivityManager.isRunningInTestHarness(); 1043 final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists(); 1044 return !configDisabled || isTestHarness || fileOverride; 1045 } 1046 1047 1048 /** 1049 * Switches to the given security view unless it's already being shown, in which case 1050 * this is a no-op. 1051 */ 1052 @VisibleForTesting showSecurityScreen(SecurityMode securityMode)1053 void showSecurityScreen(SecurityMode securityMode) { 1054 if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")"); 1055 1056 if (securityMode == SecurityMode.Invalid || securityMode == mCurrentSecurityMode) { 1057 return; 1058 } 1059 1060 getCurrentSecurityController(oldView -> oldView.onPause()); 1061 1062 mCurrentSecurityMode = securityMode; 1063 1064 getCurrentSecurityController( 1065 newView -> { 1066 newView.onResume(KeyguardSecurityView.VIEW_REVEALED); 1067 mSecurityViewFlipperController.show(newView); 1068 configureMode(); 1069 mKeyguardSecurityCallback.onSecurityModeChanged( 1070 securityMode, newView != null && newView.needsInput()); 1071 1072 }); 1073 } 1074 1075 /** 1076 * Returns whether the given security view should be used in a "one handed" way. This can be 1077 * used to change how the security view is drawn (e.g. take up less of the screen, and align to 1078 * one side). 1079 */ canUseOneHandedBouncer()1080 private boolean canUseOneHandedBouncer() { 1081 return switch (mCurrentSecurityMode) { 1082 case PIN, Pattern, SimPin, SimPuk -> getResources().getBoolean( 1083 R.bool.can_use_one_handed_bouncer); 1084 default -> false; 1085 }; 1086 } 1087 canDisplayUserSwitcher()1088 private boolean canDisplayUserSwitcher() { 1089 return getContext().getResources().getBoolean(R.bool.config_enableBouncerUserSwitcher); 1090 } 1091 configureMode()1092 private void configureMode() { 1093 boolean useSimSecurity = mCurrentSecurityMode == SimPin 1094 || mCurrentSecurityMode == SimPuk; 1095 int mode = KeyguardSecurityContainer.MODE_DEFAULT; 1096 if (canDisplayUserSwitcher() && !useSimSecurity) { 1097 mode = KeyguardSecurityContainer.MODE_USER_SWITCHER; 1098 } else if (canUseOneHandedBouncer()) { 1099 mode = KeyguardSecurityContainer.MODE_ONE_HANDED; 1100 } 1101 1102 mView.initMode(mode, mGlobalSettings, mFalsingManager, mUserSwitcherController, 1103 () -> showMessage(getContext().getString(R.string.keyguard_unlock_to_continue), 1104 /* colorState= */ null, /* animated= */ true), mFalsingA11yDelegate); 1105 } 1106 reportFailedUnlockAttempt(int userId, int timeoutMs)1107 public void reportFailedUnlockAttempt(int userId, int timeoutMs) { 1108 // +1 for this time 1109 final int failedAttempts = mLockPatternUtils.getCurrentFailedPasswordAttempts(userId) + 1; 1110 1111 if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts); 1112 1113 final int failedAttemptsBeforeWipe = 1114 mDevicePolicyManager.getMaximumFailedPasswordsForWipe(null, userId); 1115 1116 final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 1117 ? (failedAttemptsBeforeWipe - failedAttempts) 1118 : Integer.MAX_VALUE; // because DPM returns 0 if no restriction 1119 if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) { 1120 // The user has installed a DevicePolicyManager that requests a 1121 // user/profile to be wiped N attempts. Once we get below the grace period, 1122 // we post this dialog every time as a clear warning until the deletion 1123 // fires. Check which profile has the strictest policy for failed password 1124 // attempts. 1125 final int expiringUser = 1126 mDevicePolicyManager.getProfileWithMinimumFailedPasswordsForWipe(userId); 1127 Integer mainUser = mSelectedUserInteractor.getMainUserId(); 1128 showMessageForFailedUnlockAttempt( 1129 userId, expiringUser, mainUser, remainingBeforeWipe, failedAttempts); 1130 } 1131 mLockPatternUtils.reportFailedPasswordAttempt(userId); 1132 if (timeoutMs > 0) { 1133 mLockPatternUtils.reportPasswordLockout(timeoutMs, userId); 1134 if (!com.android.systemui.Flags.revampedBouncerMessages()) { 1135 mView.showTimeoutDialog(userId, timeoutMs, mLockPatternUtils, 1136 mSecurityModel.getSecurityMode(userId)); 1137 } 1138 } 1139 } 1140 1141 @VisibleForTesting showMessageForFailedUnlockAttempt(int userId, int expiringUserId, Integer mainUserId, int remainingBeforeWipe, int failedAttempts)1142 void showMessageForFailedUnlockAttempt(int userId, int expiringUserId, Integer mainUserId, 1143 int remainingBeforeWipe, int failedAttempts) { 1144 int userType = USER_TYPE_PRIMARY; 1145 if (expiringUserId == userId) { 1146 int primaryUser = UserHandle.USER_SYSTEM; 1147 if (Flags.headlessSingleUserFixes()) { 1148 if (mainUserId != null) { 1149 primaryUser = mainUserId; 1150 } 1151 } 1152 // TODO: http://b/23522538 1153 if (expiringUserId != primaryUser) { 1154 userType = USER_TYPE_SECONDARY_USER; 1155 } 1156 } else if (expiringUserId != UserHandle.USER_NULL) { 1157 userType = USER_TYPE_WORK_PROFILE; 1158 } // If USER_NULL, which shouldn't happen, leave it as USER_TYPE_PRIMARY 1159 if (remainingBeforeWipe > 0) { 1160 mView.showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe, 1161 userType); 1162 } else { 1163 // Too many attempts. The device will be wiped shortly. 1164 Slog.i(TAG, "Too many unlock attempts; user " + expiringUserId 1165 + " will be wiped!"); 1166 mView.showWipeDialog(failedAttempts, userType); 1167 } 1168 } 1169 getCurrentSecurityController( KeyguardSecurityViewFlipperController.OnViewInflatedCallback onViewInflatedCallback)1170 private void getCurrentSecurityController( 1171 KeyguardSecurityViewFlipperController.OnViewInflatedCallback onViewInflatedCallback) { 1172 mSecurityViewFlipperController 1173 .getSecurityView(mCurrentSecurityMode, mKeyguardSecurityCallback, 1174 onViewInflatedCallback); 1175 } 1176 1177 /** 1178 * Apply keyguard configuration from the currently active resources. This can be called when the 1179 * device configuration changes, to re-apply some resources that are qualified on the device 1180 * configuration. 1181 */ updateResources()1182 public void updateResources() { 1183 int gravity; 1184 1185 Resources resources = mView.getResources(); 1186 1187 if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) { 1188 gravity = resources.getInteger( 1189 R.integer.keyguard_host_view_one_handed_gravity); 1190 } else { 1191 gravity = resources.getInteger(R.integer.keyguard_host_view_gravity); 1192 } 1193 1194 mTranslationY = resources 1195 .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y); 1196 // Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout. 1197 // We're just changing the gravity here though (which can't be applied to RelativeLayout), 1198 // so only attempt the update if mView is inside a FrameLayout. 1199 if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) { 1200 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams(); 1201 if (lp.gravity != gravity) { 1202 lp.gravity = gravity; 1203 mView.setLayoutParams(lp); 1204 } 1205 } 1206 1207 int newOrientation = getResources().getConfiguration().orientation; 1208 if (newOrientation != mLastOrientation) { 1209 mLastOrientation = newOrientation; 1210 configureMode(); 1211 } 1212 } 1213 getSessionId()1214 private @Nullable InstanceId getSessionId() { 1215 return mSessionTracker.getSessionId(SESSION_KEYGUARD); 1216 } 1217 1218 /** Update keyguard position based on a tapped X coordinate. */ updateKeyguardPosition(float x)1219 public void updateKeyguardPosition(float x) { 1220 mView.updatePositionByTouchX(x); 1221 } 1222 reloadColors()1223 private void reloadColors() { 1224 mView.reloadColors(); 1225 } 1226 1227 /** Handles density or font scale changes. */ onDensityOrFontScaleOrOrientationChanged()1228 private void onDensityOrFontScaleOrOrientationChanged() { 1229 reinflateViewFlipper(controller -> mView.onDensityOrFontScaleChanged()); 1230 } 1231 1232 /** 1233 * Reinflate the view flipper child view. 1234 */ reinflateViewFlipper( KeyguardSecurityViewFlipperController.OnViewInflatedCallback onViewInflatedListener)1235 public void reinflateViewFlipper( 1236 KeyguardSecurityViewFlipperController.OnViewInflatedCallback onViewInflatedListener) { 1237 mSecurityViewFlipperController.clearViews(); 1238 mSecurityViewFlipperController.asynchronouslyInflateView(mCurrentSecurityMode, 1239 mKeyguardSecurityCallback, onViewInflatedListener); 1240 } 1241 1242 /** 1243 * Fades and translates in/out the security screen. 1244 * Fades in as expansion approaches 0. 1245 * Animation duration is between 0.33f and 0.67f of panel expansion fraction. 1246 * 1247 * @param fraction amount of the screen that should show. 1248 */ setExpansion(float fraction)1249 public void setExpansion(float fraction) { 1250 float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction); 1251 setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f)); 1252 mView.setTranslationY(scaledFraction * mTranslationY); 1253 } 1254 } 1255