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