blob: 15a49a79121697cf8604e632232ce014299f1e1b [file] [log] [blame]
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001/*
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
17package com.android.server.wm;
18
Louis Chang149d5c82019-12-30 09:47:39 +080019import static android.app.ActivityTaskManager.INVALID_TASK_ID;
20import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
21import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
22import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
23import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
25import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
26import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
27import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
28import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
29import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
30import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
31import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
32import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
Jorim Jaggi4981f152019-03-26 18:58:45 +010033import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
wilsonshihab672942018-08-06 15:42:07 +080034import static android.view.Display.DEFAULT_DISPLAY;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080035import static android.view.Display.INVALID_DISPLAY;
wilsonshihab672942018-08-06 15:42:07 +080036import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
wilsonshihab672942018-08-06 15:42:07 +080037import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
38import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
39import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
Louis Chang149d5c82019-12-30 09:47:39 +080040import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
41import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
wilsonshihab672942018-08-06 15:42:07 +080042
wilsonshihab672942018-08-06 15:42:07 +080043import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
44import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Louis Chang149d5c82019-12-30 09:47:39 +080045import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
46import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
47import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
48import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
49import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
50import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
51import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
52import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
53import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
54import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
55import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
56import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
57import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
58import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
59import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
60import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
61import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
62import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
63import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH;
Adrian Roosb125e0b2019-10-02 14:55:14 +020064import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
65import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
66import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
67import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
68import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
Wale Ogunwalef342f062020-01-27 07:34:13 -080069import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT;
70import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER;
71import static com.android.server.wm.RootWindowContainerProto.PENDING_ACTIVITIES;
wilsonshihab672942018-08-06 15:42:07 +080072import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
Louis Chang149d5c82019-12-30 09:47:39 +080073import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
74import static com.android.server.wm.Task.REPARENT_MOVE_STACK_TO_FRONT;
wilsonshihab672942018-08-06 15:42:07 +080075import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
wilsonshihab672942018-08-06 15:42:07 +080076import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
77import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
78import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
wilsonshihab672942018-08-06 15:42:07 +080079import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
80import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
wilsonshihab672942018-08-06 15:42:07 +080081import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
Tiger Huang1e5b10a2018-07-30 20:19:51 +080082import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
wilsonshihab672942018-08-06 15:42:07 +080083import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
84import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
85import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
wilsonshihab672942018-08-06 15:42:07 +080086import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
87import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
88import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
wilsonshihab672942018-08-06 15:42:07 +080089
Louis Chang149d5c82019-12-30 09:47:39 +080090import static java.lang.Integer.MAX_VALUE;
91
92import android.annotation.IntDef;
Evan Roskye747c3e2018-10-30 20:06:41 -070093import android.annotation.NonNull;
Charles Chen173ae782019-11-11 20:39:02 +080094import android.annotation.Nullable;
Louis Chang149d5c82019-12-30 09:47:39 +080095import android.annotation.UserIdInt;
96import android.app.ActivityManager;
97import android.app.ActivityOptions;
98import android.app.AppGlobals;
99import android.app.WindowConfiguration;
100import android.content.ComponentName;
Charles Chen173ae782019-11-11 20:39:02 +0800101import android.content.Context;
Louis Chang149d5c82019-12-30 09:47:39 +0800102import android.content.Intent;
103import android.content.pm.ActivityInfo;
104import android.content.pm.ApplicationInfo;
105import android.content.pm.ResolveInfo;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700106import android.content.res.Configuration;
Louis Chang149d5c82019-12-30 09:47:39 +0800107import android.content.res.Resources;
108import android.graphics.Rect;
109import android.hardware.display.DisplayManager;
110import android.hardware.display.DisplayManagerInternal;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700111import android.hardware.power.V1_0.PowerHint;
Louis Chang149d5c82019-12-30 09:47:39 +0800112import android.net.Uri;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700113import android.os.Binder;
114import android.os.Debug;
Louis Chang149d5c82019-12-30 09:47:39 +0800115import android.os.FactoryTest;
Jorim Jaggi86c39f92017-05-02 18:02:46 +0200116import android.os.Handler;
Wale Ogunwale02319a62016-09-26 15:21:22 -0700117import android.os.IBinder;
Jorim Jaggi86c39f92017-05-02 18:02:46 +0200118import android.os.Looper;
119import android.os.Message;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700120import android.os.PowerManager;
121import android.os.RemoteException;
Louis Chang149d5c82019-12-30 09:47:39 +0800122import android.os.SystemClock;
Jorim Jaggi4981f152019-03-26 18:58:45 +0100123import android.os.Trace;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700124import android.os.UserHandle;
Louis Chang149d5c82019-12-30 09:47:39 +0800125import android.os.storage.StorageManager;
126import android.provider.Settings;
127import android.service.voice.IVoiceInteractionSession;
David Stevensf833ba92017-03-16 19:00:20 -0700128import android.util.ArraySet;
Louis Chang149d5c82019-12-30 09:47:39 +0800129import android.util.DisplayMetrics;
130import android.util.IntArray;
131import android.util.Pair;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700132import android.util.Slog;
Louis Chang149d5c82019-12-30 09:47:39 +0800133import android.util.SparseArray;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700134import android.util.SparseIntArray;
Louis Chang149d5c82019-12-30 09:47:39 +0800135import android.util.TimeUtils;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700136import android.util.proto.ProtoOutputStream;
Louis Chang149d5c82019-12-30 09:47:39 +0800137import android.view.Display;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700138import android.view.DisplayInfo;
Robert Carrae606b42018-02-15 15:36:23 -0800139import android.view.SurfaceControl;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700140import android.view.WindowManager;
Jorim Jaggi86c39f92017-05-02 18:02:46 +0200141
Louis Chang149d5c82019-12-30 09:47:39 +0800142import com.android.internal.annotations.VisibleForTesting;
143import com.android.internal.app.ResolverActivity;
144import com.android.internal.util.function.pooled.PooledConsumer;
145import com.android.internal.util.function.pooled.PooledFunction;
Charles Chen173ae782019-11-11 20:39:02 +0800146import com.android.internal.util.function.pooled.PooledLambda;
147import com.android.internal.util.function.pooled.PooledPredicate;
Louis Chang149d5c82019-12-30 09:47:39 +0800148import com.android.server.LocalServices;
149import com.android.server.am.ActivityManagerService;
150import com.android.server.am.AppTimeTracker;
151import com.android.server.am.UserState;
152import com.android.server.policy.WindowManagerPolicy;
Adrian Roosb125e0b2019-10-02 14:55:14 +0200153import com.android.server.protolog.common.ProtoLog;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700154
Louis Chang149d5c82019-12-30 09:47:39 +0800155import java.io.FileDescriptor;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700156import java.io.PrintWriter;
Louis Chang149d5c82019-12-30 09:47:39 +0800157import java.lang.annotation.Retention;
158import java.lang.annotation.RetentionPolicy;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700159import java.util.ArrayList;
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800160import java.util.HashMap;
Charles Chen173ae782019-11-11 20:39:02 +0800161import java.util.List;
Louis Chang149d5c82019-12-30 09:47:39 +0800162import java.util.Objects;
163import java.util.Set;
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800164import java.util.function.Consumer;
Louis Chang149d5c82019-12-30 09:47:39 +0800165import java.util.function.Function;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700166
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700167/** Root {@link WindowContainer} for the device. */
Louis Chang149d5c82019-12-30 09:47:39 +0800168class RootWindowContainer extends WindowContainer<DisplayContent>
169 implements DisplayManager.DisplayListener {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700170 private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
171
Jorim Jaggi86c39f92017-05-02 18:02:46 +0200172 private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
173 private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
Louis Chang149d5c82019-12-30 09:47:39 +0800174 static final String TAG_TASKS = TAG + POSTFIX_TASKS;
175 private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
176 static final String TAG_STATES = TAG + POSTFIX_STATES;
177 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Jorim Jaggi86c39f92017-05-02 18:02:46 +0200178
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700179 private Object mLastWindowFreezeSource = null;
180 private Session mHoldScreen = null;
181 private float mScreenBrightness = -1;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700182 private long mUserActivityTimeout = -1;
183 private boolean mUpdateRotation = false;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700184 // Following variables are for debugging screen wakelock only.
185 // Last window that requires screen wakelock
186 WindowState mHoldScreenWindow = null;
187 // Last window that obscures all windows below
Wale Ogunwaled4a00a02016-10-10 11:29:17 -0700188 WindowState mObscuringWindow = null;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700189 // Only set while traversing the default display based on its content.
190 // Affects the behavior of mirroring on secondary displays.
191 private boolean mObscureApplicationContentOnSecondaryDisplays = false;
192
193 private boolean mSustainedPerformanceModeEnabled = false;
194 private boolean mSustainedPerformanceModeCurrent = false;
195
Robert Carr11c26c22016-09-23 12:40:27 -0700196 // During an orientation change, we track whether all windows have rendered
197 // at the new orientation, and this will be false from changing orientation until that occurs.
198 // For seamless rotation cases this always stays true, as the windows complete their orientation
199 // changes 1 by 1 without disturbing global state.
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700200 boolean mOrientationChangeComplete = true;
201 boolean mWallpaperActionPending = false;
202
Jorim Jaggi86c39f92017-05-02 18:02:46 +0200203 private final Handler mHandler;
204
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800205 private String mCloseSystemDialogsReason;
Robert Carrae606b42018-02-15 15:36:23 -0800206
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800207 // The ID of the display which is responsible for receiving display-unspecified key and pointer
208 // events.
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800209 private int mTopFocusedDisplayId = INVALID_DISPLAY;
210
211 // Map from the PID to the top most app which has a focused window of the process.
Garfield Tane8d84ab2019-10-11 09:49:40 -0700212 final HashMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new HashMap<>();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800213
Tiger Huang7c610aa2018-10-27 00:01:01 +0800214 // Only a separate transaction until we separate the apply surface changes
Robert Carrae606b42018-02-15 15:36:23 -0800215 // transaction from the global transaction.
Vishnu Nair33197392019-08-30 10:29:37 -0700216 private final SurfaceControl.Transaction mDisplayTransaction;
Robert Carrae606b42018-02-15 15:36:23 -0800217
Louis Chang149d5c82019-12-30 09:47:39 +0800218 /**
219 * The modes which affect which tasks are returned when calling
220 * {@link RootWindowContainer#anyTaskForId(int)}.
221 */
222 @Retention(RetentionPolicy.SOURCE)
223 @IntDef({
224 MATCH_TASK_IN_STACKS_ONLY,
225 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
226 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
227 })
228 public @interface AnyTaskForIdMatchTaskMode {}
229 // Match only tasks in the current stacks
230 static final int MATCH_TASK_IN_STACKS_ONLY = 0;
231 // Match either tasks in the current stacks, or in the recent tasks if not found in the stacks
232 static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS = 1;
233 // Match either tasks in the current stacks, or in the recent tasks, restoring it to the
234 // provided stack id
235 static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE = 2;
236
237 ActivityTaskManagerService mService;
238 ActivityStackSupervisor mStackSupervisor;
239 WindowManagerService mWindowManager;
240 DisplayManager mDisplayManager;
241 private DisplayManagerInternal mDisplayManagerInternal;
242
243 /** Reference to default display so we can quickly look it up. */
244 private DisplayContent mDefaultDisplay;
245 private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
246
247 /** The current user */
248 int mCurrentUser;
249 /** Stack id of the front stack when user switched, indexed by userId. */
250 SparseIntArray mUserStackInFront = new SparseIntArray(2);
251
252 /**
253 * A list of tokens that cause the top activity to be put to sleep.
254 * They are used by components that may hide and block interaction with underlying
255 * activities.
256 */
257 final ArrayList<ActivityTaskManagerInternal.SleepToken> mSleepTokens = new ArrayList<>();
258
Louis Chang149d5c82019-12-30 09:47:39 +0800259 /** Set when a power hint has started, but not ended. */
260 private boolean mPowerHintSent;
261
262 /** Used to keep ensureActivitiesVisible() from being entered recursively. */
263 private boolean mInEnsureActivitiesVisible = false;
264
265 // The default minimal size that will be used if the activity doesn't specify its minimal size.
266 // It will be calculated when the default display gets added.
267 int mDefaultMinSizeOfResizeableTaskDp = -1;
268
269 // Whether tasks have moved and we need to rank the tasks before next OOM scoring
270 private boolean mTaskLayersChanged = true;
271 private int mTmpTaskLayerRank;
272
273 private boolean mTmpBoolean;
274 private RemoteException mTmpRemoteException;
275
276 private String mDestroyAllActivitiesReason;
277 private final Runnable mDestroyAllActivitiesRunnable = new Runnable() {
278 @Override
279 public void run() {
280 synchronized (mService.mGlobalLock) {
281 try {
282 mStackSupervisor.beginDeferResume();
283
284 final PooledConsumer c = PooledLambda.obtainConsumer(
285 RootWindowContainer::destroyActivity, RootWindowContainer.this,
286 PooledLambda.__(ActivityRecord.class));
287 forAllActivities(c);
288 c.recycle();
289 } finally {
290 mStackSupervisor.endDeferResume();
291 resumeFocusedStacksTopActivities();
292 }
293 }
294 }
295
296 };
297
298 private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
299 static class FindTaskResult implements Function<Task, Boolean> {
300 ActivityRecord mRecord;
301 boolean mIdealMatch;
302
303 private ActivityRecord mTarget;
304 private Intent intent;
305 private ActivityInfo info;
306 private ComponentName cls;
307 private int userId;
308 private boolean isDocument;
309 private Uri documentData;
310
311 /**
312 * Returns the top activity in any existing task matching the given Intent in the input
313 * result. Returns null if no such task is found.
314 */
315 void process(ActivityRecord target, ActivityStack parent) {
316 mTarget = target;
317
318 intent = target.intent;
319 info = target.info;
320 cls = intent.getComponent();
321 if (info.targetActivity != null) {
322 cls = new ComponentName(info.packageName, info.targetActivity);
323 }
324 userId = UserHandle.getUserId(info.applicationInfo.uid);
325 isDocument = intent != null & intent.isDocument();
326 // If documentData is non-null then it must match the existing task data.
327 documentData = isDocument ? intent.getData() : null;
328
329 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + parent);
330 parent.forAllTasks(this);
331 }
332
333 void clear() {
334 mRecord = null;
335 mIdealMatch = false;
336 }
337
338 void setTo(FindTaskResult result) {
339 mRecord = result.mRecord;
340 mIdealMatch = result.mIdealMatch;
341 }
342
343 @Override
344 public Boolean apply(Task task) {
345 if (task.voiceSession != null) {
346 // We never match voice sessions; those always run independently.
347 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
348 return false;
349 }
350 if (task.mUserId != userId) {
351 // Looking for a different task.
352 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
353 return false;
354 }
355
356 // Overlays should not be considered as the task's logical top activity.
357 final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */);
358 if (r == null || r.finishing || r.mUserId != userId
359 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
360 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
361 return false;
362 }
363 if (!r.hasCompatibleActivityType(mTarget)) {
364 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
365 return false;
366 }
367
368 final Intent taskIntent = task.intent;
369 final Intent affinityIntent = task.affinityIntent;
370 final boolean taskIsDocument;
371 final Uri taskDocumentData;
372 if (taskIntent != null && taskIntent.isDocument()) {
373 taskIsDocument = true;
374 taskDocumentData = taskIntent.getData();
375 } else if (affinityIntent != null && affinityIntent.isDocument()) {
376 taskIsDocument = true;
377 taskDocumentData = affinityIntent.getData();
378 } else {
379 taskIsDocument = false;
380 taskDocumentData = null;
381 }
382
383 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
384 + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
385 + "/aff=" + r.getTask().rootAffinity + " to new cls="
386 + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
387 // TODO Refactor to remove duplications. Check if logic can be simplified.
388 if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
389 && Objects.equals(documentData, taskDocumentData)) {
390 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
391 //dump();
392 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
393 "For Intent " + intent + " bringing to top: " + r.intent);
394 mRecord = r;
395 mIdealMatch = true;
396 return true;
397 } else if (affinityIntent != null && affinityIntent.getComponent() != null
398 && affinityIntent.getComponent().compareTo(cls) == 0 &&
399 Objects.equals(documentData, taskDocumentData)) {
400 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
401 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
402 "For Intent " + intent + " bringing to top: " + r.intent);
403 mRecord = r;
404 mIdealMatch = true;
405 return true;
406 } else if (!isDocument && !taskIsDocument
407 && mRecord == null && task.rootAffinity != null) {
408 if (task.rootAffinity.equals(mTarget.taskAffinity)) {
409 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
410 // It is possible for multiple tasks to have the same root affinity especially
411 // if they are in separate stacks. We save off this candidate, but keep looking
412 // to see if there is a better candidate.
413 mRecord = r;
414 mIdealMatch = false;
415 }
416 } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
417
418 return false;
419 }
420 }
421
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800422 private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
423 if (w.mHasSurface) {
424 try {
425 w.mClient.closeSystemDialogs(mCloseSystemDialogsReason);
426 } catch (RemoteException e) {
427 }
428 }
429 };
430
431 private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700432 final ActivityRecord activity = w.mActivityRecord;
433 if (activity != null) {
434 activity.removeReplacedWindowIfNeeded(w);
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800435 }
436 };
437
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700438 RootWindowContainer(WindowManagerService service) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100439 super(service);
Vishnu Nair33197392019-08-30 10:29:37 -0700440 mDisplayTransaction = service.mTransactionFactory.get();
Jorim Jaggi86c39f92017-05-02 18:02:46 +0200441 mHandler = new MyHandler(service.mH.getLooper());
Louis Chang149d5c82019-12-30 09:47:39 +0800442 mService = service.mAtmService;
443 mStackSupervisor = mService.mStackSupervisor;
444 mStackSupervisor.mRootWindowContainer = this;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700445 }
446
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800447 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800448 mTopFocusedAppByProcess.clear();
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800449 boolean changed = false;
450 int topFocusedDisplayId = INVALID_DISPLAY;
lumark6f13d20b2018-10-19 14:38:15 +0800451 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700452 final DisplayContent dc = mChildren.get(i);
Louis Changa9350fe2019-04-25 17:14:20 +0800453 changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows, topFocusedDisplayId);
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800454 final WindowState newFocus = dc.mCurrentFocus;
455 if (newFocus != null) {
456 final int pidOfNewFocus = newFocus.mSession.mPid;
457 if (mTopFocusedAppByProcess.get(pidOfNewFocus) == null) {
Garfield Tane8d84ab2019-10-11 09:49:40 -0700458 mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mActivityRecord);
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800459 }
460 if (topFocusedDisplayId == INVALID_DISPLAY) {
461 topFocusedDisplayId = dc.getDisplayId();
462 }
Louis Changa9350fe2019-04-25 17:14:20 +0800463 } else if (topFocusedDisplayId == INVALID_DISPLAY && dc.mFocusedApp != null) {
464 // The top-most display that has a focused app should still be the top focused
465 // display even when the app window is not ready yet (process not attached or
466 // window not added yet).
467 topFocusedDisplayId = dc.getDisplayId();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700468 }
469 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800470 if (topFocusedDisplayId == INVALID_DISPLAY) {
471 topFocusedDisplayId = DEFAULT_DISPLAY;
472 }
473 if (mTopFocusedDisplayId != topFocusedDisplayId) {
474 mTopFocusedDisplayId = topFocusedDisplayId;
Tiger Huang51c5a1d2018-12-11 20:24:51 +0800475 mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
Tiger Huangdc7356a2018-12-17 16:15:35 +0800476 mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
Adrian Roosb125e0b2019-10-02 14:55:14 +0200477 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d",
478 topFocusedDisplayId);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800479 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800480 return changed;
481 }
482
483 DisplayContent getTopFocusedDisplayContent() {
Charles Chen37848f32019-02-27 19:27:45 +0800484 final DisplayContent dc = getDisplayContent(mTopFocusedDisplayId);
485 return dc != null ? dc : getDisplayContent(DEFAULT_DISPLAY);
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800486 }
487
488 @Override
lumarkd0b5c8f2019-09-29 11:30:37 +0800489 boolean isOnTop() {
490 // Considered always on top
491 return true;
492 }
493
494 @Override
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200495 void onChildPositionChanged(WindowContainer child) {
Tiger Huangfc90c132018-12-20 18:53:47 +0800496 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
497 !mWmService.mPerDisplayFocusEnabled /* updateInputWindows */);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700498 }
499
Garfield Tanb5910b42019-03-14 14:50:59 -0700500 /**
501 * Called when DisplayWindowSettings values may change.
502 */
503 void onSettingsRetrieved() {
504 final int numDisplays = mChildren.size();
505 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
506 final DisplayContent displayContent = mChildren.get(displayNdx);
507 final boolean changed = mWmService.mDisplayWindowSettings.updateSettingsForDisplay(
508 displayContent);
509 if (!changed) {
510 continue;
511 }
512
Shivam Agrawal6472e0e2019-07-03 16:27:49 -0700513 displayContent.reconfigureDisplayLocked();
Garfield Tanb5910b42019-03-14 14:50:59 -0700514
515 // We need to update global configuration as well if config of default display has
516 // changed. Do it inline because ATMS#retrieveSettings() will soon update the
517 // configuration inline, which will overwrite the new windowing mode.
518 if (displayContent.isDefaultDisplay) {
519 final Configuration newConfig = mWmService.computeNewConfiguration(
520 displayContent.getDisplayId());
521 mWmService.mAtmService.updateConfigurationLocked(newConfig, null /* starting */,
522 false /* initLocale */);
523 }
524 }
525 }
526
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700527 boolean isLayoutNeeded() {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700528 final int numDisplays = mChildren.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700529 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700530 final DisplayContent displayContent = mChildren.get(displayNdx);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700531 if (displayContent.isLayoutNeeded()) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700532 return true;
533 }
534 }
535 return false;
536 }
537
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000538 void getWindowsByName(ArrayList<WindowState> output, String name) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700539 int objectId = 0;
540 // See if this is an object ID.
541 try {
542 objectId = Integer.parseInt(name, 16);
543 name = null;
544 } catch (RuntimeException e) {
545 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800546
547 getWindowsByName(output, name, objectId);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700548 }
549
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000550 private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800551 forAllWindows((w) -> {
552 if (name != null) {
553 if (w.mAttrs.getTitle().toString().contains(name)) {
554 output.add(w);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700555 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800556 } else if (System.identityHashCode(w) == objectId) {
557 output.add(w);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700558 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800559 }, true /* traverseTopToBottom */);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700560 }
561
Wale Ogunwale02319a62016-09-26 15:21:22 -0700562 /**
Charles Chen173ae782019-11-11 20:39:02 +0800563 * Returns {@code true} if the callingUid has any non-toast window currently visible to the
564 * user. Also ignores {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_STARTING},
565 * since those windows don't belong to apps.
566 * @see WindowState#isNonToastOrStarting()
Michal Karpinskia606a292019-01-12 17:29:52 +0000567 */
568 boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
Charles Chen173ae782019-11-11 20:39:02 +0800569 final PooledPredicate p = PooledLambda.obtainPredicate(
570 WindowState::isNonToastWindowVisibleForUid,
571 PooledLambda.__(WindowState.class), callingUid);
572
573 final WindowState w = getWindow(p);
574 p.recycle();
575 return w != null;
Michal Karpinskia606a292019-01-12 17:29:52 +0000576 }
577
578 /**
Wale Ogunwale02319a62016-09-26 15:21:22 -0700579 * Returns the app window token for the input binder if it exist in the system.
580 * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
581 * AppWindowToken represents an activity which can only exist on one display.
582 */
Garfield Tane8d84ab2019-10-11 09:49:40 -0700583 ActivityRecord getActivityRecord(IBinder binder) {
Wale Ogunwale02319a62016-09-26 15:21:22 -0700584 for (int i = mChildren.size() - 1; i >= 0; --i) {
585 final DisplayContent dc = mChildren.get(i);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700586 final ActivityRecord activity = dc.getActivityRecord(binder);
587 if (activity != null) {
588 return activity;
Wale Ogunwale02319a62016-09-26 15:21:22 -0700589 }
590 }
591 return null;
592 }
593
wilsonshihab672942018-08-06 15:42:07 +0800594 /** Returns the window token for the input binder if it exist in the system. */
595 WindowToken getWindowToken(IBinder binder) {
596 for (int i = mChildren.size() - 1; i >= 0; --i) {
597 final DisplayContent dc = mChildren.get(i);
598 final WindowToken wtoken = dc.getWindowToken(binder);
599 if (wtoken != null) {
600 return wtoken;
601 }
602 }
603 return null;
604 }
605
Wale Ogunwale02319a62016-09-26 15:21:22 -0700606 /** Returns the display object the input window token is currently mapped on. */
607 DisplayContent getWindowTokenDisplay(WindowToken token) {
608 if (token == null) {
609 return null;
610 }
611
612 for (int i = mChildren.size() - 1; i >= 0; --i) {
613 final DisplayContent dc = mChildren.get(i);
614 final WindowToken current = dc.getWindowToken(token.token);
615 if (current == token) {
616 return dc;
617 }
618 }
619
620 return null;
621 }
622
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700623 /**
Evan Roskye747c3e2018-10-30 20:06:41 -0700624 * Set new display override config. If called for the default display, global configuration
625 * will also be updated.
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700626 */
Evan Roskye747c3e2018-10-30 20:06:41 -0700627 void setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration,
628 @NonNull DisplayContent displayContent) {
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700629
Evan Roskydfe3da72018-10-26 17:21:06 -0700630 final Configuration currentConfig = displayContent.getRequestedOverrideConfiguration();
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700631 final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
632 if (!configChanged) {
Evan Roskye747c3e2018-10-30 20:06:41 -0700633 return;
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700634 }
Bryce Leeaea60d22018-01-31 14:42:15 -0800635
Evan Roskydfe3da72018-10-26 17:21:06 -0700636 displayContent.onRequestedOverrideConfigurationChanged(newConfiguration);
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700637
Evan Roskye747c3e2018-10-30 20:06:41 -0700638 if (displayContent.getDisplayId() == DEFAULT_DISPLAY) {
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700639 // Override configuration of the default display duplicates global config. In this case
640 // we also want to update the global config.
Evan Roskye747c3e2018-10-30 20:06:41 -0700641 setGlobalConfigurationIfNeeded(newConfiguration);
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700642 }
643 }
644
Evan Roskye747c3e2018-10-30 20:06:41 -0700645 private void setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700646 final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
647 if (!configChanged) {
Bryce Leeaea60d22018-01-31 14:42:15 -0800648 return;
Andrii Kulian441e4492016-09-29 15:25:00 -0700649 }
650 onConfigurationChanged(newConfiguration);
Andrii Kulian441e4492016-09-29 15:25:00 -0700651 }
652
653 @Override
Wale Ogunwale98d62312017-07-12 09:24:56 -0700654 public void onConfigurationChanged(Configuration newParentConfig) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700655 prepareFreezingTaskBounds();
Andrii Kulian441e4492016-09-29 15:25:00 -0700656 super.onConfigurationChanged(newParentConfig);
Andrii Kulian441e4492016-09-29 15:25:00 -0700657 }
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700658
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700659 private void prepareFreezingTaskBounds() {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700660 for (int i = mChildren.size() - 1; i >= 0; i--) {
661 mChildren.get(i).prepareFreezingTaskBounds();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700662 }
663 }
664
665 void setSecureSurfaceState(int userId, boolean disabled) {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800666 forAllWindows((w) -> {
667 if (w.mHasSurface && userId == UserHandle.getUserId(w.mOwnerUid)) {
668 w.mWinAnimator.setSecureLocked(disabled);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700669 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800670 }, true /* traverseTopToBottom */);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700671 }
672
Suprabh Shukla69c71422018-04-02 18:39:01 -0700673 void updateHiddenWhileSuspendedState(final ArraySet<String> packages, final boolean suspended) {
674 forAllWindows((w) -> {
675 if (packages.contains(w.getOwningPackage())) {
676 w.setHiddenWhileSuspended(suspended);
677 }
678 }, false);
679 }
680
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700681 void updateAppOpsState() {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800682 forAllWindows((w) -> {
Svet Ganovf7b47252018-02-26 11:11:27 -0800683 w.updateAppOpsState();
Wale Ogunwaled1880962016-11-08 10:31:59 -0800684 }, false /* traverseTopToBottom */);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700685 }
686
687 boolean canShowStrictModeViolation(int pid) {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800688 final WindowState win = getWindow((w) -> w.mSession.mPid == pid && w.isVisibleLw());
689 return win != null;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700690 }
691
692 void closeSystemDialogs(String reason) {
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800693 mCloseSystemDialogsReason = reason;
694 forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700695 }
696
697 void removeReplacedWindows() {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200698 ProtoLog.i(WM_SHOW_TRANSACTIONS, ">>> OPEN TRANSACTION removeReplacedWindows");
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800699 mWmService.openSurfaceTransaction();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700700 try {
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800701 forAllWindows(sRemoveReplacedWindowsConsumer, true /* traverseTopToBottom */);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700702 } finally {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800703 mWmService.closeSurfaceTransaction("removeReplacedWindows");
Adrian Roosb125e0b2019-10-02 14:55:14 +0200704 ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION removeReplacedWindows");
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700705 }
706 }
707
708 boolean hasPendingLayoutChanges(WindowAnimator animator) {
709 boolean hasChanges = false;
710
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700711 final int count = mChildren.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700712 for (int i = 0; i < count; ++i) {
Riddle Hsu8419e4b2019-09-18 23:28:01 +0800713 final int pendingChanges = mChildren.get(i).pendingLayoutChanges;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700714 if ((pendingChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
715 animator.mBulkUpdateParams |= SET_WALLPAPER_ACTION_PENDING;
716 }
717 if (pendingChanges != 0) {
718 hasChanges = true;
719 }
720 }
721
722 return hasChanges;
723 }
724
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700725 boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
726 boolean secure) {
727 final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
728 boolean leakedSurface = false;
729 boolean killedApps = false;
Jeff Changd136e772019-11-05 20:33:52 +0800730 EventLogTags.writeWmNoSurfaceMemory(winAnimator.mWin.toString(),
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700731 winAnimator.mSession.mPid, operation);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700732 final long callingIdentity = Binder.clearCallingIdentity();
733 try {
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700734 // There was some problem...first, do a sanity check of the window list to make sure
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700735 // we haven't left any dangling surfaces around.
736
737 Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks...");
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700738 final int numDisplays = mChildren.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700739 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700740 leakedSurface |= mChildren.get(displayNdx).destroyLeakedSurfaces();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700741 }
742
743 if (!leakedSurface) {
744 Slog.w(TAG_WM, "No leaked surfaces; killing applications!");
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700745 final SparseIntArray pidCandidates = new SparseIntArray();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700746 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800747 mChildren.get(displayNdx).forAllWindows((w) -> {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800748 if (mWmService.mForceRemoves.contains(w)) {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800749 return;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700750 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800751 final WindowStateAnimator wsa = w.mWinAnimator;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700752 if (wsa.mSurfaceController != null) {
753 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
754 }
Wale Ogunwaled1880962016-11-08 10:31:59 -0800755 }, false /* traverseTopToBottom */);
Wale Ogunwalef7cab102016-10-25 15:25:14 -0700756
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700757 if (pidCandidates.size() > 0) {
758 int[] pids = new int[pidCandidates.size()];
759 for (int i = 0; i < pids.length; i++) {
760 pids[i] = pidCandidates.keyAt(i);
761 }
762 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800763 if (mWmService.mActivityManager.killPids(pids, "Free memory", secure)) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700764 killedApps = true;
765 }
766 } catch (RemoteException e) {
767 }
768 }
769 }
770 }
771
772 if (leakedSurface || killedApps) {
773 // We managed to reclaim some memory, so get rid of the trouble surface and ask the
774 // app to request another one.
775 Slog.w(TAG_WM,
776 "Looks like we have reclaimed some memory, clearing surface for retry.");
777 if (surfaceController != null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200778 ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
779 "SURFACE RECOVER DESTROY: %s", winAnimator.mWin);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700780 winAnimator.destroySurface();
Garfield Tane8d84ab2019-10-11 09:49:40 -0700781 if (winAnimator.mWin.mActivityRecord != null) {
782 winAnimator.mWin.mActivityRecord.removeStartingWindow();
Jorim Jaggiba41f4b2016-12-14 17:43:07 -0800783 }
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700784 }
785
786 try {
787 winAnimator.mWin.mClient.dispatchGetNewSurface();
788 } catch (RemoteException e) {
789 }
790 }
791 } finally {
792 Binder.restoreCallingIdentity(callingIdentity);
793 }
794
795 return leakedSurface || killedApps;
796 }
797
Jorim Jaggi4981f152019-03-26 18:58:45 +0100798 void performSurfacePlacement(boolean recoveringMemory) {
799 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
800 try {
801 performSurfacePlacementNoTrace(recoveringMemory);
802 } finally {
803 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
804 }
805 }
806
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700807 // "Something has changed! Let's make it correct now."
808 // TODO: Super crazy long method that should be broken down...
Jorim Jaggi4981f152019-03-26 18:58:45 +0100809 void performSurfacePlacementNoTrace(boolean recoveringMemory) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700810 if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
811 + Debug.getCallers(3));
812
813 int i;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700814
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800815 if (mWmService.mFocusMayChange) {
816 mWmService.mFocusMayChange = false;
Jorim Jaggi4981f152019-03-26 18:58:45 +0100817 mWmService.updateFocusedWindowLocked(
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700818 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
819 }
820
821 // Initialize state of exiting tokens.
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700822 final int numDisplays = mChildren.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700823 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700824 final DisplayContent displayContent = mChildren.get(displayNdx);
Wale Ogunwale1666e312016-12-16 11:27:18 -0800825 displayContent.setExitingTokensHasVisible(false);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700826 }
827
828 mHoldScreen = null;
829 mScreenBrightness = -1;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700830 mUserActivityTimeout = -1;
831 mObscureApplicationContentOnSecondaryDisplays = false;
832 mSustainedPerformanceModeCurrent = false;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800833 mWmService.mTransactionSequence++;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700834
lumark588a3e82018-07-20 18:53:54 +0800835 // TODO(multi-display): recents animation & wallpaper need support multi-display.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800836 final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked();
837 final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700838
839 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
840 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
Jorim Jaggi4981f152019-03-26 18:58:45 +0100841 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800842 mWmService.openSurfaceTransaction();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700843 try {
lumark588a3e82018-07-20 18:53:54 +0800844 applySurfaceChangesTransaction(recoveringMemory);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700845 } catch (RuntimeException e) {
846 Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
847 } finally {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800848 mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
Jorim Jaggi4981f152019-03-26 18:58:45 +0100849 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700850 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
851 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
852 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800853 mWmService.mAnimator.executeAfterPrepareSurfacesRunnables();
Chavi Weingarten16d0d072018-02-12 23:50:28 +0000854
lumark588a3e82018-07-20 18:53:54 +0800855 checkAppTransitionReady(surfacePlacer);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700856
Winson Chunge2d72172018-01-25 17:46:20 +0000857 // Defer starting the recents animation until the wallpaper has drawn
858 final RecentsAnimationController recentsAnimationController =
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800859 mWmService.getRecentsAnimationController();
Winson Chunge2d72172018-01-25 17:46:20 +0000860 if (recentsAnimationController != null) {
wilsonshihc32538e2018-11-07 17:27:34 +0800861 recentsAnimationController.checkAnimationReady(defaultDisplay.mWallpaperController);
Winson Chunge2d72172018-01-25 17:46:20 +0000862 }
863
wilsonshihc32538e2018-11-07 17:27:34 +0800864 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
865 final DisplayContent displayContent = mChildren.get(displayNdx);
866 if (displayContent.mWallpaperMayChange) {
867 if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change! Adjusting");
868 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
869 if (DEBUG_LAYOUT_REPEATS) {
870 surfacePlacer.debugLayoutRepeats("WallpaperMayChange",
871 displayContent.pendingLayoutChanges);
872 }
873 }
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700874 }
875
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800876 if (mWmService.mFocusMayChange) {
877 mWmService.mFocusMayChange = false;
Jorim Jaggi4981f152019-03-26 18:58:45 +0100878 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
879 false /*updateInputWindows*/);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700880 }
881
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700882 if (isLayoutNeeded()) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700883 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
884 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
885 defaultDisplay.pendingLayoutChanges);
886 }
887
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800888 handleResizingWindows();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700889
Adrian Roosb125e0b2019-10-02 14:55:14 +0200890 if (mWmService.mDisplayFrozen) {
891 ProtoLog.v(WM_DEBUG_ORIENTATION,
892 "With display frozen, orientationChangeComplete=%b",
893 mOrientationChangeComplete);
894 }
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700895 if (mOrientationChangeComplete) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800896 if (mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
897 mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
898 mWmService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
899 mWmService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700900 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800901 mWmService.stopFreezingDisplayLocked();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700902 }
903
904 // Destroy the surface of any windows that are no longer visible.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800905 i = mWmService.mDestroySurface.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700906 if (i > 0) {
907 do {
908 i--;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800909 WindowState win = mWmService.mDestroySurface.get(i);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700910 win.mDestroying = false;
lumark90120a82018-08-15 00:33:03 +0800911 final DisplayContent displayContent = win.getDisplayContent();
912 if (displayContent.mInputMethodWindow == win) {
913 displayContent.setInputMethodWindowLocked(null);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700914 }
lumark90120a82018-08-15 00:33:03 +0800915 if (displayContent.mWallpaperController.isWallpaperTarget(win)) {
wilsonshihc32538e2018-11-07 17:27:34 +0800916 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700917 }
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200918 win.destroySurfaceUnchecked();
Robert Carrfa8edf82018-04-19 12:38:47 -0700919 win.mWinAnimator.destroyPreservedSurfaceLocked();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700920 } while (i > 0);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800921 mWmService.mDestroySurface.clear();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700922 }
923
924 // Time to remove any exiting tokens?
925 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700926 final DisplayContent displayContent = mChildren.get(displayNdx);
Wale Ogunwale1666e312016-12-16 11:27:18 -0800927 displayContent.removeExistingTokensIfPossible();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700928 }
929
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700930 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700931 final DisplayContent displayContent = mChildren.get(displayNdx);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700932 if (displayContent.pendingLayoutChanges != 0) {
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700933 displayContent.setLayoutNeeded();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700934 }
935 }
936
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800937 mWmService.setHoldScreenLocked(mHoldScreen);
938 if (!mWmService.mDisplayFrozen) {
Jorim Jaggi86c39f92017-05-02 18:02:46 +0200939 final int brightness = mScreenBrightness < 0 || mScreenBrightness > 1.0f
940 ? -1 : toBrightnessOverride(mScreenBrightness);
941
942 // Post these on a handler such that we don't call into power manager service while
943 // holding the window manager lock to avoid lock contention with power manager lock.
944 mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightness, 0).sendToTarget();
945 mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700946 }
947
948 if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
949 mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800950 mWmService.mPowerManagerInternal.powerHint(
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700951 PowerHint.SUSTAINED_PERFORMANCE,
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700952 (mSustainedPerformanceModeEnabled ? 1 : 0));
953 }
954
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700955 if (mUpdateRotation) {
Adrian Roosb125e0b2019-10-02 14:55:14 +0200956 ProtoLog.d(WM_DEBUG_ORIENTATION, "Performing post-rotate rotation");
Riddle Hsu654a6f92018-07-13 22:59:36 +0800957 mUpdateRotation = updateRotationUnchecked();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700958 }
959
Yunfan Chen87b5a242019-10-01 17:53:59 +0900960 if (!mWmService.mWaitingForDrawnCallbacks.isEmpty()
lumark588a3e82018-07-20 18:53:54 +0800961 || (mOrientationChangeComplete && !isLayoutNeeded()
Jorim Jaggi4981f152019-03-26 18:58:45 +0100962 && !mUpdateRotation)) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800963 mWmService.checkDrawnWindowsLocked();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700964 }
965
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800966 final int N = mWmService.mPendingRemove.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700967 if (N > 0) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800968 if (mWmService.mPendingRemoveTmp.length < N) {
969 mWmService.mPendingRemoveTmp = new WindowState[N + 10];
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700970 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800971 mWmService.mPendingRemove.toArray(mWmService.mPendingRemoveTmp);
972 mWmService.mPendingRemove.clear();
Wale Ogunwale19e452e2016-10-12 12:36:29 -0700973 ArrayList<DisplayContent> displayList = new ArrayList();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700974 for (i = 0; i < N; i++) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800975 final WindowState w = mWmService.mPendingRemoveTmp[i];
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700976 w.removeImmediately();
977 final DisplayContent displayContent = w.getDisplayContent();
978 if (displayContent != null && !displayList.contains(displayContent)) {
979 displayList.add(displayContent);
980 }
981 }
982
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700983 for (int j = displayList.size() - 1; j >= 0; --j) {
984 final DisplayContent dc = displayList.get(j);
985 dc.assignWindowLayers(true /*setLayoutNeeded*/);
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700986 }
987 }
988
989 // Remove all deferred displays stacks, tasks, and activities.
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -0700990 for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
991 mChildren.get(displayNdx).checkCompleteDeferredRemoval();
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700992 }
993
Jorim Jaggi4981f152019-03-26 18:58:45 +0100994 forAllDisplays(dc -> {
995 dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
996 dc.updateSystemGestureExclusion();
997 dc.updateTouchExcludeRegion();
998 });
Wale Ogunwalee05f5012016-09-16 16:27:29 -0700999
1000 // Check to see if we are now in a state where the screen should
1001 // be enabled, because the window obscured flags have changed.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001002 mWmService.enableScreenIfNeededLocked();
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001003
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001004 mWmService.scheduleAnimationLocked();
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001005
Evan Rosky0037e5f2019-11-05 10:26:24 -08001006 // Send any pending task-info changes that were queued-up during a layout deferment
1007 mWmService.mAtmService.mTaskOrganizerController.dispatchPendingTaskInfoChanges();
1008
Evan Rosky73a7fe92019-11-18 18:28:01 -08001009 if (DEBUG_WINDOW_TRACE) Slog.e(TAG, "performSurfacePlacementInner exit");
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001010 }
1011
lumark588a3e82018-07-20 18:53:54 +08001012 private void checkAppTransitionReady(WindowSurfacePlacer surfacePlacer) {
1013 // Trace all displays app transition by Z-order for pending layout change.
1014 for (int i = mChildren.size() - 1; i >= 0; --i) {
1015 final DisplayContent curDisplay = mChildren.get(i);
1016
1017 // If we are ready to perform an app transition, check through all of the app tokens
1018 // to be shown and see if they are ready to go.
1019 if (curDisplay.mAppTransition.isReady()) {
1020 // handleAppTransitionReady may modify curDisplay.pendingLayoutChanges.
1021 curDisplay.mAppTransitionController.handleAppTransitionReady();
1022 if (DEBUG_LAYOUT_REPEATS) {
1023 surfacePlacer.debugLayoutRepeats("after handleAppTransitionReady",
1024 curDisplay.pendingLayoutChanges);
1025 }
1026 }
1027
lumark9bca6b42019-10-17 18:35:22 +08001028 if (curDisplay.mAppTransition.isRunning() && !curDisplay.isAppTransitioning()) {
lumark588a3e82018-07-20 18:53:54 +08001029 // We have finished the animation of an app transition. To do this, we have
1030 // delayed a lot of operations like showing and hiding apps, moving apps in
1031 // Z-order, etc.
1032 // The app token list reflects the correct Z-order, but the window list may now
1033 // be out of sync with it. So here we will just rebuild the entire app window
1034 // list. Fun!
1035 curDisplay.handleAnimatingStoppedAndTransition();
1036 if (DEBUG_LAYOUT_REPEATS) {
1037 surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock",
1038 curDisplay.pendingLayoutChanges);
1039 }
1040 }
1041 }
1042 }
1043
1044 private void applySurfaceChangesTransaction(boolean recoveringMemory) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001045 mHoldScreenWindow = null;
Wale Ogunwaled4a00a02016-10-10 11:29:17 -07001046 mObscuringWindow = null;
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001047
Andrii Kulian8ee72852017-03-10 10:36:45 -08001048 // TODO(multi-display): Support these features on secondary screens.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001049 final DisplayContent defaultDc = mWmService.getDefaultDisplayContentLocked();
lumark588a3e82018-07-20 18:53:54 +08001050 final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();
1051 final int defaultDw = defaultInfo.logicalWidth;
1052 final int defaultDh = defaultInfo.logicalHeight;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001053 if (mWmService.mWatermark != null) {
chaviw619da692019-06-10 15:39:40 -07001054 mWmService.mWatermark.positionSurface(defaultDw, defaultDh, mDisplayTransaction);
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001055 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001056 if (mWmService.mStrictModeFlash != null) {
chaviw619da692019-06-10 15:39:40 -07001057 mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh, mDisplayTransaction);
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001058 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001059 if (mWmService.mEmulatorDisplayOverlay != null) {
1060 mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
chaviw619da692019-06-10 15:39:40 -07001061 mWmService.getDefaultDisplayRotation(), mDisplayTransaction);
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001062 }
1063
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -07001064 final int count = mChildren.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001065 for (int j = 0; j < count; ++j) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -07001066 final DisplayContent dc = mChildren.get(j);
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001067 dc.applySurfaceChangesTransaction(recoveringMemory);
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001068 }
1069
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001070 // Give the display manager a chance to adjust properties like display rotation if it needs
1071 // to.
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001072 mWmService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
Robert Carrae606b42018-02-15 15:36:23 -08001073 SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001074 }
1075
1076 /**
David Stevensf833ba92017-03-16 19:00:20 -07001077 * Handles resizing windows during surface placement.
David Stevensf833ba92017-03-16 19:00:20 -07001078 */
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001079 private void handleResizingWindows() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001080 for (int i = mWmService.mResizingWindows.size() - 1; i >= 0; i--) {
1081 WindowState win = mWmService.mResizingWindows.get(i);
Louis Changc3f29da2018-12-10 18:09:06 +08001082 if (win.mAppFreezing || win.getDisplayContent().mWaitingForConfig) {
1083 // Don't remove this window until rotation has completed and is not waiting for the
1084 // complete configuration.
David Stevensf833ba92017-03-16 19:00:20 -07001085 continue;
1086 }
1087 win.reportResized();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001088 mWmService.mResizingWindows.remove(i);
David Stevensf833ba92017-03-16 19:00:20 -07001089 }
David Stevensf833ba92017-03-16 19:00:20 -07001090 }
1091
1092 /**
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001093 * @param w WindowState this method is applied to.
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001094 * @param obscured True if there is a window on top of this obscuring the display.
1095 * @param syswin System window?
1096 * @return True when the display contains content to show the user. When false, the display
1097 * manager may choose to mirror or blank the display.
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001098 */
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001099 boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001100 final WindowManager.LayoutParams attrs = w.mAttrs;
1101 final int attrFlags = attrs.flags;
Aaron Whyte8cbdf042018-01-23 12:06:02 -08001102 final boolean onScreen = w.isOnScreen();
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001103 final boolean canBeSeen = w.isDisplayedLw();
1104 final int privateflags = attrs.privateFlags;
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001105 boolean displayHasContent = false;
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001106
Adrian Roosb125e0b2019-10-02 14:55:14 +02001107 ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,
1108 "handleNotObscuredLocked w: %s, w.mHasSurface: %b, w.isOnScreen(): %b, w"
1109 + ".isDisplayedLw(): %b, w.mAttrs.userActivityTimeout: %d",
1110 w, w.mHasSurface, onScreen, w.isDisplayedLw(), w.mAttrs.userActivityTimeout);
Aaron Whyte8cbdf042018-01-23 12:06:02 -08001111 if (w.mHasSurface && onScreen) {
1112 if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) {
1113 mUserActivityTimeout = w.mAttrs.userActivityTimeout;
Adrian Roosb125e0b2019-10-02 14:55:14 +02001114 ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "mUserActivityTimeout set to %d",
1115 mUserActivityTimeout);
Aaron Whyte8cbdf042018-01-23 12:06:02 -08001116 }
1117 }
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001118 if (w.mHasSurface && canBeSeen) {
1119 if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
1120 mHoldScreen = w.mSession;
1121 mHoldScreenWindow = w;
Adrian Roosb125e0b2019-10-02 14:55:14 +02001122 } else if (w == mWmService.mLastWakeLockHoldingWindow) {
1123 ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,
1124 "handleNotObscuredLocked: %s was holding screen wakelock but no longer "
1125 + "has FLAG_KEEP_SCREEN_ON!!! called by%s",
1126 w, Debug.getCallers(10));
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001127 }
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001128 if (!syswin && w.mAttrs.screenBrightness >= 0 && mScreenBrightness < 0) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001129 mScreenBrightness = w.mAttrs.screenBrightness;
1130 }
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001131
1132 final int type = attrs.type;
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001133 // This function assumes that the contents of the default display are processed first
1134 // before secondary displays.
1135 final DisplayContent displayContent = w.getDisplayContent();
1136 if (displayContent != null && displayContent.isDefaultDisplay) {
1137 // While a dream or keyguard is showing, obscure ordinary application content on
1138 // secondary displays (by forcibly enabling mirroring unless there is other content
1139 // we want to show) but still allow opaque keyguard dialogs to be shown.
wilsonshihe8321942019-10-18 18:39:46 +08001140 if (type == TYPE_DREAM || mWmService.mPolicy.isKeyguardShowing()) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001141 mObscureApplicationContentOnSecondaryDisplays = true;
1142 }
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001143 displayHasContent = true;
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001144 } else if (displayContent != null &&
1145 (!mObscureApplicationContentOnSecondaryDisplays
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001146 || (obscured && type == TYPE_KEYGUARD_DIALOG))) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001147 // Allow full screen keyguard presentation dialogs to be seen.
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001148 displayHasContent = true;
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001149 }
1150 if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) {
1151 mSustainedPerformanceModeCurrent = true;
1152 }
1153 }
Wale Ogunwalef7cab102016-10-25 15:25:14 -07001154
1155 return displayHasContent;
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001156 }
1157
Riddle Hsu654a6f92018-07-13 22:59:36 +08001158 boolean updateRotationUnchecked() {
1159 boolean changed = false;
1160 for (int i = mChildren.size() - 1; i >= 0; i--) {
Riddle Hsuccf09402019-08-13 00:33:06 +08001161 if (mChildren.get(i).getDisplayRotation().updateRotationAndSendNewConfigIfChanged()) {
Riddle Hsu654a6f92018-07-13 22:59:36 +08001162 changed = true;
Riddle Hsu654a6f92018-07-13 22:59:36 +08001163 }
1164 }
1165 return changed;
1166 }
1167
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001168 boolean copyAnimToLayoutParams() {
1169 boolean doRequest = false;
1170
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001171 final int bulkUpdateParams = mWmService.mAnimator.mBulkUpdateParams;
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001172 if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
1173 mUpdateRotation = true;
1174 doRequest = true;
1175 }
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001176 if ((bulkUpdateParams & SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
1177 mOrientationChangeComplete = false;
1178 } else {
1179 mOrientationChangeComplete = true;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001180 mLastWindowFreezeSource = mWmService.mAnimator.mLastWindowFreezeSource;
1181 if (mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001182 doRequest = true;
1183 }
1184 }
chaviw042059d2018-01-11 11:24:08 -08001185
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001186 if ((bulkUpdateParams & SET_WALLPAPER_ACTION_PENDING) != 0) {
1187 mWallpaperActionPending = true;
1188 }
1189
1190 return doRequest;
1191 }
1192
1193 private static int toBrightnessOverride(float value) {
1194 return (int)(value * PowerManager.BRIGHTNESS_ON);
1195 }
1196
Jorim Jaggi86c39f92017-05-02 18:02:46 +02001197 private final class MyHandler extends Handler {
1198
1199 public MyHandler(Looper looper) {
1200 super(looper);
1201 }
1202
1203 @Override
1204 public void handleMessage(Message msg) {
1205 switch (msg.what) {
1206 case SET_SCREEN_BRIGHTNESS_OVERRIDE:
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001207 mWmService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
Jorim Jaggi86c39f92017-05-02 18:02:46 +02001208 msg.arg1);
1209 break;
1210 case SET_USER_ACTIVITY_TIMEOUT:
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001211 mWmService.mPowerManagerInternal.
1212 setUserActivityTimeoutOverrideFromWindowManager((Long) msg.obj);
Jorim Jaggi86c39f92017-05-02 18:02:46 +02001213 break;
1214 default:
1215 break;
1216 }
1217 }
1218 }
1219
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001220 void dumpDisplayContents(PrintWriter pw) {
1221 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001222 if (mWmService.mDisplayReady) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -07001223 final int count = mChildren.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001224 for (int i = 0; i < count; ++i) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -07001225 final DisplayContent displayContent = mChildren.get(i);
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001226 displayContent.dump(pw, " ", true /* dumpAll */);
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001227 }
1228 } else {
1229 pw.println(" NO DISPLAY");
1230 }
1231 }
1232
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001233 void dumpTopFocusedDisplayId(PrintWriter pw) {
1234 pw.print(" mTopFocusedDisplayId="); pw.println(mTopFocusedDisplayId);
1235 }
1236
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001237 void dumpLayoutNeededDisplayIds(PrintWriter pw) {
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001238 if (!isLayoutNeeded()) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001239 return;
1240 }
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001241 pw.print(" mLayoutNeeded on displays=");
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -07001242 final int count = mChildren.size();
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001243 for (int displayNdx = 0; displayNdx < count; ++displayNdx) {
Wale Ogunwaleeaabfab2016-09-16 17:19:52 -07001244 final DisplayContent displayContent = mChildren.get(displayNdx);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001245 if (displayContent.isLayoutNeeded()) {
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001246 pw.print(displayContent.getDisplayId());
1247 }
1248 }
1249 pw.println();
1250 }
1251
1252 void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) {
Wale Ogunwaled1880962016-11-08 10:31:59 -08001253 final int[] index = new int[1];
1254 forAllWindows((w) -> {
1255 if (windows == null || windows.contains(w)) {
1256 pw.println(" Window #" + index[0] + " " + w + ":");
1257 w.dump(pw, " ", dumpAll || windows != null);
1258 index[0] = index[0] + 1;
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001259 }
Wale Ogunwaled1880962016-11-08 10:31:59 -08001260 }, true /* traverseTopToBottom */);
Wale Ogunwalee05f5012016-09-16 16:27:29 -07001261 }
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07001262
Wale Ogunwale02319a62016-09-26 15:21:22 -07001263 void dumpTokens(PrintWriter pw, boolean dumpAll) {
1264 pw.println(" All tokens:");
1265 for (int i = mChildren.size() - 1; i >= 0; --i) {
1266 mChildren.get(i).dumpTokens(pw, dumpAll);
1267 }
1268 }
1269
Wale Ogunwalef342f062020-01-27 07:34:13 -08001270 @Override
1271 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -08001272 @WindowTraceLogLevel int logLevel) {
1273 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
1274 return;
1275 }
1276
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001277 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08001278 super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
Wale Ogunwalef342f062020-01-27 07:34:13 -08001279
1280 mStackSupervisor.getKeyguardController().dumpDebug(proto, KEYGUARD_CONTROLLER);
1281 proto.write(IS_HOME_RECENTS_COMPONENT,
1282 mStackSupervisor.mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
1283 mService.getActivityStartController().dumpDebug(proto, PENDING_ACTIVITIES);
1284
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001285 proto.end(token);
Steven Timotiusaf03df62017-07-18 16:56:43 -07001286 }
1287
Wale Ogunwaleba51ca22016-09-23 06:06:54 -07001288 @Override
1289 String getName() {
1290 return "ROOT";
1291 }
Robert Carrb1579c82017-09-05 14:54:47 -07001292
1293 @Override
1294 void scheduleAnimation() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001295 mWmService.scheduleAnimationLocked();
Robert Carrb1579c82017-09-05 14:54:47 -07001296 }
Arthur Hung95b38a92018-07-20 18:56:12 +08001297
Charles Chen37848f32019-02-27 19:27:45 +08001298 @Override
1299 protected void removeChild(DisplayContent dc) {
1300 super.removeChild(dc);
1301 if (mTopFocusedDisplayId == dc.getDisplayId()) {
1302 mWmService.updateFocusedWindowLocked(
1303 UPDATE_FOCUS_NORMAL, true /* updateInputWindows */);
1304 }
1305 }
1306
Arthur Hung95b38a92018-07-20 18:56:12 +08001307 /**
1308 * For all display at or below this call the callback.
1309 *
1310 * @param callback Callback to be called for every display.
1311 */
1312 void forAllDisplays(Consumer<DisplayContent> callback) {
1313 for (int i = mChildren.size() - 1; i >= 0; --i) {
1314 callback.accept(mChildren.get(i));
1315 }
1316 }
lumark90120a82018-08-15 00:33:03 +08001317
Tiger Huang7c610aa2018-10-27 00:01:01 +08001318 void forAllDisplayPolicies(Consumer<DisplayPolicy> callback) {
1319 for (int i = mChildren.size() - 1; i >= 0; --i) {
1320 callback.accept(mChildren.get(i).getDisplayPolicy());
1321 }
1322 }
1323
lumark90120a82018-08-15 00:33:03 +08001324 /**
1325 * Get current topmost focused IME window in system.
1326 * Will look on all displays in current Z-order.
1327 */
1328 WindowState getCurrentInputMethodWindow() {
1329 for (int i = mChildren.size() - 1; i >= 0; --i) {
1330 final DisplayContent displayContent = mChildren.get(i);
1331 if (displayContent.mInputMethodWindow != null) {
1332 return displayContent.mInputMethodWindow;
1333 }
1334 }
1335 return null;
1336 }
Charles Chen173ae782019-11-11 20:39:02 +08001337
1338 void getDisplayContextsWithNonToastVisibleWindows(int pid, List<Context> outContexts) {
1339 if (outContexts == null) {
1340 return;
1341 }
1342 for (int i = mChildren.size() - 1; i >= 0; --i) {
1343 DisplayContent dc = mChildren.get(i);
1344 if (dc.isAnyNonToastWindowVisibleForPid(pid)) {
1345 outContexts.add(dc.getDisplayUiContext());
1346 }
1347 }
1348 }
1349
1350 @Nullable Context getDisplayUiContext(int displayId) {
1351 return getDisplayContent(displayId) != null
1352 ? getDisplayContent(displayId).getDisplayUiContext() : null;
1353 }
Louis Chang149d5c82019-12-30 09:47:39 +08001354
1355 void setWindowManager(WindowManagerService wm) {
1356 mWindowManager = wm;
1357 mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
1358 mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
1359 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
1360
1361 final Display[] displays = mDisplayManager.getDisplays();
1362 for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
1363 final Display display = displays[displayNdx];
1364 final DisplayContent displayContent = new DisplayContent(display, this);
Garfield Tanfbd233a2019-12-26 12:39:25 -08001365 addChild(displayContent, POSITION_BOTTOM);
Louis Chang149d5c82019-12-30 09:47:39 +08001366 if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
1367 mDefaultDisplay = displayContent;
1368 }
1369 }
1370 calculateDefaultMinimalSizeOfResizeableTasks();
1371
1372 final DisplayContent defaultDisplay = getDefaultDisplay();
1373
1374 defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
1375 positionChildAt(POSITION_TOP, defaultDisplay, false /* includingParents */);
1376 }
1377
1378 // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
1379 DisplayContent getDefaultDisplay() {
1380 return mDefaultDisplay;
1381 }
1382
1383 /**
1384 * Get an existing instance of {@link DisplayContent} that has the given uniqueId. Unique ID is
1385 * defined in {@link DisplayInfo#uniqueId}.
1386 *
1387 * @param uniqueId the unique ID of the display
1388 * @return the {@link DisplayContent} or {@code null} if nothing is found.
1389 */
1390 DisplayContent getDisplayContent(String uniqueId) {
1391 for (int i = getChildCount() - 1; i >= 0; --i) {
1392 final DisplayContent display = getChildAt(i);
1393 final boolean isValid = display.mDisplay.isValid();
1394 if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) {
1395 return display;
1396 }
1397 }
1398
1399 return null;
1400 }
1401
1402 // TODO: Look into consolidating with getDisplayContentOrCreate()
1403 DisplayContent getDisplayContent(int displayId) {
1404 for (int i = getChildCount() - 1; i >= 0; --i) {
1405 final DisplayContent displayContent = getChildAt(i);
1406 if (displayContent.mDisplayId == displayId) {
1407 return displayContent;
1408 }
1409 }
1410 return null;
1411 }
1412
1413 /**
1414 * Get an existing instance of {@link DisplayContent} or create new if there is a
1415 * corresponding record in display manager.
1416 */
1417 // TODO: Look into consolidating with getDisplayContent()
1418 @Nullable DisplayContent getDisplayContentOrCreate(int displayId) {
1419 DisplayContent displayContent = getDisplayContent(displayId);
1420 if (displayContent != null) {
1421 return displayContent;
1422 }
1423 if (mDisplayManager == null) {
1424 // The system isn't fully initialized yet.
1425 return null;
1426 }
1427 final Display display = mDisplayManager.getDisplay(displayId);
1428 if (display == null) {
1429 // The display is not registered in DisplayManager.
1430 return null;
1431 }
1432 // The display hasn't been added to ActivityManager yet, create a new record now.
1433 displayContent = new DisplayContent(display, this);
Garfield Tanfbd233a2019-12-26 12:39:25 -08001434 addChild(displayContent, POSITION_BOTTOM);
Louis Chang149d5c82019-12-30 09:47:39 +08001435 return displayContent;
1436 }
1437
1438 ActivityRecord getDefaultDisplayHomeActivity() {
1439 return getDefaultDisplayHomeActivityForUser(mCurrentUser);
1440 }
1441
1442 ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
1443 return getDisplayContent(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
1444 }
1445
1446 boolean startHomeOnAllDisplays(int userId, String reason) {
1447 boolean homeStarted = false;
1448 for (int i = getChildCount() - 1; i >= 0; i--) {
1449 final int displayId = getChildAt(i).mDisplayId;
1450 homeStarted |= startHomeOnDisplay(userId, reason, displayId);
1451 }
1452 return homeStarted;
1453 }
1454
1455 void startHomeOnEmptyDisplays(String reason) {
1456 for (int i = getChildCount() - 1; i >= 0; i--) {
1457 final DisplayContent display = getChildAt(i);
1458 if (display.topRunningActivity() == null) {
1459 startHomeOnDisplay(mCurrentUser, reason, display.mDisplayId);
1460 }
1461 }
1462 }
1463
1464 boolean startHomeOnDisplay(int userId, String reason, int displayId) {
1465 return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
1466 false /* fromHomeKey */);
1467 }
1468
1469 /**
1470 * This starts home activity on displays that can have system decorations based on displayId -
1471 * Default display always use primary home component.
1472 * For Secondary displays, the home activity must have category SECONDARY_HOME and then resolves
1473 * according to the priorities listed below.
1474 * - If default home is not set, always use the secondary home defined in the config.
1475 * - Use currently selected primary home activity.
1476 * - Use the activity in the same package as currently selected primary home activity.
1477 * If there are multiple activities matched, use first one.
1478 * - Use the secondary home defined in the config.
1479 */
1480 boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
1481 boolean fromHomeKey) {
1482 // Fallback to top focused display if the displayId is invalid.
1483 if (displayId == INVALID_DISPLAY) {
1484 final ActivityStack stack = getTopDisplayFocusedStack();
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001485 displayId = stack != null ? stack.getDisplayId() : DEFAULT_DISPLAY;
Louis Chang149d5c82019-12-30 09:47:39 +08001486 }
1487
1488 Intent homeIntent = null;
1489 ActivityInfo aInfo = null;
1490 if (displayId == DEFAULT_DISPLAY) {
1491 homeIntent = mService.getHomeIntent();
1492 aInfo = resolveHomeActivity(userId, homeIntent);
1493 } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {
1494 Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId);
1495 aInfo = info.first;
1496 homeIntent = info.second;
1497 }
1498 if (aInfo == null || homeIntent == null) {
1499 return false;
1500 }
1501
1502 if (!canStartHomeOnDisplay(aInfo, displayId, allowInstrumenting)) {
1503 return false;
1504 }
1505
1506 // Updates the home component of the intent.
1507 homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
1508 homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
1509 // Updates the extra information of the intent.
1510 if (fromHomeKey) {
1511 homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
1512 }
1513 // Update the reason for ANR debugging to verify if the user activity is the one that
1514 // actually launched.
1515 final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
1516 aInfo.applicationInfo.uid) + ":" + displayId;
1517 mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
1518 displayId);
1519 return true;
1520 }
1521
1522 /**
1523 * This resolves the home activity info.
1524 * @return the home activity info if any.
1525 */
1526 @VisibleForTesting
1527 ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
1528 final int flags = ActivityManagerService.STOCK_PM_FLAGS;
1529 final ComponentName comp = homeIntent.getComponent();
1530 ActivityInfo aInfo = null;
1531 try {
1532 if (comp != null) {
1533 // Factory test.
1534 aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
1535 } else {
1536 final String resolvedType =
1537 homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
1538 final ResolveInfo info = AppGlobals.getPackageManager()
1539 .resolveIntent(homeIntent, resolvedType, flags, userId);
1540 if (info != null) {
1541 aInfo = info.activityInfo;
1542 }
1543 }
1544 } catch (RemoteException e) {
1545 // ignore
1546 }
1547
1548 if (aInfo == null) {
1549 Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
1550 return null;
1551 }
1552
1553 aInfo = new ActivityInfo(aInfo);
1554 aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
1555 return aInfo;
1556 }
1557
1558 @VisibleForTesting
1559 Pair<ActivityInfo, Intent> resolveSecondaryHomeActivity(int userId, int displayId) {
1560 if (displayId == DEFAULT_DISPLAY) {
1561 throw new IllegalArgumentException(
1562 "resolveSecondaryHomeActivity: Should not be DEFAULT_DISPLAY");
1563 }
1564 // Resolve activities in the same package as currently selected primary home activity.
1565 Intent homeIntent = mService.getHomeIntent();
1566 ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent);
1567 if (aInfo != null) {
1568 if (ResolverActivity.class.getName().equals(aInfo.name)) {
1569 // Always fallback to secondary home component if default home is not set.
1570 aInfo = null;
1571 } else {
1572 // Look for secondary home activities in the currently selected default home
1573 // package.
1574 homeIntent = mService.getSecondaryHomeIntent(aInfo.applicationInfo.packageName);
1575 final List<ResolveInfo> resolutions = resolveActivities(userId, homeIntent);
1576 final int size = resolutions.size();
1577 final String targetName = aInfo.name;
1578 aInfo = null;
1579 for (int i = 0; i < size; i++) {
1580 ResolveInfo resolveInfo = resolutions.get(i);
1581 // We need to traverse all resolutions to check if the currently selected
1582 // default home activity is present.
1583 if (resolveInfo.activityInfo.name.equals(targetName)) {
1584 aInfo = resolveInfo.activityInfo;
1585 break;
1586 }
1587 }
1588 if (aInfo == null && size > 0) {
1589 // First one is the best.
1590 aInfo = resolutions.get(0).activityInfo;
1591 }
1592 }
1593 }
1594
1595 if (aInfo != null) {
1596 if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) {
1597 aInfo = null;
1598 }
1599 }
1600
1601 // Fallback to secondary home component.
1602 if (aInfo == null) {
1603 homeIntent = mService.getSecondaryHomeIntent(null);
1604 aInfo = resolveHomeActivity(userId, homeIntent);
1605 }
1606 return Pair.create(aInfo, homeIntent);
1607 }
1608
1609 /**
1610 * Retrieve all activities that match the given intent.
1611 * The list should already ordered from best to worst matched.
1612 * {@link android.content.pm.PackageManager#queryIntentActivities}
1613 */
1614 @VisibleForTesting
1615 List<ResolveInfo> resolveActivities(int userId, Intent homeIntent) {
1616 List<ResolveInfo> resolutions;
1617 try {
1618 final String resolvedType =
1619 homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
1620 resolutions = AppGlobals.getPackageManager().queryIntentActivities(homeIntent,
1621 resolvedType, ActivityManagerService.STOCK_PM_FLAGS, userId).getList();
1622
1623 } catch (RemoteException e) {
1624 resolutions = new ArrayList<>();
1625 }
1626 return resolutions;
1627 }
1628
1629 boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) {
1630 if (!mService.isBooting() && !mService.isBooted()) {
1631 // Not ready yet!
1632 return false;
1633 }
1634
1635 if (displayId == INVALID_DISPLAY) {
1636 displayId = DEFAULT_DISPLAY;
1637 }
1638
1639 final ActivityRecord r = getDisplayContent(displayId).getHomeActivity();
1640 final String myReason = reason + " resumeHomeActivity";
1641
1642 // Only resume home activity if isn't finishing.
1643 if (r != null && !r.finishing) {
1644 r.moveFocusableActivityToTop(myReason);
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08001645 return resumeFocusedStacksTopActivities(r.getRootTask(), prev, null);
Louis Chang149d5c82019-12-30 09:47:39 +08001646 }
1647 return startHomeOnDisplay(mCurrentUser, myReason, displayId);
1648 }
1649
1650 /**
1651 * Check if the display is valid for secondary home activity.
1652 * @param displayId The id of the target display.
1653 * @return {@code true} if allow to launch, {@code false} otherwise.
1654 */
1655 boolean shouldPlaceSecondaryHomeOnDisplay(int displayId) {
1656 if (displayId == DEFAULT_DISPLAY) {
1657 throw new IllegalArgumentException(
1658 "shouldPlaceSecondaryHomeOnDisplay: Should not be DEFAULT_DISPLAY");
1659 } else if (displayId == INVALID_DISPLAY) {
1660 return false;
1661 }
1662
1663 if (!mService.mSupportsMultiDisplay) {
1664 // Can't launch home on secondary display if device does not support multi-display.
1665 return false;
1666 }
1667
1668 final boolean deviceProvisioned = Settings.Global.getInt(
1669 mService.mContext.getContentResolver(),
1670 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
1671 if (!deviceProvisioned) {
1672 // Can't launch home on secondary display before device is provisioned.
1673 return false;
1674 }
1675
1676 if (!StorageManager.isUserKeyUnlocked(mCurrentUser)) {
1677 // Can't launch home on secondary displays if device is still locked.
1678 return false;
1679 }
1680
1681 final DisplayContent display = getDisplayContent(displayId);
1682 if (display == null || display.isRemoved() || !display.supportsSystemDecorations()) {
1683 // Can't launch home on display that doesn't support system decorations.
1684 return false;
1685 }
1686
1687 return true;
1688 }
1689
1690 /**
1691 * Check if home activity start should be allowed on a display.
1692 * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched.
1693 * @param displayId The id of the target display.
1694 * @param allowInstrumenting Whether launching home should be allowed if being instrumented.
1695 * @return {@code true} if allow to launch, {@code false} otherwise.
1696 */
1697 boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId,
1698 boolean allowInstrumenting) {
1699 if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
1700 && mService.mTopAction == null) {
1701 // We are running in factory test mode, but unable to find the factory test app, so
1702 // just sit around displaying the error message and don't try to start anything.
1703 return false;
1704 }
1705
1706 final WindowProcessController app =
1707 mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
1708 if (!allowInstrumenting && app != null && app.isInstrumenting()) {
1709 // Don't do this if the home app is currently being instrumented.
1710 return false;
1711 }
1712
1713 if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
1714 && displayId == mService.mVr2dDisplayId)) {
1715 // No restrictions to default display or vr 2d display.
1716 return true;
1717 }
1718
1719 if (!shouldPlaceSecondaryHomeOnDisplay(displayId)) {
1720 return false;
1721 }
1722
1723 final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
1724 && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE;
1725 if (!supportMultipleInstance) {
1726 // Can't launch home on secondary displays if it requested to be single instance.
1727 return false;
1728 }
1729
1730 return true;
1731 }
1732
1733 /**
1734 * Ensure all activities visibility, update orientation and configuration.
1735 *
1736 * @param starting The currently starting activity or {@code null} if there is none.
1737 * @param displayId The id of the display where operation is executed.
1738 * @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to
1739 * {@code true} if config changed.
1740 * @param deferResume Whether to defer resume while updating config.
1741 * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched
1742 * because of configuration update.
1743 */
1744 boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,
1745 boolean markFrozenIfConfigChanged, boolean deferResume) {
1746 // First ensure visibility without updating the config just yet. We need this to know what
1747 // activities are affecting configuration now.
1748 // Passing null here for 'starting' param value, so that visibility of actual starting
1749 // activity will be properly updated.
1750 ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
1751 false /* preserveWindows */, false /* notifyClients */);
1752
1753 if (displayId == INVALID_DISPLAY) {
1754 // The caller didn't provide a valid display id, skip updating config.
1755 return true;
1756 }
1757
1758 // Force-update the orientation from the WindowManager, since we need the true configuration
1759 // to send to the client now.
1760 final DisplayContent displayContent = getDisplayContent(displayId);
1761 Configuration config = null;
1762 if (displayContent != null) {
1763 config = displayContent.updateOrientation(
1764 getDisplayOverrideConfiguration(displayId),
1765 starting != null && starting.mayFreezeScreenLocked()
1766 ? starting.appToken : null,
1767 true /* forceUpdate */);
1768 }
1769 // Visibilities may change so let the starting activity have a chance to report. Can't do it
1770 // when visibility is changed in each AppWindowToken because it may trigger wrong
1771 // configuration push because the visibility of some activities may not be updated yet.
1772 if (starting != null) {
1773 starting.reportDescendantOrientationChangeIfNeeded();
1774 }
1775 if (starting != null && markFrozenIfConfigChanged && config != null) {
1776 starting.frozenBeforeDestroy = true;
1777 }
1778
1779 if (displayContent != null) {
1780 // Update the configuration of the activities on the display.
1781 return displayContent.updateDisplayOverrideConfigurationLocked(config, starting,
1782 deferResume, null /* result */);
1783 } else {
1784 return true;
1785 }
1786 }
1787
1788 /**
1789 * @return a list of activities which are the top ones in each visible stack. The first
1790 * entry will be the focused activity.
1791 */
1792 List<IBinder> getTopVisibleActivities() {
1793 final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
1794 final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
1795 // Traverse all displays.
1796 for (int i = getChildCount() - 1; i >= 0; i--) {
1797 final DisplayContent display = getChildAt(i);
1798 // Traverse all stacks on a display.
1799 for (int j = display.getStackCount() - 1; j >= 0; --j) {
1800 final ActivityStack stack = display.getStackAt(j);
1801 // Get top activity from a visible stack and add it to the list.
1802 if (stack.shouldBeVisible(null /* starting */)) {
1803 final ActivityRecord top = stack.getTopNonFinishingActivity();
1804 if (top != null) {
1805 if (stack == topFocusedStack) {
1806 topActivityTokens.add(0, top.appToken);
1807 } else {
1808 topActivityTokens.add(top.appToken);
1809 }
1810 }
1811 }
1812 }
1813 }
1814 return topActivityTokens;
1815 }
1816
1817 ActivityStack getTopDisplayFocusedStack() {
1818 for (int i = getChildCount() - 1; i >= 0; --i) {
1819 final ActivityStack focusedStack = getChildAt(i).getFocusedStack();
1820 if (focusedStack != null) {
1821 return focusedStack;
1822 }
1823 }
1824 return null;
1825 }
1826
1827 ActivityRecord getTopResumedActivity() {
1828 final ActivityStack focusedStack = getTopDisplayFocusedStack();
1829 if (focusedStack == null) {
1830 return null;
1831 }
1832 final ActivityRecord resumedActivity = focusedStack.getResumedActivity();
1833 if (resumedActivity != null && resumedActivity.app != null) {
1834 return resumedActivity;
1835 }
1836 // The top focused stack might not have a resumed activity yet - look on all displays in
1837 // focus order.
1838 for (int i = getChildCount() - 1; i >= 0; --i) {
1839 final DisplayContent display = getChildAt(i);
1840 final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
1841 if (resumedActivityOnDisplay != null) {
1842 return resumedActivityOnDisplay;
1843 }
1844 }
1845 return null;
1846 }
1847
Louis Chang149d5c82019-12-30 09:47:39 +08001848 boolean isTopDisplayFocusedStack(ActivityStack stack) {
1849 return stack != null && stack == getTopDisplayFocusedStack();
1850 }
1851
1852 void updatePreviousProcess(ActivityRecord r) {
1853 // Now that this process has stopped, we may want to consider it to be the previous app to
1854 // try to keep around in case the user wants to return to it.
1855
1856 // First, found out what is currently the foreground app, so that we don't blow away the
1857 // previous app if this activity is being hosted by the process that is actually still the
1858 // foreground.
1859 WindowProcessController fgApp = null;
1860 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
1861 final DisplayContent display = getChildAt(displayNdx);
1862 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1863 final ActivityStack stack = display.getStackAt(stackNdx);
1864 if (isTopDisplayFocusedStack(stack)) {
1865 final ActivityRecord resumedActivity = stack.getResumedActivity();
1866 if (resumedActivity != null) {
1867 fgApp = resumedActivity.app;
1868 } else if (stack.mPausingActivity != null) {
1869 fgApp = stack.mPausingActivity.app;
1870 }
1871 break;
1872 }
1873 }
1874 }
1875
1876 // Now set this one as the previous process, only if that really makes sense to.
1877 if (r.hasProcess() && fgApp != null && r.app != fgApp
1878 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
1879 && r.app != mService.mHomeProcess) {
1880 mService.mPreviousProcess = r.app;
1881 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
1882 }
1883 }
1884
1885 boolean attachApplication(WindowProcessController app) throws RemoteException {
1886 final String processName = app.mName;
1887 boolean didSomething = false;
1888 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
1889 final DisplayContent display = getChildAt(displayNdx);
1890 final ActivityStack stack = display.getFocusedStack();
1891 if (stack == null) {
1892 continue;
1893 }
1894
1895 mTmpRemoteException = null;
1896 mTmpBoolean = false; // Set to true if an activity was started.
1897 final PooledFunction c = PooledLambda.obtainFunction(
1898 RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
1899 PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivity());
1900 stack.forAllActivities(c);
1901 c.recycle();
1902 if (mTmpRemoteException != null) {
1903 throw mTmpRemoteException;
1904 }
1905 didSomething |= mTmpBoolean;
1906 }
1907 if (!didSomething) {
1908 ensureActivitiesVisible(null, 0, false /* preserve_windows */);
1909 }
1910 return didSomething;
1911 }
1912
1913 private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
1914 WindowProcessController app, ActivityRecord top) {
1915 if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
1916 || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
1917 return false;
1918 }
1919
1920 try {
1921 if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,
1922 true /*checkConfig*/)) {
1923 mTmpBoolean = true;
1924 }
1925 } catch (RemoteException e) {
1926 Slog.w(TAG, "Exception in new application when starting activity "
1927 + top.intent.getComponent().flattenToShortString(), e);
1928 mTmpRemoteException = e;
1929 return true;
1930 }
1931 return false;
1932 }
1933
1934 /**
1935 * Make sure that all activities that need to be visible in the system actually are and update
1936 * their configuration.
1937 */
1938 void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
1939 boolean preserveWindows) {
1940 ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
1941 }
1942
1943 /**
1944 * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
1945 */
1946 void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
1947 boolean preserveWindows, boolean notifyClients) {
1948 if (mInEnsureActivitiesVisible) {
1949 // Don't do recursive work.
1950 return;
1951 }
1952 mInEnsureActivitiesVisible = true;
1953
1954 try {
1955 mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
1956 // First the front stacks. In case any are not fullscreen and are in front of home.
1957 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
1958 final DisplayContent display = getChildAt(displayNdx);
1959 display.ensureActivitiesVisible(starting, configChanges, preserveWindows,
1960 notifyClients);
1961 }
1962 } finally {
1963 mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate();
1964 mInEnsureActivitiesVisible = false;
1965 }
1966 }
1967
1968 boolean switchUser(int userId, UserState uss) {
Darryl L Johnson1e3885c2020-02-27 17:38:13 -08001969 final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
1970 final int focusStackId = topFocusedStack != null
1971 ? topFocusedStack.getRootTaskId() : INVALID_TASK_ID;
Louis Chang149d5c82019-12-30 09:47:39 +08001972 // We dismiss the docked stack whenever we switch users.
Wale Ogunwale734b8962020-01-21 12:17:42 -08001973 final ActivityStack dockedStack = getDefaultDisplay().getRootSplitScreenPrimaryTask();
Louis Chang149d5c82019-12-30 09:47:39 +08001974 if (dockedStack != null) {
Evan Rosky73a7fe92019-11-18 18:28:01 -08001975 getDefaultDisplay().onSplitScreenModeDismissed();
Louis Chang149d5c82019-12-30 09:47:39 +08001976 }
1977 // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
1978 // also cause all tasks to be moved to the fullscreen stack at a position that is
1979 // appropriate.
1980 removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
1981
1982 mUserStackInFront.put(mCurrentUser, focusStackId);
Louis Chang149d5c82019-12-30 09:47:39 +08001983 mCurrentUser = userId;
1984
1985 mStackSupervisor.mStartingUsers.add(uss);
1986 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
1987 final DisplayContent display = getChildAt(displayNdx);
1988 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1989 final ActivityStack stack = display.getStackAt(stackNdx);
1990 stack.switchUser(userId);
Louis Chang149d5c82019-12-30 09:47:39 +08001991 }
1992 }
1993
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001994 final int restoreStackId = mUserStackInFront.get(userId);
Louis Chang149d5c82019-12-30 09:47:39 +08001995 ActivityStack stack = getStack(restoreStackId);
1996 if (stack == null) {
Darryl L Johnson3388bd22019-12-19 17:38:41 -08001997 stack = getDefaultDisplay().getOrCreateRootHomeTask();
Louis Chang149d5c82019-12-30 09:47:39 +08001998 }
1999 final boolean homeInFront = stack.isActivityTypeHome();
2000 if (stack.isOnHomeDisplay()) {
2001 stack.moveToFront("switchUserOnHomeDisplay");
2002 } else {
2003 // Stack was moved to another display while user was swapped out.
2004 resumeHomeActivity(null, "switchUserOnOtherDisplay", DEFAULT_DISPLAY);
2005 }
2006 return homeInFront;
2007 }
2008
2009 void removeUser(int userId) {
2010 mUserStackInFront.delete(userId);
2011 }
2012
2013 /**
2014 * Update the last used stack id for non-current user (current user's last
2015 * used stack is the focused stack)
2016 */
2017 void updateUserStack(int userId, ActivityStack stack) {
2018 if (userId != mCurrentUser) {
Darryl L Johnson3388bd22019-12-19 17:38:41 -08002019 if (stack == null) {
2020 stack = getDefaultDisplay().getOrCreateRootHomeTask();
2021 }
2022
2023 mUserStackInFront.put(userId, stack.getRootTaskId());
Louis Chang149d5c82019-12-30 09:47:39 +08002024 }
2025 }
2026
2027 /**
2028 * Move stack with all its existing content to specified display.
2029 * @param stackId Id of stack to move.
2030 * @param displayId Id of display to move stack to.
2031 * @param onTop Indicates whether container should be place on top or on bottom.
2032 */
2033 void moveStackToDisplay(int stackId, int displayId, boolean onTop) {
2034 final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
2035 if (displayContent == null) {
2036 throw new IllegalArgumentException("moveStackToDisplay: Unknown displayId="
2037 + displayId);
2038 }
2039 final ActivityStack stack = getStack(stackId);
2040 if (stack == null) {
2041 throw new IllegalArgumentException("moveStackToDisplay: Unknown stackId="
2042 + stackId);
2043 }
2044
2045 final DisplayContent currentDisplay = stack.getDisplay();
2046 if (currentDisplay == null) {
2047 throw new IllegalStateException("moveStackToDisplay: Stack with stack=" + stack
2048 + " is not attached to any display.");
2049 }
2050
2051 if (currentDisplay.mDisplayId == displayId) {
2052 throw new IllegalArgumentException("Trying to move stack=" + stack
2053 + " to its current displayId=" + displayId);
2054 }
2055
2056 if (displayContent.isSingleTaskInstance() && displayContent.getStackCount() > 0) {
2057 // We don't allow moving stacks to single instance display that already has a child.
2058 Slog.e(TAG, "Can not move stack=" + stack
2059 + " to single task instance display=" + displayContent);
2060 return;
2061 }
2062
2063 stack.reparent(displayContent.mDisplayContent, onTop);
2064 // TODO(multi-display): resize stacks properly if moved from split-screen.
2065 }
2066
2067 boolean moveTopStackActivityToPinnedStack(int stackId) {
2068 final ActivityStack stack = getStack(stackId);
2069 if (stack == null) {
2070 throw new IllegalArgumentException(
2071 "moveTopStackActivityToPinnedStack: Unknown stackId=" + stackId);
2072 }
2073
2074 final ActivityRecord r = stack.topRunningActivity();
2075 if (r == null) {
2076 Slog.w(TAG, "moveTopStackActivityToPinnedStack: No top running activity"
2077 + " in stack=" + stack);
2078 return false;
2079 }
2080
2081 if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) {
2082 Slog.w(TAG, "moveTopStackActivityToPinnedStack: Picture-In-Picture not supported for "
2083 + " r=" + r);
2084 return false;
2085 }
2086
2087 moveActivityToPinnedStack(r, null /* sourceBounds */, 0f /* aspectRatio */,
2088 "moveTopActivityToPinnedStack");
2089 return true;
2090 }
2091
2092 void moveActivityToPinnedStack(ActivityRecord r, Rect sourceHintBounds, float aspectRatio,
2093 String reason) {
2094 mService.deferWindowLayout();
2095
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002096 final DisplayContent display = r.getRootTask().getDisplay();
Louis Chang149d5c82019-12-30 09:47:39 +08002097
2098 try {
2099 final Task task = r.getTask();
2100
Wale Ogunwale734b8962020-01-21 12:17:42 -08002101 final ActivityStack pinnedStack = display.getRootPinnedTask();
Louis Chang149d5c82019-12-30 09:47:39 +08002102 // This will change the pinned stack's windowing mode to its original mode, ensuring
2103 // we only have one stack that is in pinned mode.
2104 if (pinnedStack != null) {
2105 pinnedStack.dismissPip();
2106 }
2107
2108 final boolean singleActivity = task.getChildCount() == 1;
2109
2110 final ActivityStack stack;
2111 if (singleActivity) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002112 stack = r.getRootTask();
Louis Chang149d5c82019-12-30 09:47:39 +08002113 } else {
2114 // In the case of multiple activities, we will create a new stack for it and then
2115 // move the PIP activity into the stack.
2116 // We will then perform a windowing mode change for both scenarios.
2117 stack = display.createStack(
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002118 r.getRootTask().getRequestedOverrideWindowingMode(),
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002119 r.getActivityType(), ON_TOP, r.info, r.intent);
Louis Chang149d5c82019-12-30 09:47:39 +08002120 // There are multiple activities in the task and moving the top activity should
2121 // reveal/leave the other activities in their original task.
Wale Ogunwale0d465192020-01-23 19:14:44 -08002122 r.reparent(stack, MAX_VALUE, "moveActivityToStack");
Louis Chang149d5c82019-12-30 09:47:39 +08002123 }
2124
2125 stack.setWindowingMode(WINDOWING_MODE_PINNED);
2126
2127 // Reset the state that indicates it can enter PiP while pausing after we've moved it
2128 // to the pinned stack
2129 r.supportsEnterPipOnTaskSwitch = false;
2130 } finally {
2131 mService.continueWindowLayout();
2132 }
2133
Louis Chang149d5c82019-12-30 09:47:39 +08002134 // TODO: revisit the following statement after the animation is moved from WM to SysUI.
2135 // Update the visibility of all activities after the they have been reparented to the new
2136 // stack. This MUST run after the animation above is scheduled to ensure that the windows
2137 // drawn signal is scheduled after the bounds animation start call on the bounds animator
2138 // thread.
2139 ensureActivitiesVisible(null, 0, false /* preserveWindows */);
2140 resumeFocusedStacksTopActivities();
2141
2142 mService.getTaskChangeNotificationController().notifyActivityPinned(r);
2143 }
2144
2145 void executeAppTransitionForAllDisplay() {
2146 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2147 final DisplayContent display = getChildAt(displayNdx);
2148 display.mDisplayContent.executeAppTransition();
2149 }
2150 }
2151
Louis Chang149d5c82019-12-30 09:47:39 +08002152 ActivityRecord findTask(ActivityRecord r, int preferredDisplayId) {
2153 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
2154 mTmpFindTaskResult.clear();
2155
2156 // Looking up task on preferred display first
2157 final DisplayContent preferredDisplay = getDisplayContent(preferredDisplayId);
2158 if (preferredDisplay != null) {
2159 preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult);
2160 if (mTmpFindTaskResult.mIdealMatch) {
2161 return mTmpFindTaskResult.mRecord;
2162 }
2163 }
2164
2165 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2166 final DisplayContent display = getChildAt(displayNdx);
2167 if (display.mDisplayId == preferredDisplayId) {
2168 continue;
2169 }
2170
2171 display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult);
2172 if (mTmpFindTaskResult.mIdealMatch) {
2173 return mTmpFindTaskResult.mRecord;
2174 }
2175 }
2176
2177 if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found");
2178 return mTmpFindTaskResult.mRecord;
2179 }
2180
2181 /**
2182 * Finish the topmost activities in all stacks that belong to the crashed app.
2183 * @param app The app that crashed.
2184 * @param reason Reason to perform this action.
2185 * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished.
2186 */
2187 int finishTopCrashedActivities(WindowProcessController app, String reason) {
2188 Task finishedTask = null;
2189 ActivityStack focusedStack = getTopDisplayFocusedStack();
2190 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2191 final DisplayContent display = getChildAt(displayNdx);
2192 // It is possible that request to finish activity might also remove its task and stack,
2193 // so we need to be careful with indexes in the loop and check child count every time.
2194 for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
2195 final ActivityStack stack = display.getStackAt(stackNdx);
2196 final Task t = stack.finishTopCrashedActivityLocked(app, reason);
2197 if (stack == focusedStack || finishedTask == null) {
2198 finishedTask = t;
2199 }
2200 }
2201 }
2202 return finishedTask != null ? finishedTask.mTaskId : INVALID_TASK_ID;
2203 }
2204
2205 boolean resumeFocusedStacksTopActivities() {
2206 return resumeFocusedStacksTopActivities(null, null, null);
2207 }
2208
2209 boolean resumeFocusedStacksTopActivities(
2210 ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
2211
2212 if (!mStackSupervisor.readyToResume()) {
2213 return false;
2214 }
2215
2216 boolean result = false;
2217 if (targetStack != null && (targetStack.isTopStackOnDisplay()
2218 || getTopDisplayFocusedStack() == targetStack)) {
2219 result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
2220 }
2221
2222 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2223 boolean resumedOnDisplay = false;
2224 final DisplayContent display = getChildAt(displayNdx);
2225 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
2226 final ActivityStack stack = display.getStackAt(stackNdx);
2227 final ActivityRecord topRunningActivity = stack.topRunningActivity();
2228 if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
2229 continue;
2230 }
2231 if (stack == targetStack) {
2232 // Simply update the result for targetStack because the targetStack had
2233 // already resumed in above. We don't want to resume it again, especially in
2234 // some cases, it would cause a second launch failure if app process was dead.
2235 resumedOnDisplay |= result;
2236 continue;
2237 }
2238 if (display.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
2239 // Kick off any lingering app transitions form the MoveTaskToFront operation,
2240 // but only consider the top task and stack on that display.
2241 stack.executeAppTransition(targetOptions);
2242 } else {
2243 resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
2244 }
2245 }
2246 if (!resumedOnDisplay) {
2247 // In cases when there are no valid activities (e.g. device just booted or launcher
2248 // crashed) it's possible that nothing was resumed on a display. Requesting resume
2249 // of top activity in focused stack explicitly will make sure that at least home
2250 // activity is started and resumed, and no recursion occurs.
2251 final ActivityStack focusedStack = display.getFocusedStack();
2252 if (focusedStack != null) {
2253 result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
Riddle Hsu7baffbb2020-03-05 22:48:24 +08002254 } else if (targetStack == null) {
2255 result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
Louis Chang149d5c82019-12-30 09:47:39 +08002256 display.mDisplayId);
2257 }
2258 }
2259 }
2260
2261 return result;
2262 }
2263
2264 void applySleepTokens(boolean applyToStacks) {
2265 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2266 // Set the sleeping state of the display.
2267 final DisplayContent display = getChildAt(displayNdx);
2268 final boolean displayShouldSleep = display.shouldSleep();
2269 if (displayShouldSleep == display.isSleeping()) {
2270 continue;
2271 }
2272 display.setIsSleeping(displayShouldSleep);
2273
2274 if (!applyToStacks) {
2275 continue;
2276 }
2277
2278 // Set the sleeping state of the stacks on the display.
2279 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
2280 final ActivityStack stack = display.getStackAt(stackNdx);
2281 if (displayShouldSleep) {
2282 stack.goToSleepIfPossible(false /* shuttingDown */);
2283 } else {
2284 // When the display which can only contain one task turns on, start a special
2285 // transition. {@link AppTransitionController#handleAppTransitionReady} later
2286 // picks up the transition, and schedules
2287 // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is
2288 // triggered after contents are drawn on the display.
2289 if (display.isSingleTaskInstance()) {
2290 display.mDisplayContent.prepareAppTransition(
2291 TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
2292 }
2293 stack.awakeFromSleepingLocked();
2294 if (stack.isFocusedStackOnDisplay()
2295 && !mStackSupervisor.getKeyguardController()
2296 .isKeyguardOrAodShowing(display.mDisplayId)) {
2297 // If the keyguard is unlocked - resume immediately.
2298 // It is possible that the display will not be awake at the time we
2299 // process the keyguard going away, which can happen before the sleep token
2300 // is released. As a result, it is important we resume the activity here.
2301 resumeFocusedStacksTopActivities();
2302 }
2303 }
2304 }
Louis Chang149d5c82019-12-30 09:47:39 +08002305 }
2306 }
2307
2308 protected ActivityStack getStack(int stackId) {
2309 for (int i = getChildCount() - 1; i >= 0; --i) {
2310 final ActivityStack stack = getChildAt(i).getStack(stackId);
2311 if (stack != null) {
2312 return stack;
2313 }
2314 }
2315 return null;
2316 }
2317
2318 /** @see DisplayContent#getStack(int, int) */
2319 ActivityStack getStack(int windowingMode, int activityType) {
2320 for (int i = getChildCount() - 1; i >= 0; --i) {
2321 final ActivityStack stack = getChildAt(i).getStack(windowingMode, activityType);
2322 if (stack != null) {
2323 return stack;
2324 }
2325 }
2326 return null;
2327 }
2328
2329 private ActivityStack getStack(int windowingMode, int activityType,
2330 int displayId) {
2331 DisplayContent display = getDisplayContent(displayId);
2332 if (display == null) {
2333 return null;
2334 }
2335 return display.getStack(windowingMode, activityType);
2336 }
2337
2338 private ActivityManager.StackInfo getStackInfo(ActivityStack stack) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002339 final DisplayContent display = stack.getDisplayContent();
Louis Chang149d5c82019-12-30 09:47:39 +08002340 ActivityManager.StackInfo info = new ActivityManager.StackInfo();
2341 stack.getBounds(info.bounds);
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002342 info.displayId = display.mDisplayId;
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002343 info.stackId = stack.mTaskId;
Louis Chang149d5c82019-12-30 09:47:39 +08002344 info.stackToken = stack.mRemoteToken;
2345 info.userId = stack.mCurrentUser;
2346 info.visible = stack.shouldBeVisible(null);
2347 // A stack might be not attached to a display.
2348 info.position = display != null ? display.getIndexOf(stack) : 0;
2349 info.configuration.setTo(stack.getConfiguration());
2350
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002351 final int numTasks = stack.getDescendantTaskCount();
Louis Chang149d5c82019-12-30 09:47:39 +08002352 info.taskIds = new int[numTasks];
2353 info.taskNames = new String[numTasks];
2354 info.taskBounds = new Rect[numTasks];
2355 info.taskUserIds = new int[numTasks];
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002356 final int[] currentIndex = {0};
Louis Chang149d5c82019-12-30 09:47:39 +08002357
2358 final PooledConsumer c = PooledLambda.obtainConsumer(
2359 RootWindowContainer::processTaskForStackInfo, PooledLambda.__(Task.class), info,
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002360 currentIndex);
Wale Ogunwale0d465192020-01-23 19:14:44 -08002361 stack.forAllLeafTasks(c, false /* traverseTopToBottom */);
Louis Chang149d5c82019-12-30 09:47:39 +08002362 c.recycle();
2363
2364 final ActivityRecord top = stack.topRunningActivity();
2365 info.topActivity = top != null ? top.intent.getComponent() : null;
2366 return info;
2367 }
2368
2369 private static void processTaskForStackInfo(
2370 Task task, ActivityManager.StackInfo info, int[] currentIndex) {
2371 int i = currentIndex[0];
2372 info.taskIds[i] = task.mTaskId;
2373 info.taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
2374 : task.realActivity != null ? task.realActivity.flattenToString()
2375 : task.getTopNonFinishingActivity() != null
2376 ? task.getTopNonFinishingActivity().packageName : "unknown";
2377 info.taskBounds[i] = task.mAtmService.getTaskBounds(task.mTaskId);
2378 info.taskUserIds[i] = task.mUserId;
2379 currentIndex[0] = ++i;
2380 }
2381
2382 ActivityManager.StackInfo getStackInfo(int stackId) {
2383 ActivityStack stack = getStack(stackId);
2384 if (stack != null) {
2385 return getStackInfo(stack);
2386 }
2387 return null;
2388 }
2389
2390 ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) {
2391 final ActivityStack stack = getStack(windowingMode, activityType);
2392 return (stack != null) ? getStackInfo(stack) : null;
2393 }
2394
2395 ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType, int displayId) {
2396 final ActivityStack stack = getStack(windowingMode, activityType, displayId);
2397 return (stack != null) ? getStackInfo(stack) : null;
2398 }
2399
2400 /** If displayId == INVALID_DISPLAY, this will get stack infos on all displays */
2401 ArrayList<ActivityManager.StackInfo> getAllStackInfos(int displayId) {
2402 ArrayList<ActivityManager.StackInfo> list = new ArrayList<>();
2403 if (displayId == INVALID_DISPLAY) {
2404 for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
2405 final DisplayContent display = getChildAt(displayNdx);
2406 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
2407 final ActivityStack stack = display.getStackAt(stackNdx);
2408 list.add(getStackInfo(stack));
2409 }
2410 }
2411 return list;
2412 }
2413 final DisplayContent display = getDisplayContent(displayId);
2414 if (display == null) {
2415 return list;
2416 }
2417 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
2418 final ActivityStack stack = display.getStackAt(stackNdx);
2419 list.add(getStackInfo(stack));
2420 }
2421 return list;
2422 }
2423
2424 void deferUpdateBounds(int activityType) {
2425 final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
2426 if (stack != null) {
2427 stack.deferUpdateBounds();
2428 }
2429 }
2430
2431 void continueUpdateBounds(int activityType) {
2432 final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
2433 if (stack != null) {
2434 stack.continueUpdateBounds();
2435 }
2436 }
2437
2438 @Override
2439 public void onDisplayAdded(int displayId) {
2440 if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
2441 synchronized (mService.mGlobalLock) {
2442 final DisplayContent display = getDisplayContentOrCreate(displayId);
2443 if (display == null) {
2444 return;
2445 }
2446 // Do not start home before booting, or it may accidentally finish booting before it
2447 // starts. Instead, we expect home activities to be launched when the system is ready
2448 // (ActivityManagerService#systemReady).
2449 if (mService.isBooted() || mService.isBooting()) {
2450 startSystemDecorations(display.mDisplayContent);
2451 }
2452 }
2453 }
2454
2455 private void startSystemDecorations(final DisplayContent displayContent) {
2456 startHomeOnDisplay(mCurrentUser, "displayAdded", displayContent.getDisplayId());
2457 displayContent.getDisplayPolicy().notifyDisplayReady();
2458 }
2459
2460 @Override
2461 public void onDisplayRemoved(int displayId) {
2462 if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
2463 if (displayId == DEFAULT_DISPLAY) {
2464 throw new IllegalArgumentException("Can't remove the primary display.");
2465 }
2466
2467 synchronized (mService.mGlobalLock) {
2468 final DisplayContent displayContent = getDisplayContent(displayId);
2469 if (displayContent == null) {
2470 return;
2471 }
2472
2473 displayContent.remove();
2474 }
2475 }
2476
2477 @Override
2478 public void onDisplayChanged(int displayId) {
2479 if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
2480 synchronized (mService.mGlobalLock) {
2481 final DisplayContent displayContent = getDisplayContent(displayId);
2482 if (displayContent != null) {
2483 displayContent.onDisplayChanged();
2484 }
2485 }
2486 }
2487
2488 /** Update lists of UIDs that are present on displays and have access to them. */
2489 void updateUIDsPresentOnDisplay() {
2490 mDisplayAccessUIDs.clear();
2491 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2492 final DisplayContent displayContent = getChildAt(displayNdx);
2493 // Only bother calculating the whitelist for private displays
2494 if (displayContent.isPrivate()) {
2495 mDisplayAccessUIDs.append(
2496 displayContent.mDisplayId, displayContent.getPresentUIDs());
2497 }
2498 }
2499 // Store updated lists in DisplayManager. Callers from outside of AM should get them there.
2500 mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs);
2501 }
2502
2503 ActivityStack findStackBehind(ActivityStack stack) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002504 final DisplayContent display = stack.getDisplayContent();
Louis Chang149d5c82019-12-30 09:47:39 +08002505 if (display != null) {
2506 for (int i = display.getStackCount() - 1; i >= 0; i--) {
2507 if (display.getStackAt(i) == stack && i > 0) {
2508 return display.getStackAt(i - 1);
2509 }
2510 }
2511 }
2512 throw new IllegalStateException("Failed to find a stack behind stack=" + stack
2513 + " in=" + display);
2514 }
2515
2516 @Override
2517 void positionChildAt(int position, DisplayContent child, boolean includingParents) {
2518 super.positionChildAt(position, child, includingParents);
2519 mStackSupervisor.updateTopResumedActivityIfNeeded();
2520 }
2521
2522 Configuration getDisplayOverrideConfiguration(int displayId) {
2523 final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
2524 if (displayContent == null) {
2525 throw new IllegalArgumentException("No display found with id: " + displayId);
2526 }
2527
2528 return displayContent.getRequestedOverrideConfiguration();
2529 }
2530
2531 void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
2532 final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
2533 if (displayContent == null) {
2534 throw new IllegalArgumentException("No display found with id: " + displayId);
2535 }
2536
2537 displayContent.onRequestedOverrideConfigurationChanged(overrideConfiguration);
2538 }
2539
2540 void prepareForShutdown() {
2541 for (int i = 0; i < getChildCount(); i++) {
2542 createSleepToken("shutdown", getChildAt(i).mDisplayId);
2543 }
2544 }
2545
2546 ActivityTaskManagerInternal.SleepToken createSleepToken(String tag, int displayId) {
2547 final DisplayContent display = getDisplayContent(displayId);
2548 if (display == null) {
2549 throw new IllegalArgumentException("Invalid display: " + displayId);
2550 }
2551
2552 final SleepTokenImpl token = new SleepTokenImpl(tag, displayId);
2553 mSleepTokens.add(token);
2554 display.mAllSleepTokens.add(token);
2555 return token;
2556 }
2557
2558 private void removeSleepToken(SleepTokenImpl token) {
2559 mSleepTokens.remove(token);
2560
2561 final DisplayContent display = getDisplayContent(token.mDisplayId);
2562 if (display != null) {
2563 display.mAllSleepTokens.remove(token);
2564 if (display.mAllSleepTokens.isEmpty()) {
2565 mService.updateSleepIfNeededLocked();
2566 }
2567 }
2568 }
2569
2570 void addStartingWindowsForVisibleActivities() {
2571 forAllActivities((r) -> {
2572 if (r.mVisibleRequested) {
2573 r.showStartingWindow(null /* prev */, false /* newTask */, true /*taskSwitch*/);
2574 }
2575 });
2576 }
2577
2578 void invalidateTaskLayers() {
2579 mTaskLayersChanged = true;
2580 }
2581
2582 void rankTaskLayersIfNeeded() {
2583 if (!mTaskLayersChanged) {
2584 return;
2585 }
2586 mTaskLayersChanged = false;
2587 mTmpTaskLayerRank = 0;
2588 final PooledConsumer c = PooledLambda.obtainConsumer(
2589 RootWindowContainer::rankTaskLayerForActivity, this,
2590 PooledLambda.__(ActivityRecord.class));
2591 forAllActivities(c);
2592 c.recycle();
2593 }
2594
2595 private void rankTaskLayerForActivity(ActivityRecord r) {
2596 if (r.canBeTopRunning() && r.mVisibleRequested) {
2597 r.getTask().mLayerRank = ++mTmpTaskLayerRank;
2598 } else {
2599 r.getTask().mLayerRank = -1;
2600 }
2601 }
2602
2603 void clearOtherAppTimeTrackers(AppTimeTracker except) {
2604 final PooledConsumer c = PooledLambda.obtainConsumer(
2605 RootWindowContainer::clearOtherAppTimeTrackers,
2606 PooledLambda.__(ActivityRecord.class), except);
2607 forAllActivities(c);
2608 c.recycle();
2609 }
2610
2611 private static void clearOtherAppTimeTrackers(ActivityRecord r, AppTimeTracker except) {
2612 if (r.appTimeTracker != except) {
2613 r.appTimeTracker = null;
2614 }
2615 }
2616
2617 void scheduleDestroyAllActivities(String reason) {
2618 mDestroyAllActivitiesReason = reason;
2619 mService.mH.post(mDestroyAllActivitiesRunnable);
2620 }
2621
2622 private void destroyActivity(ActivityRecord r) {
2623 if (r.finishing || !r.isDestroyable()) return;
2624
2625 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState()
2626 + " resumed=" + r.getStack().mResumedActivity + " pausing="
2627 + r.getStack().mPausingActivity + " for reason " + mDestroyAllActivitiesReason);
2628
2629 r.destroyImmediately(true /* removeFromTask */, mDestroyAllActivitiesReason);
2630 }
2631
2632 // Tries to put all activity stacks to sleep. Returns true if all stacks were
2633 // successfully put to sleep.
2634 boolean putStacksToSleep(boolean allowDelay, boolean shuttingDown) {
2635 boolean allSleep = true;
2636 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2637 final DisplayContent display = getChildAt(displayNdx);
2638 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
2639 // Stacks and activities could be removed while putting activities to sleep if
2640 // the app process was gone. This prevents us getting exception by accessing an
2641 // invalid stack index.
2642 if (stackNdx >= display.getStackCount()) {
2643 continue;
2644 }
2645
2646 final ActivityStack stack = display.getStackAt(stackNdx);
2647 if (allowDelay) {
2648 allSleep &= stack.goToSleepIfPossible(shuttingDown);
2649 } else {
2650 stack.goToSleep();
2651 }
2652 }
2653 }
2654 return allSleep;
2655 }
2656
2657 void handleAppCrash(WindowProcessController app) {
2658 final PooledConsumer c = PooledLambda.obtainConsumer(
2659 RootWindowContainer::handleAppCrash, PooledLambda.__(ActivityRecord.class), app);
2660 forAllActivities(c);
2661 c.recycle();
2662 }
2663
2664 private static void handleAppCrash(ActivityRecord r, WindowProcessController app) {
2665 if (r.app != app) return;
2666 Slog.w(TAG, " Force finishing activity "
2667 + r.intent.getComponent().flattenToShortString());
2668 r.app = null;
2669 r.getDisplay().mDisplayContent.prepareAppTransition(
2670 TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
2671 r.destroyIfPossible("handleAppCrashed");
2672 }
2673
2674 ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) {
2675 ComponentName cls = intent.getComponent();
2676 if (info.targetActivity != null) {
2677 cls = new ComponentName(info.packageName, info.targetActivity);
2678 }
2679 final int userId = UserHandle.getUserId(info.applicationInfo.uid);
2680
2681 final PooledPredicate p = PooledLambda.obtainPredicate(
2682 RootWindowContainer::matchesActivity, PooledLambda.__(ActivityRecord.class),
2683 userId, compareIntentFilters, intent, cls);
2684 final ActivityRecord r = getActivity(p);
2685 p.recycle();
2686 return r;
2687 }
2688
2689 private static boolean matchesActivity(ActivityRecord r, int userId,
2690 boolean compareIntentFilters, Intent intent, ComponentName cls) {
2691 if (!r.canBeTopRunning() || r.mUserId != userId) return false;
2692
2693 if (compareIntentFilters) {
2694 if (r.intent.filterEquals(intent)) {
2695 return true;
2696 }
2697 } else {
2698 if (r.intent.getComponent().equals(cls)) {
2699 return true;
2700 }
2701 }
2702 return false;
2703 }
2704
2705 boolean hasAwakeDisplay() {
2706 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
2707 final DisplayContent display = getChildAt(displayNdx);
2708 if (!display.shouldSleep()) {
2709 return true;
2710 }
2711 }
2712 return false;
2713 }
2714
2715 ActivityStack getLaunchStack(@Nullable ActivityRecord r,
2716 @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop) {
2717 return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */,
2718 -1 /* no realCallingPid */, -1 /* no realCallingUid */);
2719 }
2720
2721 /**
2722 * Returns the right stack to use for launching factoring in all the input parameters.
2723 *
2724 * @param r The activity we are trying to launch. Can be null.
2725 * @param options The activity options used to the launch. Can be null.
2726 * @param candidateTask The possible task the activity might be launched in. Can be null.
2727 * @param launchParams The resolved launch params to use.
2728 * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid}
2729 * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid}
2730 *
2731 * @return The stack to use for the launch or INVALID_STACK_ID.
2732 */
2733 ActivityStack getLaunchStack(@Nullable ActivityRecord r,
2734 @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop,
2735 @Nullable LaunchParamsController.LaunchParams launchParams, int realCallingPid,
2736 int realCallingUid) {
2737 int taskId = INVALID_TASK_ID;
2738 int displayId = INVALID_DISPLAY;
Louis Chang149d5c82019-12-30 09:47:39 +08002739
2740 // We give preference to the launch preference in activity options.
2741 if (options != null) {
2742 taskId = options.getLaunchTaskId();
2743 displayId = options.getLaunchDisplayId();
2744 }
2745
2746 // First preference for stack goes to the task Id set in the activity options. Use the stack
2747 // associated with that if possible.
2748 if (taskId != INVALID_TASK_ID) {
2749 // Temporarily set the task id to invalid in case in re-entry.
2750 options.setLaunchTaskId(INVALID_TASK_ID);
2751 final Task task = anyTaskForId(taskId,
2752 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop);
2753 options.setLaunchTaskId(taskId);
2754 if (task != null) {
2755 return task.getStack();
2756 }
2757 }
2758
2759 final int activityType = resolveActivityType(r, options, candidateTask);
Louis Chang38430df2020-01-02 17:14:59 +08002760 ActivityStack stack = null;
Louis Chang149d5c82019-12-30 09:47:39 +08002761
2762 // Next preference for stack goes to the display Id set the candidate display.
2763 if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) {
2764 displayId = launchParams.mPreferredDisplayId;
2765 }
2766 final boolean canLaunchOnDisplayFromStartRequest =
2767 realCallingPid != 0 && realCallingUid > 0 && r != null
2768 && mStackSupervisor.canPlaceEntityOnDisplay(displayId, realCallingPid,
2769 realCallingUid, r.info);
2770 // Checking if the activity's launch caller, or the realCallerId of the activity from
2771 // start request (i.e. entity that invokes PendingIntent) is allowed to launch on the
2772 // display.
2773 if (displayId != INVALID_DISPLAY && (canLaunchOnDisplay(r, displayId)
2774 || canLaunchOnDisplayFromStartRequest)) {
2775 if (r != null) {
2776 stack = getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
2777 launchParams);
2778 if (stack != null) {
2779 return stack;
2780 }
2781 }
2782 final DisplayContent display = getDisplayContentOrCreate(displayId);
2783 if (display != null) {
2784 stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
2785 if (stack != null) {
2786 return stack;
2787 }
2788 }
2789 }
2790
2791 // Give preference to the stack and display of the input task and activity if they match the
2792 // mode we want to launch into.
Louis Chang149d5c82019-12-30 09:47:39 +08002793 DisplayContent display = null;
2794 if (candidateTask != null) {
2795 stack = candidateTask.getStack();
2796 }
2797 if (stack == null && r != null) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002798 stack = r.getRootTask();
Louis Chang149d5c82019-12-30 09:47:39 +08002799 }
2800 if (stack != null) {
2801 display = stack.getDisplay();
2802 if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) {
2803 int windowingMode = launchParams != null ? launchParams.mWindowingMode
2804 : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
2805 if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
2806 windowingMode = display.resolveWindowingMode(r, options, candidateTask,
2807 activityType);
2808 }
2809 if (stack.isCompatible(windowingMode, activityType)) {
2810 return stack;
2811 }
2812 if (windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
Wale Ogunwale734b8962020-01-21 12:17:42 -08002813 && display.getRootSplitScreenPrimaryTask() == stack
Louis Chang149d5c82019-12-30 09:47:39 +08002814 && candidateTask == stack.getTopMostTask()) {
2815 // This is a special case when we try to launch an activity that is currently on
2816 // top of split-screen primary stack, but is targeting split-screen secondary.
2817 // In this case we don't want to move it to another stack.
2818 // TODO(b/78788972): Remove after differentiating between preferred and required
2819 // launch options.
2820 return stack;
2821 }
2822 }
2823 }
2824
2825 if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) {
2826 display = getDefaultDisplay();
2827 }
2828
2829 return display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
2830 }
2831
2832 /** @return true if activity record is null or can be launched on provided display. */
2833 private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) {
2834 if (r == null) {
2835 return true;
2836 }
2837 return r.canBeLaunchedOnDisplay(displayId);
2838 }
2839
2840 /**
2841 * Get a topmost stack on the display, that is a valid launch stack for specified activity.
2842 * If there is no such stack, new dynamic stack can be created.
2843 * @param displayId Target display.
2844 * @param r Activity that should be launched there.
2845 * @param candidateTask The possible task the activity might be put in.
2846 * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
2847 */
2848 private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
2849 @Nullable Task candidateTask, @Nullable ActivityOptions options,
2850 @Nullable LaunchParamsController.LaunchParams launchParams) {
2851 final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
2852 if (displayContent == null) {
2853 throw new IllegalArgumentException(
2854 "Display with displayId=" + displayId + " not found.");
2855 }
2856
2857 if (!r.canBeLaunchedOnDisplay(displayId)) {
2858 return null;
2859 }
2860
2861 // If {@code r} is already in target display and its task is the same as the candidate task,
2862 // the intention should be getting a launch stack for the reusable activity, so we can use
2863 // the existing stack.
2864 if (candidateTask != null && (r.getTask() == null || r.getTask() == candidateTask)) {
2865 final int attachedDisplayId = r.getDisplayId();
2866 if (attachedDisplayId == INVALID_DISPLAY || attachedDisplayId == displayId) {
2867 return candidateTask.getStack();
2868 }
2869 }
2870
2871 int windowingMode;
2872 if (launchParams != null) {
2873 // When launch params is not null, we always defer to its windowing mode. Sometimes
2874 // it could be unspecified, which indicates it should inherit windowing mode from
2875 // display.
2876 windowingMode = launchParams.mWindowingMode;
2877 } else {
2878 windowingMode = options != null ? options.getLaunchWindowingMode()
2879 : r.getWindowingMode();
2880 }
2881 windowingMode = displayContent.validateWindowingMode(windowingMode, r, candidateTask,
2882 r.getActivityType());
2883
2884 // Return the topmost valid stack on the display.
2885 for (int i = displayContent.getStackCount() - 1; i >= 0; --i) {
2886 final ActivityStack stack = displayContent.getStackAt(i);
2887 if (isValidLaunchStack(stack, r, windowingMode)) {
2888 return stack;
2889 }
2890 }
2891
2892 // If there is no valid stack on the external display - check if new dynamic stack will do.
2893 if (displayId != DEFAULT_DISPLAY) {
2894 final int activityType =
2895 options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED
2896 ? options.getLaunchActivityType() : r.getActivityType();
2897 return displayContent.createStack(windowingMode, activityType, true /*onTop*/);
2898 }
2899
2900 return null;
2901 }
2902
2903 ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
2904 @Nullable ActivityOptions options,
2905 @Nullable LaunchParamsController.LaunchParams launchParams) {
2906 return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options,
2907 launchParams);
2908 }
2909
2910 // TODO: Can probably be consolidated into getLaunchStack()...
2911 private boolean isValidLaunchStack(ActivityStack stack, ActivityRecord r, int windowingMode) {
2912 switch (stack.getActivityType()) {
2913 case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome();
2914 case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents();
2915 case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant();
2916 }
Evan Rosky0037e5f2019-11-05 10:26:24 -08002917 // TODO(task-hierarchy): Find another way to differentiate tile from normal stack once it is
2918 // part of the hierarchy
2919 if (stack instanceof TaskTile) {
2920 // Don't launch directly into tiles.
2921 return false;
2922 }
Louis Chang149d5c82019-12-30 09:47:39 +08002923 // There is a 1-to-1 relationship between stack and task when not in
2924 // primary split-windowing mode.
2925 if (stack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
2926 && r.supportsSplitScreenWindowingMode()
2927 && (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
2928 || windowingMode == WINDOWING_MODE_UNDEFINED)) {
2929 return true;
2930 }
2931 return false;
2932 }
2933
2934 int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
2935 @Nullable Task task) {
2936 // Preference is given to the activity type for the activity then the task since the type
2937 // once set shouldn't change.
2938 int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
2939 if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) {
2940 activityType = task.getActivityType();
2941 }
2942 if (activityType != ACTIVITY_TYPE_UNDEFINED) {
2943 return activityType;
2944 }
2945 if (options != null) {
2946 activityType = options.getLaunchActivityType();
2947 }
2948 return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD;
2949 }
2950
2951 /**
2952 * Get next focusable stack in the system. This will search through the stack on the same
2953 * display as the current focused stack, looking for a focusable and visible stack, different
2954 * from the target stack. If no valid candidates will be found, it will then go through all
2955 * displays and stacks in last-focused order.
2956 *
2957 * @param currentFocus The stack that previously had focus.
2958 * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
2959 * candidate.
2960 * @return Next focusable {@link ActivityStack}, {@code null} if not found.
2961 */
2962 ActivityStack getNextFocusableStack(@NonNull ActivityStack currentFocus,
2963 boolean ignoreCurrent) {
2964 // First look for next focusable stack on the same display
2965 DisplayContent preferredDisplay = currentFocus.getDisplay();
2966 if (preferredDisplay == null) {
2967 // Stack is currently detached because it is being removed. Use the previous display it
2968 // was on.
2969 preferredDisplay = getDisplayContent(currentFocus.mPrevDisplayId);
2970 }
2971 final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
2972 currentFocus, ignoreCurrent);
2973 if (preferredFocusableStack != null) {
2974 return preferredFocusableStack;
2975 }
2976 if (preferredDisplay.supportsSystemDecorations()) {
2977 // Stop looking for focusable stack on other displays because the preferred display
2978 // supports system decorations. Home activity would be launched on the same display if
2979 // no focusable stack found.
2980 return null;
2981 }
2982
2983 // Now look through all displays
2984 for (int i = getChildCount() - 1; i >= 0; --i) {
2985 final DisplayContent display = getChildAt(i);
2986 if (display == preferredDisplay) {
2987 // We've already checked this one
2988 continue;
2989 }
2990 final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus,
2991 ignoreCurrent);
2992 if (nextFocusableStack != null) {
2993 return nextFocusableStack;
2994 }
2995 }
2996
2997 return null;
2998 }
2999
3000 /**
3001 * Get next valid stack for launching provided activity in the system. This will search across
3002 * displays and stacks in last-focused order for a focusable and visible stack, except those
3003 * that are on a currently focused display.
3004 *
3005 * @param r The activity that is being launched.
3006 * @param currentFocus The display that previously had focus and thus needs to be ignored when
3007 * searching for the next candidate.
3008 * @return Next valid {@link ActivityStack}, null if not found.
3009 */
3010 ActivityStack getNextValidLaunchStack(@NonNull ActivityRecord r, int currentFocus) {
3011 for (int i = getChildCount() - 1; i >= 0; --i) {
3012 final DisplayContent display = getChildAt(i);
3013 if (display.mDisplayId == currentFocus) {
3014 continue;
3015 }
3016 final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r,
3017 null /* options */, null /* launchParams */);
3018 if (stack != null) {
3019 return stack;
3020 }
3021 }
3022 return null;
3023 }
3024
3025 boolean handleAppDied(WindowProcessController app) {
3026 boolean hasVisibleActivities = false;
3027 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3028 final DisplayContent display = getChildAt(displayNdx);
3029 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
3030 final ActivityStack stack = display.getStackAt(stackNdx);
3031 hasVisibleActivities |= stack.handleAppDied(app);
3032 }
3033 }
3034 return hasVisibleActivities;
3035 }
3036
3037 void closeSystemDialogs() {
3038 forAllActivities((r) -> {
3039 if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
3040 r.finishIfPossible("close-sys", true /* oomAdj */);
3041 }
3042 });
3043 }
3044
3045 FinishDisabledPackageActivitiesHelper mFinishDisabledPackageActivitiesHelper =
3046 new FinishDisabledPackageActivitiesHelper();
3047 class FinishDisabledPackageActivitiesHelper {
3048 private boolean mDidSomething;
3049 private String mPackageName;
3050 private Set<String> mFilterByClasses;
3051 private boolean mDoit;
3052 private boolean mEvenPersistent;
3053 private int mUserId;
3054 private Task mLastTask;
3055 private ComponentName mHomeActivity;
3056
3057 private void reset(String packageName, Set<String> filterByClasses,
3058 boolean doit, boolean evenPersistent, int userId) {
3059 mDidSomething = false;
3060 mPackageName = packageName;
3061 mFilterByClasses = filterByClasses;
3062 mDoit = doit;
3063 mEvenPersistent = evenPersistent;
3064 mUserId = userId;
3065 mLastTask = null;
3066 mHomeActivity = null;
3067 }
3068
3069 boolean process(String packageName, Set<String> filterByClasses,
3070 boolean doit, boolean evenPersistent, int userId) {
3071 reset(packageName, filterByClasses, doit, evenPersistent, userId);
3072
3073 final PooledFunction f = PooledLambda.obtainFunction(
3074 FinishDisabledPackageActivitiesHelper::processActivity, this,
3075 PooledLambda.__(ActivityRecord.class));
3076 forAllActivities(f);
3077 f.recycle();
3078 return mDidSomething;
3079 }
3080
3081 private boolean processActivity(ActivityRecord r) {
3082 final boolean sameComponent =
3083 (r.packageName.equals(mPackageName) && (mFilterByClasses == null
3084 || mFilterByClasses.contains(r.mActivityComponent.getClassName())))
3085 || (mPackageName == null && r.mUserId == mUserId);
3086 if ((mUserId == UserHandle.USER_ALL || r.mUserId == mUserId)
3087 && (sameComponent || r.getTask() == mLastTask)
3088 && (r.app == null || mEvenPersistent || !r.app.isPersistent())) {
3089 if (!mDoit) {
3090 if (r.finishing) {
3091 // If this activity is just finishing, then it is not
3092 // interesting as far as something to stop.
3093 return false;
3094 }
3095 return true;
3096 }
3097 if (r.isActivityTypeHome()) {
3098 if (mHomeActivity != null && mHomeActivity.equals(r.mActivityComponent)) {
3099 Slog.i(TAG, "Skip force-stop again " + r);
3100 return false;
3101 } else {
3102 mHomeActivity = r.mActivityComponent;
3103 }
3104 }
3105 mDidSomething = true;
3106 Slog.i(TAG, " Force finishing activity " + r);
3107 mLastTask = r.getTask();
3108 r.finishIfPossible("force-stop", true);
3109 }
3110
3111 return false;
3112 }
3113 }
3114
3115 /** @return true if some activity was finished (or would have finished if doit were true). */
3116 boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses,
3117 boolean doit, boolean evenPersistent, int userId) {
3118 return mFinishDisabledPackageActivitiesHelper.process(packageName, filterByClasses, doit,
3119 evenPersistent, userId);
3120 }
3121
3122 void updateActivityApplicationInfo(ApplicationInfo aInfo) {
3123 final String packageName = aInfo.packageName;
3124 final int userId = UserHandle.getUserId(aInfo.uid);
3125 final PooledConsumer c = PooledLambda.obtainConsumer(
3126 RootWindowContainer::updateActivityApplicationInfo,
3127 PooledLambda.__(ActivityRecord.class), aInfo, userId, packageName);
3128 forAllActivities(c);
3129 c.recycle();
3130 }
3131
3132 private static void updateActivityApplicationInfo(
3133 ActivityRecord r, ApplicationInfo aInfo, int userId, String packageName) {
3134 if (r.mUserId == userId && packageName.equals(r.packageName)) {
3135 r.updateApplicationInfo(aInfo);
3136 }
3137 }
3138
3139 void finishVoiceTask(IVoiceInteractionSession session) {
3140 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3141 final DisplayContent display = getChildAt(displayNdx);
3142 final int numStacks = display.getStackCount();
3143 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
3144 final ActivityStack stack = display.getStackAt(stackNdx);
3145 stack.finishVoiceTask(session);
3146 }
3147 }
3148 }
3149
3150 /**
3151 * Removes stacks in the input windowing modes from the system if they are of activity type
3152 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
3153 */
3154 void removeStacksInWindowingModes(int... windowingModes) {
3155 for (int i = getChildCount() - 1; i >= 0; --i) {
3156 getChildAt(i).removeStacksInWindowingModes(windowingModes);
3157 }
3158 }
3159
3160 void removeStacksWithActivityTypes(int... activityTypes) {
3161 for (int i = getChildCount() - 1; i >= 0; --i) {
3162 getChildAt(i).removeStacksWithActivityTypes(activityTypes);
3163 }
3164 }
3165
3166 ActivityRecord topRunningActivity() {
3167 for (int i = getChildCount() - 1; i >= 0; --i) {
3168 final ActivityRecord topActivity = getChildAt(i).topRunningActivity();
3169 if (topActivity != null) {
3170 return topActivity;
3171 }
3172 }
3173 return null;
3174 }
3175
3176 boolean allResumedActivitiesIdle() {
3177 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3178 // TODO(b/117135575): Check resumed activities on all visible stacks.
3179 final DisplayContent display = getChildAt(displayNdx);
3180 if (display.isSleeping()) {
3181 // No resumed activities while display is sleeping.
3182 continue;
3183 }
3184
3185 // If the focused stack is not null or not empty, there should have some activities
3186 // resuming or resumed. Make sure these activities are idle.
3187 final ActivityStack stack = display.getFocusedStack();
3188 if (stack == null || !stack.hasActivity()) {
3189 continue;
3190 }
3191 final ActivityRecord resumedActivity = stack.getResumedActivity();
3192 if (resumedActivity == null || !resumedActivity.idle) {
3193 if (DEBUG_STATES) {
3194 Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003195 + stack.getRootTaskId() + " " + resumedActivity + " not idle");
Louis Chang149d5c82019-12-30 09:47:39 +08003196 }
3197 return false;
3198 }
3199 }
3200 // Send launch end powerhint when idle
3201 sendPowerHintForLaunchEndIfNeeded();
3202 return true;
3203 }
3204
3205 boolean allResumedActivitiesVisible() {
3206 boolean foundResumed = false;
3207 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3208 final DisplayContent display = getChildAt(displayNdx);
3209 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
3210 final ActivityStack stack = display.getStackAt(stackNdx);
3211 final ActivityRecord r = stack.getResumedActivity();
3212 if (r != null) {
3213 if (!r.nowVisible) {
3214 return false;
3215 }
3216 foundResumed = true;
3217 }
3218 }
3219 }
3220 return foundResumed;
3221 }
3222
3223 boolean allPausedActivitiesComplete() {
3224 boolean pausing = true;
3225 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3226 final DisplayContent display = getChildAt(displayNdx);
3227 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
3228 final ActivityStack stack = display.getStackAt(stackNdx);
3229 final ActivityRecord r = stack.mPausingActivity;
3230 if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
3231 if (DEBUG_STATES) {
3232 Slog.d(TAG_STATES,
3233 "allPausedActivitiesComplete: r=" + r + " state=" + r.getState());
3234 pausing = false;
3235 } else {
3236 return false;
3237 }
3238 }
3239 }
3240 }
3241 return pausing;
3242 }
3243
3244 /**
3245 * Find all visible task stacks containing {@param userId} and intercept them with an activity
3246 * to block out the contents and possibly start a credential-confirming intent.
3247 *
3248 * @param userId user handle for the locked managed profile.
3249 */
3250 void lockAllProfileTasks(@UserIdInt int userId) {
3251 mService.deferWindowLayout();
3252 try {
3253 final PooledConsumer c = PooledLambda.obtainConsumer(
3254 RootWindowContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
3255 userId);
Wale Ogunwale0d465192020-01-23 19:14:44 -08003256 forAllLeafTasks(c, true /* traverseTopToBottom */);
Louis Chang149d5c82019-12-30 09:47:39 +08003257 c.recycle();
3258 } finally {
3259 mService.continueWindowLayout();
3260 }
3261 }
3262
3263 /**
3264 * Detects whether we should show a lock screen in front of this task for a locked user.
3265 * <p>
3266 * We'll do this if either of the following holds:
3267 * <ul>
3268 * <li>The top activity explicitly belongs to {@param userId}.</li>
3269 * <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
3270 * </ul>
3271 *
3272 * @return {@code true} if the top activity looks like it belongs to {@param userId}.
3273 */
3274 private void taskTopActivityIsUser(Task task, @UserIdInt int userId) {
3275 // To handle the case that work app is in the task but just is not the top one.
3276 final ActivityRecord activityRecord = task.getTopNonFinishingActivity();
3277 final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
3278
3279 // Check the task for a top activity belonging to userId, or returning a
3280 // result to an activity belonging to userId. Example case: a document
3281 // picker for personal files, opened by a work app, should still get locked.
3282 if ((activityRecord != null && activityRecord.mUserId == userId)
3283 || (resultTo != null && resultTo.mUserId == userId)) {
3284 mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
3285 task.mTaskId, userId);
3286 }
3287 }
3288
3289 void cancelInitializingActivities() {
3290 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3291 final DisplayContent display = getChildAt(displayNdx);
3292 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
3293 final ActivityStack stack = display.getStackAt(stackNdx);
3294 stack.cancelInitializingActivities();
3295 }
3296 }
3297 }
3298
3299 Task anyTaskForId(int id) {
3300 return anyTaskForId(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE);
3301 }
3302
3303 Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode) {
3304 return anyTaskForId(id, matchMode, null, !ON_TOP);
3305 }
3306
3307 /**
3308 * Returns a {@link Task} for the input id if available. {@code null} otherwise.
3309 * @param id Id of the task we would like returned.
3310 * @param matchMode The mode to match the given task id in.
3311 * @param aOptions The activity options to use for restoration. Can be null.
3312 * @param onTop If the stack for the task should be the topmost on the display.
3313 */
3314 Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode,
3315 @Nullable ActivityOptions aOptions, boolean onTop) {
3316 // If options are set, ensure that we are attempting to actually restore a task
3317 if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) {
3318 throw new IllegalArgumentException("Should not specify activity options for non-restore"
3319 + " lookup");
3320 }
3321
3322 final PooledPredicate p = PooledLambda.obtainPredicate(
3323 Task::isTaskId, PooledLambda.__(Task.class), id);
3324 Task task = getTask(p);
3325 p.recycle();
3326
3327 if (task != null) {
3328 if (aOptions != null) {
3329 // Resolve the stack the task should be placed in now based on options
3330 // and reparent if needed.
3331 final ActivityStack launchStack =
3332 getLaunchStack(null, aOptions, task, onTop);
3333 if (launchStack != null && task.getStack() != launchStack) {
3334 final int reparentMode = onTop
3335 ? REPARENT_MOVE_STACK_TO_FRONT : REPARENT_LEAVE_STACK_IN_PLACE;
3336 task.reparent(launchStack, onTop, reparentMode, ANIMATE, DEFER_RESUME,
3337 "anyTaskForId");
3338 }
3339 }
3340 return task;
3341 }
3342
3343 // If we are matching stack tasks only, return now
3344 if (matchMode == MATCH_TASK_IN_STACKS_ONLY) {
3345 return null;
3346 }
3347
3348 // Otherwise, check the recent tasks and return if we find it there and we are not restoring
3349 // the task from recents
3350 if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
3351 task = mStackSupervisor.mRecentTasks.getTask(id);
3352
3353 if (task == null) {
3354 if (DEBUG_RECENTS) {
3355 Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
3356 }
3357
3358 return null;
3359 }
3360
3361 if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
3362 return task;
3363 }
3364
3365 // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
3366 if (!mStackSupervisor.restoreRecentTaskLocked(task, aOptions, onTop)) {
3367 if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
3368 "Couldn't restore task id=" + id + " found in recents");
3369 return null;
3370 }
3371 if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
3372 return task;
3373 }
3374
3375 ActivityRecord isInAnyStack(IBinder token) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08003376 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
3377 return (r != null && r.isDescendantOf(this)) ? r : null;
Louis Chang149d5c82019-12-30 09:47:39 +08003378 }
3379
3380 @VisibleForTesting
3381 void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list,
3382 @WindowConfiguration.ActivityType int ignoreActivityType,
3383 @WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid,
3384 boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
3385 mStackSupervisor.getRunningTasks().getTasks(maxNum, list, ignoreActivityType,
3386 ignoreWindowingMode, this, callingUid, allowed, crossUser, profileIds);
3387 }
3388
3389 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
3390 boolean sendHint = forceSend;
3391
3392 if (!sendHint) {
3393 // Send power hint if we don't know what we're launching yet
3394 sendHint = targetActivity == null || targetActivity.app == null;
3395 }
3396
3397 if (!sendHint) { // targetActivity != null
3398 // Send power hint when the activity's process is different than the current resumed
3399 // activity on all displays, or if there are no resumed activities in the system.
3400 boolean noResumedActivities = true;
3401 boolean allFocusedProcessesDiffer = true;
3402 for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
3403 final DisplayContent displayContent = getChildAt(displayNdx);
3404 final ActivityRecord resumedActivity = displayContent.getResumedActivity();
3405 final WindowProcessController resumedActivityProcess =
3406 resumedActivity == null ? null : resumedActivity.app;
3407
3408 noResumedActivities &= resumedActivityProcess == null;
3409 if (resumedActivityProcess != null) {
3410 allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app);
3411 }
3412 }
3413 sendHint = noResumedActivities || allFocusedProcessesDiffer;
3414 }
3415
3416 if (sendHint && mService.mPowerManagerInternal != null) {
3417 mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 1);
3418 mPowerHintSent = true;
3419 }
3420 }
3421
3422 void sendPowerHintForLaunchEndIfNeeded() {
3423 // Trigger launch power hint if activity is launched
3424 if (mPowerHintSent && mService.mPowerManagerInternal != null) {
3425 mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 0);
3426 mPowerHintSent = false;
3427 }
3428 }
3429
3430 private void calculateDefaultMinimalSizeOfResizeableTasks() {
3431 final Resources res = mService.mContext.getResources();
3432 final float minimalSize = res.getDimension(
3433 com.android.internal.R.dimen.default_minimal_size_resizable_task);
3434 final DisplayMetrics dm = res.getDisplayMetrics();
3435
3436 mDefaultMinSizeOfResizeableTaskDp = (int) (minimalSize / dm.density);
3437 }
3438
3439 /**
3440 * Dumps the activities matching the given {@param name} in the either the focused stack
3441 * or all visible stacks if {@param dumpVisibleStacks} is true.
3442 */
3443 ArrayList<ActivityRecord> getDumpActivities(String name, boolean dumpVisibleStacksOnly,
3444 boolean dumpFocusedStackOnly) {
3445 if (dumpFocusedStackOnly) {
Darryl L Johnson1e3885c2020-02-27 17:38:13 -08003446 final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
3447 if (topFocusedStack != null) {
3448 return topFocusedStack.getDumpActivitiesLocked(name);
3449 } else {
3450 return new ArrayList<>();
3451 }
Louis Chang149d5c82019-12-30 09:47:39 +08003452 } else {
3453 ArrayList<ActivityRecord> activities = new ArrayList<>();
3454 int numDisplays = getChildCount();
3455 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
3456 final DisplayContent display = getChildAt(displayNdx);
3457 for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
3458 final ActivityStack stack = display.getStackAt(stackNdx);
3459 if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
3460 activities.addAll(stack.getDumpActivitiesLocked(name));
3461 }
3462 }
3463 }
3464 return activities;
3465 }
3466 }
3467
3468 public void dump(PrintWriter pw, String prefix) {
3469 pw.print(prefix);
3470 pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack());
3471 for (int i = getChildCount() - 1; i >= 0; --i) {
3472 final DisplayContent display = getChildAt(i);
3473 display.dump(pw, prefix, true /* dumpAll */);
3474 }
3475 }
3476
3477 /**
3478 * Dump all connected displays' configurations.
3479 * @param prefix Prefix to apply to each line of the dump.
3480 */
3481 void dumpDisplayConfigs(PrintWriter pw, String prefix) {
3482 pw.print(prefix); pw.println("Display override configurations:");
3483 final int displayCount = getChildCount();
3484 for (int i = 0; i < displayCount; i++) {
3485 final DisplayContent displayContent = getChildAt(i);
3486 pw.print(prefix); pw.print(" "); pw.print(displayContent.mDisplayId); pw.print(": ");
3487 pw.println(displayContent.getRequestedOverrideConfiguration());
3488 }
3489 }
3490
Louis Chang149d5c82019-12-30 09:47:39 +08003491 boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
3492 String dumpPackage) {
3493 boolean printed = false;
3494 boolean needSep = false;
3495 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
3496 DisplayContent displayContent = getChildAt(displayNdx);
3497 pw.print("Display #"); pw.print(displayContent.mDisplayId);
3498 pw.println(" (activities from top to bottom):");
3499 for (int stackNdx = displayContent.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
3500 final ActivityStack stack = displayContent.getStackAt(stackNdx);
3501 pw.println();
3502 printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
3503 needSep = printed;
3504 }
3505 printThisActivity(pw, displayContent.getResumedActivity(), dumpPackage, needSep,
3506 " ResumedActivity:");
3507 }
3508
3509 printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, " ",
3510 "Fin", false, !dumpAll,
3511 false, dumpPackage, true, " Activities waiting to finish:", null);
3512 printed |= dumpHistoryList(fd, pw, mStackSupervisor.mStoppingActivities, " ",
3513 "Stop", false, !dumpAll,
3514 false, dumpPackage, true, " Activities waiting to stop:", null);
Louis Chang149d5c82019-12-30 09:47:39 +08003515
3516 return printed;
3517 }
3518
Louis Chang149d5c82019-12-30 09:47:39 +08003519 private final class SleepTokenImpl extends ActivityTaskManagerInternal.SleepToken {
3520 private final String mTag;
3521 private final long mAcquireTime;
3522 private final int mDisplayId;
3523
3524 public SleepTokenImpl(String tag, int displayId) {
3525 mTag = tag;
3526 mDisplayId = displayId;
3527 mAcquireTime = SystemClock.uptimeMillis();
3528 }
3529
3530 @Override
3531 public void release() {
3532 synchronized (mService.mGlobalLock) {
3533 removeSleepToken(this);
3534 }
3535 }
3536
3537 @Override
3538 public String toString() {
3539 return "{\"" + mTag + "\", display " + mDisplayId
3540 + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
3541 }
3542 }
Wale Ogunwalee05f5012016-09-16 16:27:29 -07003543}