blob: 9c41c77342e5a43588394852da69b5c805d9ad19 [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
17package com.android.server.am;
18
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -070019import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
David Stevens9440dc82017-03-16 19:00:20 -070020import static android.view.Display.DEFAULT_DISPLAY;
David Stevens53a39ea2017-08-23 18:41:49 -070021import static android.view.Display.INVALID_DISPLAY;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070022import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
23import 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;
30import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
31import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
wilsonshih0299c8a2018-08-24 15:52:57 +080032
Jorim Jaggife762342016-10-13 14:33:27 +020033import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Wale Ogunwale98875612018-10-12 07:53:02 -070034import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
35import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
wilsonshih0299c8a2018-08-24 15:52:57 +080036import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070037import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
wilsonshih0299c8a2018-08-24 15:52:57 +080038import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID;
39import static com.android.server.am.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
Jorim Jaggife762342016-10-13 14:33:27 +020040
Jorim Jaggi241ae102016-11-02 21:57:33 -070041import android.os.IBinder;
42import android.os.RemoteException;
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -070043import android.os.Trace;
Jorim Jaggi241ae102016-11-02 21:57:33 -070044import android.util.Slog;
wilsonshih0299c8a2018-08-24 15:52:57 +080045import android.util.SparseArray;
Steven Timotius4346f0a2017-09-12 11:07:21 -070046import android.util.proto.ProtoOutputStream;
Adrian Roose99bc052017-11-20 17:55:31 +010047
Jorim Jaggi241ae102016-11-02 21:57:33 -070048import com.android.internal.policy.IKeyguardDismissCallback;
Adrian Roose99bc052017-11-20 17:55:31 +010049import com.android.server.policy.WindowManagerPolicy;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070050import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
lumark588a3e82018-07-20 18:53:54 +080051import com.android.server.wm.DisplayWindowController;
Jorim Jaggife762342016-10-13 14:33:27 +020052import com.android.server.wm.WindowManagerService;
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 // TODO(b/111955725): Support multiple external displays
David Stevens53a39ea2017-08-23 18:41:49 -070075 private int mSecondaryDisplayShowing = INVALID_DISPLAY;
wilsonshih0299c8a2018-08-24 15:52:57 +080076 private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
77 private final ActivityTaskManagerService mService;
Jorim Jaggife762342016-10-13 14:33:27 +020078
Wale Ogunwalef6733932018-06-27 05:14:34 -070079 KeyguardController(ActivityTaskManagerService service,
Jorim Jaggife762342016-10-13 14:33:27 +020080 ActivityStackSupervisor stackSupervisor) {
81 mService = service;
82 mStackSupervisor = stackSupervisor;
83 }
84
85 void setWindowManager(WindowManagerService windowManager) {
86 mWindowManager = windowManager;
87 }
88
89 /**
Lucas Dupin47a65c72018-02-15 14:16:18 -080090 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
91 * on the given display, false otherwise
92 */
93 boolean isKeyguardOrAodShowing(int displayId) {
wilsonshih0299c8a2018-08-24 15:52:57 +080094 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
95 && !isDisplayOccluded(displayId);
Lucas Dupin47a65c72018-02-15 14:16:18 -080096 }
97
98 /**
David Stevens53a39ea2017-08-23 18:41:49 -070099 * @return true if Keyguard is showing, not going away, and not being occluded on the given
100 * display, false otherwise
Jorim Jaggife762342016-10-13 14:33:27 +0200101 */
David Stevens53a39ea2017-08-23 18:41:49 -0700102 boolean isKeyguardShowing(int displayId) {
wilsonshih0299c8a2018-08-24 15:52:57 +0800103 return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
Jorim Jaggife762342016-10-13 14:33:27 +0200104 }
105
106 /**
107 * @return true if Keyguard is either showing or occluded, but not going away
108 */
109 boolean isKeyguardLocked() {
110 return mKeyguardShowing && !mKeyguardGoingAway;
111 }
112
113 /**
Bryce Lee271617a2018-03-15 10:39:12 -0700114 * @return {@code true} if the keyguard is going away, {@code false} otherwise.
115 */
116 boolean isKeyguardGoingAway() {
117 // Also check keyguard showing in case value is stale.
118 return mKeyguardGoingAway && mKeyguardShowing;
119 }
120
121 /**
Jorim Jaggife762342016-10-13 14:33:27 +0200122 * Update the Keyguard showing state.
123 */
Lucas Dupin47a65c72018-02-15 14:16:18 -0800124 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing,
125 int secondaryDisplayShowing) {
126 boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
Adrian Roos6ec76b72018-04-25 14:01:11 +0200127 // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
128 showingChanged |= mKeyguardGoingAway && keyguardShowing;
David Stevens53a39ea2017-08-23 18:41:49 -0700129 if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) {
Jorim Jaggife762342016-10-13 14:33:27 +0200130 return;
131 }
Lucas Dupin47a65c72018-02-15 14:16:18 -0800132 mKeyguardShowing = keyguardShowing;
133 mAodShowing = aodShowing;
David Stevens53a39ea2017-08-23 18:41:49 -0700134 mSecondaryDisplayShowing = secondaryDisplayShowing;
chaviw0e9fb132018-06-05 16:29:13 -0700135 mWindowManager.setAodShowing(aodShowing);
David Stevens53a39ea2017-08-23 18:41:49 -0700136 if (showingChanged) {
137 dismissDockedStackIfNeeded();
Andrii Kulian0d595f32018-02-21 15:47:33 -0800138 setKeyguardGoingAway(false);
wilsonshih0299c8a2018-08-24 15:52:57 +0800139 // TODO(b/113840485): Check usage for non-default display
Adrian Roosb56b3c32018-05-17 17:32:26 +0200140 mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
141 isKeyguardOrAodShowing(DEFAULT_DISPLAY));
Lucas Dupin47a65c72018-02-15 14:16:18 -0800142 if (keyguardShowing) {
David Stevens53a39ea2017-08-23 18:41:49 -0700143 mDismissalRequested = false;
144 }
Jorim Jaggife762342016-10-13 14:33:27 +0200145 }
146 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
David Stevens9440dc82017-03-16 19:00:20 -0700147 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200148 }
149
150 /**
151 * Called when Keyguard is going away.
152 *
Adrian Roose99bc052017-11-20 17:55:31 +0100153 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
Jorim Jaggife762342016-10-13 14:33:27 +0200154 * etc.
155 */
156 void keyguardGoingAway(int flags) {
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700157 if (!mKeyguardShowing) {
158 return;
159 }
160 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway");
161 mWindowManager.deferSurfaceLayout();
162 try {
163 setKeyguardGoingAway(true);
lumark588a3e82018-07-20 18:53:54 +0800164 mStackSupervisor.getDefaultDisplay().getWindowContainerController()
165 .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
166 false /* alwaysKeepCurrent */, convertTransitFlags(flags),
167 false /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700168 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200169
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700170 // Some stack visibility might change (e.g. docked stack)
Andrii Kulianab132ee2018-07-24 22:10:21 +0800171 mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700172 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
173 mStackSupervisor.addStartingWindowsForVisibleActivities(true /* taskSwitch */);
174 mWindowManager.executeAppTransition();
175 } finally {
176 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
177 mWindowManager.continueSurfaceLayout();
178 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
179
180 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Jorim Jaggife762342016-10-13 14:33:27 +0200181 }
182 }
183
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800184 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700185 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
186 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
187 failCallback(callback);
188 return;
189 }
Jorim Jaggid7214892017-07-18 14:05:19 +0200190 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
chaviw59b98852017-06-13 12:05:44 -0700191
192 // If the client has requested to dismiss the keyguard and the Activity has the flag to
193 // turn the screen on, wakeup the screen if it's the top Activity.
194 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) {
195 mStackSupervisor.wakeUp("dismissKeyguard");
196 }
197
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800198 mWindowManager.dismissKeyguard(callback, message);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700199 }
200
Wale Ogunwalebfa81ad2017-05-24 15:14:42 -0700201 private void setKeyguardGoingAway(boolean keyguardGoingAway) {
202 mKeyguardGoingAway = keyguardGoingAway;
203 mWindowManager.setKeyguardGoingAway(keyguardGoingAway);
204 }
205
Jorim Jaggi241ae102016-11-02 21:57:33 -0700206 private void failCallback(IKeyguardDismissCallback callback) {
207 try {
208 callback.onDismissError();
209 } catch (RemoteException e) {
210 Slog.w(TAG, "Failed to call callback", e);
211 }
212 }
213
Jorim Jaggife762342016-10-13 14:33:27 +0200214 private int convertTransitFlags(int keyguardGoingAwayFlags) {
215 int result = 0;
216 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
217 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
218 }
219 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
220 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
221 }
222 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
223 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
224 }
225 return result;
226 }
227
228 /**
229 * Starts a batch of visibility updates.
230 */
231 void beginActivityVisibilityUpdate() {
232 mVisibilityTransactionDepth++;
233 }
234
235 /**
236 * Ends a batch of visibility updates. After all batches are done, this method makes sure to
237 * update lockscreen occluded/dismiss state if needed.
238 */
239 void endActivityVisibilityUpdate() {
240 mVisibilityTransactionDepth--;
241 if (mVisibilityTransactionDepth == 0) {
242 visibilitiesUpdated();
243 }
244 }
245
Jorim Jaggie69c9312016-10-31 18:24:38 -0700246 /**
247 * @return True if we may show an activity while Keyguard is showing because we are in the
248 * process of dismissing it anyways, false otherwise.
249 */
Jorim Jaggi07961872016-11-23 11:28:57 +0100250 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
251
252 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
253 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
254 // Keyguard.
Lucas Dupin47a65c72018-02-15 14:16:18 -0800255 return dismissKeyguard && canDismissKeyguard() && !mAodShowing
wilsonshih0299c8a2018-08-24 15:52:57 +0800256 && (mDismissalRequested
257 || getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r);
Jorim Jaggi07961872016-11-23 11:28:57 +0100258 }
259
260 /**
261 * @return True if we may show an activity while Keyguard is occluded, false otherwise.
262 */
263 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
264 return showWhenLocked || dismissKeyguard && !mWindowManager.isKeyguardSecure();
Jorim Jaggie69c9312016-10-31 18:24:38 -0700265 }
266
Jorim Jaggife762342016-10-13 14:33:27 +0200267 private void visibilitiesUpdated() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800268 boolean requestDismissKeyguard = false;
Pat Plunkett40426e02017-10-31 14:06:29 -0700269 for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) {
270 final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800271 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
272 state.visibilitiesUpdated(this, display);
273 requestDismissKeyguard |= state.mRequestDismissKeyguard;
Jorim Jaggife762342016-10-13 14:33:27 +0200274 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800275
276 // Dismissing Keyguard happens globally using the information from all displays.
277 if (requestDismissKeyguard) {
Jorim Jaggife762342016-10-13 14:33:27 +0200278 handleDismissKeyguard();
279 }
280 }
281
282 /**
283 * Called when occluded state changed.
284 */
285 private void handleOccludedChanged() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800286 mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY));
Jorim Jaggife762342016-10-13 14:33:27 +0200287 if (isKeyguardLocked()) {
288 mWindowManager.deferSurfaceLayout();
289 try {
lumark588a3e82018-07-20 18:53:54 +0800290 mStackSupervisor.getDefaultDisplay().getWindowContainerController()
291 .prepareAppTransition(resolveOccludeTransit(),
292 false /* alwaysKeepCurrent */, 0 /* flags */,
293 true /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700294 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200295 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
296 mWindowManager.executeAppTransition();
297 } finally {
298 mWindowManager.continueSurfaceLayout();
299 }
300 }
301 dismissDockedStackIfNeeded();
302 }
303
304 /**
wilsonshih0299c8a2018-08-24 15:52:57 +0800305 * Called when somebody wants to dismiss the Keyguard via the flag.
Jorim Jaggife762342016-10-13 14:33:27 +0200306 */
307 private void handleDismissKeyguard() {
Jorim Jaggi07961872016-11-23 11:28:57 +0100308 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
309 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
310 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
wilsonshih0299c8a2018-08-24 15:52:57 +0800311 if (mWindowManager.isKeyguardSecure()) {
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800312 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
Jorim Jaggi07961872016-11-23 11:28:57 +0100313 mDismissalRequested = true;
Jorim Jaggife762342016-10-13 14:33:27 +0200314
315 // If we are about to unocclude the Keyguard, but we can dismiss it without security,
316 // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
lumark588a3e82018-07-20 18:53:54 +0800317 final DisplayWindowController dwc =
318 mStackSupervisor.getDefaultDisplay().getWindowContainerController();
Jorim Jaggife762342016-10-13 14:33:27 +0200319 if (mKeyguardShowing && canDismissKeyguard()
lumark588a3e82018-07-20 18:53:54 +0800320 && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
321 dwc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
322 0 /* flags */, true /* forceOverride */);
Jorim Jaggife762342016-10-13 14:33:27 +0200323 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
324 mWindowManager.executeAppTransition();
325 }
326 }
327 }
328
wilsonshih0299c8a2018-08-24 15:52:57 +0800329 private boolean isDisplayOccluded(int displayId) {
330 return getDisplay(displayId).mOccluded;
331 }
332
Jorim Jaggife762342016-10-13 14:33:27 +0200333 /**
334 * @return true if Keyguard can be currently dismissed without entering credentials.
335 */
Andrii Kulianfc8f82b2017-01-26 13:17:27 -0800336 boolean canDismissKeyguard() {
Jorim Jaggife762342016-10-13 14:33:27 +0200337 return mWindowManager.isKeyguardTrusted() || !mWindowManager.isKeyguardSecure();
338 }
339
340 private int resolveOccludeTransit() {
lumark588a3e82018-07-20 18:53:54 +0800341 final DisplayWindowController dwc =
342 mStackSupervisor.getDefaultDisplay().getWindowContainerController();
Jorim Jaggife762342016-10-13 14:33:27 +0200343 if (mBeforeUnoccludeTransit != TRANSIT_UNSET
lumark588a3e82018-07-20 18:53:54 +0800344 && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
wilsonshih0299c8a2018-08-24 15:52:57 +0800345 // TODO(b/113840485): Handle app transition for individual display.
346 && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200347
348 // Reuse old transit in case we are occluding Keyguard again, meaning that we never
349 // actually occclude/unocclude Keyguard, but just run a normal transition.
350 return mBeforeUnoccludeTransit;
wilsonshih0299c8a2018-08-24 15:52:57 +0800351 // TODO(b/113840485): Handle app transition for individual display.
352 } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200353
354 // Save transit in case we dismiss/occlude Keyguard shortly after.
lumark588a3e82018-07-20 18:53:54 +0800355 mBeforeUnoccludeTransit = dwc.getPendingAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200356 return TRANSIT_KEYGUARD_UNOCCLUDE;
357 } else {
358 return TRANSIT_KEYGUARD_OCCLUDE;
359 }
360 }
361
362 private void dismissDockedStackIfNeeded() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800363 // TODO(b/113840485): Handle docked stack for individual display.
364 if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200365 // The lock screen is currently showing, but is occluded by a window that can
366 // show on top of the lock screen. In this can we want to dismiss the docked
367 // stack since it will be complicated/risky to try to put the activity on top
368 // of the lock screen in the right fullscreen configuration.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700369 final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700370 if (stack == null) {
371 return;
372 }
373 mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
Andrii Kulian52d255c2018-07-13 11:32:19 -0700374 stack.isFocusedStackOnDisplay());
Jorim Jaggife762342016-10-13 14:33:27 +0200375 }
376 }
Jorim Jaggi8d786932016-10-26 19:08:36 -0700377
David Stevens9440dc82017-03-16 19:00:20 -0700378 private void updateKeyguardSleepToken() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800379 for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) {
380 final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx);
381 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
382 if (isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken == null) {
383 state.acquiredSleepToken();
384 } else if (!isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken != null) {
385 state.releaseSleepToken();
386 }
387 }
388 }
389
390 private KeyguardDisplayState getDisplay(int displayId) {
391 if (mDisplayStates.get(displayId) == null) {
392 mDisplayStates.append(displayId,
393 new KeyguardDisplayState(mService, displayId));
394 }
395 return mDisplayStates.get(displayId);
396 }
397
398 void onDisplayRemoved(int displayId) {
399 if (mDisplayStates.get(displayId) != null) {
400 mDisplayStates.get(displayId).onRemoved();
401 mDisplayStates.remove(displayId);
402 }
403 }
404
405 /** Represents Keyguard state per individual display. */
406 private static class KeyguardDisplayState {
407 private final int mDisplayId;
408 private boolean mOccluded;
409 private ActivityRecord mDismissingKeyguardActivity;
410 private boolean mRequestDismissKeyguard;
411 private final ActivityTaskManagerService mService;
412 private SleepToken mSleepToken;
413
414 KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
415 mService = service;
416 mDisplayId = displayId;
417 }
418
419 void onRemoved() {
420 mDismissingKeyguardActivity = null;
421 releaseSleepToken();
422 }
423
424 void acquiredSleepToken() {
425 if (mSleepToken == null) {
426 mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId);
427 }
428 }
429
430 void releaseSleepToken() {
431 if (mSleepToken != null) {
432 mSleepToken.release();
433 mSleepToken = null;
434 }
435 }
436
437 void visibilitiesUpdated(KeyguardController controller, ActivityDisplay display) {
438 final boolean lastOccluded = mOccluded;
439 final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
440 mRequestDismissKeyguard = false;
441 mOccluded = false;
442 mDismissingKeyguardActivity = null;
443
444 // Only the top activity of the focused stack on each display may control it's
445 // occluded state.
446 final ActivityStack focusedStack = display.getFocusedStack();
447 if (focusedStack != null) {
448 final ActivityRecord topDismissing =
449 focusedStack.getTopDismissingKeyguardActivity();
450 mOccluded = focusedStack.topActivityOccludesKeyguard() || (topDismissing != null
451 && focusedStack.topRunningActivityLocked() == topDismissing
452 && controller.canShowWhileOccluded(
453 true /* dismissKeyguard */,
454 false /* showWhenLocked */));
455 if (focusedStack.getTopDismissingKeyguardActivity() != null) {
456 mDismissingKeyguardActivity = focusedStack.getTopDismissingKeyguardActivity();
457 }
458 mOccluded |= controller.mWindowManager.isShowingDream();
459 }
460
461 // TODO(b/113840485): Handle app transition for individual display.
462 // For now, only default display can change occluded.
463 if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) {
464 controller.handleOccludedChanged();
465 }
466 if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
467 && mDismissingKeyguardActivity != null
468 && controller.mWindowManager.isKeyguardSecure()) {
469 mRequestDismissKeyguard = true;
470 }
471 }
472
473 void dumpStatus(PrintWriter pw, String prefix) {
474 final StringBuilder sb = new StringBuilder();
475 sb.append(prefix);
476 sb.append(" Occluded=").append(mOccluded)
477 .append(" DismissingKeyguardActivity=")
478 .append(mDismissingKeyguardActivity)
479 .append(" at display=")
480 .append(mDisplayId);
481 pw.println(sb.toString());
482 }
483
484 void writeToProto(ProtoOutputStream proto, long fieldId) {
485 final long token = proto.start(fieldId);
486 proto.write(DISPLAY_ID, mDisplayId);
487 proto.write(KEYGUARD_OCCLUDED, mOccluded);
488 proto.end(token);
David Stevens9440dc82017-03-16 19:00:20 -0700489 }
490 }
491
Jorim Jaggi8d786932016-10-26 19:08:36 -0700492 void dump(PrintWriter pw, String prefix) {
493 pw.println(prefix + "KeyguardController:");
494 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800495 pw.println(prefix + " mAodShowing=" + mAodShowing);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700496 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
wilsonshih0299c8a2018-08-24 15:52:57 +0800497 dumpDisplayStates(pw, prefix);
Jorim Jaggi07961872016-11-23 11:28:57 +0100498 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700499 pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
500 }
Steven Timotius4346f0a2017-09-12 11:07:21 -0700501
502 void writeToProto(ProtoOutputStream proto, long fieldId) {
503 final long token = proto.start(fieldId);
504 proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
wilsonshih0299c8a2018-08-24 15:52:57 +0800505 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700506 proto.end(token);
507 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800508
509 private void dumpDisplayStates(PrintWriter pw, String prefix) {
510 for (int i = 0; i < mDisplayStates.size(); i++) {
511 mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
512 }
513 }
514
515 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
516 for (int i = 0; i < mDisplayStates.size(); i++) {
517 mDisplayStates.valueAt(i).writeToProto(proto, fieldId);
518 }
519 }
Jorim Jaggife762342016-10-13 14:33:27 +0200520}