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