blob: 5f56fe59c1f2acad60c70366c5de6d1c91e4093e [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;
wilsonshihe7903ea2018-09-26 16:17:59 +080052import java.util.Arrays;
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
90 * on the given display, false otherwise
91 */
92 boolean isKeyguardOrAodShowing(int displayId) {
wilsonshih0299c8a2018-08-24 15:52:57 +080093 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
wilsonshihe7903ea2018-09-26 16:17:59 +080094 && (displayId == DEFAULT_DISPLAY
95 ? !isDisplayOccluded(DEFAULT_DISPLAY)
96 : isShowingOnSecondaryDisplay(displayId));
Lucas Dupin47a65c72018-02-15 14:16:18 -080097 }
98
99 /**
David Stevens53a39ea2017-08-23 18:41:49 -0700100 * @return true if Keyguard is showing, not going away, and not being occluded on the given
101 * display, false otherwise
Jorim Jaggife762342016-10-13 14:33:27 +0200102 */
David Stevens53a39ea2017-08-23 18:41:49 -0700103 boolean isKeyguardShowing(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800104 return mKeyguardShowing && !mKeyguardGoingAway
105 && (displayId == DEFAULT_DISPLAY
106 ? !isDisplayOccluded(DEFAULT_DISPLAY)
107 : isShowingOnSecondaryDisplay(displayId));
Jorim Jaggife762342016-10-13 14:33:27 +0200108 }
109
110 /**
111 * @return true if Keyguard is either showing or occluded, but not going away
112 */
113 boolean isKeyguardLocked() {
114 return mKeyguardShowing && !mKeyguardGoingAway;
115 }
116
117 /**
Bryce Lee271617a2018-03-15 10:39:12 -0700118 * @return {@code true} if the keyguard is going away, {@code false} otherwise.
119 */
120 boolean isKeyguardGoingAway() {
121 // Also check keyguard showing in case value is stale.
122 return mKeyguardGoingAway && mKeyguardShowing;
123 }
124
125 /**
Jorim Jaggife762342016-10-13 14:33:27 +0200126 * Update the Keyguard showing state.
127 */
Lucas Dupin47a65c72018-02-15 14:16:18 -0800128 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing,
wilsonshihe7903ea2018-09-26 16:17:59 +0800129 int[] secondaryDisplaysShowing) {
Lucas Dupin47a65c72018-02-15 14:16:18 -0800130 boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
Adrian Roos6ec76b72018-04-25 14:01:11 +0200131 // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
132 showingChanged |= mKeyguardGoingAway && keyguardShowing;
wilsonshihe7903ea2018-09-26 16:17:59 +0800133 if (!showingChanged && Arrays.equals(secondaryDisplaysShowing,
134 mSecondaryDisplayIdsShowing)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200135 return;
136 }
Lucas Dupin47a65c72018-02-15 14:16:18 -0800137 mKeyguardShowing = keyguardShowing;
138 mAodShowing = aodShowing;
wilsonshihe7903ea2018-09-26 16:17:59 +0800139 mSecondaryDisplayIdsShowing = secondaryDisplaysShowing;
chaviw0e9fb132018-06-05 16:29:13 -0700140 mWindowManager.setAodShowing(aodShowing);
David Stevens53a39ea2017-08-23 18:41:49 -0700141 if (showingChanged) {
142 dismissDockedStackIfNeeded();
Andrii Kulian0d595f32018-02-21 15:47:33 -0800143 setKeyguardGoingAway(false);
wilsonshih0299c8a2018-08-24 15:52:57 +0800144 // TODO(b/113840485): Check usage for non-default display
Adrian Roosb56b3c32018-05-17 17:32:26 +0200145 mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
146 isKeyguardOrAodShowing(DEFAULT_DISPLAY));
Lucas Dupin47a65c72018-02-15 14:16:18 -0800147 if (keyguardShowing) {
David Stevens53a39ea2017-08-23 18:41:49 -0700148 mDismissalRequested = false;
149 }
Jorim Jaggife762342016-10-13 14:33:27 +0200150 }
Wale Ogunwaled32da472018-11-16 07:19:28 -0800151 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
David Stevens9440dc82017-03-16 19:00:20 -0700152 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200153 }
154
wilsonshihe7903ea2018-09-26 16:17:59 +0800155 private boolean isShowingOnSecondaryDisplay(int displayId) {
156 if (mSecondaryDisplayIdsShowing == null) return false;
157 for (int showingId : mSecondaryDisplayIdsShowing) {
158 if (displayId == showingId) return true;
159 }
160 return false;
161 }
162
Jorim Jaggife762342016-10-13 14:33:27 +0200163 /**
164 * Called when Keyguard is going away.
165 *
Adrian Roose99bc052017-11-20 17:55:31 +0100166 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
Jorim Jaggife762342016-10-13 14:33:27 +0200167 * etc.
168 */
169 void keyguardGoingAway(int flags) {
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700170 if (!mKeyguardShowing) {
171 return;
172 }
173 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway");
174 mWindowManager.deferSurfaceLayout();
175 try {
176 setKeyguardGoingAway(true);
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800177 mRootActivityContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800178 .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
179 false /* alwaysKeepCurrent */, convertTransitFlags(flags),
180 false /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700181 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200182
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700183 // Some stack visibility might change (e.g. docked stack)
Wale Ogunwaled32da472018-11-16 07:19:28 -0800184 mRootActivityContainer.resumeFocusedStacksTopActivities();
185 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
186 mRootActivityContainer.addStartingWindowsForVisibleActivities(
187 true /* taskSwitch */);
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700188 mWindowManager.executeAppTransition();
189 } finally {
190 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
191 mWindowManager.continueSurfaceLayout();
192 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
193
194 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Jorim Jaggife762342016-10-13 14:33:27 +0200195 }
196 }
197
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800198 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700199 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
200 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
201 failCallback(callback);
202 return;
203 }
Jorim Jaggid7214892017-07-18 14:05:19 +0200204 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
chaviw59b98852017-06-13 12:05:44 -0700205
206 // If the client has requested to dismiss the keyguard and the Activity has the flag to
207 // turn the screen on, wakeup the screen if it's the top Activity.
208 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) {
209 mStackSupervisor.wakeUp("dismissKeyguard");
210 }
211
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800212 mWindowManager.dismissKeyguard(callback, message);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700213 }
214
Wale Ogunwalebfa81ad2017-05-24 15:14:42 -0700215 private void setKeyguardGoingAway(boolean keyguardGoingAway) {
216 mKeyguardGoingAway = keyguardGoingAway;
217 mWindowManager.setKeyguardGoingAway(keyguardGoingAway);
218 }
219
Jorim Jaggi241ae102016-11-02 21:57:33 -0700220 private void failCallback(IKeyguardDismissCallback callback) {
221 try {
222 callback.onDismissError();
223 } catch (RemoteException e) {
224 Slog.w(TAG, "Failed to call callback", e);
225 }
226 }
227
Jorim Jaggife762342016-10-13 14:33:27 +0200228 private int convertTransitFlags(int keyguardGoingAwayFlags) {
229 int result = 0;
230 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
231 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
232 }
233 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
234 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
235 }
236 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
237 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
238 }
239 return result;
240 }
241
242 /**
243 * Starts a batch of visibility updates.
244 */
245 void beginActivityVisibilityUpdate() {
246 mVisibilityTransactionDepth++;
247 }
248
249 /**
250 * Ends a batch of visibility updates. After all batches are done, this method makes sure to
251 * update lockscreen occluded/dismiss state if needed.
252 */
253 void endActivityVisibilityUpdate() {
254 mVisibilityTransactionDepth--;
255 if (mVisibilityTransactionDepth == 0) {
256 visibilitiesUpdated();
257 }
258 }
259
Jorim Jaggie69c9312016-10-31 18:24:38 -0700260 /**
261 * @return True if we may show an activity while Keyguard is showing because we are in the
262 * process of dismissing it anyways, false otherwise.
263 */
Jorim Jaggi07961872016-11-23 11:28:57 +0100264 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
265
266 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
267 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
268 // Keyguard.
Lucas Dupin47a65c72018-02-15 14:16:18 -0800269 return dismissKeyguard && canDismissKeyguard() && !mAodShowing
wilsonshih0299c8a2018-08-24 15:52:57 +0800270 && (mDismissalRequested
271 || getDisplay(r.getDisplayId()).mDismissingKeyguardActivity != r);
Jorim Jaggi07961872016-11-23 11:28:57 +0100272 }
273
274 /**
275 * @return True if we may show an activity while Keyguard is occluded, false otherwise.
276 */
277 boolean canShowWhileOccluded(boolean dismissKeyguard, boolean showWhenLocked) {
278 return showWhenLocked || dismissKeyguard && !mWindowManager.isKeyguardSecure();
Jorim Jaggie69c9312016-10-31 18:24:38 -0700279 }
280
Jorim Jaggife762342016-10-13 14:33:27 +0200281 private void visibilitiesUpdated() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800282 boolean requestDismissKeyguard = false;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800283 for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
284 displayNdx >= 0; displayNdx--) {
285 final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800286 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
287 state.visibilitiesUpdated(this, display);
288 requestDismissKeyguard |= state.mRequestDismissKeyguard;
Jorim Jaggife762342016-10-13 14:33:27 +0200289 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800290
291 // Dismissing Keyguard happens globally using the information from all displays.
292 if (requestDismissKeyguard) {
Jorim Jaggife762342016-10-13 14:33:27 +0200293 handleDismissKeyguard();
294 }
295 }
296
297 /**
298 * Called when occluded state changed.
299 */
300 private void handleOccludedChanged() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800301 mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY));
Jorim Jaggife762342016-10-13 14:33:27 +0200302 if (isKeyguardLocked()) {
303 mWindowManager.deferSurfaceLayout();
304 try {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800305 mRootActivityContainer.getDefaultDisplay().mDisplayContent
lumark588a3e82018-07-20 18:53:54 +0800306 .prepareAppTransition(resolveOccludeTransit(),
307 false /* alwaysKeepCurrent */, 0 /* flags */,
308 true /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700309 updateKeyguardSleepToken();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800310 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
Jorim Jaggife762342016-10-13 14:33:27 +0200311 mWindowManager.executeAppTransition();
312 } finally {
313 mWindowManager.continueSurfaceLayout();
314 }
315 }
316 dismissDockedStackIfNeeded();
317 }
318
319 /**
wilsonshih0299c8a2018-08-24 15:52:57 +0800320 * Called when somebody wants to dismiss the Keyguard via the flag.
Jorim Jaggife762342016-10-13 14:33:27 +0200321 */
322 private void handleDismissKeyguard() {
Jorim Jaggi07961872016-11-23 11:28:57 +0100323 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
324 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
325 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800326 if (!mWindowManager.isKeyguardSecure()) {
327 return;
328 }
Jorim Jaggife762342016-10-13 14:33:27 +0200329
Wale Ogunwaled32da472018-11-16 07:19:28 -0800330 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
331 mDismissalRequested = true;
332
333 // If we are about to unocclude the Keyguard, but we can dismiss it without security,
334 // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800335 final DisplayContent dc =
336 mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800337 if (mKeyguardShowing && canDismissKeyguard()
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800338 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
339 dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
Wale Ogunwaled32da472018-11-16 07:19:28 -0800340 0 /* flags */, true /* forceOverride */);
341 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
342 mWindowManager.executeAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200343 }
344 }
345
wilsonshih0299c8a2018-08-24 15:52:57 +0800346 private boolean isDisplayOccluded(int displayId) {
347 return getDisplay(displayId).mOccluded;
348 }
349
Jorim Jaggife762342016-10-13 14:33:27 +0200350 /**
351 * @return true if Keyguard can be currently dismissed without entering credentials.
352 */
Andrii Kulianfc8f82b2017-01-26 13:17:27 -0800353 boolean canDismissKeyguard() {
Jorim Jaggife762342016-10-13 14:33:27 +0200354 return mWindowManager.isKeyguardTrusted() || !mWindowManager.isKeyguardSecure();
355 }
356
357 private int resolveOccludeTransit() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800358 final DisplayContent dc =
359 mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
Jorim Jaggife762342016-10-13 14:33:27 +0200360 if (mBeforeUnoccludeTransit != TRANSIT_UNSET
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800361 && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
wilsonshih0299c8a2018-08-24 15:52:57 +0800362 // TODO(b/113840485): Handle app transition for individual display.
363 && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200364
365 // Reuse old transit in case we are occluding Keyguard again, meaning that we never
366 // actually occclude/unocclude Keyguard, but just run a normal transition.
367 return mBeforeUnoccludeTransit;
wilsonshih0299c8a2018-08-24 15:52:57 +0800368 // TODO(b/113840485): Handle app transition for individual display.
369 } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200370
371 // Save transit in case we dismiss/occlude Keyguard shortly after.
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800372 mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200373 return TRANSIT_KEYGUARD_UNOCCLUDE;
374 } else {
375 return TRANSIT_KEYGUARD_OCCLUDE;
376 }
377 }
378
379 private void dismissDockedStackIfNeeded() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800380 // TODO(b/113840485): Handle docked stack for individual display.
381 if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200382 // The lock screen is currently showing, but is occluded by a window that can
383 // show on top of the lock screen. In this can we want to dismiss the docked
384 // stack since it will be complicated/risky to try to put the activity on top
385 // of the lock screen in the right fullscreen configuration.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800386 final ActivityStack stack =
387 mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700388 if (stack == null) {
389 return;
390 }
391 mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
Andrii Kulian52d255c2018-07-13 11:32:19 -0700392 stack.isFocusedStackOnDisplay());
Jorim Jaggife762342016-10-13 14:33:27 +0200393 }
394 }
Jorim Jaggi8d786932016-10-26 19:08:36 -0700395
David Stevens9440dc82017-03-16 19:00:20 -0700396 private void updateKeyguardSleepToken() {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800397 for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
398 displayNdx >= 0; displayNdx--) {
399 final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800400 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
401 if (isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken == null) {
402 state.acquiredSleepToken();
403 } else if (!isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken != null) {
404 state.releaseSleepToken();
405 }
406 }
407 }
408
409 private KeyguardDisplayState getDisplay(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800410 KeyguardDisplayState state = mDisplayStates.get(displayId);
411 if (state == null) {
412 state = new KeyguardDisplayState(mService, displayId);
413 mDisplayStates.append(displayId, state);
wilsonshih0299c8a2018-08-24 15:52:57 +0800414 }
wilsonshihe7903ea2018-09-26 16:17:59 +0800415 return state;
wilsonshih0299c8a2018-08-24 15:52:57 +0800416 }
417
418 void onDisplayRemoved(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800419 final KeyguardDisplayState state = mDisplayStates.get(displayId);
420 if (state != null) {
421 state.onRemoved();
wilsonshih0299c8a2018-08-24 15:52:57 +0800422 mDisplayStates.remove(displayId);
423 }
424 }
425
426 /** Represents Keyguard state per individual display. */
427 private static class KeyguardDisplayState {
428 private final int mDisplayId;
429 private boolean mOccluded;
430 private ActivityRecord mDismissingKeyguardActivity;
431 private boolean mRequestDismissKeyguard;
432 private final ActivityTaskManagerService mService;
433 private SleepToken mSleepToken;
434
435 KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
436 mService = service;
437 mDisplayId = displayId;
438 }
439
440 void onRemoved() {
441 mDismissingKeyguardActivity = null;
442 releaseSleepToken();
443 }
444
445 void acquiredSleepToken() {
446 if (mSleepToken == null) {
447 mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId);
448 }
449 }
450
451 void releaseSleepToken() {
452 if (mSleepToken != null) {
453 mSleepToken.release();
454 mSleepToken = null;
455 }
456 }
457
458 void visibilitiesUpdated(KeyguardController controller, ActivityDisplay display) {
459 final boolean lastOccluded = mOccluded;
460 final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
461 mRequestDismissKeyguard = false;
462 mOccluded = false;
463 mDismissingKeyguardActivity = null;
464
465 // Only the top activity of the focused stack on each display may control it's
466 // occluded state.
467 final ActivityStack focusedStack = display.getFocusedStack();
468 if (focusedStack != null) {
469 final ActivityRecord topDismissing =
470 focusedStack.getTopDismissingKeyguardActivity();
471 mOccluded = focusedStack.topActivityOccludesKeyguard() || (topDismissing != null
472 && focusedStack.topRunningActivityLocked() == topDismissing
473 && controller.canShowWhileOccluded(
474 true /* dismissKeyguard */,
475 false /* showWhenLocked */));
476 if (focusedStack.getTopDismissingKeyguardActivity() != null) {
477 mDismissingKeyguardActivity = focusedStack.getTopDismissingKeyguardActivity();
478 }
479 mOccluded |= controller.mWindowManager.isShowingDream();
480 }
481
wilsonshihe7903ea2018-09-26 16:17:59 +0800482 // TODO(b/113840485): Handle app transition for individual display, and apply occluded
483 // state change to secondary displays.
wilsonshih0299c8a2018-08-24 15:52:57 +0800484 // For now, only default display can change occluded.
485 if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) {
486 controller.handleOccludedChanged();
487 }
488 if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
489 && mDismissingKeyguardActivity != null
490 && controller.mWindowManager.isKeyguardSecure()) {
491 mRequestDismissKeyguard = true;
492 }
493 }
494
495 void dumpStatus(PrintWriter pw, String prefix) {
496 final StringBuilder sb = new StringBuilder();
497 sb.append(prefix);
498 sb.append(" Occluded=").append(mOccluded)
499 .append(" DismissingKeyguardActivity=")
500 .append(mDismissingKeyguardActivity)
501 .append(" at display=")
502 .append(mDisplayId);
503 pw.println(sb.toString());
504 }
505
506 void writeToProto(ProtoOutputStream proto, long fieldId) {
507 final long token = proto.start(fieldId);
508 proto.write(DISPLAY_ID, mDisplayId);
509 proto.write(KEYGUARD_OCCLUDED, mOccluded);
510 proto.end(token);
David Stevens9440dc82017-03-16 19:00:20 -0700511 }
512 }
513
Jorim Jaggi8d786932016-10-26 19:08:36 -0700514 void dump(PrintWriter pw, String prefix) {
515 pw.println(prefix + "KeyguardController:");
516 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800517 pw.println(prefix + " mAodShowing=" + mAodShowing);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700518 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
wilsonshih0299c8a2018-08-24 15:52:57 +0800519 dumpDisplayStates(pw, prefix);
Jorim Jaggi07961872016-11-23 11:28:57 +0100520 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700521 pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
522 }
Steven Timotius4346f0a2017-09-12 11:07:21 -0700523
524 void writeToProto(ProtoOutputStream proto, long fieldId) {
525 final long token = proto.start(fieldId);
526 proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
wilsonshih0299c8a2018-08-24 15:52:57 +0800527 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700528 proto.end(token);
529 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800530
531 private void dumpDisplayStates(PrintWriter pw, String prefix) {
532 for (int i = 0; i < mDisplayStates.size(); i++) {
533 mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
534 }
535 }
536
537 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
538 for (int i = 0; i < mDisplayStates.size(); i++) {
539 mDisplayStates.valueAt(i).writeToProto(proto, fieldId);
540 }
541 }
Jorim Jaggife762342016-10-13 14:33:27 +0200542}