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