blob: feb711abaeadb558f1d0015dbd8c89eb7fcd57ea [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
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;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070021import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
22import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
23import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
24import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
25import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
26import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
27import static android.view.WindowManager.TRANSIT_UNSET;
Adrian Roose99bc052017-11-20 17:55:31 +010028import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
29import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
30import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
wilsonshih0299c8a2018-08-24 15:52:57 +080031
wilsonshih0299c8a2018-08-24 15:52:57 +080032import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070033import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
wilsonshih0299c8a2018-08-24 15:52:57 +080034import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID;
35import static com.android.server.am.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
wilsonshihe7903ea2018-09-26 16:17:59 +080036import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
37import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
38import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Jorim Jaggife762342016-10-13 14:33:27 +020039
Jorim Jaggi241ae102016-11-02 21:57:33 -070040import android.os.IBinder;
41import android.os.RemoteException;
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -070042import android.os.Trace;
Jorim Jaggi241ae102016-11-02 21:57:33 -070043import android.util.Slog;
wilsonshih0299c8a2018-08-24 15:52:57 +080044import android.util.SparseArray;
Steven Timotius4346f0a2017-09-12 11:07:21 -070045import android.util.proto.ProtoOutputStream;
Adrian Roose99bc052017-11-20 17:55:31 +010046
Jorim Jaggi241ae102016-11-02 21:57:33 -070047import com.android.internal.policy.IKeyguardDismissCallback;
Adrian Roose99bc052017-11-20 17:55:31 +010048import com.android.server.policy.WindowManagerPolicy;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070049import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
Adrian Roose99bc052017-11-20 17:55:31 +010050
Jorim Jaggi8d786932016-10-26 19:08:36 -070051import java.io.PrintWriter;
Jorim Jaggife762342016-10-13 14:33:27 +020052
53/**
54 * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
55 * currently visible.
56 * <p>
57 * Note that everything in this class should only be accessed with the AM lock being held.
58 */
59class KeyguardController {
60
Wale Ogunwale98875612018-10-12 07:53:02 -070061 private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM;
Jorim Jaggi241ae102016-11-02 21:57:33 -070062
Jorim Jaggife762342016-10-13 14:33:27 +020063 private final ActivityStackSupervisor mStackSupervisor;
64 private WindowManagerService mWindowManager;
Jorim Jaggife762342016-10-13 14:33:27 +020065 private boolean mKeyguardShowing;
Lucas Dupin47a65c72018-02-15 14:16:18 -080066 private boolean mAodShowing;
Jorim Jaggi8d786932016-10-26 19:08:36 -070067 private boolean mKeyguardGoingAway;
Jorim Jaggi07961872016-11-23 11:28:57 +010068 private boolean mDismissalRequested;
wilsonshihe7903ea2018-09-26 16:17:59 +080069 private int[] mSecondaryDisplayIdsShowing;
Jorim Jaggife762342016-10-13 14:33:27 +020070 private int mBeforeUnoccludeTransit;
71 private int mVisibilityTransactionDepth;
wilsonshih0299c8a2018-08-24 15:52:57 +080072 private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
73 private final ActivityTaskManagerService mService;
Wale Ogunwaled32da472018-11-16 07:19:28 -080074 private RootActivityContainer mRootActivityContainer;
Jorim Jaggife762342016-10-13 14:33:27 +020075
Wale Ogunwalef6733932018-06-27 05:14:34 -070076 KeyguardController(ActivityTaskManagerService service,
Jorim Jaggife762342016-10-13 14:33:27 +020077 ActivityStackSupervisor stackSupervisor) {
78 mService = service;
79 mStackSupervisor = stackSupervisor;
80 }
81
82 void setWindowManager(WindowManagerService windowManager) {
83 mWindowManager = windowManager;
Wale Ogunwaled32da472018-11-16 07:19:28 -080084 mRootActivityContainer = mService.mRootActivityContainer;
Jorim Jaggife762342016-10-13 14:33:27 +020085 }
86
87 /**
Lucas Dupin47a65c72018-02-15 14:16:18 -080088 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
89 * on the given display, false otherwise
90 */
91 boolean isKeyguardOrAodShowing(int displayId) {
wilsonshih0299c8a2018-08-24 15:52:57 +080092 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
wilsonshih498a4b82018-12-11 16:10:16 +080093 && !isDisplayOccluded(displayId);
Lucas Dupin47a65c72018-02-15 14:16:18 -080094 }
95
96 /**
David Stevens53a39ea2017-08-23 18:41:49 -070097 * @return true if Keyguard is showing, not going away, and not being occluded on the given
98 * display, false otherwise
Jorim Jaggife762342016-10-13 14:33:27 +020099 */
David Stevens53a39ea2017-08-23 18:41:49 -0700100 boolean isKeyguardShowing(int displayId) {
wilsonshih498a4b82018-12-11 16:10:16 +0800101 return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
Jorim Jaggife762342016-10-13 14:33:27 +0200102 }
103
104 /**
105 * @return true if Keyguard is either showing or occluded, but not going away
106 */
107 boolean isKeyguardLocked() {
108 return mKeyguardShowing && !mKeyguardGoingAway;
109 }
110
111 /**
Bryce Lee271617a2018-03-15 10:39:12 -0700112 * @return {@code true} if the keyguard is going away, {@code false} otherwise.
113 */
114 boolean isKeyguardGoingAway() {
115 // Also check keyguard showing in case value is stale.
116 return mKeyguardGoingAway && mKeyguardShowing;
117 }
118
119 /**
Jorim Jaggife762342016-10-13 14:33:27 +0200120 * Update the Keyguard showing state.
121 */
wilsonshih177261f2019-02-22 12:02:18 +0800122 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) {
Lucas Dupin47a65c72018-02-15 14:16:18 -0800123 boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
Adrian Roos6ec76b72018-04-25 14:01:11 +0200124 // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
125 showingChanged |= mKeyguardGoingAway && keyguardShowing;
wilsonshih177261f2019-02-22 12:02:18 +0800126 if (!showingChanged) {
Jorim Jaggife762342016-10-13 14:33:27 +0200127 return;
128 }
Lucas Dupin47a65c72018-02-15 14:16:18 -0800129 mKeyguardShowing = keyguardShowing;
130 mAodShowing = aodShowing;
chaviw0e9fb132018-06-05 16:29:13 -0700131 mWindowManager.setAodShowing(aodShowing);
David Stevens53a39ea2017-08-23 18:41:49 -0700132 if (showingChanged) {
133 dismissDockedStackIfNeeded();
Andrii Kulian0d595f32018-02-21 15:47:33 -0800134 setKeyguardGoingAway(false);
wilsonshih0299c8a2018-08-24 15:52:57 +0800135 // TODO(b/113840485): Check usage for non-default display
Adrian Roosb56b3c32018-05-17 17:32:26 +0200136 mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
137 isKeyguardOrAodShowing(DEFAULT_DISPLAY));
Lucas Dupin47a65c72018-02-15 14:16:18 -0800138 if (keyguardShowing) {
David Stevens53a39ea2017-08-23 18:41:49 -0700139 mDismissalRequested = false;
140 }
Jorim Jaggife762342016-10-13 14:33:27 +0200141 }
Wale Ogunwaled32da472018-11-16 07:19:28 -0800142 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
David Stevens9440dc82017-03-16 19:00:20 -0700143 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200144 }
145
146 /**
147 * Called when Keyguard is going away.
148 *
Adrian Roose99bc052017-11-20 17:55:31 +0100149 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
Jorim Jaggife762342016-10-13 14:33:27 +0200150 * etc.
151 */
152 void keyguardGoingAway(int flags) {
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700153 if (!mKeyguardShowing) {
154 return;
155 }
156 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway");
157 mWindowManager.deferSurfaceLayout();
158 try {
159 setKeyguardGoingAway(true);
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800160 mRootActivityContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800161 .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
162 false /* alwaysKeepCurrent */, convertTransitFlags(flags),
163 false /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700164 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200165
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700166 // Some stack visibility might change (e.g. docked stack)
Wale Ogunwaled32da472018-11-16 07:19:28 -0800167 mRootActivityContainer.resumeFocusedStacksTopActivities();
168 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
169 mRootActivityContainer.addStartingWindowsForVisibleActivities(
170 true /* taskSwitch */);
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700171 mWindowManager.executeAppTransition();
172 } finally {
173 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
174 mWindowManager.continueSurfaceLayout();
175 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
176
177 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Jorim Jaggife762342016-10-13 14:33:27 +0200178 }
179 }
180
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800181 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700182 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
183 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
184 failCallback(callback);
185 return;
186 }
Jorim Jaggid7214892017-07-18 14:05:19 +0200187 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
chaviw59b98852017-06-13 12:05:44 -0700188
189 // If the client has requested to dismiss the keyguard and the Activity has the flag to
190 // turn the screen on, wakeup the screen if it's the top Activity.
191 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) {
192 mStackSupervisor.wakeUp("dismissKeyguard");
193 }
194
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800195 mWindowManager.dismissKeyguard(callback, message);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700196 }
197
Wale Ogunwalebfa81ad2017-05-24 15:14:42 -0700198 private void setKeyguardGoingAway(boolean keyguardGoingAway) {
199 mKeyguardGoingAway = keyguardGoingAway;
200 mWindowManager.setKeyguardGoingAway(keyguardGoingAway);
201 }
202
Jorim Jaggi241ae102016-11-02 21:57:33 -0700203 private void failCallback(IKeyguardDismissCallback callback) {
204 try {
205 callback.onDismissError();
206 } catch (RemoteException e) {
207 Slog.w(TAG, "Failed to call callback", e);
208 }
209 }
210
Jorim Jaggife762342016-10-13 14:33:27 +0200211 private int convertTransitFlags(int keyguardGoingAwayFlags) {
212 int result = 0;
213 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
214 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
215 }
216 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
217 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
218 }
219 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
220 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
221 }
222 return result;
223 }
224
225 /**
226 * Starts a batch of visibility updates.
227 */
228 void beginActivityVisibilityUpdate() {
229 mVisibilityTransactionDepth++;
230 }
231
232 /**
233 * Ends a batch of visibility updates. After all batches are done, this method makes sure to
234 * update lockscreen occluded/dismiss state if needed.
235 */
236 void endActivityVisibilityUpdate() {
237 mVisibilityTransactionDepth--;
238 if (mVisibilityTransactionDepth == 0) {
239 visibilitiesUpdated();
240 }
241 }
242
Jorim Jaggie69c9312016-10-31 18:24:38 -0700243 /**
244 * @return True if we may show an activity while Keyguard is showing because we are in the
245 * process of dismissing it anyways, false otherwise.
246 */
Jorim Jaggi07961872016-11-23 11:28:57 +0100247 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
248
249 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
250 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
251 // Keyguard.
Lucas Dupin47a65c72018-02-15 14:16:18 -0800252 return dismissKeyguard && canDismissKeyguard() && !mAodShowing
wilsonshih0299c8a2018-08-24 15:52:57 +0800253 && (mDismissalRequested
254 || getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r);
Jorim Jaggi07961872016-11-23 11:28:57 +0100255 }
256
257 /**
258 * @return True if we may show an activity while Keyguard is occluded, false otherwise.
259 */
260 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
261 return showWhenLocked || dismissKeyguard && !mWindowManager.isKeyguardSecure();
Jorim Jaggie69c9312016-10-31 18:24:38 -0700262 }
263
Jorim Jaggife762342016-10-13 14:33:27 +0200264 private void visibilitiesUpdated() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800265 boolean requestDismissKeyguard = false;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800266 for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
267 displayNdx >= 0; displayNdx--) {
268 final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800269 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
270 state.visibilitiesUpdated(this, display);
271 requestDismissKeyguard |= state.mRequestDismissKeyguard;
Jorim Jaggife762342016-10-13 14:33:27 +0200272 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800273
274 // Dismissing Keyguard happens globally using the information from all displays.
275 if (requestDismissKeyguard) {
Jorim Jaggife762342016-10-13 14:33:27 +0200276 handleDismissKeyguard();
277 }
278 }
279
280 /**
281 * Called when occluded state changed.
282 */
283 private void handleOccludedChanged() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800284 mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY));
Jorim Jaggife762342016-10-13 14:33:27 +0200285 if (isKeyguardLocked()) {
286 mWindowManager.deferSurfaceLayout();
287 try {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800288 mRootActivityContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800289 .prepareAppTransition(resolveOccludeTransit(),
290 false /* alwaysKeepCurrent */, 0 /* flags */,
291 true /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700292 updateKeyguardSleepToken();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800293 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Jorim Jaggife762342016-10-13 14:33:27 +0200294 mWindowManager.executeAppTransition();
295 } finally {
296 mWindowManager.continueSurfaceLayout();
297 }
298 }
299 dismissDockedStackIfNeeded();
300 }
301
302 /**
wilsonshih0299c8a2018-08-24 15:52:57 +0800303 * Called when somebody wants to dismiss the Keyguard via the flag.
Jorim Jaggife762342016-10-13 14:33:27 +0200304 */
305 private void handleDismissKeyguard() {
Jorim Jaggi07961872016-11-23 11:28:57 +0100306 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
307 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
308 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800309 if (!mWindowManager.isKeyguardSecure()) {
310 return;
311 }
Jorim Jaggife762342016-10-13 14:33:27 +0200312
Wale Ogunwaled32da472018-11-16 07:19:28 -0800313 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
314 mDismissalRequested = true;
315
316 // If we are about to unocclude the Keyguard, but we can dismiss it without security,
317 // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800318 final DisplayContent dc =
319 mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800320 if (mKeyguardShowing && canDismissKeyguard()
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800321 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
322 dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
Wale Ogunwaled32da472018-11-16 07:19:28 -0800323 0 /* flags */, true /* forceOverride */);
324 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
325 mWindowManager.executeAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200326 }
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() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800341 final DisplayContent dc =
342 mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Jorim Jaggife762342016-10-13 14:33:27 +0200343 if (mBeforeUnoccludeTransit != TRANSIT_UNSET
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800344 && dc.mAppTransition.getAppTransition() == 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.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800355 mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition();
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 Ogunwaled32da472018-11-16 07:19:28 -0800369 final ActivityStack stack =
370 mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700371 if (stack == null) {
372 return;
373 }
374 mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
Andrii Kulian52d255c2018-07-13 11:32:19 -0700375 stack.isFocusedStackOnDisplay());
Jorim Jaggife762342016-10-13 14:33:27 +0200376 }
377 }
Jorim Jaggi8d786932016-10-26 19:08:36 -0700378
David Stevens9440dc82017-03-16 19:00:20 -0700379 private void updateKeyguardSleepToken() {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800380 for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
381 displayNdx >= 0; displayNdx--) {
382 final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800383 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
384 if (isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken == null) {
385 state.acquiredSleepToken();
386 } else if (!isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken != null) {
387 state.releaseSleepToken();
388 }
389 }
390 }
391
392 private KeyguardDisplayState getDisplay(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800393 KeyguardDisplayState state = mDisplayStates.get(displayId);
394 if (state == null) {
395 state = new KeyguardDisplayState(mService, displayId);
396 mDisplayStates.append(displayId, state);
wilsonshih0299c8a2018-08-24 15:52:57 +0800397 }
wilsonshihe7903ea2018-09-26 16:17:59 +0800398 return state;
wilsonshih0299c8a2018-08-24 15:52:57 +0800399 }
400
401 void onDisplayRemoved(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800402 final KeyguardDisplayState state = mDisplayStates.get(displayId);
403 if (state != null) {
404 state.onRemoved();
wilsonshih0299c8a2018-08-24 15:52:57 +0800405 mDisplayStates.remove(displayId);
406 }
407 }
408
409 /** Represents Keyguard state per individual display. */
410 private static class KeyguardDisplayState {
411 private final int mDisplayId;
412 private boolean mOccluded;
413 private ActivityRecord mDismissingKeyguardActivity;
414 private boolean mRequestDismissKeyguard;
415 private final ActivityTaskManagerService mService;
416 private SleepToken mSleepToken;
417
418 KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
419 mService = service;
420 mDisplayId = displayId;
421 }
422
423 void onRemoved() {
424 mDismissingKeyguardActivity = null;
425 releaseSleepToken();
426 }
427
428 void acquiredSleepToken() {
429 if (mSleepToken == null) {
430 mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId);
431 }
432 }
433
434 void releaseSleepToken() {
435 if (mSleepToken != null) {
436 mSleepToken.release();
437 mSleepToken = null;
438 }
439 }
440
441 void visibilitiesUpdated(KeyguardController controller, ActivityDisplay display) {
442 final boolean lastOccluded = mOccluded;
443 final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
444 mRequestDismissKeyguard = false;
445 mOccluded = false;
446 mDismissingKeyguardActivity = null;
447
wilsonshih9a10e9d2019-01-11 14:39:27 +0800448 final ActivityStack stack = getStackForControllingOccluding(display);
449 if (stack != null) {
450 final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
451 mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null
452 && stack.topRunningActivityLocked() == topDismissing
453 && controller.canShowWhileOccluded(
wilsonshih0299c8a2018-08-24 15:52:57 +0800454 true /* dismissKeyguard */,
455 false /* showWhenLocked */));
wilsonshih9a10e9d2019-01-11 14:39:27 +0800456 if (stack.getTopDismissingKeyguardActivity() != null) {
457 mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
wilsonshih0299c8a2018-08-24 15:52:57 +0800458 }
wilsonshih498a4b82018-12-11 16:10:16 +0800459 // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display.
460 if (mDisplayId != DEFAULT_DISPLAY) {
461 mOccluded |= stack.canShowWithInsecureKeyguard()
462 && controller.canDismissKeyguard();
463 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800464 }
wilsonshih498a4b82018-12-11 16:10:16 +0800465 // TODO(b/123372519): isShowingDream can only works on default display.
466 if (mDisplayId == DEFAULT_DISPLAY) {
467 mOccluded |= controller.mWindowManager.isShowingDream();
468 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800469
wilsonshihe7903ea2018-09-26 16:17:59 +0800470 // TODO(b/113840485): Handle app transition for individual display, and apply occluded
471 // state change to secondary displays.
wilsonshih0299c8a2018-08-24 15:52:57 +0800472 // For now, only default display can change occluded.
473 if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) {
474 controller.handleOccludedChanged();
475 }
476 if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
477 && mDismissingKeyguardActivity != null
478 && controller.mWindowManager.isKeyguardSecure()) {
479 mRequestDismissKeyguard = true;
480 }
481 }
482
wilsonshih9a10e9d2019-01-11 14:39:27 +0800483 /**
484 * Gets the stack used to check the occluded state.
485 * <p>
486 * Only the top non-pinned activity of the focusable stack on each display can control its
487 * occlusion state.
488 */
489 private ActivityStack getStackForControllingOccluding(ActivityDisplay display) {
490 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
491 final ActivityStack stack = display.getChildAt(stackNdx);
492 if (stack != null && stack.isFocusableAndVisible()
493 && !stack.inPinnedWindowingMode()) {
494 return stack;
495 }
496 }
497 return null;
498 }
499
wilsonshih0299c8a2018-08-24 15:52:57 +0800500 void dumpStatus(PrintWriter pw, String prefix) {
501 final StringBuilder sb = new StringBuilder();
502 sb.append(prefix);
503 sb.append(" Occluded=").append(mOccluded)
504 .append(" DismissingKeyguardActivity=")
505 .append(mDismissingKeyguardActivity)
506 .append(" at display=")
507 .append(mDisplayId);
508 pw.println(sb.toString());
509 }
510
511 void writeToProto(ProtoOutputStream proto, long fieldId) {
512 final long token = proto.start(fieldId);
513 proto.write(DISPLAY_ID, mDisplayId);
514 proto.write(KEYGUARD_OCCLUDED, mOccluded);
515 proto.end(token);
David Stevens9440dc82017-03-16 19:00:20 -0700516 }
517 }
518
Jorim Jaggi8d786932016-10-26 19:08:36 -0700519 void dump(PrintWriter pw, String prefix) {
520 pw.println(prefix + "KeyguardController:");
521 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800522 pw.println(prefix + " mAodShowing=" + mAodShowing);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700523 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
wilsonshih0299c8a2018-08-24 15:52:57 +0800524 dumpDisplayStates(pw, prefix);
Jorim Jaggi07961872016-11-23 11:28:57 +0100525 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700526 pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
527 }
Steven Timotius4346f0a2017-09-12 11:07:21 -0700528
529 void writeToProto(ProtoOutputStream proto, long fieldId) {
530 final long token = proto.start(fieldId);
531 proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
wilsonshih0299c8a2018-08-24 15:52:57 +0800532 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700533 proto.end(token);
534 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800535
536 private void dumpDisplayStates(PrintWriter pw, String prefix) {
537 for (int i = 0; i < mDisplayStates.size(); i++) {
538 mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
539 }
540 }
541
542 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
543 for (int i = 0; i < mDisplayStates.size(); i++) {
544 mDisplayStates.valueAt(i).writeToProto(proto, fieldId);
545 }
546 }
Jorim Jaggife762342016-10-13 14:33:27 +0200547}