blob: c91af73dc6ddbd5354d30d9845ddba7e9b4a3ff7 [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;
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;
84 }
85
86 /**
Lucas Dupin47a65c72018-02-15 14:16:18 -080087 * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
88 * on the given display, false otherwise
89 */
90 boolean isKeyguardOrAodShowing(int displayId) {
wilsonshih0299c8a2018-08-24 15:52:57 +080091 return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
wilsonshihe7903ea2018-09-26 16:17:59 +080092 && (displayId == DEFAULT_DISPLAY
93 ? !isDisplayOccluded(DEFAULT_DISPLAY)
94 : isShowingOnSecondaryDisplay(displayId));
Lucas Dupin47a65c72018-02-15 14:16:18 -080095 }
96
97 /**
David Stevens53a39ea2017-08-23 18:41:49 -070098 * @return true if Keyguard is showing, not going away, and not being occluded on the given
99 * display, false otherwise
Jorim Jaggife762342016-10-13 14:33:27 +0200100 */
David Stevens53a39ea2017-08-23 18:41:49 -0700101 boolean isKeyguardShowing(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800102 return mKeyguardShowing && !mKeyguardGoingAway
103 && (displayId == DEFAULT_DISPLAY
104 ? !isDisplayOccluded(DEFAULT_DISPLAY)
105 : isShowingOnSecondaryDisplay(displayId));
Jorim Jaggife762342016-10-13 14:33:27 +0200106 }
107
108 /**
109 * @return true if Keyguard is either showing or occluded, but not going away
110 */
111 boolean isKeyguardLocked() {
112 return mKeyguardShowing && !mKeyguardGoingAway;
113 }
114
115 /**
Bryce Lee271617a2018-03-15 10:39:12 -0700116 * @return {@code true} if the keyguard is going away, {@code false} otherwise.
117 */
118 boolean isKeyguardGoingAway() {
119 // Also check keyguard showing in case value is stale.
120 return mKeyguardGoingAway && mKeyguardShowing;
121 }
122
123 /**
Jorim Jaggife762342016-10-13 14:33:27 +0200124 * Update the Keyguard showing state.
125 */
Lucas Dupin47a65c72018-02-15 14:16:18 -0800126 void setKeyguardShown(boolean keyguardShowing, boolean aodShowing,
wilsonshihe7903ea2018-09-26 16:17:59 +0800127 int[] secondaryDisplaysShowing) {
Lucas Dupin47a65c72018-02-15 14:16:18 -0800128 boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
Adrian Roos6ec76b72018-04-25 14:01:11 +0200129 // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
130 showingChanged |= mKeyguardGoingAway && keyguardShowing;
wilsonshihe7903ea2018-09-26 16:17:59 +0800131 if (!showingChanged && Arrays.equals(secondaryDisplaysShowing,
132 mSecondaryDisplayIdsShowing)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200133 return;
134 }
Lucas Dupin47a65c72018-02-15 14:16:18 -0800135 mKeyguardShowing = keyguardShowing;
136 mAodShowing = aodShowing;
wilsonshihe7903ea2018-09-26 16:17:59 +0800137 mSecondaryDisplayIdsShowing = secondaryDisplaysShowing;
chaviw0e9fb132018-06-05 16:29:13 -0700138 mWindowManager.setAodShowing(aodShowing);
David Stevens53a39ea2017-08-23 18:41:49 -0700139 if (showingChanged) {
140 dismissDockedStackIfNeeded();
Andrii Kulian0d595f32018-02-21 15:47:33 -0800141 setKeyguardGoingAway(false);
wilsonshih0299c8a2018-08-24 15:52:57 +0800142 // TODO(b/113840485): Check usage for non-default display
Adrian Roosb56b3c32018-05-17 17:32:26 +0200143 mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
144 isKeyguardOrAodShowing(DEFAULT_DISPLAY));
Lucas Dupin47a65c72018-02-15 14:16:18 -0800145 if (keyguardShowing) {
David Stevens53a39ea2017-08-23 18:41:49 -0700146 mDismissalRequested = false;
147 }
Jorim Jaggife762342016-10-13 14:33:27 +0200148 }
149 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
David Stevens9440dc82017-03-16 19:00:20 -0700150 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200151 }
152
wilsonshihe7903ea2018-09-26 16:17:59 +0800153 private boolean isShowingOnSecondaryDisplay(int displayId) {
154 if (mSecondaryDisplayIdsShowing == null) return false;
155 for (int showingId : mSecondaryDisplayIdsShowing) {
156 if (displayId == showingId) return true;
157 }
158 return false;
159 }
160
Jorim Jaggife762342016-10-13 14:33:27 +0200161 /**
162 * Called when Keyguard is going away.
163 *
Adrian Roose99bc052017-11-20 17:55:31 +0100164 * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
Jorim Jaggife762342016-10-13 14:33:27 +0200165 * etc.
166 */
167 void keyguardGoingAway(int flags) {
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700168 if (!mKeyguardShowing) {
169 return;
170 }
171 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway");
172 mWindowManager.deferSurfaceLayout();
173 try {
174 setKeyguardGoingAway(true);
lumark588a3e82018-07-20 18:53:54 +0800175 mStackSupervisor.getDefaultDisplay().getWindowContainerController()
176 .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
177 false /* alwaysKeepCurrent */, convertTransitFlags(flags),
178 false /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700179 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200180
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700181 // Some stack visibility might change (e.g. docked stack)
Andrii Kulianab132ee2018-07-24 22:10:21 +0800182 mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
Wale Ogunwaledfb7fb22017-06-23 14:52:40 -0700183 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
184 mStackSupervisor.addStartingWindowsForVisibleActivities(true /* taskSwitch */);
185 mWindowManager.executeAppTransition();
186 } finally {
187 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
188 mWindowManager.continueSurfaceLayout();
189 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
190
191 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
Jorim Jaggife762342016-10-13 14:33:27 +0200192 }
193 }
194
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800195 void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message) {
Jorim Jaggi241ae102016-11-02 21:57:33 -0700196 final ActivityRecord activityRecord = ActivityRecord.forTokenLocked(token);
197 if (activityRecord == null || !activityRecord.visibleIgnoringKeyguard) {
198 failCallback(callback);
199 return;
200 }
Jorim Jaggid7214892017-07-18 14:05:19 +0200201 Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
chaviw59b98852017-06-13 12:05:44 -0700202
203 // If the client has requested to dismiss the keyguard and the Activity has the flag to
204 // turn the screen on, wakeup the screen if it's the top Activity.
205 if (activityRecord.getTurnScreenOnFlag() && activityRecord.isTopRunningActivity()) {
206 mStackSupervisor.wakeUp("dismissKeyguard");
207 }
208
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800209 mWindowManager.dismissKeyguard(callback, message);
Jorim Jaggi241ae102016-11-02 21:57:33 -0700210 }
211
Wale Ogunwalebfa81ad2017-05-24 15:14:42 -0700212 private void setKeyguardGoingAway(boolean keyguardGoingAway) {
213 mKeyguardGoingAway = keyguardGoingAway;
214 mWindowManager.setKeyguardGoingAway(keyguardGoingAway);
215 }
216
Jorim Jaggi241ae102016-11-02 21:57:33 -0700217 private void failCallback(IKeyguardDismissCallback callback) {
218 try {
219 callback.onDismissError();
220 } catch (RemoteException e) {
221 Slog.w(TAG, "Failed to call callback", e);
222 }
223 }
224
Jorim Jaggife762342016-10-13 14:33:27 +0200225 private int convertTransitFlags(int keyguardGoingAwayFlags) {
226 int result = 0;
227 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
228 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
229 }
230 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
231 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
232 }
233 if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
234 result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
235 }
236 return result;
237 }
238
239 /**
240 * Starts a batch of visibility updates.
241 */
242 void beginActivityVisibilityUpdate() {
243 mVisibilityTransactionDepth++;
244 }
245
246 /**
247 * Ends a batch of visibility updates. After all batches are done, this method makes sure to
248 * update lockscreen occluded/dismiss state if needed.
249 */
250 void endActivityVisibilityUpdate() {
251 mVisibilityTransactionDepth--;
252 if (mVisibilityTransactionDepth == 0) {
253 visibilitiesUpdated();
254 }
255 }
256
Jorim Jaggie69c9312016-10-31 18:24:38 -0700257 /**
258 * @return True if we may show an activity while Keyguard is showing because we are in the
259 * process of dismissing it anyways, false otherwise.
260 */
Jorim Jaggi07961872016-11-23 11:28:57 +0100261 boolean canShowActivityWhileKeyguardShowing(ActivityRecord r, boolean dismissKeyguard) {
262
263 // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
264 // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
265 // Keyguard.
Lucas Dupin47a65c72018-02-15 14:16:18 -0800266 return dismissKeyguard && canDismissKeyguard() && !mAodShowing
wilsonshih0299c8a2018-08-24 15:52:57 +0800267 && (mDismissalRequested
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) {
275 return showWhenLocked || dismissKeyguard && !mWindowManager.isKeyguardSecure();
Jorim Jaggie69c9312016-10-31 18:24:38 -0700276 }
277
Jorim Jaggife762342016-10-13 14:33:27 +0200278 private void visibilitiesUpdated() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800279 boolean requestDismissKeyguard = false;
Pat Plunkett40426e02017-10-31 14:06:29 -0700280 for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) {
281 final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx);
wilsonshih0299c8a2018-08-24 15:52:57 +0800282 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
283 state.visibilitiesUpdated(this, display);
284 requestDismissKeyguard |= state.mRequestDismissKeyguard;
Jorim Jaggife762342016-10-13 14:33:27 +0200285 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800286
287 // Dismissing Keyguard happens globally using the information from all displays.
288 if (requestDismissKeyguard) {
Jorim Jaggife762342016-10-13 14:33:27 +0200289 handleDismissKeyguard();
290 }
291 }
292
293 /**
294 * Called when occluded state changed.
295 */
296 private void handleOccludedChanged() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800297 mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY));
Jorim Jaggife762342016-10-13 14:33:27 +0200298 if (isKeyguardLocked()) {
299 mWindowManager.deferSurfaceLayout();
300 try {
lumark588a3e82018-07-20 18:53:54 +0800301 mStackSupervisor.getDefaultDisplay().getWindowContainerController()
302 .prepareAppTransition(resolveOccludeTransit(),
303 false /* alwaysKeepCurrent */, 0 /* flags */,
304 true /* forceOverride */);
David Stevens9440dc82017-03-16 19:00:20 -0700305 updateKeyguardSleepToken();
Jorim Jaggife762342016-10-13 14:33:27 +0200306 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
307 mWindowManager.executeAppTransition();
308 } finally {
309 mWindowManager.continueSurfaceLayout();
310 }
311 }
312 dismissDockedStackIfNeeded();
313 }
314
315 /**
wilsonshih0299c8a2018-08-24 15:52:57 +0800316 * Called when somebody wants to dismiss the Keyguard via the flag.
Jorim Jaggife762342016-10-13 14:33:27 +0200317 */
318 private void handleDismissKeyguard() {
Jorim Jaggi07961872016-11-23 11:28:57 +0100319 // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
320 // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
321 // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
wilsonshih0299c8a2018-08-24 15:52:57 +0800322 if (mWindowManager.isKeyguardSecure()) {
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800323 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
Jorim Jaggi07961872016-11-23 11:28:57 +0100324 mDismissalRequested = true;
Jorim Jaggife762342016-10-13 14:33:27 +0200325
326 // If we are about to unocclude the Keyguard, but we can dismiss it without security,
327 // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
lumark588a3e82018-07-20 18:53:54 +0800328 final DisplayWindowController dwc =
329 mStackSupervisor.getDefaultDisplay().getWindowContainerController();
Jorim Jaggife762342016-10-13 14:33:27 +0200330 if (mKeyguardShowing && canDismissKeyguard()
lumark588a3e82018-07-20 18:53:54 +0800331 && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
332 dwc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
333 0 /* flags */, true /* forceOverride */);
Jorim Jaggife762342016-10-13 14:33:27 +0200334 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
335 mWindowManager.executeAppTransition();
336 }
337 }
338 }
339
wilsonshih0299c8a2018-08-24 15:52:57 +0800340 private boolean isDisplayOccluded(int displayId) {
341 return getDisplay(displayId).mOccluded;
342 }
343
Jorim Jaggife762342016-10-13 14:33:27 +0200344 /**
345 * @return true if Keyguard can be currently dismissed without entering credentials.
346 */
Andrii Kulianfc8f82b2017-01-26 13:17:27 -0800347 boolean canDismissKeyguard() {
Jorim Jaggife762342016-10-13 14:33:27 +0200348 return mWindowManager.isKeyguardTrusted() || !mWindowManager.isKeyguardSecure();
349 }
350
351 private int resolveOccludeTransit() {
lumark588a3e82018-07-20 18:53:54 +0800352 final DisplayWindowController dwc =
353 mStackSupervisor.getDefaultDisplay().getWindowContainerController();
Jorim Jaggife762342016-10-13 14:33:27 +0200354 if (mBeforeUnoccludeTransit != TRANSIT_UNSET
lumark588a3e82018-07-20 18:53:54 +0800355 && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
wilsonshih0299c8a2018-08-24 15:52:57 +0800356 // TODO(b/113840485): Handle app transition for individual display.
357 && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200358
359 // Reuse old transit in case we are occluding Keyguard again, meaning that we never
360 // actually occclude/unocclude Keyguard, but just run a normal transition.
361 return mBeforeUnoccludeTransit;
wilsonshih0299c8a2018-08-24 15:52:57 +0800362 // TODO(b/113840485): Handle app transition for individual display.
363 } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200364
365 // Save transit in case we dismiss/occlude Keyguard shortly after.
lumark588a3e82018-07-20 18:53:54 +0800366 mBeforeUnoccludeTransit = dwc.getPendingAppTransition();
Jorim Jaggife762342016-10-13 14:33:27 +0200367 return TRANSIT_KEYGUARD_UNOCCLUDE;
368 } else {
369 return TRANSIT_KEYGUARD_OCCLUDE;
370 }
371 }
372
373 private void dismissDockedStackIfNeeded() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800374 // TODO(b/113840485): Handle docked stack for individual display.
375 if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
Jorim Jaggife762342016-10-13 14:33:27 +0200376 // The lock screen is currently showing, but is occluded by a window that can
377 // show on top of the lock screen. In this can we want to dismiss the docked
378 // stack since it will be complicated/risky to try to put the activity on top
379 // of the lock screen in the right fullscreen configuration.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700380 final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700381 if (stack == null) {
382 return;
383 }
384 mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
Andrii Kulian52d255c2018-07-13 11:32:19 -0700385 stack.isFocusedStackOnDisplay());
Jorim Jaggife762342016-10-13 14:33:27 +0200386 }
387 }
Jorim Jaggi8d786932016-10-26 19:08:36 -0700388
David Stevens9440dc82017-03-16 19:00:20 -0700389 private void updateKeyguardSleepToken() {
wilsonshih0299c8a2018-08-24 15:52:57 +0800390 for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) {
391 final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx);
392 final KeyguardDisplayState state = getDisplay(display.mDisplayId);
393 if (isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken == null) {
394 state.acquiredSleepToken();
395 } else if (!isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken != null) {
396 state.releaseSleepToken();
397 }
398 }
399 }
400
401 private KeyguardDisplayState getDisplay(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800402 KeyguardDisplayState state = mDisplayStates.get(displayId);
403 if (state == null) {
404 state = new KeyguardDisplayState(mService, displayId);
405 mDisplayStates.append(displayId, state);
wilsonshih0299c8a2018-08-24 15:52:57 +0800406 }
wilsonshihe7903ea2018-09-26 16:17:59 +0800407 return state;
wilsonshih0299c8a2018-08-24 15:52:57 +0800408 }
409
410 void onDisplayRemoved(int displayId) {
wilsonshihe7903ea2018-09-26 16:17:59 +0800411 final KeyguardDisplayState state = mDisplayStates.get(displayId);
412 if (state != null) {
413 state.onRemoved();
wilsonshih0299c8a2018-08-24 15:52:57 +0800414 mDisplayStates.remove(displayId);
415 }
416 }
417
418 /** Represents Keyguard state per individual display. */
419 private static class KeyguardDisplayState {
420 private final int mDisplayId;
421 private boolean mOccluded;
422 private ActivityRecord mDismissingKeyguardActivity;
423 private boolean mRequestDismissKeyguard;
424 private final ActivityTaskManagerService mService;
425 private SleepToken mSleepToken;
426
427 KeyguardDisplayState(ActivityTaskManagerService service, int displayId) {
428 mService = service;
429 mDisplayId = displayId;
430 }
431
432 void onRemoved() {
433 mDismissingKeyguardActivity = null;
434 releaseSleepToken();
435 }
436
437 void acquiredSleepToken() {
438 if (mSleepToken == null) {
439 mSleepToken = mService.acquireSleepToken("keyguard", mDisplayId);
440 }
441 }
442
443 void releaseSleepToken() {
444 if (mSleepToken != null) {
445 mSleepToken.release();
446 mSleepToken = null;
447 }
448 }
449
450 void visibilitiesUpdated(KeyguardController controller, ActivityDisplay display) {
451 final boolean lastOccluded = mOccluded;
452 final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity;
453 mRequestDismissKeyguard = false;
454 mOccluded = false;
455 mDismissingKeyguardActivity = null;
456
457 // Only the top activity of the focused stack on each display may control it's
458 // occluded state.
459 final ActivityStack focusedStack = display.getFocusedStack();
460 if (focusedStack != null) {
461 final ActivityRecord topDismissing =
462 focusedStack.getTopDismissingKeyguardActivity();
463 mOccluded = focusedStack.topActivityOccludesKeyguard() || (topDismissing != null
464 && focusedStack.topRunningActivityLocked() == topDismissing
465 && controller.canShowWhileOccluded(
466 true /* dismissKeyguard */,
467 false /* showWhenLocked */));
468 if (focusedStack.getTopDismissingKeyguardActivity() != null) {
469 mDismissingKeyguardActivity = focusedStack.getTopDismissingKeyguardActivity();
470 }
471 mOccluded |= controller.mWindowManager.isShowingDream();
472 }
473
wilsonshihe7903ea2018-09-26 16:17:59 +0800474 // TODO(b/113840485): Handle app transition for individual display, and apply occluded
475 // state change to secondary displays.
wilsonshih0299c8a2018-08-24 15:52:57 +0800476 // For now, only default display can change occluded.
477 if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) {
478 controller.handleOccludedChanged();
479 }
480 if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded
481 && mDismissingKeyguardActivity != null
482 && controller.mWindowManager.isKeyguardSecure()) {
483 mRequestDismissKeyguard = true;
484 }
485 }
486
487 void dumpStatus(PrintWriter pw, String prefix) {
488 final StringBuilder sb = new StringBuilder();
489 sb.append(prefix);
490 sb.append(" Occluded=").append(mOccluded)
491 .append(" DismissingKeyguardActivity=")
492 .append(mDismissingKeyguardActivity)
493 .append(" at display=")
494 .append(mDisplayId);
495 pw.println(sb.toString());
496 }
497
498 void writeToProto(ProtoOutputStream proto, long fieldId) {
499 final long token = proto.start(fieldId);
500 proto.write(DISPLAY_ID, mDisplayId);
501 proto.write(KEYGUARD_OCCLUDED, mOccluded);
502 proto.end(token);
David Stevens9440dc82017-03-16 19:00:20 -0700503 }
504 }
505
Jorim Jaggi8d786932016-10-26 19:08:36 -0700506 void dump(PrintWriter pw, String prefix) {
507 pw.println(prefix + "KeyguardController:");
508 pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
Lucas Dupin47a65c72018-02-15 14:16:18 -0800509 pw.println(prefix + " mAodShowing=" + mAodShowing);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700510 pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
wilsonshih0299c8a2018-08-24 15:52:57 +0800511 dumpDisplayStates(pw, prefix);
Jorim Jaggi07961872016-11-23 11:28:57 +0100512 pw.println(prefix + " mDismissalRequested=" + mDismissalRequested);
Jorim Jaggi8d786932016-10-26 19:08:36 -0700513 pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
514 }
Steven Timotius4346f0a2017-09-12 11:07:21 -0700515
516 void writeToProto(ProtoOutputStream proto, long fieldId) {
517 final long token = proto.start(fieldId);
518 proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
wilsonshih0299c8a2018-08-24 15:52:57 +0800519 writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
Steven Timotius4346f0a2017-09-12 11:07:21 -0700520 proto.end(token);
521 }
wilsonshih0299c8a2018-08-24 15:52:57 +0800522
523 private void dumpDisplayStates(PrintWriter pw, String prefix) {
524 for (int i = 0; i < mDisplayStates.size(); i++) {
525 mDisplayStates.valueAt(i).dumpStatus(pw, prefix);
526 }
527 }
528
529 private void writeDisplayStatesToProto(ProtoOutputStream proto, long fieldId) {
530 for (int i = 0; i < mDisplayStates.size(); i++) {
531 mDisplayStates.valueAt(i).writeToProto(proto, fieldId);
532 }
533 }
Jorim Jaggife762342016-10-13 14:33:27 +0200534}