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.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 21 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 22 import static android.view.Display.DEFAULT_DISPLAY; 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_SHADE; 26 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; 27 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY; 28 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE; 29 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; 30 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; 31 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS; 32 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; 33 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; 34 35 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 36 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 37 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; 38 import static com.android.server.wm.KeyguardControllerProto.AOD_SHOWING; 39 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES; 40 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_SHOWING; 41 import static com.android.server.wm.KeyguardOccludedProto.DISPLAY_ID; 42 import static com.android.server.wm.KeyguardOccludedProto.KEYGUARD_OCCLUDED; 43 44 import android.annotation.Nullable; 45 import android.os.IBinder; 46 import android.os.RemoteException; 47 import android.os.Trace; 48 import android.util.Slog; 49 import android.util.SparseArray; 50 import android.util.proto.ProtoOutputStream; 51 import android.view.Display; 52 53 import com.android.internal.policy.IKeyguardDismissCallback; 54 import com.android.server.inputmethod.InputMethodManagerInternal; 55 import com.android.server.policy.WindowManagerPolicy; 56 57 import java.io.PrintWriter; 58 59 /** 60 * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are 61 * currently visible. 62 * <p> 63 * Note that everything in this class should only be accessed with the AM lock being held. 64 */ 65 class KeyguardController { 66 67 private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM; 68 69 static final String KEYGUARD_SLEEP_TOKEN_TAG = "keyguard"; 70 71 private final ActivityTaskSupervisor mTaskSupervisor; 72 private WindowManagerService mWindowManager; 73 private boolean mKeyguardShowing; 74 private boolean mAodShowing; 75 private boolean mKeyguardGoingAway; 76 private boolean mDismissalRequested; 77 private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>(); 78 private final ActivityTaskManagerService mService; 79 private RootWindowContainer mRootWindowContainer; 80 private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer; 81 82 KeyguardController(ActivityTaskManagerService service, ActivityTaskSupervisor taskSupervisor)83 KeyguardController(ActivityTaskManagerService service, 84 ActivityTaskSupervisor taskSupervisor) { 85 mService = service; 86 mTaskSupervisor = taskSupervisor; 87 mSleepTokenAcquirer = mService.new SleepTokenAcquirerImpl(KEYGUARD_SLEEP_TOKEN_TAG); 88 } 89 setWindowManager(WindowManagerService windowManager)90 void setWindowManager(WindowManagerService windowManager) { 91 mWindowManager = windowManager; 92 mRootWindowContainer = mService.mRootWindowContainer; 93 } 94 isAodShowing()95 boolean isAodShowing() { 96 return mAodShowing; 97 } 98 99 /** 100 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded 101 * on the given display, false otherwise. 102 */ isKeyguardOrAodShowing(int displayId)103 boolean isKeyguardOrAodShowing(int displayId) { 104 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway 105 && !isDisplayOccluded(displayId); 106 } 107 108 /** 109 * @return {@code true} for default display when AOD is showing. Otherwise, same as 110 * {@link #isKeyguardOrAodShowing(int)} 111 * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic. 112 */ isKeyguardUnoccludedOrAodShowing(int displayId)113 boolean isKeyguardUnoccludedOrAodShowing(int displayId) { 114 if (displayId == DEFAULT_DISPLAY && mAodShowing) { 115 return true; 116 } 117 return isKeyguardOrAodShowing(displayId); 118 } 119 120 /** 121 * @return true if Keyguard is showing, not going away, and not being occluded on the given 122 * display, false otherwise 123 */ isKeyguardShowing(int displayId)124 boolean isKeyguardShowing(int displayId) { 125 return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId); 126 } 127 128 /** 129 * @return true if Keyguard is either showing or occluded, but not going away 130 */ isKeyguardLocked()131 boolean isKeyguardLocked() { 132 return mKeyguardShowing && !mKeyguardGoingAway; 133 } 134 135 /** 136 * 137 * @return true if the activity is controlling keyguard state. 138 */ topActivityOccludesKeyguard(ActivityRecord r)139 boolean topActivityOccludesKeyguard(ActivityRecord r) { 140 return getDisplayState(r.getDisplayId()).mTopOccludesActivity == r; 141 } 142 143 /** 144 * @return {@code true} if the keyguard is going away, {@code false} otherwise. 145 */ isKeyguardGoingAway()146 boolean isKeyguardGoingAway() { 147 // Also check keyguard showing in case value is stale. 148 return mKeyguardGoingAway && mKeyguardShowing; 149 } 150 151 /** 152 * Update the Keyguard showing state. 153 */ setKeyguardShown(boolean keyguardShowing, boolean aodShowing)154 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) { 155 final boolean aodChanged = aodShowing != mAodShowing; 156 // If keyguard is going away, but SystemUI aborted the transition, need to reset state. 157 // Do not reset keyguardChanged status if this is aodChanged. 158 final boolean keyguardChanged = (keyguardShowing != mKeyguardShowing) 159 || (mKeyguardGoingAway && keyguardShowing && !aodChanged); 160 if (!keyguardChanged && !aodChanged) { 161 return; 162 } 163 EventLogTags.writeWmSetKeyguardShown( 164 keyguardShowing ? 1 : 0, 165 aodShowing ? 1 : 0, 166 mKeyguardGoingAway ? 1 : 0, 167 "setKeyguardShown"); 168 169 // Update the task snapshot if the screen will not be turned off. To make sure that the 170 // unlocking animation can animate consistent content. The conditions are: 171 // - Either AOD or keyguard changes to be showing. So if the states change individually, 172 // the later one can be skipped to avoid taking snapshot again. While it still accepts 173 // if both of them change to show at the same time. 174 // - Keyguard was not going away. Because if it was, the closing transition is able to 175 // handle the snapshot. 176 // - The display state is ON. Because if AOD is not on or pulsing, the display state will 177 // be OFF or DOZE (the path of screen off may have handled it). 178 if (((aodShowing ^ keyguardShowing) || (aodShowing && aodChanged && keyguardChanged)) 179 && !mKeyguardGoingAway && Display.isOnState( 180 mRootWindowContainer.getDefaultDisplay().getDisplayInfo().state)) { 181 mWindowManager.mTaskSnapshotController.snapshotForSleeping(DEFAULT_DISPLAY); 182 } 183 184 mKeyguardShowing = keyguardShowing; 185 mAodShowing = aodShowing; 186 if (aodChanged) { 187 // Ensure the new state takes effect. 188 mWindowManager.mWindowPlacerLocked.performSurfacePlacement(); 189 } 190 191 if (keyguardChanged) { 192 // Irrelevant to AOD. 193 dismissMultiWindowModeForTaskIfNeeded(null /* currentTaskControllsingOcclusion */, 194 false /* turningScreenOn */); 195 mKeyguardGoingAway = false; 196 if (keyguardShowing) { 197 mDismissalRequested = false; 198 } 199 } 200 201 // Update the sleep token first such that ensureActivitiesVisible has correct sleep token 202 // state when evaluating visibilities. 203 updateKeyguardSleepToken(); 204 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 205 InputMethodManagerInternal.get().updateImeWindowStatus(false /* disableImeIcon */); 206 } 207 208 /** 209 * Called when Keyguard is going away. 210 * 211 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE} 212 * etc. 213 */ keyguardGoingAway(int flags)214 void keyguardGoingAway(int flags) { 215 if (!mKeyguardShowing) { 216 return; 217 } 218 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway"); 219 mService.deferWindowLayout(); 220 mKeyguardGoingAway = true; 221 try { 222 EventLogTags.writeWmSetKeyguardShown( 223 1 /* keyguardShowing */, 224 mAodShowing ? 1 : 0, 225 1 /* keyguardGoingAway */, 226 "keyguardGoingAway"); 227 mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare( 228 TRANSIT_KEYGUARD_GOING_AWAY, convertTransitFlags(flags)); 229 updateKeyguardSleepToken(); 230 231 // Some stack visibility might change (e.g. docked stack) 232 mRootWindowContainer.resumeFocusedTasksTopActivities(); 233 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 234 mRootWindowContainer.addStartingWindowsForVisibleActivities(); 235 mWindowManager.executeAppTransition(); 236 } finally { 237 mService.continueWindowLayout(); 238 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 239 } 240 } 241 dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message)242 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) { 243 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token); 244 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) { 245 failCallback(callback); 246 return; 247 } 248 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord); 249 250 // If the client has requested to dismiss the keyguard and the Activity has the flag to 251 // turn the screen on, wakeup the screen if it's the top Activity. 252 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) { 253 mTaskSupervisor.wakeUp("dismissKeyguard"); 254 } 255 256 mWindowManager.dismissKeyguard(callback, message); 257 } 258 failCallback(IKeyguardDismissCallback callback)259 private void failCallback(IKeyguardDismissCallback callback) { 260 try { 261 callback.onDismissError(); 262 } catch (RemoteException e) { 263 Slog.w(TAG, "Failed to call callback", e); 264 } 265 } 266 convertTransitFlags(int keyguardGoingAwayFlags)267 private int convertTransitFlags(int keyguardGoingAwayFlags) { 268 int result = 0; 269 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) { 270 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; 271 } 272 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) { 273 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; 274 } 275 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) { 276 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; 277 } 278 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS) != 0) { 279 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION; 280 } 281 return result; 282 } 283 284 /** 285 * @return True if we may show an activity while Keyguard is showing because we are in the 286 * process of dismissing it anyways, false otherwise. 287 */ canShowActivityWhileKeyguardShowing(ActivityRecord r)288 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r) { 289 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is 290 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss 291 // Keyguard. 292 return r.containsDismissKeyguardWindow() && canDismissKeyguard() && !mAodShowing 293 && (mDismissalRequested 294 || (r.canShowWhenLocked() 295 && getDisplayState(r.getDisplayId()).mDismissingKeyguardActivity != r)); 296 } 297 298 /** 299 * @return True if we may show an activity while Keyguard is occluded, false otherwise. 300 */ canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked)301 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) { 302 return showWhenLocked || dismissKeyguard 303 && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId()); 304 } 305 306 /** 307 * Checks whether {@param r} should be visible depending on Keyguard state. 308 * 309 * @return true if {@param r} is visible taken Keyguard state into account, false otherwise 310 */ checkKeyguardVisibility(ActivityRecord r)311 boolean checkKeyguardVisibility(ActivityRecord r) { 312 if (r.mDisplayContent.canShowWithInsecureKeyguard() && canDismissKeyguard()) { 313 return true; 314 } 315 316 if (isKeyguardOrAodShowing(r.mDisplayContent.getDisplayId())) { 317 // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard 318 // right away and AOD isn't visible. 319 return canShowActivityWhileKeyguardShowing(r); 320 } else if (isKeyguardLocked()) { 321 return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked()); 322 } else { 323 return true; 324 } 325 } 326 327 /** 328 * Makes sure to update lockscreen occluded/dismiss/turnScreenOn state if needed before 329 * completing set all visibility 330 * ({@link ActivityTaskSupervisor#beginActivityVisibilityUpdate}). 331 */ updateVisibility()332 void updateVisibility() { 333 boolean requestDismissKeyguard = false; 334 for (int displayNdx = mRootWindowContainer.getChildCount() - 1; 335 displayNdx >= 0; displayNdx--) { 336 final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx); 337 final KeyguardDisplayState state = getDisplayState(display.mDisplayId); 338 state.updateVisibility(this, display); 339 requestDismissKeyguard |= state.mRequestDismissKeyguard; 340 } 341 342 // Dismissing Keyguard happens globally using the information from all displays. 343 if (requestDismissKeyguard) { 344 handleDismissKeyguard(); 345 } 346 } 347 348 /** 349 * Called when occluded state changed. 350 * 351 * @param topActivity the activity that controls the state whether keyguard should 352 * be occluded. That is the activity to be shown on top of keyguard if it requests so. 353 */ handleOccludedChanged(int displayId, @Nullable ActivityRecord topActivity)354 private void handleOccludedChanged(int displayId, @Nullable ActivityRecord topActivity) { 355 // TODO(b/113840485): Handle app transition for individual display, and apply occluded 356 // state change to secondary displays. 357 // For now, only default display fully supports occluded change. Other displays only 358 // updates keygaurd sleep token on that display. 359 if (displayId != DEFAULT_DISPLAY) { 360 updateKeyguardSleepToken(displayId); 361 return; 362 } 363 364 mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY)); 365 if (isKeyguardLocked()) { 366 mService.deferWindowLayout(); 367 try { 368 mRootWindowContainer.getDefaultDisplay() 369 .prepareAppTransition( 370 isDisplayOccluded(DEFAULT_DISPLAY) 371 ? TRANSIT_KEYGUARD_OCCLUDE 372 : TRANSIT_KEYGUARD_UNOCCLUDE); 373 // When the occluding activity also turns on the display, visibility of the activity 374 // can be committed before KEYGUARD_OCCLUDE transition is handled. 375 // Set mRequestForceTransition flag to make sure that the app transition animation 376 // is applied for such case. 377 // TODO(b/194243906): Fix this before enabling the remote keyguard animation. 378 if (WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation 379 && topActivity != null) { 380 topActivity.mRequestForceTransition = true; 381 } 382 updateKeyguardSleepToken(DEFAULT_DISPLAY); 383 mWindowManager.executeAppTransition(); 384 } finally { 385 mService.continueWindowLayout(); 386 } 387 } 388 } 389 390 /** 391 * Called when somebody wants to dismiss the Keyguard via the flag. 392 */ handleDismissKeyguard()393 private void handleDismissKeyguard() { 394 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy 395 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the 396 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded. 397 if (!mWindowManager.isKeyguardSecure(mService.getCurrentUserId())) { 398 return; 399 } 400 401 mWindowManager.dismissKeyguard(null /* callback */, null /* message */); 402 mDismissalRequested = true; 403 404 // If we are about to unocclude the Keyguard, but we can dismiss it without security, 405 // we immediately dismiss the Keyguard so the activity gets shown without a flicker. 406 final DisplayContent dc = mRootWindowContainer.getDefaultDisplay(); 407 if (mKeyguardShowing && canDismissKeyguard() 408 && dc.mAppTransition.containsTransitRequest(TRANSIT_KEYGUARD_UNOCCLUDE)) { 409 mWindowManager.executeAppTransition(); 410 } 411 } 412 413 /** 414 * Called when somebody wants to turn screen on. 415 */ handleTurnScreenOn(int displayId)416 private void handleTurnScreenOn(int displayId) { 417 if (displayId != DEFAULT_DISPLAY) { 418 return; 419 } 420 421 mTaskSupervisor.wakeUp("handleTurnScreenOn"); 422 if (mKeyguardShowing && canDismissKeyguard()) { 423 mWindowManager.dismissKeyguard(null /* callback */, null /* message */); 424 mDismissalRequested = true; 425 } 426 } 427 isDisplayOccluded(int displayId)428 boolean isDisplayOccluded(int displayId) { 429 return getDisplayState(displayId).mOccluded; 430 } 431 432 /** 433 * @return true if Keyguard can be currently dismissed without entering credentials. 434 */ canDismissKeyguard()435 boolean canDismissKeyguard() { 436 return mWindowManager.mPolicy.isKeyguardTrustedLw() 437 || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId()); 438 } 439 dismissMultiWindowModeForTaskIfNeeded( @ullable Task currentTaskControllingOcclusion, boolean turningScreenOn)440 private void dismissMultiWindowModeForTaskIfNeeded( 441 @Nullable Task currentTaskControllingOcclusion, boolean turningScreenOn) { 442 // If turningScreenOn is true, it means that the visibility state has changed from 443 // currentTaskControllingOcclusion and we should update windowing mode. 444 // TODO(b/113840485): Handle docked stack for individual display. 445 if (!turningScreenOn && (!mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY))) { 446 return; 447 } 448 449 // Dismiss split screen 450 // The lock screen is currently showing, but is occluded by a window that can 451 // show on top of the lock screen. In this can we want to dismiss the docked 452 // stack since it will be complicated/risky to try to put the activity on top 453 // of the lock screen in the right fullscreen configuration. 454 final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); 455 if (taskDisplayArea.isSplitScreenModeActivated()) { 456 taskDisplayArea.onSplitScreenModeDismissed(); 457 } 458 459 // Dismiss freeform windowing mode 460 if (currentTaskControllingOcclusion == null) { 461 return; 462 } 463 if (currentTaskControllingOcclusion.inFreeformWindowingMode()) { 464 currentTaskControllingOcclusion.setWindowingMode(WINDOWING_MODE_FULLSCREEN); 465 } 466 } 467 updateKeyguardSleepToken()468 private void updateKeyguardSleepToken() { 469 for (int displayNdx = mRootWindowContainer.getChildCount() - 1; 470 displayNdx >= 0; displayNdx--) { 471 final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx); 472 updateKeyguardSleepToken(display.mDisplayId); 473 } 474 } 475 updateKeyguardSleepToken(int displayId)476 private void updateKeyguardSleepToken(int displayId) { 477 final KeyguardDisplayState state = getDisplayState(displayId); 478 if (isKeyguardUnoccludedOrAodShowing(displayId)) { 479 state.mSleepTokenAcquirer.acquire(displayId); 480 } else if (!isKeyguardUnoccludedOrAodShowing(displayId)) { 481 state.mSleepTokenAcquirer.release(displayId); 482 } 483 } 484 getDisplayState(int displayId)485 private KeyguardDisplayState getDisplayState(int displayId) { 486 KeyguardDisplayState state = mDisplayStates.get(displayId); 487 if (state == null) { 488 state = new KeyguardDisplayState(mService, displayId, mSleepTokenAcquirer); 489 mDisplayStates.append(displayId, state); 490 } 491 return state; 492 } 493 onDisplayRemoved(int displayId)494 void onDisplayRemoved(int displayId) { 495 final KeyguardDisplayState state = mDisplayStates.get(displayId); 496 if (state != null) { 497 state.onRemoved(); 498 mDisplayStates.remove(displayId); 499 } 500 } 501 502 /** Represents Keyguard state per individual display. */ 503 private static class KeyguardDisplayState { 504 private final int mDisplayId; 505 private boolean mOccluded; 506 507 private ActivityRecord mTopOccludesActivity; 508 private ActivityRecord mDismissingKeyguardActivity; 509 private ActivityRecord mTopTurnScreenOnActivity; 510 511 private boolean mRequestDismissKeyguard; 512 private final ActivityTaskManagerService mService; 513 private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer; 514 KeyguardDisplayState(ActivityTaskManagerService service, int displayId, ActivityTaskManagerInternal.SleepTokenAcquirer acquirer)515 KeyguardDisplayState(ActivityTaskManagerService service, int displayId, 516 ActivityTaskManagerInternal.SleepTokenAcquirer acquirer) { 517 mService = service; 518 mDisplayId = displayId; 519 mSleepTokenAcquirer = acquirer; 520 } 521 onRemoved()522 void onRemoved() { 523 mTopOccludesActivity = null; 524 mDismissingKeyguardActivity = null; 525 mTopTurnScreenOnActivity = null; 526 mSleepTokenAcquirer.release(mDisplayId); 527 } 528 529 /** 530 * Updates {@link #mOccluded}, {@link #mTopTurnScreenOnActivity} and 531 * {@link #mDismissingKeyguardActivity} if the top task could be visible. 532 */ updateVisibility(KeyguardController controller, DisplayContent display)533 void updateVisibility(KeyguardController controller, DisplayContent display) { 534 final boolean lastOccluded = mOccluded; 535 536 final ActivityRecord lastDismissKeyguardActivity = mDismissingKeyguardActivity; 537 final ActivityRecord lastTurnScreenOnActivity = mTopTurnScreenOnActivity; 538 539 mRequestDismissKeyguard = false; 540 mOccluded = false; 541 542 mTopOccludesActivity = null; 543 mDismissingKeyguardActivity = null; 544 mTopTurnScreenOnActivity = null; 545 546 boolean occludedByActivity = false; 547 final Task task = getRootTaskForControllingOccluding(display); 548 final ActivityRecord top = task != null ? task.getTopNonFinishingActivity() : null; 549 if (top != null) { 550 if (top.containsDismissKeyguardWindow()) { 551 mDismissingKeyguardActivity = top; 552 } 553 if (top.getTurnScreenOnFlag() && top.currentLaunchCanTurnScreenOn()) { 554 mTopTurnScreenOnActivity = top; 555 } 556 557 final boolean showWhenLocked = top.canShowWhenLocked(); 558 if (showWhenLocked) { 559 mTopOccludesActivity = top; 560 } 561 562 // Only the top activity may control occluded, as we can't occlude the Keyguard 563 // if the top app doesn't want to occlude it. 564 occludedByActivity = showWhenLocked || (mDismissingKeyguardActivity != null 565 && task.topRunningActivity() == mDismissingKeyguardActivity 566 && controller.canShowWhileOccluded( 567 true /* dismissKeyguard */, false /* showWhenLocked */)); 568 // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display. 569 if (mDisplayId != DEFAULT_DISPLAY) { 570 occludedByActivity |= display.canShowWithInsecureKeyguard() 571 && controller.canDismissKeyguard(); 572 } 573 } 574 575 final boolean dreaming = display.getDisplayPolicy().isShowingDreamLw() && (top != null 576 && top.getActivityType() == ACTIVITY_TYPE_DREAM); 577 mOccluded = dreaming || occludedByActivity; 578 mRequestDismissKeyguard = lastDismissKeyguardActivity != mDismissingKeyguardActivity 579 && !mOccluded 580 && mDismissingKeyguardActivity != null 581 && controller.mWindowManager.isKeyguardSecure( 582 controller.mService.getCurrentUserId()); 583 584 boolean occludingChange = false; 585 boolean turningScreenOn = false; 586 if (mTopTurnScreenOnActivity != lastTurnScreenOnActivity 587 && mTopTurnScreenOnActivity != null 588 && !mService.mWindowManager.mPowerManager.isInteractive() 589 && (mRequestDismissKeyguard || occludedByActivity 590 || controller.canDismissKeyguard())) { 591 turningScreenOn = true; 592 controller.handleTurnScreenOn(mDisplayId); 593 mTopTurnScreenOnActivity.setCurrentLaunchCanTurnScreenOn(false); 594 } 595 596 if (lastOccluded != mOccluded) { 597 occludingChange = true; 598 controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity); 599 } 600 601 if (occludingChange || turningScreenOn) { 602 controller.dismissMultiWindowModeForTaskIfNeeded(task, turningScreenOn); 603 } 604 } 605 606 /** 607 * Gets the stack used to check the occluded state. 608 * <p> 609 * Only the top non-pinned activity of the focusable stack on each display can control its 610 * occlusion state. 611 */ 612 @Nullable getRootTaskForControllingOccluding(DisplayContent display)613 private Task getRootTaskForControllingOccluding(DisplayContent display) { 614 return display.getRootTask(task -> 615 task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode()); 616 } 617 dumpStatus(PrintWriter pw, String prefix)618 void dumpStatus(PrintWriter pw, String prefix) { 619 final StringBuilder sb = new StringBuilder(); 620 sb.append(prefix); 621 sb.append(" Occluded=").append(mOccluded) 622 .append(" DismissingKeyguardActivity=") 623 .append(mDismissingKeyguardActivity) 624 .append(" TurnScreenOnActivity=") 625 .append(mTopTurnScreenOnActivity) 626 .append(" at display=") 627 .append(mDisplayId); 628 pw.println(sb.toString()); 629 } 630 dumpDebug(ProtoOutputStream proto, long fieldId)631 void dumpDebug(ProtoOutputStream proto, long fieldId) { 632 final long token = proto.start(fieldId); 633 proto.write(DISPLAY_ID, mDisplayId); 634 proto.write(KEYGUARD_OCCLUDED, mOccluded); 635 proto.end(token); 636 } 637 } 638 dump(PrintWriter pw, String prefix)639 void dump(PrintWriter pw, String prefix) { 640 pw.println(prefix + "KeyguardController:"); 641 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing); 642 pw.println(prefix + " mAodShowing=" + mAodShowing); 643 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway); 644 dumpDisplayStates(pw, prefix); 645 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested); 646 pw.println(); 647 } 648 dumpDebug(ProtoOutputStream proto, long fieldId)649 void dumpDebug(ProtoOutputStream proto, long fieldId) { 650 final long token = proto.start(fieldId); 651 proto.write(AOD_SHOWING, mAodShowing); 652 proto.write(KEYGUARD_SHOWING, mKeyguardShowing); 653 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES); 654 proto.end(token); 655 } 656 dumpDisplayStates(PrintWriter pw, String prefix)657 private void dumpDisplayStates(PrintWriter pw, String prefix) { 658 for (int i = 0; i < mDisplayStates.size(); i++) { 659 mDisplayStates.valueAt(i).dumpStatus(pw, prefix); 660 } 661 } 662 writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId)663 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) { 664 for (int i = 0; i < mDisplayStates.size(); i++) { 665 mDisplayStates.valueAt(i).dumpDebug(proto, fieldId); 666 } 667 } 668 } 669