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