blob: f672394251f223fca7f7855847ce5a8d75b56b92 [file] [log] [blame]
Jorim Jaggife762342016-10-13 14:33:27 +02001/*
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
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
Jorim Jaggife762342016-10-13 14:33:27 +020018
Riddle Hsu2ca561b2019-10-08 21:58:58 +080019import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
David Stevens9440dc82017-03-16 19:00:20 -070020import static android.view.Display.DEFAULT_DISPLAY;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070021import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
Issei Suzuki5609ccb2019-06-13 15:04:08 +020022import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070023import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
24import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
25import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
26import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
27import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
28import static android.view.WindowManager.TRANSIT_UNSET;
Adrian Roose99bc052017-11-20 17:55:31 +010029import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
Issei Suzuki5609ccb2019-06-13 15:04:08 +020030import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
Adrian Roose99bc052017-11-20 17:55:31 +010031import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
32import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
wilsonshih0299c8a2018-08-24 15:52:57 +080033
Evan Roskyaf9f27c2020-02-18 18:58:35 +000034import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
35import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
36import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwalef342f062020-01-27 07:34:13 -080037import static com.android.server.wm.KeyguardControllerProto.AOD_SHOWING;
38import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
39import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_SHOWING;
40import static com.android.server.wm.KeyguardOccludedProto.DISPLAY_ID;
41import static com.android.server.wm.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
Jorim Jaggife762342016-10-13 14:33:27 +020042
Jorim Jaggi241ae102016-11-02 21:57:33 -070043import android.os.IBinder;
44import android.os.RemoteException;
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -070045import android.os.Trace;
Jorim Jaggi241ae102016-11-02 21:57:33 -070046import android.util.Slog;
wilsonshih0299c8a2018-08-24 15:52:57 +080047import android.util.SparseArray;
Steven Timotius4346f0a2017-09-12 11:07:21 -070048import android.util.proto.ProtoOutputStream;
Adrian Roose99bc052017-11-20 17:55:31 +010049
Jorim Jaggi241ae102016-11-02 21:57:33 -070050import com.android.internal.policy.IKeyguardDismissCallback;
Adrian Roose99bc052017-11-20 17:55:31 +010051import com.android.server.policy.WindowManagerPolicy;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070052import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
Adrian Roose99bc052017-11-20 17:55:31 +010053
Jorim Jaggi8d786932016-10-26 19:08:36 -070054import java.io.PrintWriter;
Jorim Jaggife762342016-10-13 14:33:27 +020055
56/**
57 * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
58 * currently visible.
59 * <p>
60 * Note that everything in this class should only be accessed with the AM lock being held.
61 */
62class KeyguardController {
63
Wale Ogunwale98875612018-10-12 07:53:02 -070064 private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM;
Jorim Jaggi241ae102016-11-02 21:57:33 -070065
Jorim Jaggife762342016-10-13 14:33:27 +020066 private final ActivityStackSupervisor mStackSupervisor;
67 private WindowManagerService mWindowManager;
Jorim Jaggife762342016-10-13 14:33:27 +020068 private boolean mKeyguardShowing;
Lucas Dupin47a65c72018-02-15 14:16:18 -080069 private boolean mAodShowing;
Jorim Jaggi8d786932016-10-26 19:08:36 -070070 private boolean mKeyguardGoingAway;
Jorim Jaggi07961872016-11-23 11:28:57 +010071 private boolean mDismissalRequested;
Jorim Jaggife762342016-10-13 14:33:27 +020072 private int mBeforeUnoccludeTransit;
73 private int mVisibilityTransactionDepth;
wilsonshih0299c8a2018-08-24 15:52:57 +080074 private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
75 private final ActivityTaskManagerService mService;
Louis Chang149d5c82019-12-30 09:47:39 +080076 private RootWindowContainer mRootWindowContainer;
Jorim Jaggife762342016-10-13 14:33:27 +020077
Wale Ogunwalef6733932018-06-27 05:14:34 -070078 KeyguardController(ActivityTaskManagerService service,
Jorim Jaggife762342016-10-13 14:33:27 +020079 ActivityStackSupervisor stackSupervisor) {
80 mService = service;
81 mStackSupervisor = stackSupervisor;
82 }
83
84 void setWindowManager(WindowManagerService windowManager) {
85 mWindowManager = windowManager;
Louis Chang149d5c82019-12-30 09:47:39 +080086 mRootWindowContainer = mService.mRootWindowContainer;
Jorim Jaggife762342016-10-13 14:33:27 +020087 }
88
89 /**
Issei Suzuki16d4de52019-07-29 13:12:01 +000090 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
91 * on the given display, false otherwise.
Lucas Dupin47a65c72018-02-15 14:16:18 -080092 */
93 boolean isKeyguardOrAodShowing(int displayId) {
Issei Suzuki16d4de52019-07-29 13:12:01 +000094 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
95 && !isDisplayOccluded(displayId);
96 }
97
98 /**
99 * @return {@code true} for default display when AOD is showing. Otherwise, same as
100 * {@link #isKeyguardOrAodShowing(int)}
101 * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic.
102 */
103 boolean isKeyguardUnoccludedOrAodShowing(int displayId) {
104 if (displayId == DEFAULT_DISPLAY && mAodShowing) {
105 return true;
106 }
107 return isKeyguardOrAodShowing(displayId);
Issei Suzukid6eb5a22019-02-20 23:08:03 +0100108 }
109
110 /**
David Stevens53a39ea2017-08-23 18:41:49 -0700111 * @return true if Keyguard is showing, not going away, and not being occluded on the given
112 * display, false otherwise
Jorim Jaggife762342016-10-13 14:33:27 +0200113 */
David Stevens53a39ea2017-08-23 18:41:49 -0700114 boolean isKeyguardShowing(int displayId) {
Issei Suzuki16d4de52019-07-29 13:12:01 +0000115 return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
Jorim Jaggife762342016-10-13 14:33:27 +0200116 }
117
118 /**
119 * @return true if Keyguard is either showing or occluded, but not going away
120 */
121 boolean isKeyguardLocked() {
122 return mKeyguardShowing && !mKeyguardGoingAway;
123 }
124
125 /**
Bryce Lee271617a2018-03-15 10:39:12 -0700126 * @return {@code true} if the keyguard is going away, {@code false} otherwise.
127 */
128 boolean isKeyguardGoingAway() {
129 // Also check keyguard showing in case value is stale.
130 return mKeyguardGoingAway && mKeyguardShowing;
131 }
132
133 /**
Jorim Jaggife762342016-10-13 14:33:27 +0200134 * Update the Keyguard showing state.
135 */
wilsonshih177261f2019-02-22 12:02:18 +0800136 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) {
Adrian Roos6ec76b72018-04-25 14:01:11 +0200137 // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
wilsonshih2bc846c2019-05-02 14:35:21 +0800138 final boolean keyguardChanged = keyguardShowing != mKeyguardShowing
139 || mKeyguardGoingAway && keyguardShowing;
140 final boolean aodChanged = aodShowing != mAodShowing;
141 if (!keyguardChanged && !aodChanged) {
Jorim Jaggife762342016-10-13 14:33:27 +0200142 return;
143 }
Jeff Changd136e772019-11-05 20:33:52 +0800144 EventLogTags.writeWmSetKeyguardShown(
wilsonshih30eca702019-07-10 09:22:11 +0800145 keyguardShowing ? 1 : 0,
146 aodShowing ? 1 : 0,
147 mKeyguardGoingAway ? 1 : 0,
148 "setKeyguardShown");
Lucas Dupin47a65c72018-02-15 14:16:18 -0800149 mKeyguardShowing = keyguardShowing;
150 mAodShowing = aodShowing;
chaviw0e9fb132018-06-05 16:29:13 -0700151 mWindowManager.setAodShowing(aodShowing);
wilsonshih2bc846c2019-05-02 14:35:21 +0800152
153 if (keyguardChanged) {
154 // Irrelevant to AOD.
David Stevens53a39ea2017-08-23 18:41:49 -0700155 dismissDockedStackIfNeeded();
Andrii Kulian0d595f32018-02-21 15:47:33 -0800156 setKeyguardGoingAway(false);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800157 if (keyguardShowing) {
David Stevens53a39ea2017-08-23 18:41:49 -0700158 mDismissalRequested = false;
159 }
Jorim Jaggife762342016-10-13 14:33:27 +0200160 }
wilsonshih2bc846c2019-05-02 14:35:21 +0800161 // TODO(b/113840485): Check usage for non-default display
162 mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
163 isKeyguardOrAodShowing(DEFAULT_DISPLAY));
164
165 // Update the sleep token first such that ensureActivitiesVisible has correct sleep token
166 // state when evaluating visibilities.
David Stevens9440dc82017-03-16 19:00:20 -0700167 updateKeyguardSleepToken();
Louis Chang149d5c82019-12-30 09:47:39 +0800168 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Jorim Jaggife762342016-10-13 14:33:27 +0200169 }
170
171 /**
172 * Called when Keyguard is going away.
173 *
Adrian Roose99bc052017-11-20 17:55:31 +0100174 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
Jorim Jaggife762342016-10-13 14:33:27 +0200175 * etc.
176 */
177 void keyguardGoingAway(int flags) {
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700178 if (!mKeyguardShowing) {
179 return;
180 }
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800181 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway");
Riddle Hsua0022cd2019-09-09 21:12:41 +0800182 mService.deferWindowLayout();
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700183 try {
184 setKeyguardGoingAway(true);
Jeff Changd136e772019-11-05 20:33:52 +0800185 EventLogTags.writeWmSetKeyguardShown(
wilsonshih30eca702019-07-10 09:22:11 +0800186 1 /* keyguardShowing */,
187 mAodShowing ? 1 : 0,
188 1 /* keyguardGoingAway */,
189 "keyguardGoingAway");
Louis Chang149d5c82019-12-30 09:47:39 +0800190 mRootWindowContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800191 .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
192 false /* alwaysKeepCurrent */, convertTransitFlags(flags),
193 false /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700194 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200195
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700196 // Some stack visibility might change (e.g. docked stack)
Louis Chang149d5c82019-12-30 09:47:39 +0800197 mRootWindowContainer.resumeFocusedStacksTopActivities();
198 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
199 mRootWindowContainer.addStartingWindowsForVisibleActivities();
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700200 mWindowManager.executeAppTransition();
201 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800202 mService.continueWindowLayout();
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800203 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Jorim Jaggife762342016-10-13 14:33:27 +0200204 }
205 }
206
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800207 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700208 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
209 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
210 failCallback(callback);
211 return;
212 }
Jorim Jaggid7214892017-07-18 14:05:19 +0200213 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
chaviw59b98852017-06-13 12:05:44 -0700214
215 // If the client has requested to dismiss the keyguard and the Activity has the flag to
216 // turn the screen on, wakeup the screen if it's the top Activity.
217 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) {
218 mStackSupervisor.wakeUp("dismissKeyguard");
219 }
220
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800221 mWindowManager.dismissKeyguard(callback, message);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700222 }
223
Wale Ogunwalebfa81ad2017-05-24 15:14:42 -0700224 private void setKeyguardGoingAway(boolean keyguardGoingAway) {
225 mKeyguardGoingAway = keyguardGoingAway;
226 mWindowManager.setKeyguardGoingAway(keyguardGoingAway);
227 }
228
Jorim Jaggi241ae102016-11-02 21:57:33 -0700229 private void failCallback(IKeyguardDismissCallback callback) {
230 try {
231 callback.onDismissError();
232 } catch (RemoteException e) {
233 Slog.w(TAG, "Failed to call callback", e);
234 }
235 }
236
Jorim Jaggife762342016-10-13 14:33:27 +0200237 private int convertTransitFlags(int keyguardGoingAwayFlags) {
238 int result = 0;
239 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
240 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
241 }
242 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
243 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
244 }
245 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
246 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
247 }
Issei Suzuki5609ccb2019-06-13 15:04:08 +0200248 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS) != 0) {
249 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
250 }
Jorim Jaggife762342016-10-13 14:33:27 +0200251 return result;
252 }
253
254 /**
255 * Starts a batch of visibility updates.
256 */
257 void beginActivityVisibilityUpdate() {
258 mVisibilityTransactionDepth++;
259 }
260
261 /**
262 * Ends a batch of visibility updates. After all batches are done, this method makes sure to
263 * update lockscreen occluded/dismiss state if needed.
264 */
265 void endActivityVisibilityUpdate() {
266 mVisibilityTransactionDepth--;
267 if (mVisibilityTransactionDepth == 0) {
268 visibilitiesUpdated();
269 }
270 }
271
Jorim Jaggie69c9312016-10-31 18:24:38 -0700272 /**
273 * @return True if we may show an activity while Keyguard is showing because we are in the
274 * process of dismissing it anyways, false otherwise.
275 */
Jorim Jaggi07961872016-11-23 11:28:57 +0100276 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
277
278 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
279 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
280 // Keyguard.
Lucas Dupin47a65c72018-02-15 14:16:18 -0800281 return dismissKeyguard && canDismissKeyguard() && !mAodShowing
wilsonshih0299c8a2018-08-24 15:52:57 +0800282 && (mDismissalRequested
Arthur Hungcf58b332019-04-17 16:07:10 +0800283 || (r.canShowWhenLocked()
284 && getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r));
Jorim Jaggi07961872016-11-23 11:28:57 +0100285 }
286
287 /**
288 * @return True if we may show an activity while Keyguard is occluded, false otherwise.
289 */
290 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700291 return showWhenLocked || dismissKeyguard
292 && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
Jorim Jaggie69c9312016-10-31 18:24:38 -0700293 }
294
Jorim Jaggife762342016-10-13 14:33:27 +0200295 private void visibilitiesUpdated() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800296 boolean requestDismissKeyguard = false;
Louis Chang149d5c82019-12-30 09:47:39 +0800297 for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800298 displayNdx >= 0; displayNdx--) {
Louis Chang149d5c82019-12-30 09:47:39 +0800299 final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800300 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
301 state.visibilitiesUpdated(this, display);
302 requestDismissKeyguard |= state.mRequestDismissKeyguard;
Jorim Jaggife762342016-10-13 14:33:27 +0200303 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800304
305 // Dismissing Keyguard happens globally using the information from all displays.
306 if (requestDismissKeyguard) {
Jorim Jaggife762342016-10-13 14:33:27 +0200307 handleDismissKeyguard();
308 }
309 }
310
311 /**
312 * Called when occluded state changed.
313 */
Issei Suzuki62356a22019-04-11 16:46:37 +0200314 private void handleOccludedChanged(int displayId) {
315 // TODO(b/113840485): Handle app transition for individual display, and apply occluded
316 // state change to secondary displays.
317 // For now, only default display fully supports occluded change. Other displays only
318 // updates keygaurd sleep token on that display.
319 if (displayId != DEFAULT_DISPLAY) {
320 updateKeyguardSleepToken(displayId);
321 return;
322 }
323
Riddle Hsu8419e4b2019-09-18 23:28:01 +0800324 mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY));
Jorim Jaggife762342016-10-13 14:33:27 +0200325 if (isKeyguardLocked()) {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800326 mService.deferWindowLayout();
Jorim Jaggife762342016-10-13 14:33:27 +0200327 try {
Louis Chang149d5c82019-12-30 09:47:39 +0800328 mRootWindowContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800329 .prepareAppTransition(resolveOccludeTransit(),
330 false /* alwaysKeepCurrent */, 0 /* flags */,
331 true /* forceOverride */);
Issei Suzuki62356a22019-04-11 16:46:37 +0200332 updateKeyguardSleepToken(DEFAULT_DISPLAY);
Louis Chang149d5c82019-12-30 09:47:39 +0800333 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Jorim Jaggife762342016-10-13 14:33:27 +0200334 mWindowManager.executeAppTransition();
335 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800336 mService.continueWindowLayout();
Jorim Jaggife762342016-10-13 14:33:27 +0200337 }
338 }
339 dismissDockedStackIfNeeded();
340 }
341
342 /**
wilsonshih0299c8a2018-08-24 15:52:57 +0800343 * Called when somebody wants to dismiss the Keyguard via the flag.
Jorim Jaggife762342016-10-13 14:33:27 +0200344 */
345 private void handleDismissKeyguard() {
Jorim Jaggi07961872016-11-23 11:28:57 +0100346 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
347 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
348 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700349 if (!mWindowManager.isKeyguardSecure(mService.getCurrentUserId())) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800350 return;
351 }
Jorim Jaggife762342016-10-13 14:33:27 +0200352
Wale Ogunwaled32da472018-11-16 07:19:28 -0800353 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
354 mDismissalRequested = true;
355
356 // If we are about to unocclude the Keyguard, but we can dismiss it without security,
357 // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800358 final DisplayContent dc =
Louis Chang149d5c82019-12-30 09:47:39 +0800359 mRootWindowContainer.getDefaultDisplay().mDisplayContent;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800360 if (mKeyguardShowing && canDismissKeyguard()
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800361 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
362 dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
Wale Ogunwaled32da472018-11-16 07:19:28 -0800363 0 /* flags */, true /* forceOverride */);
Louis Chang149d5c82019-12-30 09:47:39 +0800364 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800365 mWindowManager.executeAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200366 }
367 }
368
Issei Suzuki16d4de52019-07-29 13:12:01 +0000369 private boolean isDisplayOccluded(int displayId) {
wilsonshih0299c8a2018-08-24 15:52:57 +0800370 return getDisplay(displayId).mOccluded;
371 }
372
Jorim Jaggife762342016-10-13 14:33:27 +0200373 /**
374 * @return true if Keyguard can be currently dismissed without entering credentials.
375 */
Andrii Kulianfc8f82b2017-01-26 13:17:27 -0800376 boolean canDismissKeyguard() {
Riddle Hsu8419e4b2019-09-18 23:28:01 +0800377 return mWindowManager.mPolicy.isKeyguardTrustedLw()
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700378 || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
Jorim Jaggife762342016-10-13 14:33:27 +0200379 }
380
381 private int resolveOccludeTransit() {
Louis Chang149d5c82019-12-30 09:47:39 +0800382 final DisplayContent dc = mRootWindowContainer.getDefaultDisplay().mDisplayContent;
Jorim Jaggife762342016-10-13 14:33:27 +0200383 if (mBeforeUnoccludeTransit != TRANSIT_UNSET
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800384 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
wilsonshih0299c8a2018-08-24 15:52:57 +0800385 // TODO(b/113840485): Handle app transition for individual display.
Issei Suzuki16d4de52019-07-29 13:12:01 +0000386 && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200387
388 // Reuse old transit in case we are occluding Keyguard again, meaning that we never
389 // actually occclude/unocclude Keyguard, but just run a normal transition.
390 return mBeforeUnoccludeTransit;
wilsonshih0299c8a2018-08-24 15:52:57 +0800391 // TODO(b/113840485): Handle app transition for individual display.
Issei Suzuki16d4de52019-07-29 13:12:01 +0000392 } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200393
394 // Save transit in case we dismiss/occlude Keyguard shortly after.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800395 mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200396 return TRANSIT_KEYGUARD_UNOCCLUDE;
397 } else {
398 return TRANSIT_KEYGUARD_OCCLUDE;
399 }
400 }
401
402 private void dismissDockedStackIfNeeded() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800403 // TODO(b/113840485): Handle docked stack for individual display.
Issei Suzuki16d4de52019-07-29 13:12:01 +0000404 if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200405 // The lock screen is currently showing, but is occluded by a window that can
406 // show on top of the lock screen. In this can we want to dismiss the docked
407 // stack since it will be complicated/risky to try to put the activity on top
408 // of the lock screen in the right fullscreen configuration.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700409 final TaskDisplayArea taskDisplayArea = mRootWindowContainer
410 .getDefaultTaskDisplayArea();
411 if (!taskDisplayArea.isSplitScreenModeActivated()) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700412 return;
413 }
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700414 taskDisplayArea.onSplitScreenModeDismissed();
Jorim Jaggife762342016-10-13 14:33:27 +0200415 }
416 }
Jorim Jaggi8d786932016-10-26 19:08:36 -0700417
David Stevens9440dc82017-03-16 19:00:20 -0700418 private void updateKeyguardSleepToken() {
Louis Chang149d5c82019-12-30 09:47:39 +0800419 for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800420 displayNdx >= 0; displayNdx--) {
Louis Chang149d5c82019-12-30 09:47:39 +0800421 final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
Issei Suzuki62356a22019-04-11 16:46:37 +0200422 updateKeyguardSleepToken(display.mDisplayId);
423 }
424 }
425
426 private void updateKeyguardSleepToken(int displayId) {
427 final KeyguardDisplayState state = getDisplay(displayId);
Issei Suzuki16d4de52019-07-29 13:12:01 +0000428 if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) {
Issei Suzuki62356a22019-04-11 16:46:37 +0200429 state.acquiredSleepToken();
Issei Suzuki16d4de52019-07-29 13:12:01 +0000430 } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) {
Issei Suzuki62356a22019-04-11 16:46:37 +0200431 state.releaseSleepToken();
wilsonshih0299c8a2018-08-24 15:52:57 +0800432 }
433 }
434
435 private KeyguardDisplayState getDisplay(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800436 KeyguardDisplayState state = mDisplayStates.get(displayId);
437 if (state == null) {
438 state = new KeyguardDisplayState(mService, displayId);
439 mDisplayStates.append(displayId, state);
wilsonshih0299c8a2018-08-24 15:52:57 +0800440 }
wilsonshihe7903ea2018-09-26 16:17:59 +0800441 return state;
wilsonshih0299c8a2018-08-24 15:52:57 +0800442 }
443
444 void onDisplayRemoved(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800445 final KeyguardDisplayState state = mDisplayStates.get(displayId);
446 if (state != null) {
447 state.onRemoved();
wilsonshih0299c8a2018-08-24 15:52:57 +0800448 mDisplayStates.remove(displayId);
449 }
450 }
451
452 /** Represents Keyguard state per individual display. */
453 private static class KeyguardDisplayState {
454 private final int mDisplayId;
455 private boolean mOccluded;
456 private ActivityRecord mDismissingKeyguardActivity;
457 private boolean mRequestDismissKeyguard;
458 private final ActivityTaskManagerService mService;
459 private SleepToken mSleepToken;
460
461 KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
462 mService = service;
463 mDisplayId = displayId;
464 }
465
466 void onRemoved() {
467 mDismissingKeyguardActivity = null;
468 releaseSleepToken();
469 }
470
471 void acquiredSleepToken() {
472 if (mSleepToken == null) {
473 mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId);
474 }
475 }
476
477 void releaseSleepToken() {
478 if (mSleepToken != null) {
479 mSleepToken.release();
480 mSleepToken = null;
481 }
482 }
483
Louis Chang677921f2019-12-06 16:44:24 +0800484 void visibilitiesUpdated(KeyguardController controller, DisplayContent display) {
wilsonshih0299c8a2018-08-24 15:52:57 +0800485 final boolean lastOccluded = mOccluded;
486 final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
487 mRequestDismissKeyguard = false;
488 mOccluded = false;
489 mDismissingKeyguardActivity = null;
490
wilsonshih9a10e9d2019-01-11 14:39:27 +0800491 final ActivityStack stack = getStackForControllingOccluding(display);
492 if (stack != null) {
493 final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
494 mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900495 && stack.topRunningActivity() == topDismissing
wilsonshih9a10e9d2019-01-11 14:39:27 +0800496 && controller.canShowWhileOccluded(
wilsonshih0299c8a2018-08-24 15:52:57 +0800497 true /* dismissKeyguard */,
498 false /* showWhenLocked */));
wilsonshih9a10e9d2019-01-11 14:39:27 +0800499 if (stack.getTopDismissingKeyguardActivity() != null) {
500 mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
wilsonshih0299c8a2018-08-24 15:52:57 +0800501 }
wilsonshih498a4b82018-12-11 16:10:16 +0800502 // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display.
503 if (mDisplayId != DEFAULT_DISPLAY) {
504 mOccluded |= stack.canShowWithInsecureKeyguard()
505 && controller.canDismissKeyguard();
506 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800507 }
wilsonshih498a4b82018-12-11 16:10:16 +0800508 // TODO(b/123372519): isShowingDream can only works on default display.
509 if (mDisplayId == DEFAULT_DISPLAY) {
Louis Chang149d5c82019-12-30 09:47:39 +0800510 mOccluded |= mService.mRootWindowContainer.getDefaultDisplay().mDisplayContent
Riddle Hsu8419e4b2019-09-18 23:28:01 +0800511 .getDisplayPolicy().isShowingDreamLw();
wilsonshih498a4b82018-12-11 16:10:16 +0800512 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800513
Issei Suzuki62356a22019-04-11 16:46:37 +0200514 if (lastOccluded != mOccluded) {
515 controller.handleOccludedChanged(mDisplayId);
wilsonshih0299c8a2018-08-24 15:52:57 +0800516 }
517 if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
518 && mDismissingKeyguardActivity != null
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700519 && controller.mWindowManager.isKeyguardSecure(
520 controller.mService.getCurrentUserId())) {
wilsonshih0299c8a2018-08-24 15:52:57 +0800521 mRequestDismissKeyguard = true;
522 }
523 }
524
wilsonshih9a10e9d2019-01-11 14:39:27 +0800525 /**
526 * Gets the stack used to check the occluded state.
527 * <p>
528 * Only the top non-pinned activity of the focusable stack on each display can control its
529 * occlusion state.
530 */
Louis Chang677921f2019-12-06 16:44:24 +0800531 private ActivityStack getStackForControllingOccluding(DisplayContent display) {
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700532 for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
533 final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
534 for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
535 final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
536 if (stack != null && stack.isFocusableAndVisible()
537 && !stack.inPinnedWindowingMode()) {
538 return stack;
539 }
wilsonshih9a10e9d2019-01-11 14:39:27 +0800540 }
541 }
542 return null;
543 }
544
wilsonshih0299c8a2018-08-24 15:52:57 +0800545 void dumpStatus(PrintWriter pw, String prefix) {
546 final StringBuilder sb = new StringBuilder();
547 sb.append(prefix);
548 sb.append(" Occluded=").append(mOccluded)
549 .append(" DismissingKeyguardActivity=")
550 .append(mDismissingKeyguardActivity)
551 .append(" at display=")
552 .append(mDisplayId);
553 pw.println(sb.toString());
554 }
555
Jeffrey Huangcb782852019-12-05 11:28:11 -0800556 void dumpDebug(ProtoOutputStream proto, long fieldId) {
wilsonshih0299c8a2018-08-24 15:52:57 +0800557 final long token = proto.start(fieldId);
558 proto.write(DISPLAY_ID, mDisplayId);
559 proto.write(KEYGUARD_OCCLUDED, mOccluded);
560 proto.end(token);
David Stevens9440dc82017-03-16 19:00:20 -0700561 }
562 }
563
Jorim Jaggi8d786932016-10-26 19:08:36 -0700564 void dump(PrintWriter pw, String prefix) {
565 pw.println(prefix + "KeyguardController:");
566 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800567 pw.println(prefix + " mAodShowing=" + mAodShowing);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700568 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
wilsonshih0299c8a2018-08-24 15:52:57 +0800569 dumpDisplayStates(pw, prefix);
Jorim Jaggi07961872016-11-23 11:28:57 +0100570 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700571 pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
Winson Chung268eccb2020-03-26 13:43:44 -0700572 pw.println();
Jorim Jaggi8d786932016-10-26 19:08:36 -0700573 }
Steven Timotius4346f0a2017-09-12 11:07:21 -0700574
Jeffrey Huangcb782852019-12-05 11:28:11 -0800575 void dumpDebug(ProtoOutputStream proto, long fieldId) {
Steven Timotius4346f0a2017-09-12 11:07:21 -0700576 final long token = proto.start(fieldId);
Issei Suzukid6eb5a22019-02-20 23:08:03 +0100577 proto.write(AOD_SHOWING, mAodShowing);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700578 proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
wilsonshih0299c8a2018-08-24 15:52:57 +0800579 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700580 proto.end(token);
581 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800582
583 private void dumpDisplayStates(PrintWriter pw, String prefix) {
584 for (int i = 0; i < mDisplayStates.size(); i++) {
585 mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
586 }
587 }
588
589 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
590 for (int i = 0; i < mDisplayStates.size(); i++) {
Jeffrey Huangcb782852019-12-05 11:28:11 -0800591 mDisplayStates.valueAt(i).dumpDebug(proto, fieldId);
wilsonshih0299c8a2018-08-24 15:52:57 +0800592 }
593 }
Jorim Jaggife762342016-10-13 14:33:27 +0200594}