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