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