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_GOING_AWAY_NO_ANIMATION; 22 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION; 23 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; 24 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; 25 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY; 26 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE; 27 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; 28 import static android.view.WindowManager.TRANSIT_UNSET; 29 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; 30 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS; 31 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; 32 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; 33 34 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; 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.KeyguardControllerProto.AOD_SHOWING; 38 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES; 39 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_SHOWING; 40 import static com.android.server.wm.KeyguardOccludedProto.DISPLAY_ID; 41 import static com.android.server.wm.KeyguardOccludedProto.KEYGUARD_OCCLUDED; 42 43 import android.os.IBinder; 44 import android.os.RemoteException; 45 import android.os.Trace; 46 import android.util.Slog; 47 import android.util.SparseArray; 48 import android.util.proto.ProtoOutputStream; 49 50 import com.android.internal.policy.IKeyguardDismissCallback; 51 import com.android.server.policy.WindowManagerPolicy; 52 import com.android.server.wm.ActivityTaskManagerInternal.SleepToken; 53 54 import java.io.PrintWriter; 55 56 /** 57 * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are 58 * currently visible. 59 * <p> 60 * Note that everything in this class should only be accessed with the AM lock being held. 61 */ 62 class KeyguardController { 63 64 private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM; 65 66 private final ActivityStackSupervisor mStackSupervisor; 67 private WindowManagerService mWindowManager; 68 private boolean mKeyguardShowing; 69 private boolean mAodShowing; 70 private boolean mKeyguardGoingAway; 71 private boolean mDismissalRequested; 72 private int mBeforeUnoccludeTransit; 73 private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>(); 74 private final ActivityTaskManagerService mService; 75 private RootWindowContainer mRootWindowContainer; 76 KeyguardController(ActivityTaskManagerService service, ActivityStackSupervisor stackSupervisor)77 KeyguardController(ActivityTaskManagerService service, 78 ActivityStackSupervisor stackSupervisor) { 79 mService = service; 80 mStackSupervisor = stackSupervisor; 81 } 82 setWindowManager(WindowManagerService windowManager)83 void setWindowManager(WindowManagerService windowManager) { 84 mWindowManager = windowManager; 85 mRootWindowContainer = mService.mRootWindowContainer; 86 } 87 88 /** 89 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded 90 * on the given display, false otherwise. 91 */ isKeyguardOrAodShowing(int displayId)92 boolean isKeyguardOrAodShowing(int displayId) { 93 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway 94 && !isDisplayOccluded(displayId); 95 } 96 97 /** 98 * @return {@code true} for default display when AOD is showing. Otherwise, same as 99 * {@link #isKeyguardOrAodShowing(int)} 100 * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic. 101 */ isKeyguardUnoccludedOrAodShowing(int displayId)102 boolean isKeyguardUnoccludedOrAodShowing(int displayId) { 103 if (displayId == DEFAULT_DISPLAY && mAodShowing) { 104 return true; 105 } 106 return isKeyguardOrAodShowing(displayId); 107 } 108 109 /** 110 * @return true if Keyguard is showing, not going away, and not being occluded on the given 111 * display, false otherwise 112 */ isKeyguardShowing(int displayId)113 boolean isKeyguardShowing(int displayId) { 114 return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId); 115 } 116 117 /** 118 * @return true if Keyguard is either showing or occluded, but not going away 119 */ isKeyguardLocked()120 boolean isKeyguardLocked() { 121 return mKeyguardShowing && !mKeyguardGoingAway; 122 } 123 124 /** 125 * @return {@code true} if the keyguard is going away, {@code false} otherwise. 126 */ isKeyguardGoingAway()127 boolean isKeyguardGoingAway() { 128 // Also check keyguard showing in case value is stale. 129 return mKeyguardGoingAway && mKeyguardShowing; 130 } 131 132 /** 133 * Update the Keyguard showing state. 134 */ setKeyguardShown(boolean keyguardShowing, boolean aodShowing)135 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) { 136 final boolean aodChanged = aodShowing != mAodShowing; 137 // If keyguard is going away, but SystemUI aborted the transition, need to reset state. 138 // Do not reset keyguardChanged status if this is aodChanged. 139 final boolean keyguardChanged = (keyguardShowing != mKeyguardShowing) 140 || (mKeyguardGoingAway && keyguardShowing && !aodChanged); 141 if (!keyguardChanged && !aodChanged) { 142 return; 143 } 144 EventLogTags.writeWmSetKeyguardShown( 145 keyguardShowing ? 1 : 0, 146 aodShowing ? 1 : 0, 147 mKeyguardGoingAway ? 1 : 0, 148 "setKeyguardShown"); 149 mKeyguardShowing = keyguardShowing; 150 mAodShowing = aodShowing; 151 mWindowManager.setAodShowing(aodShowing); 152 153 if (keyguardChanged) { 154 // Irrelevant to AOD. 155 dismissDockedStackIfNeeded(); 156 setKeyguardGoingAway(false); 157 if (keyguardShowing) { 158 mDismissalRequested = false; 159 } 160 } 161 // TODO(b/113840485): Check usage for non-default display 162 mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay( 163 isKeyguardOrAodShowing(DEFAULT_DISPLAY)); 164 165 // Update the sleep token first such that ensureActivitiesVisible has correct sleep token 166 // state when evaluating visibilities. 167 updateKeyguardSleepToken(); 168 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 169 } 170 171 /** 172 * Called when Keyguard is going away. 173 * 174 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE} 175 * etc. 176 */ keyguardGoingAway(int flags)177 void keyguardGoingAway(int flags) { 178 if (!mKeyguardShowing) { 179 return; 180 } 181 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway"); 182 mService.deferWindowLayout(); 183 try { 184 setKeyguardGoingAway(true); 185 EventLogTags.writeWmSetKeyguardShown( 186 1 /* keyguardShowing */, 187 mAodShowing ? 1 : 0, 188 1 /* keyguardGoingAway */, 189 "keyguardGoingAway"); 190 mRootWindowContainer.getDefaultDisplay().mDisplayContent 191 .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, 192 false /* alwaysKeepCurrent */, convertTransitFlags(flags), 193 false /* forceOverride */); 194 updateKeyguardSleepToken(); 195 196 // Some stack visibility might change (e.g. docked stack) 197 mRootWindowContainer.resumeFocusedStacksTopActivities(); 198 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 199 mRootWindowContainer.addStartingWindowsForVisibleActivities(); 200 mWindowManager.executeAppTransition(); 201 } finally { 202 mService.continueWindowLayout(); 203 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 204 } 205 } 206 dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message)207 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) { 208 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token); 209 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) { 210 failCallback(callback); 211 return; 212 } 213 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord); 214 215 // If the client has requested to dismiss the keyguard and the Activity has the flag to 216 // turn the screen on, wakeup the screen if it's the top Activity. 217 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) { 218 mStackSupervisor.wakeUp("dismissKeyguard"); 219 } 220 221 mWindowManager.dismissKeyguard(callback, message); 222 } 223 setKeyguardGoingAway(boolean keyguardGoingAway)224 private void setKeyguardGoingAway(boolean keyguardGoingAway) { 225 mKeyguardGoingAway = keyguardGoingAway; 226 mWindowManager.setKeyguardGoingAway(keyguardGoingAway); 227 } 228 failCallback(IKeyguardDismissCallback callback)229 private void failCallback(IKeyguardDismissCallback callback) { 230 try { 231 callback.onDismissError(); 232 } catch (RemoteException e) { 233 Slog.w(TAG, "Failed to call callback", e); 234 } 235 } 236 convertTransitFlags(int keyguardGoingAwayFlags)237 private int convertTransitFlags(int keyguardGoingAwayFlags) { 238 int result = 0; 239 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) { 240 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; 241 } 242 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) { 243 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; 244 } 245 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) { 246 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; 247 } 248 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS) != 0) { 249 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION; 250 } 251 return result; 252 } 253 254 /** 255 * @return True if we may show an activity while Keyguard is showing because we are in the 256 * process of dismissing it anyways, false otherwise. 257 */ canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard)258 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) { 259 260 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is 261 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss 262 // Keyguard. 263 return dismissKeyguard && canDismissKeyguard() && !mAodShowing 264 && (mDismissalRequested 265 || (r.canShowWhenLocked() 266 && getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r)); 267 } 268 269 /** 270 * @return True if we may show an activity while Keyguard is occluded, false otherwise. 271 */ canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked)272 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) { 273 return showWhenLocked || dismissKeyguard 274 && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId()); 275 } 276 277 /** 278 * Makes sure to update lockscreen occluded/dismiss state if needed after completing all 279 * visibility updates ({@link ActivityStackSupervisor#endActivityVisibilityUpdate}). 280 */ visibilitiesUpdated()281 void visibilitiesUpdated() { 282 boolean requestDismissKeyguard = false; 283 for (int displayNdx = mRootWindowContainer.getChildCount() - 1; 284 displayNdx >= 0; displayNdx--) { 285 final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx); 286 final KeyguardDisplayState state = getDisplay(display.mDisplayId); 287 state.visibilitiesUpdated(this, display); 288 requestDismissKeyguard |= state.mRequestDismissKeyguard; 289 } 290 291 // Dismissing Keyguard happens globally using the information from all displays. 292 if (requestDismissKeyguard) { 293 handleDismissKeyguard(); 294 } 295 } 296 297 /** 298 * Called when occluded state changed. 299 */ handleOccludedChanged(int displayId)300 private void handleOccludedChanged(int displayId) { 301 // TODO(b/113840485): Handle app transition for individual display, and apply occluded 302 // state change to secondary displays. 303 // For now, only default display fully supports occluded change. Other displays only 304 // updates keygaurd sleep token on that display. 305 if (displayId != DEFAULT_DISPLAY) { 306 updateKeyguardSleepToken(displayId); 307 return; 308 } 309 310 mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY)); 311 if (isKeyguardLocked()) { 312 mService.deferWindowLayout(); 313 try { 314 mRootWindowContainer.getDefaultDisplay().mDisplayContent 315 .prepareAppTransition(resolveOccludeTransit(), 316 false /* alwaysKeepCurrent */, 0 /* flags */, 317 true /* forceOverride */); 318 updateKeyguardSleepToken(DEFAULT_DISPLAY); 319 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 320 mWindowManager.executeAppTransition(); 321 } finally { 322 mService.continueWindowLayout(); 323 } 324 } 325 dismissDockedStackIfNeeded(); 326 } 327 328 /** 329 * Called when somebody wants to dismiss the Keyguard via the flag. 330 */ handleDismissKeyguard()331 private void handleDismissKeyguard() { 332 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy 333 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the 334 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded. 335 if (!mWindowManager.isKeyguardSecure(mService.getCurrentUserId())) { 336 return; 337 } 338 339 mWindowManager.dismissKeyguard(null /* callback */, null /* message */); 340 mDismissalRequested = true; 341 342 // If we are about to unocclude the Keyguard, but we can dismiss it without security, 343 // we immediately dismiss the Keyguard so the activity gets shown without a flicker. 344 final DisplayContent dc = 345 mRootWindowContainer.getDefaultDisplay().mDisplayContent; 346 if (mKeyguardShowing && canDismissKeyguard() 347 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) { 348 dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */, 349 0 /* flags */, true /* forceOverride */); 350 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 351 mWindowManager.executeAppTransition(); 352 } 353 } 354 isDisplayOccluded(int displayId)355 private boolean isDisplayOccluded(int displayId) { 356 return getDisplay(displayId).mOccluded; 357 } 358 359 /** 360 * @return true if Keyguard can be currently dismissed without entering credentials. 361 */ canDismissKeyguard()362 boolean canDismissKeyguard() { 363 return mWindowManager.mPolicy.isKeyguardTrustedLw() 364 || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId()); 365 } 366 resolveOccludeTransit()367 private int resolveOccludeTransit() { 368 final DisplayContent dc = mRootWindowContainer.getDefaultDisplay().mDisplayContent; 369 if (mBeforeUnoccludeTransit != TRANSIT_UNSET 370 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE 371 // TODO(b/113840485): Handle app transition for individual display. 372 && isDisplayOccluded(DEFAULT_DISPLAY)) { 373 374 // Reuse old transit in case we are occluding Keyguard again, meaning that we never 375 // actually occclude/unocclude Keyguard, but just run a normal transition. 376 return mBeforeUnoccludeTransit; 377 // TODO(b/113840485): Handle app transition for individual display. 378 } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) { 379 380 // Save transit in case we dismiss/occlude Keyguard shortly after. 381 mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition(); 382 return TRANSIT_KEYGUARD_UNOCCLUDE; 383 } else { 384 return TRANSIT_KEYGUARD_OCCLUDE; 385 } 386 } 387 dismissDockedStackIfNeeded()388 private void dismissDockedStackIfNeeded() { 389 // TODO(b/113840485): Handle docked stack for individual display. 390 if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) { 391 // The lock screen is currently showing, but is occluded by a window that can 392 // show on top of the lock screen. In this can we want to dismiss the docked 393 // stack since it will be complicated/risky to try to put the activity on top 394 // of the lock screen in the right fullscreen configuration. 395 final TaskDisplayArea taskDisplayArea = mRootWindowContainer 396 .getDefaultTaskDisplayArea(); 397 if (!taskDisplayArea.isSplitScreenModeActivated()) { 398 return; 399 } 400 taskDisplayArea.onSplitScreenModeDismissed(); 401 } 402 } 403 updateKeyguardSleepToken()404 private void updateKeyguardSleepToken() { 405 for (int displayNdx = mRootWindowContainer.getChildCount() - 1; 406 displayNdx >= 0; displayNdx--) { 407 final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx); 408 updateKeyguardSleepToken(display.mDisplayId); 409 } 410 } 411 updateKeyguardSleepToken(int displayId)412 private void updateKeyguardSleepToken(int displayId) { 413 final KeyguardDisplayState state = getDisplay(displayId); 414 if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) { 415 state.acquiredSleepToken(); 416 } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) { 417 state.releaseSleepToken(); 418 } 419 } 420 getDisplay(int displayId)421 private KeyguardDisplayState getDisplay(int displayId) { 422 KeyguardDisplayState state = mDisplayStates.get(displayId); 423 if (state == null) { 424 state = new KeyguardDisplayState(mService, displayId); 425 mDisplayStates.append(displayId, state); 426 } 427 return state; 428 } 429 onDisplayRemoved(int displayId)430 void onDisplayRemoved(int displayId) { 431 final KeyguardDisplayState state = mDisplayStates.get(displayId); 432 if (state != null) { 433 state.onRemoved(); 434 mDisplayStates.remove(displayId); 435 } 436 } 437 438 /** Represents Keyguard state per individual display. */ 439 private static class KeyguardDisplayState { 440 private final int mDisplayId; 441 private boolean mOccluded; 442 private ActivityRecord mDismissingKeyguardActivity; 443 private boolean mRequestDismissKeyguard; 444 private final ActivityTaskManagerService mService; 445 private SleepToken mSleepToken; 446 KeyguardDisplayState(ActivityTaskManagerService service, int displayId)447 KeyguardDisplayState(ActivityTaskManagerService service, int displayId) { 448 mService = service; 449 mDisplayId = displayId; 450 } 451 onRemoved()452 void onRemoved() { 453 mDismissingKeyguardActivity = null; 454 releaseSleepToken(); 455 } 456 acquiredSleepToken()457 void acquiredSleepToken() { 458 if (mSleepToken == null) { 459 mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId); 460 } 461 } 462 releaseSleepToken()463 void releaseSleepToken() { 464 if (mSleepToken != null) { 465 mSleepToken.release(); 466 mSleepToken = null; 467 } 468 } 469 visibilitiesUpdated(KeyguardController controller, DisplayContent display)470 void visibilitiesUpdated(KeyguardController controller, DisplayContent display) { 471 final boolean lastOccluded = mOccluded; 472 final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity; 473 mRequestDismissKeyguard = false; 474 mOccluded = false; 475 mDismissingKeyguardActivity = null; 476 477 final ActivityStack stack = getStackForControllingOccluding(display); 478 if (stack != null) { 479 final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity(); 480 mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null 481 && stack.topRunningActivity() == topDismissing 482 && controller.canShowWhileOccluded( 483 true /* dismissKeyguard */, 484 false /* showWhenLocked */)); 485 if (stack.getTopDismissingKeyguardActivity() != null) { 486 mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity(); 487 } 488 // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display. 489 if (mDisplayId != DEFAULT_DISPLAY) { 490 mOccluded |= stack.canShowWithInsecureKeyguard() 491 && controller.canDismissKeyguard(); 492 } 493 } 494 // TODO(b/123372519): isShowingDream can only works on default display. 495 if (mDisplayId == DEFAULT_DISPLAY) { 496 mOccluded |= mService.mRootWindowContainer.getDefaultDisplay().mDisplayContent 497 .getDisplayPolicy().isShowingDreamLw(); 498 } 499 500 if (lastOccluded != mOccluded) { 501 controller.handleOccludedChanged(mDisplayId); 502 } 503 if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded 504 && mDismissingKeyguardActivity != null 505 && controller.mWindowManager.isKeyguardSecure( 506 controller.mService.getCurrentUserId())) { 507 mRequestDismissKeyguard = true; 508 } 509 } 510 511 /** 512 * Gets the stack used to check the occluded state. 513 * <p> 514 * Only the top non-pinned activity of the focusable stack on each display can control its 515 * occlusion state. 516 */ getStackForControllingOccluding(DisplayContent display)517 private ActivityStack getStackForControllingOccluding(DisplayContent display) { 518 for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) { 519 final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx); 520 for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) { 521 final ActivityStack stack = taskDisplayArea.getStackAt(sNdx); 522 if (stack != null && stack.isFocusableAndVisible() 523 && !stack.inPinnedWindowingMode()) { 524 return stack; 525 } 526 } 527 } 528 return null; 529 } 530 dumpStatus(PrintWriter pw, String prefix)531 void dumpStatus(PrintWriter pw, String prefix) { 532 final StringBuilder sb = new StringBuilder(); 533 sb.append(prefix); 534 sb.append(" Occluded=").append(mOccluded) 535 .append(" DismissingKeyguardActivity=") 536 .append(mDismissingKeyguardActivity) 537 .append(" at display=") 538 .append(mDisplayId); 539 pw.println(sb.toString()); 540 } 541 dumpDebug(ProtoOutputStream proto, long fieldId)542 void dumpDebug(ProtoOutputStream proto, long fieldId) { 543 final long token = proto.start(fieldId); 544 proto.write(DISPLAY_ID, mDisplayId); 545 proto.write(KEYGUARD_OCCLUDED, mOccluded); 546 proto.end(token); 547 } 548 } 549 dump(PrintWriter pw, String prefix)550 void dump(PrintWriter pw, String prefix) { 551 pw.println(prefix + "KeyguardController:"); 552 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing); 553 pw.println(prefix + " mAodShowing=" + mAodShowing); 554 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway); 555 dumpDisplayStates(pw, prefix); 556 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested); 557 pw.println(); 558 } 559 dumpDebug(ProtoOutputStream proto, long fieldId)560 void dumpDebug(ProtoOutputStream proto, long fieldId) { 561 final long token = proto.start(fieldId); 562 proto.write(AOD_SHOWING, mAodShowing); 563 proto.write(KEYGUARD_SHOWING, mKeyguardShowing); 564 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES); 565 proto.end(token); 566 } 567 dumpDisplayStates(PrintWriter pw, String prefix)568 private void dumpDisplayStates(PrintWriter pw, String prefix) { 569 for (int i = 0; i < mDisplayStates.size(); i++) { 570 mDisplayStates.valueAt(i).dumpStatus(pw, prefix); 571 } 572 } 573 writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId)574 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) { 575 for (int i = 0; i < mDisplayStates.size(); i++) { 576 mDisplayStates.valueAt(i).dumpDebug(proto, fieldId); 577 } 578 } 579 } 580