• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
20 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
21 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
22 import static android.view.Display.DEFAULT_DISPLAY;
23 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_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_SHADE;
26 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
27 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
28 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
29 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
30 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
31 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
32 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
33 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
34 
35 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
36 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
37 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
38 import static com.android.server.wm.KeyguardControllerProto.AOD_SHOWING;
39 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
40 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_SHOWING;
41 import static com.android.server.wm.KeyguardOccludedProto.DISPLAY_ID;
42 import static com.android.server.wm.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
43 
44 import android.annotation.Nullable;
45 import android.os.IBinder;
46 import android.os.RemoteException;
47 import android.os.Trace;
48 import android.util.Slog;
49 import android.util.SparseArray;
50 import android.util.proto.ProtoOutputStream;
51 import android.view.Display;
52 
53 import com.android.internal.policy.IKeyguardDismissCallback;
54 import com.android.server.inputmethod.InputMethodManagerInternal;
55 import com.android.server.policy.WindowManagerPolicy;
56 
57 import java.io.PrintWriter;
58 
59 /**
60  * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
61  * currently visible.
62  * <p>
63  * Note that everything in this class should only be accessed with the AM lock being held.
64  */
65 class KeyguardController {
66 
67     private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM;
68 
69     static final String KEYGUARD_SLEEP_TOKEN_TAG = "keyguard";
70 
71     private final ActivityTaskSupervisor mTaskSupervisor;
72     private WindowManagerService mWindowManager;
73     private boolean mKeyguardShowing;
74     private boolean mAodShowing;
75     private boolean mKeyguardGoingAway;
76     private boolean mDismissalRequested;
77     private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
78     private final ActivityTaskManagerService mService;
79     private RootWindowContainer mRootWindowContainer;
80     private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
81 
82 
KeyguardController(ActivityTaskManagerService service, ActivityTaskSupervisor taskSupervisor)83     KeyguardController(ActivityTaskManagerService service,
84             ActivityTaskSupervisor taskSupervisor) {
85         mService = service;
86         mTaskSupervisor = taskSupervisor;
87         mSleepTokenAcquirer = mService.new SleepTokenAcquirerImpl(KEYGUARD_SLEEP_TOKEN_TAG);
88     }
89 
setWindowManager(WindowManagerService windowManager)90     void setWindowManager(WindowManagerService windowManager) {
91         mWindowManager = windowManager;
92         mRootWindowContainer = mService.mRootWindowContainer;
93     }
94 
isAodShowing()95     boolean isAodShowing() {
96         return mAodShowing;
97     }
98 
99     /**
100      * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
101      *         on the given display, false otherwise.
102      */
isKeyguardOrAodShowing(int displayId)103     boolean isKeyguardOrAodShowing(int displayId) {
104         return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
105                 && !isDisplayOccluded(displayId);
106     }
107 
108     /**
109      * @return {@code true} for default display when AOD is showing. Otherwise, same as
110      *         {@link #isKeyguardOrAodShowing(int)}
111      * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic.
112      */
isKeyguardUnoccludedOrAodShowing(int displayId)113     boolean isKeyguardUnoccludedOrAodShowing(int displayId) {
114         if (displayId == DEFAULT_DISPLAY && mAodShowing) {
115             return true;
116         }
117         return isKeyguardOrAodShowing(displayId);
118     }
119 
120     /**
121      * @return true if Keyguard is showing, not going away, and not being occluded on the given
122      *         display, false otherwise
123      */
isKeyguardShowing(int displayId)124     boolean isKeyguardShowing(int displayId) {
125         return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
126     }
127 
128     /**
129      * @return true if Keyguard is either showing or occluded, but not going away
130      */
isKeyguardLocked()131     boolean isKeyguardLocked() {
132         return mKeyguardShowing && !mKeyguardGoingAway;
133     }
134 
135     /**
136      *
137      * @return true if the activity is controlling keyguard state.
138      */
topActivityOccludesKeyguard(ActivityRecord r)139     boolean topActivityOccludesKeyguard(ActivityRecord r) {
140         return getDisplayState(r.getDisplayId()).mTopOccludesActivity == r;
141     }
142 
143     /**
144      * @return {@code true} if the keyguard is going away, {@code false} otherwise.
145      */
isKeyguardGoingAway()146     boolean isKeyguardGoingAway() {
147         // Also check keyguard showing in case value is stale.
148         return mKeyguardGoingAway && mKeyguardShowing;
149     }
150 
151     /**
152      * Update the Keyguard showing state.
153      */
setKeyguardShown(boolean keyguardShowing, boolean aodShowing)154     void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) {
155         final boolean aodChanged = aodShowing != mAodShowing;
156         // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
157         // Do not reset keyguardChanged status if this is aodChanged.
158         final boolean keyguardChanged = (keyguardShowing != mKeyguardShowing)
159                 || (mKeyguardGoingAway && keyguardShowing && !aodChanged);
160         if (!keyguardChanged && !aodChanged) {
161             return;
162         }
163         EventLogTags.writeWmSetKeyguardShown(
164                 keyguardShowing ? 1 : 0,
165                 aodShowing ? 1 : 0,
166                 mKeyguardGoingAway ? 1 : 0,
167                 "setKeyguardShown");
168 
169         // Update the task snapshot if the screen will not be turned off. To make sure that the
170         // unlocking animation can animate consistent content. The conditions are:
171         // - Either AOD or keyguard changes to be showing. So if the states change individually,
172         //   the later one can be skipped to avoid taking snapshot again. While it still accepts
173         //   if both of them change to show at the same time.
174         // - Keyguard was not going away. Because if it was, the closing transition is able to
175         //   handle the snapshot.
176         // - The display state is ON. Because if AOD is not on or pulsing, the display state will
177         //   be OFF or DOZE (the path of screen off may have handled it).
178         if (((aodShowing ^ keyguardShowing) || (aodShowing && aodChanged && keyguardChanged))
179                 && !mKeyguardGoingAway && Display.isOnState(
180                         mRootWindowContainer.getDefaultDisplay().getDisplayInfo().state)) {
181             mWindowManager.mTaskSnapshotController.snapshotForSleeping(DEFAULT_DISPLAY);
182         }
183 
184         mKeyguardShowing = keyguardShowing;
185         mAodShowing = aodShowing;
186         if (aodChanged) {
187             // Ensure the new state takes effect.
188             mWindowManager.mWindowPlacerLocked.performSurfacePlacement();
189         }
190 
191         if (keyguardChanged) {
192             // Irrelevant to AOD.
193             dismissMultiWindowModeForTaskIfNeeded(null /* currentTaskControllsingOcclusion */,
194                     false /* turningScreenOn */);
195             mKeyguardGoingAway = false;
196             if (keyguardShowing) {
197                 mDismissalRequested = false;
198             }
199         }
200 
201         // Update the sleep token first such that ensureActivitiesVisible has correct sleep token
202         // state when evaluating visibilities.
203         updateKeyguardSleepToken();
204         mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
205         InputMethodManagerInternal.get().updateImeWindowStatus(false /* disableImeIcon */);
206     }
207 
208     /**
209      * Called when Keyguard is going away.
210      *
211      * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
212      *              etc.
213      */
keyguardGoingAway(int flags)214     void keyguardGoingAway(int flags) {
215         if (!mKeyguardShowing) {
216             return;
217         }
218         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway");
219         mService.deferWindowLayout();
220         mKeyguardGoingAway = true;
221         try {
222             EventLogTags.writeWmSetKeyguardShown(
223                     1 /* keyguardShowing */,
224                     mAodShowing ? 1 : 0,
225                     1 /* keyguardGoingAway */,
226                     "keyguardGoingAway");
227             mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare(
228                     TRANSIT_KEYGUARD_GOING_AWAY, convertTransitFlags(flags));
229             updateKeyguardSleepToken();
230 
231             // Some stack visibility might change (e.g. docked stack)
232             mRootWindowContainer.resumeFocusedTasksTopActivities();
233             mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
234             mRootWindowContainer.addStartingWindowsForVisibleActivities();
235             mWindowManager.executeAppTransition();
236         } finally {
237             mService.continueWindowLayout();
238             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
239         }
240     }
241 
dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message)242     void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
243         final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
244         if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
245             failCallback(callback);
246             return;
247         }
248         Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
249 
250         // If the client has requested to dismiss the keyguard and the Activity has the flag to
251         // turn the screen on, wakeup the screen if it's the top Activity.
252         if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) {
253             mTaskSupervisor.wakeUp("dismissKeyguard");
254         }
255 
256         mWindowManager.dismissKeyguard(callback, message);
257     }
258 
failCallback(IKeyguardDismissCallback callback)259     private void failCallback(IKeyguardDismissCallback callback) {
260         try {
261             callback.onDismissError();
262         } catch (RemoteException e) {
263             Slog.w(TAG, "Failed to call callback", e);
264         }
265     }
266 
convertTransitFlags(int keyguardGoingAwayFlags)267     private int convertTransitFlags(int keyguardGoingAwayFlags) {
268         int result = 0;
269         if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
270             result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
271         }
272         if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
273             result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
274         }
275         if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
276             result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
277         }
278         if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS) != 0) {
279             result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
280         }
281         return result;
282     }
283 
284     /**
285      * @return True if we may show an activity while Keyguard is showing because we are in the
286      *         process of dismissing it anyways, false otherwise.
287      */
canShowActivityWhileKeyguardShowing(ActivityRecord r)288     boolean canShowActivityWhileKeyguardShowing(ActivityRecord r) {
289         // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
290         // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
291         // Keyguard.
292         return r.containsDismissKeyguardWindow() && canDismissKeyguard() && !mAodShowing
293                 && (mDismissalRequested
294                 || (r.canShowWhenLocked()
295                         && getDisplayState(r.getDisplayId()).mDismissingKeyguardActivity != r));
296     }
297 
298     /**
299      * @return True if we may show an activity while Keyguard is occluded, false otherwise.
300      */
canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked)301     boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
302         return showWhenLocked || dismissKeyguard
303                 && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
304     }
305 
306     /**
307      * Checks whether {@param r} should be visible depending on Keyguard state.
308      *
309      * @return true if {@param r} is visible taken Keyguard state into account, false otherwise
310      */
checkKeyguardVisibility(ActivityRecord r)311     boolean checkKeyguardVisibility(ActivityRecord r) {
312         if (r.mDisplayContent.canShowWithInsecureKeyguard() && canDismissKeyguard()) {
313             return true;
314         }
315 
316         if (isKeyguardOrAodShowing(r.mDisplayContent.getDisplayId())) {
317             // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
318             // right away and AOD isn't visible.
319             return canShowActivityWhileKeyguardShowing(r);
320         } else if (isKeyguardLocked()) {
321             return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked());
322         } else {
323             return true;
324         }
325     }
326 
327     /**
328      * Makes sure to update lockscreen occluded/dismiss/turnScreenOn state if needed before
329      * completing set all visibility
330      * ({@link ActivityTaskSupervisor#beginActivityVisibilityUpdate}).
331      */
updateVisibility()332     void updateVisibility() {
333         boolean requestDismissKeyguard = false;
334         for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
335              displayNdx >= 0; displayNdx--) {
336             final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
337             final KeyguardDisplayState state = getDisplayState(display.mDisplayId);
338             state.updateVisibility(this, display);
339             requestDismissKeyguard |= state.mRequestDismissKeyguard;
340         }
341 
342         // Dismissing Keyguard happens globally using the information from all displays.
343         if (requestDismissKeyguard) {
344             handleDismissKeyguard();
345         }
346     }
347 
348     /**
349      * Called when occluded state changed.
350      *
351      * @param topActivity the activity that controls the state whether keyguard should
352      *      be occluded. That is the activity to be shown on top of keyguard if it requests so.
353      */
handleOccludedChanged(int displayId, @Nullable ActivityRecord topActivity)354     private void handleOccludedChanged(int displayId, @Nullable ActivityRecord topActivity) {
355         // TODO(b/113840485): Handle app transition for individual display, and apply occluded
356         // state change to secondary displays.
357         // For now, only default display fully supports occluded change. Other displays only
358         // updates keygaurd sleep token on that display.
359         if (displayId != DEFAULT_DISPLAY) {
360             updateKeyguardSleepToken(displayId);
361             return;
362         }
363 
364         mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY));
365         if (isKeyguardLocked()) {
366             mService.deferWindowLayout();
367             try {
368                 mRootWindowContainer.getDefaultDisplay()
369                         .prepareAppTransition(
370                                 isDisplayOccluded(DEFAULT_DISPLAY)
371                                         ? TRANSIT_KEYGUARD_OCCLUDE
372                                         : TRANSIT_KEYGUARD_UNOCCLUDE);
373                 // When the occluding activity also turns on the display, visibility of the activity
374                 // can be committed before KEYGUARD_OCCLUDE transition is handled.
375                 // Set mRequestForceTransition flag to make sure that the app transition animation
376                 // is applied for such case.
377                 // TODO(b/194243906): Fix this before enabling the remote keyguard animation.
378                 if (WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation
379                         && topActivity != null) {
380                     topActivity.mRequestForceTransition = true;
381                 }
382                 updateKeyguardSleepToken(DEFAULT_DISPLAY);
383                 mWindowManager.executeAppTransition();
384             } finally {
385                 mService.continueWindowLayout();
386             }
387         }
388     }
389 
390     /**
391      * Called when somebody wants to dismiss the Keyguard via the flag.
392      */
handleDismissKeyguard()393     private void handleDismissKeyguard() {
394         // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
395         // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
396         // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
397         if (!mWindowManager.isKeyguardSecure(mService.getCurrentUserId())) {
398             return;
399         }
400 
401         mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
402         mDismissalRequested = true;
403 
404         // If we are about to unocclude the Keyguard, but we can dismiss it without security,
405         // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
406         final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
407         if (mKeyguardShowing && canDismissKeyguard()
408                 && dc.mAppTransition.containsTransitRequest(TRANSIT_KEYGUARD_UNOCCLUDE)) {
409             mWindowManager.executeAppTransition();
410         }
411     }
412 
413     /**
414      * Called when somebody wants to turn screen on.
415      */
handleTurnScreenOn(int displayId)416     private void handleTurnScreenOn(int displayId) {
417         if (displayId != DEFAULT_DISPLAY) {
418             return;
419         }
420 
421         mTaskSupervisor.wakeUp("handleTurnScreenOn");
422         if (mKeyguardShowing && canDismissKeyguard()) {
423             mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
424             mDismissalRequested = true;
425         }
426     }
427 
isDisplayOccluded(int displayId)428     boolean isDisplayOccluded(int displayId) {
429         return getDisplayState(displayId).mOccluded;
430     }
431 
432     /**
433      * @return true if Keyguard can be currently dismissed without entering credentials.
434      */
canDismissKeyguard()435     boolean canDismissKeyguard() {
436         return mWindowManager.mPolicy.isKeyguardTrustedLw()
437                 || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
438     }
439 
dismissMultiWindowModeForTaskIfNeeded( @ullable Task currentTaskControllingOcclusion, boolean turningScreenOn)440     private void dismissMultiWindowModeForTaskIfNeeded(
441             @Nullable Task currentTaskControllingOcclusion, boolean turningScreenOn) {
442         // If turningScreenOn is true, it means that the visibility state has changed from
443         // currentTaskControllingOcclusion and we should update windowing mode.
444         // TODO(b/113840485): Handle docked stack for individual display.
445         if (!turningScreenOn && (!mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY))) {
446             return;
447         }
448 
449         // Dismiss split screen
450         // The lock screen is currently showing, but is occluded by a window that can
451         // show on top of the lock screen. In this can we want to dismiss the docked
452         // stack since it will be complicated/risky to try to put the activity on top
453         // of the lock screen in the right fullscreen configuration.
454         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
455         if (taskDisplayArea.isSplitScreenModeActivated()) {
456             taskDisplayArea.onSplitScreenModeDismissed();
457         }
458 
459         // Dismiss freeform windowing mode
460         if (currentTaskControllingOcclusion == null) {
461             return;
462         }
463         if (currentTaskControllingOcclusion.inFreeformWindowingMode()) {
464             currentTaskControllingOcclusion.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
465         }
466     }
467 
updateKeyguardSleepToken()468     private void updateKeyguardSleepToken() {
469         for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
470              displayNdx >= 0; displayNdx--) {
471             final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
472             updateKeyguardSleepToken(display.mDisplayId);
473         }
474     }
475 
updateKeyguardSleepToken(int displayId)476     private void updateKeyguardSleepToken(int displayId) {
477         final KeyguardDisplayState state = getDisplayState(displayId);
478         if (isKeyguardUnoccludedOrAodShowing(displayId)) {
479             state.mSleepTokenAcquirer.acquire(displayId);
480         } else if (!isKeyguardUnoccludedOrAodShowing(displayId)) {
481             state.mSleepTokenAcquirer.release(displayId);
482         }
483     }
484 
getDisplayState(int displayId)485     private KeyguardDisplayState getDisplayState(int displayId) {
486         KeyguardDisplayState state = mDisplayStates.get(displayId);
487         if (state == null) {
488             state = new KeyguardDisplayState(mService, displayId, mSleepTokenAcquirer);
489             mDisplayStates.append(displayId, state);
490         }
491         return state;
492     }
493 
onDisplayRemoved(int displayId)494     void onDisplayRemoved(int displayId) {
495         final KeyguardDisplayState state = mDisplayStates.get(displayId);
496         if (state != null) {
497             state.onRemoved();
498             mDisplayStates.remove(displayId);
499         }
500     }
501 
502     /** Represents Keyguard state per individual display. */
503     private static class KeyguardDisplayState {
504         private final int mDisplayId;
505         private boolean mOccluded;
506 
507         private ActivityRecord mTopOccludesActivity;
508         private ActivityRecord mDismissingKeyguardActivity;
509         private ActivityRecord mTopTurnScreenOnActivity;
510 
511         private boolean mRequestDismissKeyguard;
512         private final ActivityTaskManagerService mService;
513         private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
514 
KeyguardDisplayState(ActivityTaskManagerService service, int displayId, ActivityTaskManagerInternal.SleepTokenAcquirer acquirer)515         KeyguardDisplayState(ActivityTaskManagerService service, int displayId,
516                 ActivityTaskManagerInternal.SleepTokenAcquirer acquirer) {
517             mService = service;
518             mDisplayId = displayId;
519             mSleepTokenAcquirer = acquirer;
520         }
521 
onRemoved()522         void onRemoved() {
523             mTopOccludesActivity = null;
524             mDismissingKeyguardActivity = null;
525             mTopTurnScreenOnActivity = null;
526             mSleepTokenAcquirer.release(mDisplayId);
527         }
528 
529         /**
530          * Updates {@link #mOccluded}, {@link #mTopTurnScreenOnActivity} and
531          * {@link #mDismissingKeyguardActivity} if the top task could be visible.
532          */
updateVisibility(KeyguardController controller, DisplayContent display)533         void updateVisibility(KeyguardController controller, DisplayContent display) {
534             final boolean lastOccluded = mOccluded;
535 
536             final ActivityRecord lastDismissKeyguardActivity = mDismissingKeyguardActivity;
537             final ActivityRecord lastTurnScreenOnActivity = mTopTurnScreenOnActivity;
538 
539             mRequestDismissKeyguard = false;
540             mOccluded = false;
541 
542             mTopOccludesActivity = null;
543             mDismissingKeyguardActivity = null;
544             mTopTurnScreenOnActivity = null;
545 
546             boolean occludedByActivity = false;
547             final Task task = getRootTaskForControllingOccluding(display);
548             final ActivityRecord top = task != null ? task.getTopNonFinishingActivity() : null;
549             if (top != null) {
550                 if (top.containsDismissKeyguardWindow()) {
551                     mDismissingKeyguardActivity = top;
552                 }
553                 if (top.getTurnScreenOnFlag() && top.currentLaunchCanTurnScreenOn()) {
554                     mTopTurnScreenOnActivity = top;
555                 }
556 
557                 final boolean showWhenLocked = top.canShowWhenLocked();
558                 if (showWhenLocked) {
559                     mTopOccludesActivity = top;
560                 }
561 
562                 // Only the top activity may control occluded, as we can't occlude the Keyguard
563                 // if the top app doesn't want to occlude it.
564                 occludedByActivity = showWhenLocked || (mDismissingKeyguardActivity != null
565                         && task.topRunningActivity() == mDismissingKeyguardActivity
566                         && controller.canShowWhileOccluded(
567                                 true /* dismissKeyguard */, false /* showWhenLocked */));
568                 // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display.
569                 if (mDisplayId != DEFAULT_DISPLAY) {
570                     occludedByActivity |= display.canShowWithInsecureKeyguard()
571                             && controller.canDismissKeyguard();
572                 }
573             }
574 
575             final boolean dreaming = display.getDisplayPolicy().isShowingDreamLw() && (top != null
576                     && top.getActivityType() == ACTIVITY_TYPE_DREAM);
577             mOccluded = dreaming || occludedByActivity;
578             mRequestDismissKeyguard = lastDismissKeyguardActivity != mDismissingKeyguardActivity
579                     && !mOccluded
580                     && mDismissingKeyguardActivity != null
581                     && controller.mWindowManager.isKeyguardSecure(
582                     controller.mService.getCurrentUserId());
583 
584             boolean occludingChange = false;
585             boolean turningScreenOn = false;
586             if (mTopTurnScreenOnActivity != lastTurnScreenOnActivity
587                     && mTopTurnScreenOnActivity != null
588                     && !mService.mWindowManager.mPowerManager.isInteractive()
589                     && (mRequestDismissKeyguard || occludedByActivity
590                         || controller.canDismissKeyguard())) {
591                 turningScreenOn = true;
592                 controller.handleTurnScreenOn(mDisplayId);
593                 mTopTurnScreenOnActivity.setCurrentLaunchCanTurnScreenOn(false);
594             }
595 
596             if (lastOccluded != mOccluded) {
597                 occludingChange = true;
598                 controller.handleOccludedChanged(mDisplayId, mTopOccludesActivity);
599             }
600 
601             if (occludingChange || turningScreenOn) {
602                 controller.dismissMultiWindowModeForTaskIfNeeded(task, turningScreenOn);
603             }
604         }
605 
606         /**
607          * Gets the stack used to check the occluded state.
608          * <p>
609          * Only the top non-pinned activity of the focusable stack on each display can control its
610          * occlusion state.
611          */
612         @Nullable
getRootTaskForControllingOccluding(DisplayContent display)613         private Task getRootTaskForControllingOccluding(DisplayContent display) {
614             return display.getRootTask(task ->
615                     task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode());
616         }
617 
dumpStatus(PrintWriter pw, String prefix)618         void dumpStatus(PrintWriter pw, String prefix) {
619             final StringBuilder sb = new StringBuilder();
620             sb.append(prefix);
621             sb.append("  Occluded=").append(mOccluded)
622                     .append(" DismissingKeyguardActivity=")
623                     .append(mDismissingKeyguardActivity)
624                     .append(" TurnScreenOnActivity=")
625                     .append(mTopTurnScreenOnActivity)
626                     .append(" at display=")
627                     .append(mDisplayId);
628             pw.println(sb.toString());
629         }
630 
dumpDebug(ProtoOutputStream proto, long fieldId)631         void dumpDebug(ProtoOutputStream proto, long fieldId) {
632             final long token = proto.start(fieldId);
633             proto.write(DISPLAY_ID, mDisplayId);
634             proto.write(KEYGUARD_OCCLUDED, mOccluded);
635             proto.end(token);
636         }
637     }
638 
dump(PrintWriter pw, String prefix)639     void dump(PrintWriter pw, String prefix) {
640         pw.println(prefix + "KeyguardController:");
641         pw.println(prefix + "  mKeyguardShowing=" + mKeyguardShowing);
642         pw.println(prefix + "  mAodShowing=" + mAodShowing);
643         pw.println(prefix + "  mKeyguardGoingAway=" + mKeyguardGoingAway);
644         dumpDisplayStates(pw, prefix);
645         pw.println(prefix + "  mDismissalRequested=" + mDismissalRequested);
646         pw.println();
647     }
648 
dumpDebug(ProtoOutputStream proto, long fieldId)649     void dumpDebug(ProtoOutputStream proto, long fieldId) {
650         final long token = proto.start(fieldId);
651         proto.write(AOD_SHOWING, mAodShowing);
652         proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
653         writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
654         proto.end(token);
655     }
656 
dumpDisplayStates(PrintWriter pw, String prefix)657     private void dumpDisplayStates(PrintWriter pw, String prefix) {
658         for (int i = 0; i < mDisplayStates.size(); i++) {
659             mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
660         }
661     }
662 
writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId)663     private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
664         for (int i = 0; i < mDisplayStates.size(); i++) {
665             mDisplayStates.valueAt(i).dumpDebug(proto, fieldId);
666         }
667     }
668 }
669