blob: df36b09d56e8d32f752d66e990a406ac673682d5 [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
Issei Suzukid6eb5a22019-02-20 23:08:03 +010032import static com.android.server.am.KeyguardControllerProto.AOD_SHOWING;
wilsonshih0299c8a2018-08-24 15:52:57 +080033import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070034import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
wilsonshih0299c8a2018-08-24 15:52:57 +080035import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID;
36import static com.android.server.am.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
wilsonshihe7903ea2018-09-26 16:17:59 +080037import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
38import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
39import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
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;
Adrian Roose99bc052017-11-20 17:55:31 +010051
Jorim Jaggi8d786932016-10-26 19:08:36 -070052import java.io.PrintWriter;
Jorim Jaggife762342016-10-13 14:33:27 +020053
54/**
55 * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
56 * currently visible.
57 * <p>
58 * Note that everything in this class should only be accessed with the AM lock being held.
59 */
60class KeyguardController {
61
Wale Ogunwale98875612018-10-12 07:53:02 -070062 private static final String TAG = TAG_WITH_CLASS_NAME ? "KeyguardController" : TAG_ATM;
Jorim Jaggi241ae102016-11-02 21:57:33 -070063
Jorim Jaggife762342016-10-13 14:33:27 +020064 private final ActivityStackSupervisor mStackSupervisor;
65 private WindowManagerService mWindowManager;
Jorim Jaggife762342016-10-13 14:33:27 +020066 private boolean mKeyguardShowing;
Lucas Dupin47a65c72018-02-15 14:16:18 -080067 private boolean mAodShowing;
Jorim Jaggi8d786932016-10-26 19:08:36 -070068 private boolean mKeyguardGoingAway;
Jorim Jaggi07961872016-11-23 11:28:57 +010069 private boolean mDismissalRequested;
wilsonshihe7903ea2018-09-26 16:17:59 +080070 private int[] mSecondaryDisplayIdsShowing;
Jorim Jaggife762342016-10-13 14:33:27 +020071 private int mBeforeUnoccludeTransit;
72 private int mVisibilityTransactionDepth;
wilsonshih0299c8a2018-08-24 15:52:57 +080073 private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
74 private final ActivityTaskManagerService mService;
Wale Ogunwaled32da472018-11-16 07:19:28 -080075 private RootActivityContainer mRootActivityContainer;
Jorim Jaggife762342016-10-13 14:33:27 +020076
Wale Ogunwalef6733932018-06-27 05:14:34 -070077 KeyguardController(ActivityTaskManagerService service,
Jorim Jaggife762342016-10-13 14:33:27 +020078 ActivityStackSupervisor stackSupervisor) {
79 mService = service;
80 mStackSupervisor = stackSupervisor;
81 }
82
83 void setWindowManager(WindowManagerService windowManager) {
84 mWindowManager = windowManager;
Wale Ogunwaled32da472018-11-16 07:19:28 -080085 mRootActivityContainer = mService.mRootActivityContainer;
Jorim Jaggife762342016-10-13 14:33:27 +020086 }
87
88 /**
Lucas Dupin47a65c72018-02-15 14:16:18 -080089 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
Issei Suzukid6eb5a22019-02-20 23:08:03 +010090 * on the given display, false otherwise.
Lucas Dupin47a65c72018-02-15 14:16:18 -080091 */
92 boolean isKeyguardOrAodShowing(int displayId) {
wilsonshih0299c8a2018-08-24 15:52:57 +080093 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
wilsonshih498a4b82018-12-11 16:10:16 +080094 && !isDisplayOccluded(displayId);
Lucas Dupin47a65c72018-02-15 14:16:18 -080095 }
96
97 /**
Louis Chang3319d022019-03-12 11:53:14 +080098 * @return {@code true} for default display when AOD is showing. Otherwise, same as
99 * {@link #isKeyguardOrAodShowing(int)}
Issei Suzukid6eb5a22019-02-20 23:08:03 +0100100 * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic.
101 */
102 boolean isKeyguardUnoccludedOrAodShowing(int displayId) {
Louis Chang3319d022019-03-12 11:53:14 +0800103 if (displayId == DEFAULT_DISPLAY && mAodShowing) {
104 return true;
105 }
106 return isKeyguardOrAodShowing(displayId);
Issei Suzukid6eb5a22019-02-20 23:08:03 +0100107 }
108
109 /**
David Stevens53a39ea2017-08-23 18:41:49 -0700110 * @return true if Keyguard is showing, not going away, and not being occluded on the given
111 * display, false otherwise
Jorim Jaggife762342016-10-13 14:33:27 +0200112 */
David Stevens53a39ea2017-08-23 18:41:49 -0700113 boolean isKeyguardShowing(int displayId) {
wilsonshih498a4b82018-12-11 16:10:16 +0800114 return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
Jorim Jaggife762342016-10-13 14:33:27 +0200115 }
116
117 /**
118 * @return true if Keyguard is either showing or occluded, but not going away
119 */
120 boolean isKeyguardLocked() {
121 return mKeyguardShowing && !mKeyguardGoingAway;
122 }
123
124 /**
Bryce Lee271617a2018-03-15 10:39:12 -0700125 * @return {@code true} if the keyguard is going away, {@code false} otherwise.
126 */
127 boolean isKeyguardGoingAway() {
128 // Also check keyguard showing in case value is stale.
129 return mKeyguardGoingAway && mKeyguardShowing;
130 }
131
132 /**
Jorim Jaggife762342016-10-13 14:33:27 +0200133 * Update the Keyguard showing state.
134 */
wilsonshih177261f2019-02-22 12:02:18 +0800135 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) {
Lucas Dupin47a65c72018-02-15 14:16:18 -0800136 boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
Adrian Roos6ec76b72018-04-25 14:01:11 +0200137 // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
138 showingChanged |= mKeyguardGoingAway && keyguardShowing;
wilsonshih177261f2019-02-22 12:02:18 +0800139 if (!showingChanged) {
Jorim Jaggife762342016-10-13 14:33:27 +0200140 return;
141 }
Lucas Dupin47a65c72018-02-15 14:16:18 -0800142 mKeyguardShowing = keyguardShowing;
143 mAodShowing = aodShowing;
chaviw0e9fb132018-06-05 16:29:13 -0700144 mWindowManager.setAodShowing(aodShowing);
David Stevens53a39ea2017-08-23 18:41:49 -0700145 if (showingChanged) {
146 dismissDockedStackIfNeeded();
Andrii Kulian0d595f32018-02-21 15:47:33 -0800147 setKeyguardGoingAway(false);
wilsonshih0299c8a2018-08-24 15:52:57 +0800148 // TODO(b/113840485): Check usage for non-default display
Adrian Roosb56b3c32018-05-17 17:32:26 +0200149 mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
150 isKeyguardOrAodShowing(DEFAULT_DISPLAY));
Lucas Dupin47a65c72018-02-15 14:16:18 -0800151 if (keyguardShowing) {
David Stevens53a39ea2017-08-23 18:41:49 -0700152 mDismissalRequested = false;
153 }
Jorim Jaggife762342016-10-13 14:33:27 +0200154 }
Wale Ogunwaled32da472018-11-16 07:19:28 -0800155 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
David Stevens9440dc82017-03-16 19:00:20 -0700156 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200157 }
158
159 /**
160 * Called when Keyguard is going away.
161 *
Adrian Roose99bc052017-11-20 17:55:31 +0100162 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
Jorim Jaggife762342016-10-13 14:33:27 +0200163 * etc.
164 */
165 void keyguardGoingAway(int flags) {
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700166 if (!mKeyguardShowing) {
167 return;
168 }
169 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway");
170 mWindowManager.deferSurfaceLayout();
171 try {
172 setKeyguardGoingAway(true);
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800173 mRootActivityContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800174 .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
175 false /* alwaysKeepCurrent */, convertTransitFlags(flags),
176 false /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700177 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200178
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700179 // Some stack visibility might change (e.g. docked stack)
Wale Ogunwaled32da472018-11-16 07:19:28 -0800180 mRootActivityContainer.resumeFocusedStacksTopActivities();
181 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
182 mRootActivityContainer.addStartingWindowsForVisibleActivities(
183 true /* taskSwitch */);
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700184 mWindowManager.executeAppTransition();
185 } finally {
186 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
187 mWindowManager.continueSurfaceLayout();
188 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
189
190 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Jorim Jaggife762342016-10-13 14:33:27 +0200191 }
192 }
193
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800194 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700195 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
196 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
197 failCallback(callback);
198 return;
199 }
Jorim Jaggid7214892017-07-18 14:05:19 +0200200 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
chaviw59b98852017-06-13 12:05:44 -0700201
202 // If the client has requested to dismiss the keyguard and the Activity has the flag to
203 // turn the screen on, wakeup the screen if it's the top Activity.
204 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) {
205 mStackSupervisor.wakeUp("dismissKeyguard");
206 }
207
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800208 mWindowManager.dismissKeyguard(callback, message);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700209 }
210
Wale Ogunwalebfa81ad2017-05-24 15:14:42 -0700211 private void setKeyguardGoingAway(boolean keyguardGoingAway) {
212 mKeyguardGoingAway = keyguardGoingAway;
213 mWindowManager.setKeyguardGoingAway(keyguardGoingAway);
214 }
215
Jorim Jaggi241ae102016-11-02 21:57:33 -0700216 private void failCallback(IKeyguardDismissCallback callback) {
217 try {
218 callback.onDismissError();
219 } catch (RemoteException e) {
220 Slog.w(TAG, "Failed to call callback", e);
221 }
222 }
223
Jorim Jaggife762342016-10-13 14:33:27 +0200224 private int convertTransitFlags(int keyguardGoingAwayFlags) {
225 int result = 0;
226 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
227 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
228 }
229 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
230 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
231 }
232 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
233 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
234 }
235 return result;
236 }
237
238 /**
239 * Starts a batch of visibility updates.
240 */
241 void beginActivityVisibilityUpdate() {
242 mVisibilityTransactionDepth++;
243 }
244
245 /**
246 * Ends a batch of visibility updates. After all batches are done, this method makes sure to
247 * update lockscreen occluded/dismiss state if needed.
248 */
249 void endActivityVisibilityUpdate() {
250 mVisibilityTransactionDepth--;
251 if (mVisibilityTransactionDepth == 0) {
252 visibilitiesUpdated();
253 }
254 }
255
Jorim Jaggie69c9312016-10-31 18:24:38 -0700256 /**
257 * @return True if we may show an activity while Keyguard is showing because we are in the
258 * process of dismissing it anyways, false otherwise.
259 */
Jorim Jaggi07961872016-11-23 11:28:57 +0100260 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
261
262 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
263 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
264 // Keyguard.
Lucas Dupin47a65c72018-02-15 14:16:18 -0800265 return dismissKeyguard && canDismissKeyguard() && !mAodShowing
wilsonshih0299c8a2018-08-24 15:52:57 +0800266 && (mDismissalRequested
Arthur Hungcf58b332019-04-17 16:07:10 +0800267 || (r.canShowWhenLocked()
268 && getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r));
Jorim Jaggi07961872016-11-23 11:28:57 +0100269 }
270
271 /**
272 * @return True if we may show an activity while Keyguard is occluded, false otherwise.
273 */
274 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700275 return showWhenLocked || dismissKeyguard
276 && !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
Jorim Jaggie69c9312016-10-31 18:24:38 -0700277 }
278
Jorim Jaggife762342016-10-13 14:33:27 +0200279 private void visibilitiesUpdated() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800280 boolean requestDismissKeyguard = false;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800281 for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
282 displayNdx >= 0; displayNdx--) {
283 final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800284 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
285 state.visibilitiesUpdated(this, display);
286 requestDismissKeyguard |= state.mRequestDismissKeyguard;
Jorim Jaggife762342016-10-13 14:33:27 +0200287 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800288
289 // Dismissing Keyguard happens globally using the information from all displays.
290 if (requestDismissKeyguard) {
Jorim Jaggife762342016-10-13 14:33:27 +0200291 handleDismissKeyguard();
292 }
293 }
294
295 /**
296 * Called when occluded state changed.
297 */
Issei Suzuki62356a22019-04-11 16:46:37 +0200298 private void handleOccludedChanged(int displayId) {
299 // TODO(b/113840485): Handle app transition for individual display, and apply occluded
300 // state change to secondary displays.
301 // For now, only default display fully supports occluded change. Other displays only
302 // updates keygaurd sleep token on that display.
303 if (displayId != DEFAULT_DISPLAY) {
304 updateKeyguardSleepToken(displayId);
305 return;
306 }
307
wilsonshih0299c8a2018-08-24 15:52:57 +0800308 mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY));
Jorim Jaggife762342016-10-13 14:33:27 +0200309 if (isKeyguardLocked()) {
310 mWindowManager.deferSurfaceLayout();
311 try {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800312 mRootActivityContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800313 .prepareAppTransition(resolveOccludeTransit(),
314 false /* alwaysKeepCurrent */, 0 /* flags */,
315 true /* forceOverride */);
Issei Suzuki62356a22019-04-11 16:46:37 +0200316 updateKeyguardSleepToken(DEFAULT_DISPLAY);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800317 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Jorim Jaggife762342016-10-13 14:33:27 +0200318 mWindowManager.executeAppTransition();
319 } finally {
320 mWindowManager.continueSurfaceLayout();
321 }
322 }
323 dismissDockedStackIfNeeded();
324 }
325
326 /**
wilsonshih0299c8a2018-08-24 15:52:57 +0800327 * Called when somebody wants to dismiss the Keyguard via the flag.
Jorim Jaggife762342016-10-13 14:33:27 +0200328 */
329 private void handleDismissKeyguard() {
Jorim Jaggi07961872016-11-23 11:28:57 +0100330 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
331 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
332 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700333 if (!mWindowManager.isKeyguardSecure(mService.getCurrentUserId())) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800334 return;
335 }
Jorim Jaggife762342016-10-13 14:33:27 +0200336
Wale Ogunwaled32da472018-11-16 07:19:28 -0800337 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
338 mDismissalRequested = true;
339
340 // If we are about to unocclude the Keyguard, but we can dismiss it without security,
341 // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800342 final DisplayContent dc =
343 mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800344 if (mKeyguardShowing && canDismissKeyguard()
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800345 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
346 dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
Wale Ogunwaled32da472018-11-16 07:19:28 -0800347 0 /* flags */, true /* forceOverride */);
348 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
349 mWindowManager.executeAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200350 }
351 }
352
wilsonshih0299c8a2018-08-24 15:52:57 +0800353 private boolean isDisplayOccluded(int displayId) {
354 return getDisplay(displayId).mOccluded;
355 }
356
Jorim Jaggife762342016-10-13 14:33:27 +0200357 /**
358 * @return true if Keyguard can be currently dismissed without entering credentials.
359 */
Andrii Kulianfc8f82b2017-01-26 13:17:27 -0800360 boolean canDismissKeyguard() {
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700361 return mWindowManager.isKeyguardTrusted()
362 || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
Jorim Jaggife762342016-10-13 14:33:27 +0200363 }
364
365 private int resolveOccludeTransit() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800366 final DisplayContent dc =
367 mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Jorim Jaggife762342016-10-13 14:33:27 +0200368 if (mBeforeUnoccludeTransit != TRANSIT_UNSET
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800369 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
wilsonshih0299c8a2018-08-24 15:52:57 +0800370 // TODO(b/113840485): Handle app transition for individual display.
371 && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200372
373 // Reuse old transit in case we are occluding Keyguard again, meaning that we never
374 // actually occclude/unocclude Keyguard, but just run a normal transition.
375 return mBeforeUnoccludeTransit;
wilsonshih0299c8a2018-08-24 15:52:57 +0800376 // TODO(b/113840485): Handle app transition for individual display.
377 } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200378
379 // Save transit in case we dismiss/occlude Keyguard shortly after.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800380 mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200381 return TRANSIT_KEYGUARD_UNOCCLUDE;
382 } else {
383 return TRANSIT_KEYGUARD_OCCLUDE;
384 }
385 }
386
387 private void dismissDockedStackIfNeeded() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800388 // TODO(b/113840485): Handle docked stack for individual display.
389 if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200390 // The lock screen is currently showing, but is occluded by a window that can
391 // show on top of the lock screen. In this can we want to dismiss the docked
392 // stack since it will be complicated/risky to try to put the activity on top
393 // of the lock screen in the right fullscreen configuration.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800394 final ActivityStack stack =
395 mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700396 if (stack == null) {
397 return;
398 }
399 mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
Andrii Kulian52d255c2018-07-13 11:32:19 -0700400 stack.isFocusedStackOnDisplay());
Jorim Jaggife762342016-10-13 14:33:27 +0200401 }
402 }
Jorim Jaggi8d786932016-10-26 19:08:36 -0700403
David Stevens9440dc82017-03-16 19:00:20 -0700404 private void updateKeyguardSleepToken() {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800405 for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
406 displayNdx >= 0; displayNdx--) {
407 final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
Issei Suzuki62356a22019-04-11 16:46:37 +0200408 updateKeyguardSleepToken(display.mDisplayId);
409 }
410 }
411
412 private void updateKeyguardSleepToken(int displayId) {
413 final KeyguardDisplayState state = getDisplay(displayId);
414 if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) {
415 state.acquiredSleepToken();
416 } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) {
417 state.releaseSleepToken();
wilsonshih0299c8a2018-08-24 15:52:57 +0800418 }
419 }
420
421 private KeyguardDisplayState getDisplay(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800422 KeyguardDisplayState state = mDisplayStates.get(displayId);
423 if (state == null) {
424 state = new KeyguardDisplayState(mService, displayId);
425 mDisplayStates.append(displayId, state);
wilsonshih0299c8a2018-08-24 15:52:57 +0800426 }
wilsonshihe7903ea2018-09-26 16:17:59 +0800427 return state;
wilsonshih0299c8a2018-08-24 15:52:57 +0800428 }
429
430 void onDisplayRemoved(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800431 final KeyguardDisplayState state = mDisplayStates.get(displayId);
432 if (state != null) {
433 state.onRemoved();
wilsonshih0299c8a2018-08-24 15:52:57 +0800434 mDisplayStates.remove(displayId);
435 }
436 }
437
438 /** Represents Keyguard state per individual display. */
439 private static class KeyguardDisplayState {
440 private final int mDisplayId;
441 private boolean mOccluded;
442 private ActivityRecord mDismissingKeyguardActivity;
443 private boolean mRequestDismissKeyguard;
444 private final ActivityTaskManagerService mService;
445 private SleepToken mSleepToken;
446
447 KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
448 mService = service;
449 mDisplayId = displayId;
450 }
451
452 void onRemoved() {
453 mDismissingKeyguardActivity = null;
454 releaseSleepToken();
455 }
456
457 void acquiredSleepToken() {
458 if (mSleepToken == null) {
459 mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId);
460 }
461 }
462
463 void releaseSleepToken() {
464 if (mSleepToken != null) {
465 mSleepToken.release();
466 mSleepToken = null;
467 }
468 }
469
470 void visibilitiesUpdated(KeyguardController controller, ActivityDisplay display) {
471 final boolean lastOccluded = mOccluded;
472 final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
473 mRequestDismissKeyguard = false;
474 mOccluded = false;
475 mDismissingKeyguardActivity = null;
476
wilsonshih9a10e9d2019-01-11 14:39:27 +0800477 final ActivityStack stack = getStackForControllingOccluding(display);
478 if (stack != null) {
479 final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
480 mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null
481 && stack.topRunningActivityLocked() == topDismissing
482 && controller.canShowWhileOccluded(
wilsonshih0299c8a2018-08-24 15:52:57 +0800483 true /* dismissKeyguard */,
484 false /* showWhenLocked */));
wilsonshih9a10e9d2019-01-11 14:39:27 +0800485 if (stack.getTopDismissingKeyguardActivity() != null) {
486 mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
wilsonshih0299c8a2018-08-24 15:52:57 +0800487 }
wilsonshih498a4b82018-12-11 16:10:16 +0800488 // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display.
489 if (mDisplayId != DEFAULT_DISPLAY) {
490 mOccluded |= stack.canShowWithInsecureKeyguard()
491 && controller.canDismissKeyguard();
492 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800493 }
wilsonshih498a4b82018-12-11 16:10:16 +0800494 // TODO(b/123372519): isShowingDream can only works on default display.
495 if (mDisplayId == DEFAULT_DISPLAY) {
496 mOccluded |= controller.mWindowManager.isShowingDream();
497 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800498
Issei Suzuki62356a22019-04-11 16:46:37 +0200499 if (lastOccluded != mOccluded) {
500 controller.handleOccludedChanged(mDisplayId);
wilsonshih0299c8a2018-08-24 15:52:57 +0800501 }
502 if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
503 && mDismissingKeyguardActivity != null
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700504 && controller.mWindowManager.isKeyguardSecure(
505 controller.mService.getCurrentUserId())) {
wilsonshih0299c8a2018-08-24 15:52:57 +0800506 mRequestDismissKeyguard = true;
507 }
508 }
509
wilsonshih9a10e9d2019-01-11 14:39:27 +0800510 /**
511 * Gets the stack used to check the occluded state.
512 * <p>
513 * Only the top non-pinned activity of the focusable stack on each display can control its
514 * occlusion state.
515 */
516 private ActivityStack getStackForControllingOccluding(ActivityDisplay display) {
517 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
518 final ActivityStack stack = display.getChildAt(stackNdx);
519 if (stack != null && stack.isFocusableAndVisible()
520 && !stack.inPinnedWindowingMode()) {
521 return stack;
522 }
523 }
524 return null;
525 }
526
wilsonshih0299c8a2018-08-24 15:52:57 +0800527 void dumpStatus(PrintWriter pw, String prefix) {
528 final StringBuilder sb = new StringBuilder();
529 sb.append(prefix);
530 sb.append(" Occluded=").append(mOccluded)
531 .append(" DismissingKeyguardActivity=")
532 .append(mDismissingKeyguardActivity)
533 .append(" at display=")
534 .append(mDisplayId);
535 pw.println(sb.toString());
536 }
537
538 void writeToProto(ProtoOutputStream proto, long fieldId) {
539 final long token = proto.start(fieldId);
540 proto.write(DISPLAY_ID, mDisplayId);
541 proto.write(KEYGUARD_OCCLUDED, mOccluded);
542 proto.end(token);
David Stevens9440dc82017-03-16 19:00:20 -0700543 }
544 }
545
Jorim Jaggi8d786932016-10-26 19:08:36 -0700546 void dump(PrintWriter pw, String prefix) {
547 pw.println(prefix + "KeyguardController:");
548 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800549 pw.println(prefix + " mAodShowing=" + mAodShowing);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700550 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
wilsonshih0299c8a2018-08-24 15:52:57 +0800551 dumpDisplayStates(pw, prefix);
Jorim Jaggi07961872016-11-23 11:28:57 +0100552 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700553 pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
554 }
Steven Timotius4346f0a2017-09-12 11:07:21 -0700555
556 void writeToProto(ProtoOutputStream proto, long fieldId) {
557 final long token = proto.start(fieldId);
Issei Suzukid6eb5a22019-02-20 23:08:03 +0100558 proto.write(AOD_SHOWING, mAodShowing);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700559 proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
wilsonshih0299c8a2018-08-24 15:52:57 +0800560 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700561 proto.end(token);
562 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800563
564 private void dumpDisplayStates(PrintWriter pw, String prefix) {
565 for (int i = 0; i < mDisplayStates.size(); i++) {
566 mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
567 }
568 }
569
570 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
571 for (int i = 0; i < mDisplayStates.size(); i++) {
572 mDisplayStates.valueAt(i).writeToProto(proto, fieldId);
573 }
574 }
Jorim Jaggife762342016-10-13 14:33:27 +0200575}