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