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