1 /* 2 * Copyright (C) 2016 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.server.wm; 18 19 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 20 import static android.view.Display.DEFAULT_DISPLAY; 21 import static android.view.WindowManager.TRANSIT_FLAG_AOD_APPEARING; 22 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING; 23 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; 24 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; 25 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION; 26 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT; 27 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; 28 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; 29 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING; 30 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING; 31 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE; 32 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; 33 import static android.view.WindowManager.TRANSIT_OPEN; 34 import static android.view.WindowManager.TRANSIT_TO_BACK; 35 import static android.view.WindowManager.TRANSIT_TO_FRONT; 36 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; 37 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS; 38 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT; 39 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; 40 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; 41 42 import static com.android.window.flags.Flags.reduceKeyguardTransitions; 43 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 44 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 45 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 46 import static com.android.server.wm.KeyguardControllerProto.AOD_SHOWING; 47 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_GOING_AWAY; 48 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_PER_DISPLAY; 49 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_SHOWING; 50 51 import android.annotation.Nullable; 52 import android.os.IBinder; 53 import android.os.RemoteException; 54 import android.os.SystemClock; 55 import android.os.Trace; 56 import android.util.Slog; 57 import android.util.SparseArray; 58 import android.util.proto.ProtoOutputStream; 59 import android.view.Display; 60 import android.view.WindowManager; 61 62 import com.android.internal.policy.IKeyguardDismissCallback; 63 import com.android.server.inputmethod.InputMethodManagerInternal; 64 import com.android.server.policy.WindowManagerPolicy; 65 import com.android.window.flags.Flags; 66 67 import java.io.PrintWriter; 68 69 /** 70 * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are 71 * currently visible. 72 * <p> 73 * Note that everything in this class should only be accessed with the AM lock being held. 74 */ 75 class KeyguardController { 76 77 private static final boolean ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS = 78 Flags.ensureKeyguardDoesTransitionStarting(); 79 80 private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM; 81 82 static final String KEYGUARD_SLEEP_TOKEN_TAG = "keyguard"; 83 84 private static final int DEFER_WAKE_TRANSITION_TIMEOUT_MS = 5000; 85 86 private static final int GOING_AWAY_TIMEOUT_MS = 10500; 87 88 private final ActivityTaskSupervisor mTaskSupervisor; 89 private WindowManagerService mWindowManager; 90 91 private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>(); 92 private final ActivityTaskManagerService mService; 93 private RootWindowContainer mRootWindowContainer; 94 private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer; 95 private boolean mWaitingForWakeTransition; 96 private Transition.ReadyCondition mWaitAodHide = null; 97 KeyguardController(ActivityTaskManagerService service, ActivityTaskSupervisor taskSupervisor)98 KeyguardController(ActivityTaskManagerService service, 99 ActivityTaskSupervisor taskSupervisor) { 100 mService = service; 101 mTaskSupervisor = taskSupervisor; 102 mSleepTokenAcquirer = mService.new SleepTokenAcquirer(KEYGUARD_SLEEP_TOKEN_TAG); 103 } 104 setWindowManager(WindowManagerService windowManager)105 void setWindowManager(WindowManagerService windowManager) { 106 mWindowManager = windowManager; 107 mRootWindowContainer = mService.mRootWindowContainer; 108 } 109 isAodShowing(int displayId)110 boolean isAodShowing(int displayId) { 111 return getDisplayState(displayId).mAodShowing; 112 } 113 114 /** 115 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded 116 * on the given display, false otherwise. 117 */ isKeyguardOrAodShowing(int displayId)118 boolean isKeyguardOrAodShowing(int displayId) { 119 final KeyguardDisplayState state = getDisplayState(displayId); 120 return (state.mKeyguardShowing || state.mAodShowing) 121 && !state.mKeyguardGoingAway 122 && !state.mOccluded; 123 } 124 125 /** 126 * @return {@code true} for default display when AOD is showing, not going away. Otherwise, same 127 * as {@link #isKeyguardOrAodShowing(int)} 128 * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic. 129 */ isKeyguardUnoccludedOrAodShowing(int displayId)130 boolean isKeyguardUnoccludedOrAodShowing(int displayId) { 131 final KeyguardDisplayState state = getDisplayState(displayId); 132 if (displayId == DEFAULT_DISPLAY && state.mAodShowing) { 133 return !state.mKeyguardGoingAway; 134 } 135 return isKeyguardOrAodShowing(displayId); 136 } 137 138 /** 139 * @return true if Keyguard is showing, not going away, and not being occluded on the given 140 * display, false otherwise 141 */ isKeyguardShowing(int displayId)142 boolean isKeyguardShowing(int displayId) { 143 final KeyguardDisplayState state = getDisplayState(displayId); 144 return state.mKeyguardShowing && !state.mKeyguardGoingAway && !state.mOccluded; 145 } 146 147 /** 148 * @return true if Keyguard is either showing or occluded, but not going away 149 */ isKeyguardLocked(int displayId)150 boolean isKeyguardLocked(int displayId) { 151 final KeyguardDisplayState state = getDisplayState(displayId); 152 return state.mKeyguardShowing && !state.mKeyguardGoingAway; 153 } 154 155 /** Returns {code @true} if Keyguard is occluded while it is showing and not going away. */ isKeyguardOccluded(int displayId)156 boolean isKeyguardOccluded(int displayId) { 157 final KeyguardDisplayState state = getDisplayState(displayId); 158 return state.mKeyguardShowing && !state.mKeyguardGoingAway && state.mOccluded; 159 } 160 161 /** 162 * 163 * @return true if the activity is controlling keyguard state. 164 */ topActivityOccludesKeyguard(ActivityRecord r)165 boolean topActivityOccludesKeyguard(ActivityRecord r) { 166 return getDisplayState(r.getDisplayId()).mTopOccludesActivity == r; 167 } 168 169 /** 170 * @return {@code true} if the keyguard is going away, {@code false} otherwise. 171 */ isKeyguardGoingAway(int displayId)172 boolean isKeyguardGoingAway(int displayId) { 173 final KeyguardDisplayState state = getDisplayState(displayId); 174 // Also check keyguard showing in case value is stale. 175 return state.mKeyguardGoingAway && state.mKeyguardShowing; 176 } 177 178 /** 179 * Update the Keyguard showing state. 180 */ setKeyguardShown(int displayId, boolean keyguardShowing, boolean aodShowing)181 void setKeyguardShown(int displayId, boolean keyguardShowing, boolean aodShowing) { 182 final DisplayContent dc = mRootWindowContainer.getDisplayContent(displayId); 183 184 if (dc == null) { 185 Slog.w(TAG, "setKeyguardShown called on non-existent display " + displayId); 186 return; 187 } 188 if (dc.isKeyguardAlwaysUnlocked()) { 189 Slog.i(TAG, "setKeyguardShown ignoring always unlocked display " + displayId); 190 return; 191 } 192 193 final KeyguardDisplayState state = getDisplayState(displayId); 194 final boolean aodChanged = aodShowing != state.mAodShowing; 195 final boolean aodRemoved = state.mAodShowing && !aodShowing; 196 final boolean goingAwayRemoved = state.mKeyguardGoingAway && keyguardShowing; 197 // If keyguard is going away, but SystemUI aborted the transition, need to reset state. 198 // Do not reset keyguardChanged status when only AOD is removed. 199 final boolean keyguardChanged = (keyguardShowing != state.mKeyguardShowing) 200 || (goingAwayRemoved && !aodRemoved); 201 if (aodRemoved) { 202 updateDeferTransitionForAod(false /* waiting */); 203 } 204 if (!keyguardChanged && !aodChanged) { 205 setWakeTransitionReady(); 206 return; 207 } 208 209 if (ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS) { 210 final TransitionController transitionController = 211 mWindowManager.mAtmService.getTransitionController(); 212 final Transition transition = transitionController.getCollectingTransition(); 213 if (transition != null && displayId == DEFAULT_DISPLAY) { 214 if (!keyguardShowing && state.mKeyguardShowing) { 215 transition.addFlag(TRANSIT_FLAG_KEYGUARD_GOING_AWAY); 216 } else if (keyguardShowing && !state.mKeyguardShowing) { 217 transition.addFlag(TRANSIT_FLAG_KEYGUARD_APPEARING); 218 } 219 if (mWindowManager.mFlags.mAodTransition && aodShowing && !state.mAodShowing) { 220 transition.addFlag(TRANSIT_FLAG_AOD_APPEARING); 221 } 222 } 223 } 224 // Update the task snapshot if the screen will not be turned off. To make sure that the 225 // unlocking animation can animate consistent content. The conditions are: 226 // - Either AOD or keyguard changes to be showing. So if the states change individually, 227 // the later one can be skipped to avoid taking snapshot again. While it still accepts 228 // if both of them change to show at the same time. 229 // - Keyguard was not going away. Because if it was, the closing transition is able to 230 // handle the snapshot. 231 // - The display state is ON. Because if AOD is not on or pulsing, the display state will 232 // be OFF or DOZE (the path of screen off may have handled it). 233 if (displayId == DEFAULT_DISPLAY 234 && ((aodShowing ^ keyguardShowing) || (aodShowing && aodChanged && keyguardChanged)) 235 && !state.mKeyguardGoingAway 236 && Display.isOnState(dc.getDisplayInfo().state)) { 237 mWindowManager.mTaskSnapshotController.snapshotForSleeping(DEFAULT_DISPLAY); 238 } 239 240 state.mKeyguardShowing = keyguardShowing; 241 state.mAodShowing = aodShowing; 242 state.writeEventLog("setKeyguardShown"); 243 244 if (keyguardChanged || (mWindowManager.mFlags.mAodTransition && aodChanged)) { 245 if (keyguardChanged) { 246 // Irrelevant to AOD. 247 state.mKeyguardGoingAway = false; 248 if (keyguardShowing) { 249 state.mDismissalRequested = false; 250 } 251 } 252 if (goingAwayRemoved 253 || (keyguardShowing && !Display.isOffState(dc.getDisplayInfo().state)) 254 || (mWindowManager.mFlags.mAodTransition && aodShowing)) { 255 // Keyguard decided to show or stopped going away. Send a transition to animate back 256 // to the locked state before holding the sleep token again 257 if (!ENABLE_NEW_KEYGUARD_SHELL_TRANSITIONS) { 258 if (keyguardChanged) { 259 dc.requestTransitionAndLegacyPrepare(TRANSIT_TO_FRONT, 260 TRANSIT_FLAG_KEYGUARD_APPEARING, /* trigger= */ null); 261 } 262 if (mWindowManager.mFlags.mAodTransition && aodChanged && aodShowing) { 263 dc.requestTransitionAndLegacyPrepare(TRANSIT_TO_FRONT, 264 TRANSIT_FLAG_AOD_APPEARING, /* trigger= */ null); 265 } 266 } 267 dc.mWallpaperController.adjustWallpaperWindows(); 268 dc.executeAppTransition(); 269 } 270 scheduleGoingAwayTimeout(displayId); 271 } 272 273 // Update the sleep token first such that ensureActivitiesVisible has correct sleep token 274 // state when evaluating visibilities. 275 updateKeyguardSleepToken(); 276 mRootWindowContainer.ensureActivitiesVisible(); 277 InputMethodManagerInternal.get().updateImeWindowStatus(false /* disableImeIcon */, 278 displayId); 279 setWakeTransitionReady(); 280 if (aodChanged) { 281 // Ensure the new state takes effect. 282 mWindowManager.mWindowPlacerLocked.performSurfacePlacement(); 283 } 284 } 285 setWakeTransitionReady()286 private void setWakeTransitionReady() { 287 if (mWindowManager.mAtmService.getTransitionController().getCollectingTransitionType() 288 == WindowManager.TRANSIT_WAKE) { 289 mWindowManager.mAtmService.getTransitionController().setReady( 290 mRootWindowContainer.getDefaultDisplay()); 291 } 292 } 293 294 /** 295 * Called when Keyguard is going away. 296 * 297 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE} 298 * etc. 299 */ keyguardGoingAway(int displayId, int flags)300 void keyguardGoingAway(int displayId, int flags) { 301 final KeyguardDisplayState state = getDisplayState(displayId); 302 if (!state.mKeyguardShowing || state.mKeyguardGoingAway) { 303 return; 304 } 305 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway"); 306 mService.deferWindowLayout(); 307 state.mKeyguardGoingAway = true; 308 try { 309 state.writeEventLog("keyguardGoingAway"); 310 final int transitFlags = convertTransitFlags(flags); 311 final DisplayContent dc = mRootWindowContainer.getDefaultDisplay(); 312 // We are deprecating TRANSIT_KEYGUARD_GOING_AWAY for Shell transition and use 313 // TRANSIT_FLAG_KEYGUARD_GOING_AWAY to indicate that it should animate keyguard going 314 // away. 315 dc.mAtmService.getTransitionController().requestTransitionIfNeeded( 316 TRANSIT_TO_BACK, transitFlags, null /* trigger */, dc); 317 updateKeyguardSleepToken(); 318 319 // Some stack visibility might change (e.g. docked stack) 320 mRootWindowContainer.resumeFocusedTasksTopActivities(); 321 mRootWindowContainer.ensureActivitiesVisible(); 322 mRootWindowContainer.addStartingWindowsForVisibleActivities(); 323 mWindowManager.executeAppTransition(); 324 325 scheduleGoingAwayTimeout(displayId); 326 } finally { 327 mService.continueWindowLayout(); 328 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 329 } 330 } 331 dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message)332 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) { 333 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token); 334 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) { 335 failCallback(callback); 336 return; 337 } 338 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord); 339 340 // If the client has requested to dismiss the keyguard and the Activity has the flag to 341 // turn the screen on, wakeup the screen if it's the top Activity. 342 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) { 343 mTaskSupervisor.wakeUp(activityRecord.getDisplayId(), "dismissKeyguard"); 344 } 345 346 mWindowManager.dismissKeyguard(callback, message); 347 } 348 failCallback(IKeyguardDismissCallback callback)349 private void failCallback(IKeyguardDismissCallback callback) { 350 try { 351 callback.onDismissError(); 352 } catch (RemoteException e) { 353 Slog.w(TAG, "Failed to call callback", e); 354 } 355 } 356 convertTransitFlags(int keyguardGoingAwayFlags)357 private int convertTransitFlags(int keyguardGoingAwayFlags) { 358 int result = TRANSIT_FLAG_KEYGUARD_GOING_AWAY; 359 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) { 360 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; 361 } 362 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) { 363 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; 364 } 365 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) { 366 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; 367 } 368 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS) != 0) { 369 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION; 370 } 371 if ((keyguardGoingAwayFlags 372 & KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT) != 0) { 373 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT; 374 } 375 return result; 376 } 377 378 /** 379 * @return True if we may show an activity while Keyguard is showing because we are in the 380 * process of dismissing it anyways, false otherwise. 381 */ canShowActivityWhileKeyguardShowing(ActivityRecord r)382 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r) { 383 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is 384 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss 385 // Keyguard. 386 final KeyguardDisplayState state = getDisplayState(r.getDisplayId()); 387 return r.containsDismissKeyguardWindow() && canDismissKeyguard() && !state.mAodShowing 388 && (state.mDismissalRequested 389 || (r.canShowWhenLocked() && state.mDismissingKeyguardActivity != r)); 390 } 391 392 /** 393 * @return True if we may show an activity while Keyguard is occluded, false otherwise. 394 */ canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked)395 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) { 396 return showWhenLocked || dismissKeyguard 397 && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId()); 398 } 399 400 /** 401 * Checks whether {@param r} should be visible depending on Keyguard state. 402 * 403 * @return true if {@param r} is visible taken Keyguard state into account, false otherwise 404 */ checkKeyguardVisibility(ActivityRecord r)405 boolean checkKeyguardVisibility(ActivityRecord r) { 406 if (r.mDisplayContent.canShowWithInsecureKeyguard() && canDismissKeyguard()) { 407 return true; 408 } 409 410 if (isKeyguardOrAodShowing(r.mDisplayContent.getDisplayId())) { 411 // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard 412 // right away and AOD isn't visible. 413 return canShowActivityWhileKeyguardShowing(r); 414 } else if (isKeyguardLocked(r.getDisplayId())) { 415 return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked()); 416 } else { 417 return true; 418 } 419 } 420 421 /** 422 * Makes sure to update lockscreen occluded/dismiss/turnScreenOn state if needed before 423 * completing set all visibility 424 * ({@link ActivityTaskSupervisor#beginActivityVisibilityUpdate}). 425 */ updateVisibility()426 void updateVisibility() { 427 for (int displayNdx = mRootWindowContainer.getChildCount() - 1; 428 displayNdx >= 0; displayNdx--) { 429 final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx); 430 if (display.isRemoving() || display.isRemoved()) continue; 431 final KeyguardDisplayState state = getDisplayState(display.mDisplayId); 432 state.updateVisibility(this, display); 433 if (state.mRequestDismissKeyguard) { 434 handleDismissKeyguard(display.getDisplayId()); 435 } 436 } 437 } 438 439 /** 440 * Called when occluded state changed. 441 * 442 * @param topActivity the activity that controls the state whether keyguard should 443 * be occluded. That is the activity to be shown on top of keyguard if it requests so. 444 */ handleOccludedChanged(int displayId, @Nullable ActivityRecord topActivity)445 private void handleOccludedChanged(int displayId, @Nullable ActivityRecord topActivity) { 446 // TODO(b/113840485): Handle app transition for individual display, and apply occluded 447 // state change to secondary displays. 448 // For now, only default display fully supports occluded change. Other displays only 449 // updates keyguard sleep token on that display. 450 if (displayId != DEFAULT_DISPLAY) { 451 updateKeyguardSleepToken(displayId); 452 return; 453 } 454 455 final TransitionController tc = mRootWindowContainer.mTransitionController; 456 final KeyguardDisplayState state = getDisplayState(displayId); 457 final DisplayContent dc = mRootWindowContainer.getDisplayContent(displayId); 458 459 final boolean locked = isKeyguardLocked(displayId); 460 final boolean executeTransition = !tc.isShellTransitionsEnabled() 461 || (locked && !tc.isCollecting() && !reduceKeyguardTransitions()); 462 463 final int transitType, transitFlags, notFlags; 464 if (state.mOccluded) { 465 transitType = TRANSIT_KEYGUARD_OCCLUDE; 466 transitFlags = TRANSIT_FLAG_KEYGUARD_OCCLUDING; 467 notFlags = TRANSIT_FLAG_KEYGUARD_UNOCCLUDING; 468 } else { 469 transitType = TRANSIT_KEYGUARD_UNOCCLUDE; 470 transitFlags = TRANSIT_FLAG_KEYGUARD_UNOCCLUDING; 471 notFlags = TRANSIT_FLAG_KEYGUARD_OCCLUDING; 472 } 473 474 mWindowManager.mPolicy.onKeyguardOccludedChangedLw(state.mOccluded); 475 mService.deferWindowLayout(); 476 try { 477 if (locked) { 478 if (tc.isShellTransitionsEnabled()) { 479 final Task trigger = (state.mOccluded && topActivity != null) 480 ? topActivity.getRootTask() : null; 481 tc.requestTransitionIfNeeded(transitType, transitFlags, trigger, dc); 482 final Transition transition = tc.getCollectingTransition(); 483 if ((transition.getFlags() & notFlags) != 0 && reduceKeyguardTransitions()) { 484 transition.removeFlag(notFlags); 485 } else { 486 transition.addFlag(transitFlags); 487 } 488 if (trigger != null) { 489 transition.collect(trigger); 490 } 491 } 492 } else { 493 if (tc.inTransition()) { 494 tc.mStateValidators.add(mWindowManager.mPolicy::applyKeyguardOcclusionChange); 495 } else { 496 mWindowManager.mPolicy.applyKeyguardOcclusionChange(); 497 } 498 } 499 updateKeyguardSleepToken(displayId); 500 if (executeTransition) { 501 dc.executeAppTransition(); 502 } 503 } finally { 504 mService.continueWindowLayout(); 505 } 506 } 507 508 /** 509 * Called when keyguard going away state changed. 510 */ handleDismissInsecureKeyguard(DisplayContent dc)511 private void handleDismissInsecureKeyguard(DisplayContent dc) { 512 mService.deferWindowLayout(); 513 try { 514 // We are deprecating TRANSIT_KEYGUARD_GOING_AWAY for Shell transition and use 515 // TRANSIT_FLAG_KEYGUARD_GOING_AWAY to indicate that it should animate keyguard going 516 // away. 517 dc.mAtmService.getTransitionController().requestTransitionIfNeeded( 518 TRANSIT_OPEN, TRANSIT_FLAG_KEYGUARD_GOING_AWAY, null /* trigger */, dc); 519 updateKeyguardSleepToken(); 520 mWindowManager.executeAppTransition(); 521 } finally { 522 mService.continueWindowLayout(); 523 } 524 } 525 526 /** 527 * Called when somebody wants to dismiss the Keyguard via the flag. 528 */ handleDismissKeyguard(int displayId)529 private void handleDismissKeyguard(int displayId) { 530 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy 531 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the 532 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded. 533 if (!mWindowManager.isKeyguardSecure(mService.getCurrentUserId())) { 534 return; 535 } 536 537 mWindowManager.dismissKeyguard(null /* callback */, null /* message */); 538 final KeyguardDisplayState state = getDisplayState(displayId); 539 state.mDismissalRequested = true; 540 } 541 getTopOccludingActivity(int displayId)542 ActivityRecord getTopOccludingActivity(int displayId) { 543 return getDisplayState(displayId).mTopOccludesActivity; 544 } 545 getDismissKeyguardActivity(int displayId)546 ActivityRecord getDismissKeyguardActivity(int displayId) { 547 return getDisplayState(displayId).mDismissingKeyguardActivity; 548 } 549 550 /** 551 * @return true if Keyguard can be currently dismissed without entering credentials. 552 */ canDismissKeyguard()553 boolean canDismissKeyguard() { 554 return mWindowManager.mPolicy.isKeyguardTrustedLw() 555 || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId()); 556 } 557 updateKeyguardSleepToken()558 private void updateKeyguardSleepToken() { 559 for (int displayNdx = mRootWindowContainer.getChildCount() - 1; 560 displayNdx >= 0; displayNdx--) { 561 final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx); 562 updateKeyguardSleepToken(display.mDisplayId); 563 } 564 } 565 updateKeyguardSleepToken(int displayId)566 private void updateKeyguardSleepToken(int displayId) { 567 final KeyguardDisplayState state = getDisplayState(displayId); 568 if (isKeyguardUnoccludedOrAodShowing(displayId)) { 569 state.mSleepTokenAcquirer.acquire(displayId); 570 } else { 571 state.mSleepTokenAcquirer.release(displayId); 572 } 573 } 574 getDisplayState(int displayId)575 private KeyguardDisplayState getDisplayState(int displayId) { 576 KeyguardDisplayState state = mDisplayStates.get(displayId); 577 if (state == null) { 578 state = new KeyguardDisplayState(mService, displayId, mSleepTokenAcquirer); 579 mDisplayStates.append(displayId, state); 580 } 581 return state; 582 } 583 onDisplayRemoved(int displayId)584 void onDisplayRemoved(int displayId) { 585 final KeyguardDisplayState state = mDisplayStates.get(displayId); 586 if (state != null) { 587 state.onRemoved(); 588 mDisplayStates.remove(displayId); 589 } 590 } 591 592 private final Runnable mResetWaitTransition = () -> { 593 synchronized (mWindowManager.mGlobalLock) { 594 updateDeferTransitionForAod(false /* waiting */); 595 } 596 }; 597 598 // Defer transition until AOD dismissed. updateDeferTransitionForAod(boolean waiting)599 void updateDeferTransitionForAod(boolean waiting) { 600 if (mService.getTransitionController().useFullReadyTracking()) { 601 if (waiting == (mWaitAodHide != null)) { 602 return; 603 } 604 } else { 605 if (waiting == mWaitingForWakeTransition) { 606 return; 607 } 608 } 609 if (!mService.getTransitionController().isCollecting()) { 610 return; 611 } 612 // if AOD is showing, defer the wake transition until AOD state changed. 613 if (waiting && isAodShowing(DEFAULT_DISPLAY)) { 614 mWaitingForWakeTransition = true; 615 mWindowManager.mAtmService.getTransitionController().deferTransitionReady(); 616 mWaitAodHide = new Transition.ReadyCondition("AOD hidden"); 617 mWindowManager.mAtmService.getTransitionController().waitFor(mWaitAodHide); 618 mWindowManager.mH.postDelayed(mResetWaitTransition, DEFER_WAKE_TRANSITION_TIMEOUT_MS); 619 } else if (!waiting) { 620 // dismiss the deferring if the AOD state change or cancel awake. 621 mWaitingForWakeTransition = false; 622 mWindowManager.mAtmService.getTransitionController().continueTransitionReady(); 623 mWindowManager.mH.removeCallbacks(mResetWaitTransition); 624 final Transition.ReadyCondition waitAodHide = mWaitAodHide; 625 mWaitAodHide = null; 626 waitAodHide.meet(); 627 } 628 } 629 630 /** 631 * Called when the default display's mKeyguardGoingAway has been left as {@code true} for too 632 * long. Send an explicit message to the KeyguardService asking it to wrap up. 633 */ 634 private final Runnable mGoingAwayTimeout = () -> { 635 synchronized (mWindowManager.mGlobalLock) { 636 KeyguardDisplayState state = getDisplayState(DEFAULT_DISPLAY); 637 if (!state.mKeyguardGoingAway) { 638 return; 639 } 640 state.mKeyguardGoingAway = false; 641 state.writeEventLog("goingAwayTimeout"); 642 mWindowManager.mPolicy.startKeyguardExitAnimation( 643 SystemClock.uptimeMillis() - GOING_AWAY_TIMEOUT_MS); 644 } 645 }; 646 scheduleGoingAwayTimeout(int displayId)647 private void scheduleGoingAwayTimeout(int displayId) { 648 if (displayId != DEFAULT_DISPLAY) { 649 return; 650 } 651 if (getDisplayState(displayId).mKeyguardGoingAway) { 652 if (!mWindowManager.mH.hasCallbacks(mGoingAwayTimeout)) { 653 mWindowManager.mH.postDelayed(mGoingAwayTimeout, GOING_AWAY_TIMEOUT_MS); 654 } 655 } else { 656 mWindowManager.mH.removeCallbacks(mGoingAwayTimeout); 657 } 658 } 659 660 /** Represents Keyguard state per individual display. */ 661 private static class KeyguardDisplayState { 662 private final int mDisplayId; 663 private boolean mKeyguardShowing; 664 private boolean mAodShowing; 665 private boolean mKeyguardGoingAway; 666 private boolean mDismissalRequested; 667 668 /** 669 * True if the top activity on the display can occlude keyguard or the device is dreaming. 670 * Note that this can be true even if the keyguard is disabled or not showing. 671 */ 672 private boolean mOccluded; 673 674 private ActivityRecord mTopOccludesActivity; 675 private ActivityRecord mDismissingKeyguardActivity; 676 private ActivityRecord mTopTurnScreenOnActivity; 677 678 private boolean mRequestDismissKeyguard; 679 private final ActivityTaskManagerService mService; 680 private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer; 681 KeyguardDisplayState(ActivityTaskManagerService service, int displayId, ActivityTaskManagerService.SleepTokenAcquirer acquirer)682 KeyguardDisplayState(ActivityTaskManagerService service, int displayId, 683 ActivityTaskManagerService.SleepTokenAcquirer acquirer) { 684 mService = service; 685 mDisplayId = displayId; 686 mSleepTokenAcquirer = acquirer; 687 } 688 onRemoved()689 void onRemoved() { 690 mTopOccludesActivity = null; 691 mDismissingKeyguardActivity = null; 692 mTopTurnScreenOnActivity = null; 693 mSleepTokenAcquirer.release(mDisplayId); 694 } 695 writeEventLog(String reason)696 void writeEventLog(String reason) { 697 EventLogTags.writeWmSetKeyguardShown( 698 mDisplayId, 699 mKeyguardShowing ? 1 : 0, 700 mAodShowing ? 1 : 0, 701 mKeyguardGoingAway ? 1 : 0, 702 mOccluded ? 1 : 0, 703 reason); 704 } 705 706 /** 707 * Updates keyguard status if the top task could be visible. The top task may occlude 708 * keyguard, request to dismiss keyguard or make insecure keyguard go away based on its 709 * properties. 710 */ updateVisibility(KeyguardController controller, DisplayContent display)711 void updateVisibility(KeyguardController controller, DisplayContent display) { 712 final boolean lastOccluded = mOccluded; 713 final boolean lastKeyguardGoingAway = mKeyguardGoingAway; 714 715 final ActivityRecord lastDismissKeyguardActivity = mDismissingKeyguardActivity; 716 717 mRequestDismissKeyguard = false; 718 mOccluded = false; 719 720 mTopOccludesActivity = null; 721 mDismissingKeyguardActivity = null; 722 mTopTurnScreenOnActivity = null; 723 724 final Task task = getRootTaskForControllingOccluding(display); 725 final ActivityRecord top = task != null ? task.getTopNonFinishingActivity() : null; 726 if (top != null) { 727 if (top.containsDismissKeyguardWindow()) { 728 mDismissingKeyguardActivity = top; 729 } 730 if (top.getTurnScreenOnFlag() && top.currentLaunchCanTurnScreenOn()) { 731 mTopTurnScreenOnActivity = top; 732 } 733 734 final boolean isKeyguardSecure = controller.mWindowManager.isKeyguardSecure( 735 controller.mService.getCurrentUserId()); 736 if (top.mDismissKeyguardIfInsecure && mKeyguardShowing && !isKeyguardSecure) { 737 mKeyguardGoingAway = true; 738 } else if (top.canShowWhenLocked()) { 739 mTopOccludesActivity = top; 740 } 741 top.mDismissKeyguardIfInsecure = false; 742 743 // Only the top activity may control occluded, as we can't occlude the Keyguard 744 // if the top app doesn't want to occlude it. 745 mOccluded = mTopOccludesActivity != null 746 || (mDismissingKeyguardActivity != null 747 && task.topRunningActivity() == mDismissingKeyguardActivity 748 && controller.canShowWhileOccluded( 749 true /* dismissKeyguard */, false /* showWhenLocked */)); 750 // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display. 751 if (mDisplayId != DEFAULT_DISPLAY) { 752 mOccluded |= display.canShowWithInsecureKeyguard() 753 && controller.canDismissKeyguard(); 754 } 755 } 756 757 mRequestDismissKeyguard = lastDismissKeyguardActivity != mDismissingKeyguardActivity 758 && !mOccluded && !mKeyguardGoingAway 759 && mDismissingKeyguardActivity != null; 760 if (mOccluded && mKeyguardShowing && !display.isSleeping() && !top.fillsParent() 761 && display.mWallpaperController.getWallpaperTarget() == null) { 762 // The occluding activity may be translucent or not fill screen. Then let wallpaper 763 // to check whether it should set itself as target to avoid blank background. 764 display.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 765 } 766 767 if (mTopTurnScreenOnActivity != null 768 && !mService.mWindowManager.mPowerManager.isInteractive(display.getDisplayId()) 769 && (mRequestDismissKeyguard || mOccluded)) { 770 controller.mTaskSupervisor.wakeUp(display.getDisplayId(), "handleTurnScreenOn"); 771 mTopTurnScreenOnActivity.setCurrentLaunchCanTurnScreenOn(false); 772 } 773 774 final boolean startedGoingAway = (!lastKeyguardGoingAway && mKeyguardGoingAway); 775 final boolean occludedChanged = (lastOccluded != mOccluded); 776 777 if (startedGoingAway) { 778 writeEventLog("dismissIfInsecure"); 779 controller.handleDismissInsecureKeyguard(display); 780 controller.scheduleGoingAwayTimeout(mDisplayId); 781 } 782 if (occludedChanged && (reduceKeyguardTransitions() || !startedGoingAway)) { 783 controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity); 784 } 785 786 // Collect the participants for shell transition, so that transition won't happen too 787 // early since the transition was set ready. 788 if (top != null && (startedGoingAway || (occludedChanged && mOccluded))) { 789 display.mTransitionController.collect(top); 790 } 791 } 792 793 /** 794 * Gets the stack used to check the occluded state. 795 * <p> 796 * Only the top non-pinned activity of the focusable stack on each display can control its 797 * occlusion state. 798 */ 799 @Nullable getRootTaskForControllingOccluding(DisplayContent display)800 private Task getRootTaskForControllingOccluding(DisplayContent display) { 801 return display.getRootTask(task -> 802 task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode()); 803 } 804 dumpStatus(PrintWriter pw, String prefix)805 void dumpStatus(PrintWriter pw, String prefix) { 806 final StringBuilder sb = new StringBuilder(); 807 sb.append(prefix); 808 sb.append(" KeyguardShowing=") 809 .append(mKeyguardShowing) 810 .append(" AodShowing=") 811 .append(mAodShowing) 812 .append(" KeyguardGoingAway=") 813 .append(mKeyguardGoingAway) 814 .append(" DismissalRequested=") 815 .append(mDismissalRequested) 816 .append(" Occluded=") 817 .append(mOccluded) 818 .append(" DismissingKeyguardActivity=") 819 .append(mDismissingKeyguardActivity) 820 .append(" TurnScreenOnActivity=") 821 .append(mTopTurnScreenOnActivity) 822 .append(" at display=") 823 .append(mDisplayId); 824 pw.println(sb.toString()); 825 } 826 dumpDebug(ProtoOutputStream proto, long fieldId)827 void dumpDebug(ProtoOutputStream proto, long fieldId) { 828 final long token = proto.start(fieldId); 829 proto.write(KeyguardPerDisplayProto.DISPLAY_ID, mDisplayId); 830 proto.write(KeyguardPerDisplayProto.KEYGUARD_SHOWING, mKeyguardShowing); 831 proto.write(KeyguardPerDisplayProto.AOD_SHOWING, mAodShowing); 832 proto.write(KeyguardPerDisplayProto.KEYGUARD_OCCLUDED, mOccluded); 833 proto.write(KeyguardPerDisplayProto.KEYGUARD_GOING_AWAY, mKeyguardGoingAway); 834 proto.end(token); 835 } 836 } 837 dump(PrintWriter pw, String prefix)838 void dump(PrintWriter pw, String prefix) { 839 final KeyguardDisplayState default_state = getDisplayState(DEFAULT_DISPLAY); 840 pw.println(prefix + "KeyguardController:"); 841 pw.println(prefix + " mKeyguardShowing=" + default_state.mKeyguardShowing); 842 pw.println(prefix + " mAodShowing=" + default_state.mAodShowing); 843 pw.println(prefix + " mKeyguardGoingAway=" + default_state.mKeyguardGoingAway); 844 dumpDisplayStates(pw, prefix); 845 pw.println(prefix + " mDismissalRequested=" + default_state.mDismissalRequested); 846 pw.println(); 847 } 848 dumpDebug(ProtoOutputStream proto, long fieldId)849 void dumpDebug(ProtoOutputStream proto, long fieldId) { 850 final KeyguardDisplayState default_state = getDisplayState(DEFAULT_DISPLAY); 851 final long token = proto.start(fieldId); 852 proto.write(AOD_SHOWING, default_state.mAodShowing); 853 proto.write(KEYGUARD_SHOWING, default_state.mKeyguardShowing); 854 proto.write(KEYGUARD_GOING_AWAY, default_state.mKeyguardGoingAway); 855 writeDisplayStatesToProto(proto, KEYGUARD_PER_DISPLAY); 856 proto.end(token); 857 } 858 dumpDisplayStates(PrintWriter pw, String prefix)859 private void dumpDisplayStates(PrintWriter pw, String prefix) { 860 for (int i = 0; i < mDisplayStates.size(); i++) { 861 mDisplayStates.valueAt(i).dumpStatus(pw, prefix); 862 } 863 } 864 writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId)865 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) { 866 for (int i = 0; i < mDisplayStates.size(); i++) { 867 mDisplayStates.valueAt(i).dumpDebug(proto, fieldId); 868 } 869 } 870 } 871