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