blob: ca4749f7b3654593331713c4c2e4a73cac7bb6b6 [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;
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
Issei Suzukid6eb5a22019-02-20 23:08:03 +010034import static com.android.server.am.KeyguardControllerProto.AOD_SHOWING;
wilsonshih0299c8a2018-08-24 15:52:57 +080035import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070036import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
wilsonshih0299c8a2018-08-24 15:52:57 +080037import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID;
38import static com.android.server.am.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
wilsonshihe7903ea2018-09-26 16:17:59 +080039import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
40import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
41import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
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;
wilsonshihe7903ea2018-09-26 16:17:59 +080072 private int[] mSecondaryDisplayIdsShowing;
Jorim Jaggife762342016-10-13 14:33:27 +020073 private int mBeforeUnoccludeTransit;
74 private int mVisibilityTransactionDepth;
wilsonshih0299c8a2018-08-24 15:52:57 +080075 private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
76 private final ActivityTaskManagerService mService;
Wale Ogunwaled32da472018-11-16 07:19:28 -080077 private RootActivityContainer mRootActivityContainer;
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;
Wale Ogunwaled32da472018-11-16 07:19:28 -080087 mRootActivityContainer = mService.mRootActivityContainer;
Jorim Jaggife762342016-10-13 14:33:27 +020088 }
89
90 /**
Lucas Dupin47a65c72018-02-15 14:16:18 -080091 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
Issei Suzukid6eb5a22019-02-20 23:08:03 +010092 * on the given display, false otherwise.
Lucas Dupin47a65c72018-02-15 14:16:18 -080093 */
94 boolean isKeyguardOrAodShowing(int displayId) {
wilsonshih0299c8a2018-08-24 15:52:57 +080095 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
wilsonshih498a4b82018-12-11 16:10:16 +080096 && !isDisplayOccluded(displayId);
Lucas Dupin47a65c72018-02-15 14:16:18 -080097 }
98
99 /**
Louis Chang3319d022019-03-12 11:53:14 +0800100 * @return {@code true} for default display when AOD is showing. Otherwise, same as
101 * {@link #isKeyguardOrAodShowing(int)}
Issei Suzukid6eb5a22019-02-20 23:08:03 +0100102 * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic.
103 */
104 boolean isKeyguardUnoccludedOrAodShowing(int displayId) {
Louis Chang3319d022019-03-12 11:53:14 +0800105 if (displayId == DEFAULT_DISPLAY && mAodShowing) {
106 return true;
107 }
108 return isKeyguardOrAodShowing(displayId);
Issei Suzukid6eb5a22019-02-20 23:08:03 +0100109 }
110
111 /**
David Stevens53a39ea2017-08-23 18:41:49 -0700112 * @return true if Keyguard is showing, not going away, and not being occluded on the given
113 * display, false otherwise
Jorim Jaggife762342016-10-13 14:33:27 +0200114 */
David Stevens53a39ea2017-08-23 18:41:49 -0700115 boolean isKeyguardShowing(int displayId) {
wilsonshih498a4b82018-12-11 16:10:16 +0800116 return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
Jorim Jaggife762342016-10-13 14:33:27 +0200117 }
118
119 /**
120 * @return true if Keyguard is either showing or occluded, but not going away
121 */
122 boolean isKeyguardLocked() {
123 return mKeyguardShowing && !mKeyguardGoingAway;
124 }
125
126 /**
Bryce Lee271617a2018-03-15 10:39:12 -0700127 * @return {@code true} if the keyguard is going away, {@code false} otherwise.
128 */
129 boolean isKeyguardGoingAway() {
130 // Also check keyguard showing in case value is stale.
131 return mKeyguardGoingAway && mKeyguardShowing;
132 }
133
134 /**
Jorim Jaggife762342016-10-13 14:33:27 +0200135 * Update the Keyguard showing state.
136 */
wilsonshih177261f2019-02-22 12:02:18 +0800137 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) {
Adrian Roos6ec76b72018-04-25 14:01:11 +0200138 // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
wilsonshih2bc846c2019-05-02 14:35:21 +0800139 final boolean keyguardChanged = keyguardShowing != mKeyguardShowing
140 || mKeyguardGoingAway && keyguardShowing;
141 final boolean aodChanged = aodShowing != mAodShowing;
142 if (!keyguardChanged && !aodChanged) {
Jorim Jaggife762342016-10-13 14:33:27 +0200143 return;
144 }
Lucas Dupin47a65c72018-02-15 14:16:18 -0800145 mKeyguardShowing = keyguardShowing;
146 mAodShowing = aodShowing;
chaviw0e9fb132018-06-05 16:29:13 -0700147 mWindowManager.setAodShowing(aodShowing);
wilsonshih2bc846c2019-05-02 14:35:21 +0800148
149 if (keyguardChanged) {
150 // Irrelevant to AOD.
David Stevens53a39ea2017-08-23 18:41:49 -0700151 dismissDockedStackIfNeeded();
Andrii Kulian0d595f32018-02-21 15:47:33 -0800152 setKeyguardGoingAway(false);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800153 if (keyguardShowing) {
David Stevens53a39ea2017-08-23 18:41:49 -0700154 mDismissalRequested = false;
155 }
Jorim Jaggife762342016-10-13 14:33:27 +0200156 }
wilsonshih2bc846c2019-05-02 14:35:21 +0800157 // TODO(b/113840485): Check usage for non-default display
158 mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
159 isKeyguardOrAodShowing(DEFAULT_DISPLAY));
160
161 // Update the sleep token first such that ensureActivitiesVisible has correct sleep token
162 // state when evaluating visibilities.
David Stevens9440dc82017-03-16 19:00:20 -0700163 updateKeyguardSleepToken();
wilsonshih2bc846c2019-05-02 14:35:21 +0800164 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Jorim Jaggife762342016-10-13 14:33:27 +0200165 }
166
167 /**
168 * Called when Keyguard is going away.
169 *
Adrian Roose99bc052017-11-20 17:55:31 +0100170 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
Jorim Jaggife762342016-10-13 14:33:27 +0200171 * etc.
172 */
173 void keyguardGoingAway(int flags) {
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700174 if (!mKeyguardShowing) {
175 return;
176 }
177 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway");
178 mWindowManager.deferSurfaceLayout();
179 try {
180 setKeyguardGoingAway(true);
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800181 mRootActivityContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800182 .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
183 false /* alwaysKeepCurrent */, convertTransitFlags(flags),
184 false /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700185 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200186
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700187 // Some stack visibility might change (e.g. docked stack)
Wale Ogunwaled32da472018-11-16 07:19:28 -0800188 mRootActivityContainer.resumeFocusedStacksTopActivities();
189 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
190 mRootActivityContainer.addStartingWindowsForVisibleActivities(
191 true /* taskSwitch */);
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700192 mWindowManager.executeAppTransition();
193 } finally {
194 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
195 mWindowManager.continueSurfaceLayout();
196 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
197
198 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Jorim Jaggife762342016-10-13 14:33:27 +0200199 }
200 }
201
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800202 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700203 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
204 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
205 failCallback(callback);
206 return;
207 }
Jorim Jaggid7214892017-07-18 14:05:19 +0200208 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
chaviw59b98852017-06-13 12:05:44 -0700209
210 // If the client has requested to dismiss the keyguard and the Activity has the flag to
211 // turn the screen on, wakeup the screen if it's the top Activity.
212 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) {
213 mStackSupervisor.wakeUp("dismissKeyguard");
214 }
215
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800216 mWindowManager.dismissKeyguard(callback, message);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700217 }
218
Wale Ogunwalebfa81ad2017-05-24 15:14:42 -0700219 private void setKeyguardGoingAway(boolean keyguardGoingAway) {
220 mKeyguardGoingAway = keyguardGoingAway;
221 mWindowManager.setKeyguardGoingAway(keyguardGoingAway);
222 }
223
Jorim Jaggi241ae102016-11-02 21:57:33 -0700224 private void failCallback(IKeyguardDismissCallback callback) {
225 try {
226 callback.onDismissError();
227 } catch (RemoteException e) {
228 Slog.w(TAG, "Failed to call callback", e);
229 }
230 }
231
Jorim Jaggife762342016-10-13 14:33:27 +0200232 private int convertTransitFlags(int keyguardGoingAwayFlags) {
233 int result = 0;
234 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
235 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
236 }
237 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
238 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
239 }
240 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
241 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
242 }
Issei Suzuki5609ccb2019-06-13 15:04:08 +0200243 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS) != 0) {
244 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
245 }
Jorim Jaggife762342016-10-13 14:33:27 +0200246 return result;
247 }
248
249 /**
250 * Starts a batch of visibility updates.
251 */
252 void beginActivityVisibilityUpdate() {
253 mVisibilityTransactionDepth++;
254 }
255
256 /**
257 * Ends a batch of visibility updates. After all batches are done, this method makes sure to
258 * update lockscreen occluded/dismiss state if needed.
259 */
260 void endActivityVisibilityUpdate() {
261 mVisibilityTransactionDepth--;
262 if (mVisibilityTransactionDepth == 0) {
263 visibilitiesUpdated();
264 }
265 }
266
Jorim Jaggie69c9312016-10-31 18:24:38 -0700267 /**
268 * @return True if we may show an activity while Keyguard is showing because we are in the
269 * process of dismissing it anyways, false otherwise.
270 */
Jorim Jaggi07961872016-11-23 11:28:57 +0100271 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
272
273 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
274 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
275 // Keyguard.
Lucas Dupin47a65c72018-02-15 14:16:18 -0800276 return dismissKeyguard && canDismissKeyguard() && !mAodShowing
wilsonshih0299c8a2018-08-24 15:52:57 +0800277 && (mDismissalRequested
Arthur Hungcf58b332019-04-17 16:07:10 +0800278 || (r.canShowWhenLocked()
279 && getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r));
Jorim Jaggi07961872016-11-23 11:28:57 +0100280 }
281
282 /**
283 * @return True if we may show an activity while Keyguard is occluded, false otherwise.
284 */
285 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700286 return showWhenLocked || dismissKeyguard
287 && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
Jorim Jaggie69c9312016-10-31 18:24:38 -0700288 }
289
Jorim Jaggife762342016-10-13 14:33:27 +0200290 private void visibilitiesUpdated() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800291 boolean requestDismissKeyguard = false;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800292 for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
293 displayNdx >= 0; displayNdx--) {
294 final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800295 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
296 state.visibilitiesUpdated(this, display);
297 requestDismissKeyguard |= state.mRequestDismissKeyguard;
Jorim Jaggife762342016-10-13 14:33:27 +0200298 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800299
300 // Dismissing Keyguard happens globally using the information from all displays.
301 if (requestDismissKeyguard) {
Jorim Jaggife762342016-10-13 14:33:27 +0200302 handleDismissKeyguard();
303 }
304 }
305
306 /**
307 * Called when occluded state changed.
308 */
Issei Suzuki62356a22019-04-11 16:46:37 +0200309 private void handleOccludedChanged(int displayId) {
310 // TODO(b/113840485): Handle app transition for individual display, and apply occluded
311 // state change to secondary displays.
312 // For now, only default display fully supports occluded change. Other displays only
313 // updates keygaurd sleep token on that display.
314 if (displayId != DEFAULT_DISPLAY) {
315 updateKeyguardSleepToken(displayId);
316 return;
317 }
318
wilsonshih0299c8a2018-08-24 15:52:57 +0800319 mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY));
Jorim Jaggife762342016-10-13 14:33:27 +0200320 if (isKeyguardLocked()) {
321 mWindowManager.deferSurfaceLayout();
322 try {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800323 mRootActivityContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800324 .prepareAppTransition(resolveOccludeTransit(),
325 false /* alwaysKeepCurrent */, 0 /* flags */,
326 true /* forceOverride */);
Issei Suzuki62356a22019-04-11 16:46:37 +0200327 updateKeyguardSleepToken(DEFAULT_DISPLAY);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800328 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Jorim Jaggife762342016-10-13 14:33:27 +0200329 mWindowManager.executeAppTransition();
330 } finally {
331 mWindowManager.continueSurfaceLayout();
332 }
333 }
334 dismissDockedStackIfNeeded();
335 }
336
337 /**
wilsonshih0299c8a2018-08-24 15:52:57 +0800338 * Called when somebody wants to dismiss the Keyguard via the flag.
Jorim Jaggife762342016-10-13 14:33:27 +0200339 */
340 private void handleDismissKeyguard() {
Jorim Jaggi07961872016-11-23 11:28:57 +0100341 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
342 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
343 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700344 if (!mWindowManager.isKeyguardSecure(mService.getCurrentUserId())) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800345 return;
346 }
Jorim Jaggife762342016-10-13 14:33:27 +0200347
Wale Ogunwaled32da472018-11-16 07:19:28 -0800348 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
349 mDismissalRequested = true;
350
351 // If we are about to unocclude the Keyguard, but we can dismiss it without security,
352 // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800353 final DisplayContent dc =
354 mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800355 if (mKeyguardShowing && canDismissKeyguard()
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800356 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
357 dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
Wale Ogunwaled32da472018-11-16 07:19:28 -0800358 0 /* flags */, true /* forceOverride */);
359 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
360 mWindowManager.executeAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200361 }
362 }
363
wilsonshih0299c8a2018-08-24 15:52:57 +0800364 private boolean isDisplayOccluded(int displayId) {
365 return getDisplay(displayId).mOccluded;
366 }
367
Jorim Jaggife762342016-10-13 14:33:27 +0200368 /**
369 * @return true if Keyguard can be currently dismissed without entering credentials.
370 */
Andrii Kulianfc8f82b2017-01-26 13:17:27 -0800371 boolean canDismissKeyguard() {
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700372 return mWindowManager.isKeyguardTrusted()
373 || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
Jorim Jaggife762342016-10-13 14:33:27 +0200374 }
375
376 private int resolveOccludeTransit() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800377 final DisplayContent dc =
378 mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Jorim Jaggife762342016-10-13 14:33:27 +0200379 if (mBeforeUnoccludeTransit != TRANSIT_UNSET
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800380 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
wilsonshih0299c8a2018-08-24 15:52:57 +0800381 // TODO(b/113840485): Handle app transition for individual display.
382 && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200383
384 // Reuse old transit in case we are occluding Keyguard again, meaning that we never
385 // actually occclude/unocclude Keyguard, but just run a normal transition.
386 return mBeforeUnoccludeTransit;
wilsonshih0299c8a2018-08-24 15:52:57 +0800387 // TODO(b/113840485): Handle app transition for individual display.
388 } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200389
390 // Save transit in case we dismiss/occlude Keyguard shortly after.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800391 mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200392 return TRANSIT_KEYGUARD_UNOCCLUDE;
393 } else {
394 return TRANSIT_KEYGUARD_OCCLUDE;
395 }
396 }
397
398 private void dismissDockedStackIfNeeded() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800399 // TODO(b/113840485): Handle docked stack for individual display.
400 if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200401 // The lock screen is currently showing, but is occluded by a window that can
402 // show on top of the lock screen. In this can we want to dismiss the docked
403 // stack since it will be complicated/risky to try to put the activity on top
404 // of the lock screen in the right fullscreen configuration.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800405 final ActivityStack stack =
406 mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700407 if (stack == null) {
408 return;
409 }
410 mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
Andrii Kulian52d255c2018-07-13 11:32:19 -0700411 stack.isFocusedStackOnDisplay());
Jorim Jaggife762342016-10-13 14:33:27 +0200412 }
413 }
Jorim Jaggi8d786932016-10-26 19:08:36 -0700414
David Stevens9440dc82017-03-16 19:00:20 -0700415 private void updateKeyguardSleepToken() {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800416 for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
417 displayNdx >= 0; displayNdx--) {
418 final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
Issei Suzuki62356a22019-04-11 16:46:37 +0200419 updateKeyguardSleepToken(display.mDisplayId);
420 }
421 }
422
423 private void updateKeyguardSleepToken(int displayId) {
424 final KeyguardDisplayState state = getDisplay(displayId);
425 if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) {
426 state.acquiredSleepToken();
427 } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) {
428 state.releaseSleepToken();
wilsonshih0299c8a2018-08-24 15:52:57 +0800429 }
430 }
431
432 private KeyguardDisplayState getDisplay(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800433 KeyguardDisplayState state = mDisplayStates.get(displayId);
434 if (state == null) {
435 state = new KeyguardDisplayState(mService, displayId);
436 mDisplayStates.append(displayId, state);
wilsonshih0299c8a2018-08-24 15:52:57 +0800437 }
wilsonshihe7903ea2018-09-26 16:17:59 +0800438 return state;
wilsonshih0299c8a2018-08-24 15:52:57 +0800439 }
440
441 void onDisplayRemoved(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800442 final KeyguardDisplayState state = mDisplayStates.get(displayId);
443 if (state != null) {
444 state.onRemoved();
wilsonshih0299c8a2018-08-24 15:52:57 +0800445 mDisplayStates.remove(displayId);
446 }
447 }
448
449 /** Represents Keyguard state per individual display. */
450 private static class KeyguardDisplayState {
451 private final int mDisplayId;
452 private boolean mOccluded;
453 private ActivityRecord mDismissingKeyguardActivity;
454 private boolean mRequestDismissKeyguard;
455 private final ActivityTaskManagerService mService;
456 private SleepToken mSleepToken;
457
458 KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
459 mService = service;
460 mDisplayId = displayId;
461 }
462
463 void onRemoved() {
464 mDismissingKeyguardActivity = null;
465 releaseSleepToken();
466 }
467
468 void acquiredSleepToken() {
469 if (mSleepToken == null) {
470 mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId);
471 }
472 }
473
474 void releaseSleepToken() {
475 if (mSleepToken != null) {
476 mSleepToken.release();
477 mSleepToken = null;
478 }
479 }
480
481 void visibilitiesUpdated(KeyguardController controller, ActivityDisplay display) {
482 final boolean lastOccluded = mOccluded;
483 final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
484 mRequestDismissKeyguard = false;
485 mOccluded = false;
486 mDismissingKeyguardActivity = null;
487
wilsonshih9a10e9d2019-01-11 14:39:27 +0800488 final ActivityStack stack = getStackForControllingOccluding(display);
489 if (stack != null) {
490 final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
491 mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null
492 && stack.topRunningActivityLocked() == topDismissing
493 && controller.canShowWhileOccluded(
wilsonshih0299c8a2018-08-24 15:52:57 +0800494 true /* dismissKeyguard */,
495 false /* showWhenLocked */));
wilsonshih9a10e9d2019-01-11 14:39:27 +0800496 if (stack.getTopDismissingKeyguardActivity() != null) {
497 mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
wilsonshih0299c8a2018-08-24 15:52:57 +0800498 }
wilsonshih498a4b82018-12-11 16:10:16 +0800499 // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display.
500 if (mDisplayId != DEFAULT_DISPLAY) {
501 mOccluded |= stack.canShowWithInsecureKeyguard()
502 && controller.canDismissKeyguard();
503 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800504 }
wilsonshih498a4b82018-12-11 16:10:16 +0800505 // TODO(b/123372519): isShowingDream can only works on default display.
506 if (mDisplayId == DEFAULT_DISPLAY) {
507 mOccluded |= controller.mWindowManager.isShowingDream();
508 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800509
Issei Suzuki62356a22019-04-11 16:46:37 +0200510 if (lastOccluded != mOccluded) {
511 controller.handleOccludedChanged(mDisplayId);
wilsonshih0299c8a2018-08-24 15:52:57 +0800512 }
513 if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
514 && mDismissingKeyguardActivity != null
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700515 && controller.mWindowManager.isKeyguardSecure(
516 controller.mService.getCurrentUserId())) {
wilsonshih0299c8a2018-08-24 15:52:57 +0800517 mRequestDismissKeyguard = true;
518 }
519 }
520
wilsonshih9a10e9d2019-01-11 14:39:27 +0800521 /**
522 * Gets the stack used to check the occluded state.
523 * <p>
524 * Only the top non-pinned activity of the focusable stack on each display can control its
525 * occlusion state.
526 */
527 private ActivityStack getStackForControllingOccluding(ActivityDisplay display) {
528 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
529 final ActivityStack stack = display.getChildAt(stackNdx);
530 if (stack != null && stack.isFocusableAndVisible()
531 && !stack.inPinnedWindowingMode()) {
532 return stack;
533 }
534 }
535 return null;
536 }
537
wilsonshih0299c8a2018-08-24 15:52:57 +0800538 void dumpStatus(PrintWriter pw, String prefix) {
539 final StringBuilder sb = new StringBuilder();
540 sb.append(prefix);
541 sb.append(" Occluded=").append(mOccluded)
542 .append(" DismissingKeyguardActivity=")
543 .append(mDismissingKeyguardActivity)
544 .append(" at display=")
545 .append(mDisplayId);
546 pw.println(sb.toString());
547 }
548
549 void writeToProto(ProtoOutputStream proto, long fieldId) {
550 final long token = proto.start(fieldId);
551 proto.write(DISPLAY_ID, mDisplayId);
552 proto.write(KEYGUARD_OCCLUDED, mOccluded);
553 proto.end(token);
David Stevens9440dc82017-03-16 19:00:20 -0700554 }
555 }
556
Jorim Jaggi8d786932016-10-26 19:08:36 -0700557 void dump(PrintWriter pw, String prefix) {
558 pw.println(prefix + "KeyguardController:");
559 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800560 pw.println(prefix + " mAodShowing=" + mAodShowing);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700561 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
wilsonshih0299c8a2018-08-24 15:52:57 +0800562 dumpDisplayStates(pw, prefix);
Jorim Jaggi07961872016-11-23 11:28:57 +0100563 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700564 pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
565 }
Steven Timotius4346f0a2017-09-12 11:07:21 -0700566
567 void writeToProto(ProtoOutputStream proto, long fieldId) {
568 final long token = proto.start(fieldId);
Issei Suzukid6eb5a22019-02-20 23:08:03 +0100569 proto.write(AOD_SHOWING, mAodShowing);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700570 proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
wilsonshih0299c8a2018-08-24 15:52:57 +0800571 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700572 proto.end(token);
573 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800574
575 private void dumpDisplayStates(PrintWriter pw, String prefix) {
576 for (int i = 0; i < mDisplayStates.size(); i++) {
577 mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
578 }
579 }
580
581 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
582 for (int i = 0; i < mDisplayStates.size(); i++) {
583 mDisplayStates.valueAt(i).writeToProto(proto, fieldId);
584 }
585 }
Jorim Jaggife762342016-10-13 14:33:27 +0200586}