• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
17 package com.android.server.wm;
18 
19 import static android.Manifest.permission.EMBED_ANY_APP_IN_UNTRUSTED_MODE;
20 import static android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
21 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
24 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
25 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
26 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
27 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
28 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
29 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
30 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
31 import static android.app.WindowConfiguration.isFloating;
32 import static android.content.pm.ActivityInfo.FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING;
33 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
34 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
35 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
36 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
37 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
38 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
39 import static android.os.Process.INVALID_UID;
40 import static android.os.Process.SYSTEM_UID;
41 import static android.os.UserHandle.USER_NULL;
42 import static android.view.Display.INVALID_DISPLAY;
43 import static android.view.Surface.ROTATION_270;
44 import static android.view.Surface.ROTATION_90;
45 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
46 
47 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_STATES;
48 import static com.android.server.wm.ActivityRecord.State.PAUSED;
49 import static com.android.server.wm.ActivityRecord.State.PAUSING;
50 import static com.android.server.wm.ActivityRecord.State.RESUMED;
51 import static com.android.server.wm.ActivityRecord.State.STOPPING;
52 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
53 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
54 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
55 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
56 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
57 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
58 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
59 import static com.android.server.wm.ActivityTaskManagerService.checkPermission;
60 import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
61 import static com.android.server.wm.IdentifierProto.HASH_CODE;
62 import static com.android.server.wm.IdentifierProto.TITLE;
63 import static com.android.server.wm.IdentifierProto.USER_ID;
64 import static com.android.server.wm.TaskFragmentProto.ACTIVITY_TYPE;
65 import static com.android.server.wm.TaskFragmentProto.DISPLAY_ID;
66 import static com.android.server.wm.TaskFragmentProto.MIN_HEIGHT;
67 import static com.android.server.wm.TaskFragmentProto.MIN_WIDTH;
68 import static com.android.server.wm.TaskFragmentProto.WINDOW_CONTAINER;
69 import static com.android.server.wm.WindowContainerChildProto.TASK_FRAGMENT;
70 
71 import android.annotation.IntDef;
72 import android.annotation.NonNull;
73 import android.annotation.Nullable;
74 import android.app.ActivityOptions;
75 import android.app.IApplicationThread;
76 import android.app.ResultInfo;
77 import android.app.WindowConfiguration;
78 import android.app.servertransaction.ActivityResultItem;
79 import android.app.servertransaction.NewIntentItem;
80 import android.app.servertransaction.PauseActivityItem;
81 import android.app.servertransaction.ResumeActivityItem;
82 import android.content.PermissionChecker;
83 import android.content.pm.ActivityInfo;
84 import android.content.pm.PackageManager;
85 import android.content.res.Configuration;
86 import android.graphics.Insets;
87 import android.graphics.Point;
88 import android.graphics.Rect;
89 import android.os.IBinder;
90 import android.os.RemoteException;
91 import android.os.UserHandle;
92 import android.util.ArraySet;
93 import android.util.DisplayMetrics;
94 import android.util.Slog;
95 import android.util.proto.ProtoOutputStream;
96 import android.view.DisplayInfo;
97 import android.view.SurfaceControl;
98 import android.window.ITaskFragmentOrganizer;
99 import android.window.TaskFragmentAnimationParams;
100 import android.window.TaskFragmentInfo;
101 import android.window.TaskFragmentOrganizerToken;
102 
103 import com.android.internal.annotations.VisibleForTesting;
104 import com.android.internal.protolog.ProtoLog;
105 import com.android.internal.util.ToBooleanFunction;
106 import com.android.server.am.HostingRecord;
107 import com.android.server.pm.pkg.AndroidPackage;
108 import com.android.window.flags.Flags;
109 
110 import java.io.FileDescriptor;
111 import java.io.PrintWriter;
112 import java.util.ArrayList;
113 import java.util.List;
114 import java.util.Set;
115 import java.util.function.Consumer;
116 import java.util.function.Predicate;
117 
118 /**
119  * A basic container that can be used to contain activities or other {@link TaskFragment}, which
120  * also able to manage the activity lifecycle and updates the visibilities of the activities in it.
121  */
122 class TaskFragment extends WindowContainer<WindowContainer> {
123     @IntDef(prefix = {"TASK_FRAGMENT_VISIBILITY"}, value = {
124             TASK_FRAGMENT_VISIBILITY_VISIBLE,
125             TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
126             TASK_FRAGMENT_VISIBILITY_INVISIBLE,
127     })
128     @interface TaskFragmentVisibility {}
129 
130     /**
131      * TaskFragment is visible. No other TaskFragment(s) on top that fully or partially occlude it.
132      */
133     static final int TASK_FRAGMENT_VISIBILITY_VISIBLE = 0;
134 
135     /** TaskFragment is partially occluded by other translucent TaskFragment(s) on top of it. */
136     static final int TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT = 1;
137 
138     /** TaskFragment is completely invisible. */
139     static final int TASK_FRAGMENT_VISIBILITY_INVISIBLE = 2;
140 
141     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskFragment" : TAG_ATM;
142     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
143     private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
144     private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
145 
146     /** Set to false to disable the preview that is shown while a new activity is being started. */
147     static final boolean SHOW_APP_STARTING_PREVIEW = true;
148 
149     /**
150      * An embedding check result of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
151      * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
152      * indicate that an Activity can be embedded successfully.
153      */
154     static final int EMBEDDING_ALLOWED = 0;
155     /**
156      * An embedding check result of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
157      * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
158      * indicate that an Activity can't be embedded because either the Activity does not allow
159      * untrusted embedding, and the embedding host app is not trusted.
160      */
161     static final int EMBEDDING_DISALLOWED_UNTRUSTED_HOST = 1;
162     /**
163      * An embedding check result of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
164      * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
165      * indicate that an Activity can't be embedded because this taskFragment's bounds are
166      * {@link #smallerThanMinDimension(ActivityRecord)}.
167      */
168     static final int EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION = 2;
169     /**
170      * An embedding check result of
171      * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}:
172      * indicate that an Activity can't be embedded because the Activity is started on a new task.
173      */
174     static final int EMBEDDING_DISALLOWED_NEW_TASK = 3;
175 
176     /**
177      * Embedding check results of {@link #isAllowedToEmbedActivity(ActivityRecord)} or
178      * {@link ActivityStarter#canEmbedActivity(TaskFragment, ActivityRecord, Task)}.
179      */
180     @IntDef(prefix = {"EMBEDDING_"}, value = {
181             EMBEDDING_ALLOWED,
182             EMBEDDING_DISALLOWED_UNTRUSTED_HOST,
183             EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION,
184             EMBEDDING_DISALLOWED_NEW_TASK,
185     })
186     @interface EmbeddingCheckResult {}
187 
188     /**
189      * Indicate that the minimal width/height should use the default value.
190      *
191      * @see #mMinWidth
192      * @see #mMinHeight
193      */
194     static final int INVALID_MIN_SIZE = -1;
195 
196     final ActivityTaskManagerService mAtmService;
197     final ActivityTaskSupervisor mTaskSupervisor;
198     final RootWindowContainer mRootWindowContainer;
199     private final TaskFragmentOrganizerController mTaskFragmentOrganizerController;
200 
201     // TODO(b/233177466): Move mMinWidth and mMinHeight to Task and remove usages in TaskFragment
202     /**
203      * Minimal width of this task fragment when it's resizeable. {@link #INVALID_MIN_SIZE} means it
204      * should use the default minimal width.
205      */
206     int mMinWidth;
207 
208     /**
209      * Minimal height of this task fragment when it's resizeable. {@link #INVALID_MIN_SIZE} means it
210      * should use the default minimal height.
211      */
212     int mMinHeight;
213 
214     Dimmer mDimmer = new Dimmer(this);
215 
216     /** Apply the dim layer on the embedded TaskFragment. */
217     static final int EMBEDDED_DIM_AREA_TASK_FRAGMENT = 0;
218 
219     /** Apply the dim layer on the parent Task for an embedded TaskFragment. */
220     static final int EMBEDDED_DIM_AREA_PARENT_TASK = 1;
221 
222     /**
223      * The type of dim layer area for an embedded TaskFragment.
224      */
225     @IntDef(prefix = {"EMBEDDED_DIM_AREA_"}, value = {
226             EMBEDDED_DIM_AREA_TASK_FRAGMENT,
227             EMBEDDED_DIM_AREA_PARENT_TASK,
228     })
229     @interface EmbeddedDimArea {}
230 
231     @EmbeddedDimArea
232     private int mEmbeddedDimArea = EMBEDDED_DIM_AREA_TASK_FRAGMENT;
233 
234     /** This task fragment will be removed when the cleanup of its children are done. */
235     private boolean mIsRemovalRequested;
236 
237     /**
238      * The TaskFragments that are adjacent to each other, including this TaskFragment.
239      * All TaskFragments in this set share the same set instance.
240      */
241     @Nullable
242     private AdjacentSet mAdjacentTaskFragments;
243 
244     /**
245      * Unlike the {@link #mAdjacentTaskFragments}, the companion TaskFragment is not always visually
246      * adjacent to this one, but this TaskFragment will be removed by the organizer if the
247      * companion TaskFragment is removed.
248      */
249     @Nullable
250     private TaskFragment mCompanionTaskFragment;
251 
252     /**
253      * Prevents duplicate calls to onTaskFragmentAppeared.
254      */
255     boolean mTaskFragmentAppearedSent;
256 
257     /**
258      * Prevents unnecessary callbacks after onTaskFragmentVanished.
259      */
260     boolean mTaskFragmentVanishedSent;
261 
262     /**
263      * The last running activity of the TaskFragment was finished due to clear task while launching
264      * an activity in the Task.
265      */
266     boolean mClearedTaskForReuse;
267 
268     /**
269      * The last running activity of the TaskFragment was reparented to a different Task because it
270      * is entering PiP.
271      */
272     boolean mClearedTaskFragmentForPip;
273 
274     /**
275      * The last running activity of the TaskFragment was removed and added to the top-most of the
276      * Task because it was launched with FLAG_ACTIVITY_REORDER_TO_FRONT.
277      */
278     boolean mClearedForReorderActivityToFront;
279 
280     /**
281      * When we are in the process of pausing an activity, before starting the
282      * next one, this variable holds the activity that is currently being paused.
283      *
284      * Only set at leaf task fragments.
285      */
286     @Nullable
287     private ActivityRecord mPausingActivity = null;
288 
289     /**
290      * This is the last activity that we put into the paused state.  This is
291      * used to determine if we need to do an activity transition while sleeping,
292      * when we normally hold the top activity paused.
293      */
294     ActivityRecord mLastPausedActivity = null;
295 
296     /**
297      * Current activity that is resumed, or null if there is none.
298      * Only set at leaf task fragments.
299      */
300     @Nullable
301     private ActivityRecord mResumedActivity = null;
302 
303     /**
304      * This TaskFragment was created by an organizer which has the following implementations.
305      * <ul>
306      *     <li>The TaskFragment won't be removed when it is empty. Removal has to be an explicit
307      *     request from the organizer.</li>
308      *     <li>If this fragment is a Task object then unlike other non-root tasks, it's direct
309      *     children are visible to the organizer for ordering purposes.</li>
310      *     <li>A TaskFragment can be created by {@link android.window.TaskFragmentOrganizer}, and
311      *     a Task can be created by {@link android.window.TaskOrganizer}.</li>
312      * </ul>
313      */
314     @VisibleForTesting
315     boolean mCreatedByOrganizer;
316 
317     /** Whether this TaskFragment is embedded in a task. */
318     private final boolean mIsEmbedded;
319 
320     /** Organizer that organizing this TaskFragment. */
321     @Nullable
322     private ITaskFragmentOrganizer mTaskFragmentOrganizer;
323 
324     int mTaskFragmentOrganizerUid = INVALID_UID;
325     @Nullable String mTaskFragmentOrganizerProcessName;
326 
327     /** Client assigned unique token for this TaskFragment if this is created by an organizer. */
328     @Nullable
329     private final IBinder mFragmentToken;
330 
331     /** The animation override params for animation running on this TaskFragment. */
332     @NonNull
333     private TaskFragmentAnimationParams mAnimationParams = TaskFragmentAnimationParams.DEFAULT;
334 
335     /**
336      * The organizer requested bounds of the embedded TaskFragment relative to the parent Task.
337      * {@code null} if it is not {@link #mIsEmbedded}
338      */
339     @Nullable
340     private final Rect mRelativeEmbeddedBounds;
341 
342     /**
343      * Whether to delay the call to {@link #updateOrganizedTaskFragmentSurface()} when there is a
344      * configuration change.
345      */
346     private boolean mDelayOrganizedTaskFragmentSurfaceUpdate;
347 
348     /**
349      * Whether to delay the last activity of TaskFragment being immediately removed while finishing.
350      * This should only be set on a embedded TaskFragment, where the organizer can have the
351      * opportunity to perform animations and finishing the adjacent TaskFragment.
352      */
353     private boolean mDelayLastActivityRemoval;
354 
355     /**
356      * Whether the activity navigation should be isolated. That is, Activities cannot be launched
357      * on an isolated TaskFragment unless explicitly requested to be launched to.
358      */
359     private boolean mIsolatedNav;
360 
361     /**
362      * Whether the TaskFragment to be pinned.
363      * <p>
364      * If a TaskFragment is pinned, the TaskFragment should be the top-most TaskFragment among other
365      * sibling TaskFragments. Any newly launched and embeddable activity should not be placed in the
366      * pinned TaskFragment, unless the activity is launched from the pinned TaskFragment or
367      * explicitly requested to. Non-embeddable activities are not restricted to.
368      */
369     private boolean mPinned;
370 
371     /**
372      * Whether the TaskFragment should move to bottom of task when any activity below it is
373      * launched in clear top mode.
374      */
375     private boolean mMoveToBottomIfClearWhenLaunch;
376 
377     /**
378      * If {@code true}, transitions are allowed even if this TaskFragment is empty. If
379      * {@code false}, transitions will wait until this TaskFragment becomes non-empty or other
380      * conditions are met. Default to {@code false}.
381      *
382      * @see #isReadyToTransit
383      */
384     private boolean mAllowTransitionWhenEmpty;
385 
386     /**
387      * Specifies which configuration changes should trigger TaskFragment info changed callbacks.
388      * Only system TaskFragment organizers are allowed to set this value.
389      */
390     private @ActivityInfo.Config int mConfigurationChangeMaskForOrganizer;
391 
392     /** When set, will force the task to report as invisible. */
393     static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1;
394     static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1;
395     static final int FLAG_FORCE_HIDDEN_FOR_TASK_FRAGMENT_ORG = 1 << 2;
396 
397     @IntDef(prefix = {"FLAG_FORCE_HIDDEN_"}, value = {
398             FLAG_FORCE_HIDDEN_FOR_PINNED_TASK,
399             FLAG_FORCE_HIDDEN_FOR_TASK_ORG,
400             FLAG_FORCE_HIDDEN_FOR_TASK_FRAGMENT_ORG,
401     }, flag = true)
402     @interface FlagForceHidden {}
403     protected int mForceHiddenFlags = 0;
404 
405     private boolean mForceTranslucent = false;
406 
407     /** @see #setCanAffectSystemUiFlags */
408     private boolean mCanAffectSystemUiFlags = true;
409 
410     final Point mLastSurfaceSize = new Point();
411 
412     private final Rect mTmpBounds = new Rect();
413     private final Rect mTmpAbsBounds = new Rect();
414     private final Rect mTmpFullBounds = new Rect();
415     /** For calculating screenWidthDp and screenWidthDp, i.e. the area without the system bars. */
416     private final Rect mTmpStableBounds = new Rect();
417     /** For calculating app bounds, i.e. the area without the nav bar and display cutout. */
418     private final Rect mTmpNonDecorBounds = new Rect();
419 
420     private final EnsureActivitiesVisibleHelper mEnsureActivitiesVisibleHelper =
421             new EnsureActivitiesVisibleHelper(this);
422 
423     /** Creates an embedded task fragment. */
TaskFragment(ActivityTaskManagerService atmService, IBinder fragmentToken, boolean createdByOrganizer)424     TaskFragment(ActivityTaskManagerService atmService, IBinder fragmentToken,
425             boolean createdByOrganizer) {
426         this(atmService, fragmentToken, createdByOrganizer, true /* isEmbedded */);
427     }
428 
TaskFragment(ActivityTaskManagerService atmService, IBinder fragmentToken, boolean createdByOrganizer, boolean isEmbedded)429     TaskFragment(ActivityTaskManagerService atmService, IBinder fragmentToken,
430             boolean createdByOrganizer, boolean isEmbedded) {
431         super(atmService.mWindowManager);
432 
433         mAtmService = atmService;
434         mTaskSupervisor = mAtmService.mTaskSupervisor;
435         mRootWindowContainer = mAtmService.mRootWindowContainer;
436         mCreatedByOrganizer = createdByOrganizer;
437         mIsEmbedded = isEmbedded;
438         mRelativeEmbeddedBounds = isEmbedded ? new Rect() : null;
439         mTaskFragmentOrganizerController =
440                 mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController;
441         mFragmentToken = fragmentToken;
442         mRemoteToken = new RemoteToken(this);
443     }
444 
445     @NonNull
fromTaskFragmentToken(@ullable IBinder token, @NonNull ActivityTaskManagerService service)446     static TaskFragment fromTaskFragmentToken(@Nullable IBinder token,
447             @NonNull ActivityTaskManagerService service) {
448         if (token == null) return null;
449         return service.mWindowOrganizerController.getTaskFragment(token);
450     }
451 
setAdjacentTaskFragments(@onNull AdjacentSet adjacentTaskFragments)452     void setAdjacentTaskFragments(@NonNull AdjacentSet adjacentTaskFragments) {
453         adjacentTaskFragments.setAsAdjacent();
454     }
455 
setCompanionTaskFragment(@ullable TaskFragment companionTaskFragment)456     void setCompanionTaskFragment(@Nullable TaskFragment companionTaskFragment) {
457         mCompanionTaskFragment = companionTaskFragment;
458     }
459 
getCompanionTaskFragment()460     TaskFragment getCompanionTaskFragment() {
461         return mCompanionTaskFragment;
462     }
463 
clearAdjacentTaskFragments()464     void clearAdjacentTaskFragments() {
465         if (mAdjacentTaskFragments != null) {
466             mAdjacentTaskFragments.clear();
467         }
468     }
469 
removeFromAdjacentTaskFragments()470     void removeFromAdjacentTaskFragments() {
471         if (mAdjacentTaskFragments != null) {
472             mAdjacentTaskFragments.remove(this);
473         }
474     }
475 
476     @Nullable
getAdjacentTaskFragments()477     AdjacentSet getAdjacentTaskFragments() {
478         return mAdjacentTaskFragments;
479     }
480 
481     /**
482      * Runs callback on all TaskFragments that are adjacent to this. The invoke order is not
483      * guaranteed.
484      */
forOtherAdjacentTaskFragments(@onNull Consumer<TaskFragment> callback)485     void forOtherAdjacentTaskFragments(@NonNull Consumer<TaskFragment> callback) {
486         if (mAdjacentTaskFragments == null) {
487             return;
488         }
489         mAdjacentTaskFragments.forAllTaskFragments(callback, this /* exclude */);
490     }
491 
492     /**
493      * Runs callback on all TaskFragments that are adjacent to this. Returns early if callback
494      * returns true on any of them. The invoke order is not guaranteed.
495      */
forOtherAdjacentTaskFragments(@onNull Predicate<TaskFragment> callback)496     boolean forOtherAdjacentTaskFragments(@NonNull Predicate<TaskFragment> callback) {
497         if (mAdjacentTaskFragments == null) {
498             return false;
499         }
500         return mAdjacentTaskFragments.forAllTaskFragments(callback, this /* exclude */);
501     }
502 
hasAdjacentTaskFragment()503     boolean hasAdjacentTaskFragment() {
504         return mAdjacentTaskFragments != null;
505     }
506 
isAdjacentTo(@onNull TaskFragment other)507     boolean isAdjacentTo(@NonNull TaskFragment other) {
508         return other != this
509                 && mAdjacentTaskFragments != null
510                 && mAdjacentTaskFragments.contains(other);
511     }
512 
setTaskFragmentOrganizer(@onNull TaskFragmentOrganizerToken organizer, int uid, @NonNull String processName)513     void setTaskFragmentOrganizer(@NonNull TaskFragmentOrganizerToken organizer, int uid,
514             @NonNull String processName) {
515         mTaskFragmentOrganizer = ITaskFragmentOrganizer.Stub.asInterface(organizer.asBinder());
516         mTaskFragmentOrganizerUid = uid;
517         mTaskFragmentOrganizerProcessName = processName;
518     }
519 
onTaskFragmentOrganizerRestarted(@onNull ITaskFragmentOrganizer organizer)520     void onTaskFragmentOrganizerRestarted(@NonNull ITaskFragmentOrganizer organizer) {
521         mTaskFragmentOrganizer = organizer;
522     }
523 
onTaskFragmentOrganizerRemoved()524     void onTaskFragmentOrganizerRemoved() {
525         mTaskFragmentOrganizer = null;
526     }
527 
528     /** Whether this TaskFragment is organized by the given {@code organizer}. */
hasTaskFragmentOrganizer(ITaskFragmentOrganizer organizer)529     boolean hasTaskFragmentOrganizer(ITaskFragmentOrganizer organizer) {
530         return organizer != null && mTaskFragmentOrganizer != null
531                 && organizer.asBinder().equals(mTaskFragmentOrganizer.asBinder());
532     }
533 
534     /**
535      * Returns the process of organizer if this TaskFragment is organized and the activity lives in
536      * a different process than the organizer.
537      */
538     @Nullable
getOrganizerProcessIfDifferent(@ullable ActivityRecord r)539     private WindowProcessController getOrganizerProcessIfDifferent(@Nullable ActivityRecord r) {
540         final Task task = getTask();
541         if (r == null || task == null || task.mTaskFragmentHostProcessName == null) {
542             return null;
543         }
544         if (task.mTaskFragmentHostProcessName.equals(r.processName)
545                 && task.mTaskFragmentHostUid == r.getUid()) {
546             return null;
547         }
548         return mAtmService.getProcessController(task.mTaskFragmentHostProcessName,
549                 task.mTaskFragmentHostUid);
550     }
551 
setAnimationParams(@onNull TaskFragmentAnimationParams animationParams)552     void setAnimationParams(@NonNull TaskFragmentAnimationParams animationParams) {
553         mAnimationParams = animationParams;
554     }
555 
556     @NonNull
getAnimationParams()557     TaskFragmentAnimationParams getAnimationParams() {
558         return mAnimationParams;
559     }
560 
561     /** @see #mIsolatedNav */
setIsolatedNav(boolean isolatedNav)562     void setIsolatedNav(boolean isolatedNav) {
563         if (!isEmbedded()) {
564             return;
565         }
566         mIsolatedNav = isolatedNav;
567     }
568 
569     /**
570      * Sets whether this TaskFragment {@link #isPinned()}.
571      * <p>
572      * Note that this is no-op if the TaskFragment is not {@link #isEmbedded() embedded}.
573      */
setPinned(boolean pinned)574     void setPinned(boolean pinned) {
575         if (!isEmbedded()) {
576             return;
577         }
578         mPinned = pinned;
579     }
580 
581     /**
582      * Sets whether transitions are allowed when the TaskFragment is empty. If {@code true},
583      * transitions are allowed when the TaskFragment is empty. If {@code false}, transitions
584      * will wait until the TaskFragment becomes non-empty or other conditions are met. Default
585      * to {@code false}.
586      */
setAllowTransitionWhenEmpty(boolean allowTransitionWhenEmpty)587     void setAllowTransitionWhenEmpty(boolean allowTransitionWhenEmpty) {
588         if (!isEmbedded()) {
589             return;
590         }
591         mAllowTransitionWhenEmpty = allowTransitionWhenEmpty;
592     }
593 
setConfigurationChangeMaskForOrganizer(@ctivityInfo.Config int mask)594     void setConfigurationChangeMaskForOrganizer(@ActivityInfo.Config int mask) {
595         // Only system organizers are allowed to set configuration change mask.
596         if (mTaskFragmentOrganizerController.isSystemOrganizer(mTaskFragmentOrganizer.asBinder())) {
597             mConfigurationChangeMaskForOrganizer = mask;
598         }
599     }
600 
getConfigurationChangeMaskForOrganizer()601     @ActivityInfo.Config int getConfigurationChangeMaskForOrganizer() {
602         return mConfigurationChangeMaskForOrganizer;
603     }
604 
605     /** @see #mIsolatedNav */
isIsolatedNav()606     boolean isIsolatedNav() {
607         return isEmbedded() && mIsolatedNav;
608     }
609 
610     /**
611      * Indicates whether this TaskFragment is pinned.
612      *
613      * @see android.window.TaskFragmentOperation#OP_TYPE_SET_PINNED
614      */
isPinned()615     boolean isPinned() {
616         return isEmbedded() && mPinned;
617     }
618 
619     /** Returns the currently topmost resumed activity. */
620     @Nullable
getTopResumedActivity()621     ActivityRecord getTopResumedActivity() {
622         final ActivityRecord taskFragResumedActivity = getResumedActivity();
623         for (int i = getChildCount() - 1; i >= 0; --i) {
624             WindowContainer<?> child = getChildAt(i);
625             ActivityRecord topResumedActivity = null;
626             if (taskFragResumedActivity != null && child == taskFragResumedActivity) {
627                 topResumedActivity = child.asActivityRecord();
628             } else if (child.asTaskFragment() != null) {
629                 topResumedActivity = child.asTaskFragment().getTopResumedActivity();
630             }
631             if (topResumedActivity != null) {
632                 return topResumedActivity;
633             }
634         }
635         return null;
636     }
637 
638     /**
639      * Returns the currently resumed activity in this TaskFragment's
640      * {@link #mChildren direct children}
641      */
getResumedActivity()642     ActivityRecord getResumedActivity() {
643         return mResumedActivity;
644     }
645 
setResumedActivity(ActivityRecord r, String reason)646     void setResumedActivity(ActivityRecord r, String reason) {
647         if (mResumedActivity == r) {
648             return;
649         }
650 
651         if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
652             Slog.d(TAG, "setResumedActivity taskFrag:" + this + " + from: "
653                     + mResumedActivity + " to:" + r + " reason:" + reason);
654         }
655 
656         if (r != null && mResumedActivity == null) {
657             // Task is becoming active.
658             getTask().touchActiveTime();
659         }
660 
661         final ActivityRecord prevR = mResumedActivity;
662         mResumedActivity = r;
663         final ActivityRecord topResumed = mTaskSupervisor.updateTopResumedActivityIfNeeded(reason);
664         if (mResumedActivity != null && topResumed != null && topResumed.isEmbedded()
665                 && topResumed.getTaskFragment().isAdjacentTo(this)) {
666             // Explicitly updates the last resumed Activity if the resumed activity is
667             // adjacent to the top-resumed embedded activity.
668             mAtmService.setLastResumedActivityUncheckLocked(mResumedActivity, reason);
669         }
670         if (r == null && prevR.mDisplayContent != null
671                 && prevR.mDisplayContent.getFocusedRootTask() == null) {
672             // Only need to notify DWPC when no activity will resume.
673             prevR.mDisplayContent.onRunningActivityChanged();
674         } else if (r != null) {
675             r.mDisplayContent.onRunningActivityChanged();
676         }
677     }
678 
679     @VisibleForTesting
setPausingActivity(ActivityRecord pausing)680     void setPausingActivity(ActivityRecord pausing) {
681         mPausingActivity = pausing;
682     }
683 
684     /** Returns the currently topmost pausing activity. */
685     @Nullable
getTopPausingActivity()686     ActivityRecord getTopPausingActivity() {
687         final ActivityRecord taskFragPausingActivity = getPausingActivity();
688         for (int i = getChildCount() - 1; i >= 0; --i) {
689             WindowContainer<?> child = getChildAt(i);
690             ActivityRecord topPausingActivity = null;
691             if (taskFragPausingActivity != null && child == taskFragPausingActivity) {
692                 topPausingActivity = child.asActivityRecord();
693             } else if (child.asTaskFragment() != null) {
694                 topPausingActivity = child.asTaskFragment().getTopPausingActivity();
695             }
696             if (topPausingActivity != null) {
697                 return topPausingActivity;
698             }
699         }
700         return null;
701     }
702 
getPausingActivity()703     ActivityRecord getPausingActivity() {
704         return mPausingActivity;
705     }
706 
getDisplayId()707     int getDisplayId() {
708         final DisplayContent dc = getDisplayContent();
709         return dc != null ? dc.mDisplayId : INVALID_DISPLAY;
710     }
711 
712     @Nullable
getTask()713     Task getTask() {
714         if (asTask() != null) {
715             return asTask();
716         }
717 
718         TaskFragment parent = getParent() != null ? getParent().asTaskFragment() : null;
719         return parent != null ? parent.getTask() : null;
720     }
721 
722     @Override
723     @Nullable
getDisplayArea()724     TaskDisplayArea getDisplayArea() {
725         return (TaskDisplayArea) super.getDisplayArea();
726     }
727 
728     @Override
isAttached()729     public boolean isAttached() {
730         final TaskDisplayArea taskDisplayArea = getDisplayArea();
731         return taskDisplayArea != null && !taskDisplayArea.isRemoved();
732     }
733 
734     /**
735      * Returns the root {@link TaskFragment}, which is usually also a {@link Task}.
736      */
737     @NonNull
getRootTaskFragment()738     TaskFragment getRootTaskFragment() {
739         final WindowContainer parent = getParent();
740         if (parent == null) return this;
741 
742         final TaskFragment parentTaskFragment = parent.asTaskFragment();
743         return parentTaskFragment == null ? this : parentTaskFragment.getRootTaskFragment();
744     }
745 
746     @Nullable
getRootTask()747     Task getRootTask() {
748         return getRootTaskFragment().asTask();
749     }
750 
751     @Override
asTaskFragment()752     TaskFragment asTaskFragment() {
753         return this;
754     }
755 
756     @Override
isEmbedded()757     boolean isEmbedded() {
758         return mIsEmbedded;
759     }
760 
761     @EmbeddingCheckResult
isAllowedToEmbedActivity(@onNull ActivityRecord a)762     int isAllowedToEmbedActivity(@NonNull ActivityRecord a) {
763         return isAllowedToEmbedActivity(a, mTaskFragmentOrganizerUid);
764     }
765 
766     /**
767      * Checks if the organized task fragment is allowed to have the specified activity, which is
768      * allowed if an activity allows embedding in untrusted mode, if the trusted mode can be
769      * enabled, or if the organized task fragment bounds are not
770      * {@link #smallerThanMinDimension(ActivityRecord)}.
771      *
772      * @param uid   uid of the TaskFragment organizer.
773      * @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord)
774      */
775     @EmbeddingCheckResult
isAllowedToEmbedActivity(@onNull ActivityRecord a, int uid)776     int isAllowedToEmbedActivity(@NonNull ActivityRecord a, int uid) {
777         if (!isAllowedToEmbedActivityInUntrustedMode(a)
778                 && !isAllowedToEmbedActivityInTrustedMode(a, uid)) {
779             return EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
780         }
781 
782         if (smallerThanMinDimension(a)) {
783             return EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION;
784         }
785 
786         return EMBEDDING_ALLOWED;
787     }
788 
smallerThanMinDimension(@onNull ActivityRecord activity)789     boolean smallerThanMinDimension(@NonNull ActivityRecord activity) {
790         final Rect taskFragBounds = getBounds();
791         final Task task = getTask();
792         // Don't need to check if the bounds match parent Task bounds because the fallback mechanism
793         // is to reparent the Activity to parent if minimum dimensions are not satisfied.
794         if (task == null || taskFragBounds.equals(task.getBounds())) {
795             return false;
796         }
797         final Point minDimensions = activity.getMinDimensions();
798         if (minDimensions == null) {
799             return false;
800         }
801         final int minWidth = minDimensions.x;
802         final int minHeight = minDimensions.y;
803         return taskFragBounds.width() < minWidth
804                 || taskFragBounds.height() < minHeight;
805     }
806 
807     /**
808      * Checks if the organized task fragment is allowed to embed activity in untrusted mode.
809      */
isAllowedToEmbedActivityInUntrustedMode(@onNull ActivityRecord a)810     boolean isAllowedToEmbedActivityInUntrustedMode(@NonNull ActivityRecord a) {
811         final WindowContainer parent = getParent();
812         if (parent == null || !parent.getBounds().contains(getBounds())) {
813             // Without full trust between the host and the embedded activity, we don't allow
814             // TaskFragment to have bounds outside of the parent bounds.
815             return false;
816         }
817         if (hasEmbedAnyAppInUntrustedModePermission(mTaskFragmentOrganizerUid)) {
818             return true;
819         }
820         return (a.info.flags & FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING)
821                 == FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING;
822     }
823 
isAllowedToEmbedActivityInTrustedMode(@onNull ActivityRecord a)824     boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a) {
825         return isAllowedToEmbedActivityInTrustedMode(a, mTaskFragmentOrganizerUid);
826     }
827 
828     /**
829      * Checks if the organized task fragment is allowed to embed activity in fully trusted mode,
830      * which means that all transactions are allowed. This is supported in the following cases:
831      * <li>the activity belongs to the same app as the organizer host;</li>
832      * <li>the activity has declared the organizer host as trusted explicitly via known
833      * certificate.</li>
834      * @param uid   uid of the TaskFragment organizer.
835      */
isAllowedToEmbedActivityInTrustedMode(@onNull ActivityRecord a, int uid)836     boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a, int uid) {
837         if (isFullyTrustedEmbedding(a, uid)) {
838             return true;
839         }
840 
841         final AndroidPackage hostPackage = mAtmService.getPackageManagerInternalLocked()
842                 .getPackage(uid);
843 
844         return hostPackage != null
845                 && isAllowedToEmbedActivityInTrustedModeByHostPackage(a, hostPackage);
846     }
847 
848     @VisibleForTesting
isAllowedToEmbedActivityInTrustedModeByHostPackage( @onNull ActivityRecord a, @NonNull AndroidPackage hostPackage)849     boolean isAllowedToEmbedActivityInTrustedModeByHostPackage(
850             @NonNull ActivityRecord a, @NonNull AndroidPackage hostPackage) {
851 
852         // Known certs declared in the <activity> tag
853         Set<String> knownActivityEmbeddingCerts = a.info.getKnownActivityEmbeddingCerts();
854 
855         // If the activity-level value is specified, it takes precedence. Otherwise, we read the
856         // application-level value.
857         if (knownActivityEmbeddingCerts.isEmpty()) {
858             // Known certs declared in the <application> tag
859             knownActivityEmbeddingCerts = a.info.applicationInfo.getKnownActivityEmbeddingCerts();
860         }
861 
862         // An application must specify a set of app certificates that are allowed to embed it in
863         // trusted mode.
864         return hostPackage.getSigningDetails().hasAncestorOrSelfWithDigest(
865                 knownActivityEmbeddingCerts);
866     }
867 
868     /**
869      * It is fully trusted for embedding in the system app or embedding in the same app. This is
870      * different from {@link #isAllowedToBeEmbeddedInTrustedMode()} since there may be a small
871      * chance for a previous trusted app to start doing something bad.
872      */
isFullyTrustedEmbedding(@onNull ActivityRecord a, int uid)873     private static boolean isFullyTrustedEmbedding(@NonNull ActivityRecord a, int uid) {
874         // The system is trusted to embed other apps securely and for all users.
875         return UserHandle.getAppId(uid) == SYSTEM_UID
876                 // Activities from the same UID can be embedded freely by the host.
877                 || a.isUid(uid)
878                 // Apps which have the signature MANAGE_ACTIVITY_TASK permission are trusted.
879                 || hasManageTaskPermission(uid);
880     }
881 
882     /**
883      * Checks if a particular app uid has the {@link MANAGE_ACTIVITY_TASKS} permission.
884      */
hasManageTaskPermission(int uid)885     private static boolean hasManageTaskPermission(int uid) {
886         return checkPermission(MANAGE_ACTIVITY_TASKS, PermissionChecker.PID_UNKNOWN, uid)
887                 == PackageManager.PERMISSION_GRANTED;
888     }
889 
890     /**
891      * Checks if a particular app uid has the {@link EMBED_ANY_APP_IN_UNTRUSTED_MODE} permission.
892      */
hasEmbedAnyAppInUntrustedModePermission(int uid)893     private static boolean hasEmbedAnyAppInUntrustedModePermission(int uid) {
894         return Flags.untrustedEmbeddingAnyAppPermission()
895                 && checkPermission(EMBED_ANY_APP_IN_UNTRUSTED_MODE,
896                 PermissionChecker.PID_UNKNOWN, uid) == PackageManager.PERMISSION_GRANTED;
897     }
898 
899     /**
900      * Checks if all activities in the task fragment are embedded as fully trusted.
901      * @see #isFullyTrustedEmbedding(ActivityRecord, int)
902      * @param uid   uid of the TaskFragment organizer.
903      */
isFullyTrustedEmbedding(int uid)904     boolean isFullyTrustedEmbedding(int uid) {
905         // Traverse all activities to see if any of them are not fully trusted embedding.
906         return !forAllActivities(r -> !isFullyTrustedEmbedding(r, uid));
907     }
908 
909     /**
910      * Checks if all activities in the task fragment are allowed to be embedded in trusted mode.
911      * @see #isAllowedToEmbedActivityInTrustedMode(ActivityRecord)
912      */
isAllowedToBeEmbeddedInTrustedMode()913     boolean isAllowedToBeEmbeddedInTrustedMode() {
914         // Traverse all activities to see if any of them are not in the trusted mode.
915         return !forAllActivities(r -> !isAllowedToEmbedActivityInTrustedMode(r));
916     }
917 
918     /**
919      * @param canAffectSystemUiFlags If false, all windows in this taskfragment can not affect
920      *                               SystemUI flags. See
921      *                               {@link WindowState#canAffectSystemUiFlags()}.
922      */
setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags)923     void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
924         mCanAffectSystemUiFlags = canAffectSystemUiFlags;
925     }
926 
927     /**
928      * @see #setCanAffectSystemUiFlags
929      */
canAffectSystemUiFlags()930     boolean canAffectSystemUiFlags() {
931         if (!mCanAffectSystemUiFlags) {
932             return false;
933         }
934         final TaskFragment parentTaskFragment =
935                 getParent() != null ? getParent().asTaskFragment() : null;
936         return parentTaskFragment == null || parentTaskFragment.canAffectSystemUiFlags();
937     }
938 
939     /**
940      * Returns the TaskFragment that is being organized, which could be this or the ascendant
941      * TaskFragment.
942      */
943     @Nullable
getOrganizedTaskFragment()944     TaskFragment getOrganizedTaskFragment() {
945         if (mTaskFragmentOrganizer != null) {
946             return this;
947         }
948 
949         TaskFragment parentTaskFragment = getParent() != null ? getParent().asTaskFragment() : null;
950         return parentTaskFragment != null ? parentTaskFragment.getOrganizedTaskFragment() : null;
951     }
952 
hasDirectChildActivities()953     boolean hasDirectChildActivities() {
954         for (int i = mChildren.size() - 1; i >= 0; --i) {
955             if (mChildren.get(i).asActivityRecord() != null) {
956                 return true;
957             }
958         }
959         return false;
960     }
961 
cleanUpActivityReferences(@onNull ActivityRecord r)962     void cleanUpActivityReferences(@NonNull ActivityRecord r) {
963         if (mPausingActivity != null && mPausingActivity == r) {
964             mPausingActivity = null;
965         }
966 
967         if (mResumedActivity != null && mResumedActivity == r) {
968             setResumedActivity(null, "cleanUpActivityReferences");
969         }
970         r.removeTimeouts();
971     }
972 
973     /**
974      * Returns whether this TaskFragment is currently forced to be hidden for any reason.
975      */
isForceHidden()976     protected boolean isForceHidden() {
977         return mForceHiddenFlags != 0;
978     }
979 
980     /**
981      * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
982      * @return Whether the force hidden state changed
983      */
setForceHidden(@lagForceHidden int flags, boolean set)984     boolean setForceHidden(@FlagForceHidden int flags, boolean set) {
985         int newFlags = mForceHiddenFlags;
986         if (set) {
987             newFlags |= flags;
988         } else {
989             newFlags &= ~flags;
990         }
991         if (mForceHiddenFlags == newFlags) {
992             return false;
993         }
994         mForceHiddenFlags = newFlags;
995         return true;
996     }
997 
isForceTranslucent()998     boolean isForceTranslucent() {
999         return mForceTranslucent;
1000     }
1001 
setForceTranslucent(boolean set)1002     boolean setForceTranslucent(boolean set) {
1003         if (mForceTranslucent == set) {
1004             return false;
1005         }
1006         mForceTranslucent = set;
1007         return true;
1008     }
1009 
isLeafTaskFragment()1010     boolean isLeafTaskFragment() {
1011         for (int i = mChildren.size() - 1; i >= 0; --i) {
1012             if (mChildren.get(i).asTaskFragment() != null) {
1013                 return false;
1014             }
1015         }
1016         return true;
1017     }
1018 
1019     /**
1020      * This should be called when an child activity changes state. This should only
1021      * be called from
1022      * {@link ActivityRecord#setState(ActivityRecord.State, String)} .
1023      * @param record The {@link ActivityRecord} whose state has changed.
1024      * @param state The new state.
1025      * @param reason The reason for the change.
1026      */
onActivityStateChanged(ActivityRecord record, ActivityRecord.State state, String reason)1027     void onActivityStateChanged(ActivityRecord record, ActivityRecord.State state,
1028             String reason) {
1029         if (record == mResumedActivity && state != RESUMED) {
1030             setResumedActivity(null, reason + " - onActivityStateChanged");
1031         }
1032 
1033         if (state == RESUMED) {
1034             if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
1035                 Slog.v(TAG, "set resumed activity to:" + record + " reason:" + reason);
1036             }
1037             setResumedActivity(record, reason + " - onActivityStateChanged");
1038             mTaskSupervisor.mRecentTasks.add(record.getTask());
1039         }
1040 
1041         // Update the process state for the organizer process if the activity is in a different
1042         // process in case the organizer process may not have activity state change in its process.
1043         final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(record);
1044         if (hostProcess != null) {
1045             mTaskSupervisor.onProcessActivityStateChanged(hostProcess, false /* forceBatch */);
1046             hostProcess.updateProcessInfo(false /* updateServiceConnectionActivities */,
1047                     true /* activityChange */, true /* updateOomAdj */,
1048                     false /* addPendingTopUid */);
1049         }
1050     }
1051 
1052     /**
1053      * Resets local parameters because an app's activity died.
1054      * @param app The app of the activity that died.
1055      * @return {@code true} if the process of the pausing activity is died.
1056      */
handleAppDied(WindowProcessController app)1057     boolean handleAppDied(WindowProcessController app) {
1058         boolean isPausingDied = false;
1059         if (mPausingActivity != null && mPausingActivity.app == app) {
1060             ProtoLog.v(WM_DEBUG_STATES, "App died while pausing: %s",
1061                     mPausingActivity);
1062             mPausingActivity = null;
1063             isPausingDied = true;
1064         }
1065         if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
1066             mLastPausedActivity = null;
1067         }
1068         return isPausingDied;
1069     }
1070 
awakeFromSleeping()1071     void awakeFromSleeping() {
1072         if (mPausingActivity != null) {
1073             Slog.d(TAG, "awakeFromSleeping: previously pausing activity didn't pause");
1074             mPausingActivity.activityPaused(true);
1075         }
1076     }
1077 
1078     /**
1079      * Tries to put the activities in the task fragment to sleep.
1080      *
1081      * If the task fragment is not in a state where its activities can be put to sleep, this
1082      * function will start any necessary actions to move the task fragment into such a state.
1083      * It is expected that this function get called again when those actions complete.
1084      *
1085      * @param shuttingDown {@code true} when the called because the device is shutting down.
1086      * @return true if the root task finished going to sleep, false if the root task only started
1087      * the process of going to sleep (checkReadyForSleep will be called when that process finishes).
1088      */
sleepIfPossible(boolean shuttingDown)1089     boolean sleepIfPossible(boolean shuttingDown) {
1090         boolean shouldSleep = true;
1091         if (mResumedActivity != null) {
1092             if (!shuttingDown && mResumedActivity.canTurnScreenOn()) {
1093                 ProtoLog.v(WM_DEBUG_STATES, "Waiting for screen on due to %s", mResumedActivity);
1094             } else {
1095                 // Still have something resumed; can't sleep until it is paused.
1096                 ProtoLog.v(WM_DEBUG_STATES, "Sleep needs to pause %s", mResumedActivity);
1097                 startPausing(true /* uiSleeping */, null /* resuming */, "sleep");
1098             }
1099             shouldSleep = false;
1100         } else if (mPausingActivity != null) {
1101             // Still waiting for something to pause; can't sleep yet.
1102             ProtoLog.v(WM_DEBUG_STATES, "Sleep still waiting to pause %s", mPausingActivity);
1103             shouldSleep = false;
1104         }
1105 
1106         if (!shuttingDown) {
1107             if (containsStoppingActivity()) {
1108                 // Still need to tell some activities to stop; can't sleep yet.
1109                 ProtoLog.v(WM_DEBUG_STATES, "Sleep still need to stop %d activities",
1110                         mTaskSupervisor.mStoppingActivities.size());
1111 
1112                 mTaskSupervisor.scheduleIdle();
1113                 shouldSleep = false;
1114             }
1115         }
1116 
1117         if (shouldSleep) {
1118             updateActivityVisibilities(null /* starting */, true /* notifyClients */);
1119         }
1120 
1121         return shouldSleep;
1122     }
1123 
containsStoppingActivity()1124     private boolean containsStoppingActivity() {
1125         for (int i = mTaskSupervisor.mStoppingActivities.size() - 1; i >= 0; --i) {
1126             ActivityRecord r = mTaskSupervisor.mStoppingActivities.get(i);
1127             if (r.getTaskFragment() == this) {
1128                 return true;
1129             }
1130         }
1131         return false;
1132     }
1133 
1134     /**
1135      * Returns true if the TaskFragment is translucent and can have other contents visible behind
1136      * it if needed. A TaskFragment is considered translucent if it don't contain a visible or
1137      * starting (about to be visible) activity that is fullscreen (opaque).
1138      * @param starting The currently starting activity or null if there is none.
1139      */
isTranslucent(@ullable ActivityRecord starting)1140     boolean isTranslucent(@Nullable ActivityRecord starting) {
1141         if (!isAttached() || isForceHidden() || isForceTranslucent()) {
1142             return true;
1143         }
1144         return !mTaskSupervisor.mOpaqueContainerHelper.isOpaque(
1145                 this, starting, true /* ignoringKeyguard */, true /* ignoringInvisibleActivity */);
1146     }
1147 
1148     /**
1149      * Whether the TaskFragment should be treated as translucent for the current transition.
1150      * This is different from {@link #isTranslucent(ActivityRecord)} as this function also checks
1151      * finishing activities when the TaskFragment itself is becoming invisible.
1152      */
isTranslucentForTransition()1153     boolean isTranslucentForTransition() {
1154         if (!isAttached() || isForceHidden() || isForceTranslucent()) {
1155             return true;
1156         }
1157         // Including finishing Activity if the TaskFragment is becoming invisible in the transition.
1158         return !mTaskSupervisor.mOpaqueContainerHelper.isOpaque(this);
1159     }
1160 
1161     /**
1162      * Like {@link  #isTranslucent(ActivityRecord)} but evaluating the actual visibility of the
1163      * windows rather than their visibility ignoring keyguard.
1164      */
isTranslucentAndVisible()1165     boolean isTranslucentAndVisible() {
1166         if (!isAttached() || isForceHidden() || isForceTranslucent()) {
1167             return true;
1168         }
1169         return !mTaskSupervisor.mOpaqueContainerHelper.isOpaque(this, /* starting */ null,
1170                 false /* ignoringKeyguard */, true /* ignoringInvisibleActivity */);
1171     }
1172 
1173     @Override
getTopNonFinishingActivity()1174     ActivityRecord getTopNonFinishingActivity() {
1175         return getTopNonFinishingActivity(
1176                 true /* includeOverlays */, true /* includeLaunchedFromBubble */);
1177     }
1178 
1179     /**
1180      * Returns the top-most non-finishing activity, even if the activity is NOT ok to show to
1181      * the current user.
1182      * @param includeOverlays whether the task overlay activity should be included.
1183      * @param includeLaunchedFromBubble whether activities that were launched from a bubble should
1184      *                                  be included.
1185      * @see #topRunningActivity(boolean)
1186      */
getTopNonFinishingActivity(boolean includeOverlays, boolean includeLaunchedFromBubble)1187     ActivityRecord getTopNonFinishingActivity(boolean includeOverlays,
1188             boolean includeLaunchedFromBubble) {
1189         // Split to avoid object creation due to variable capture.
1190         if (includeOverlays) {
1191             if (includeLaunchedFromBubble) {
1192                 return getActivity(r -> !r.finishing);
1193             } else {
1194                 return getActivity(r -> !r.finishing && !r.getLaunchedFromBubble());
1195             }
1196         }
1197         if (includeLaunchedFromBubble) {
1198             return getActivity(r -> !r.finishing && !r.isTaskOverlay());
1199         } else {
1200             return getActivity(
1201                     r -> !r.finishing && !r.isTaskOverlay() && !r.getLaunchedFromBubble());
1202         }
1203     }
1204 
topRunningActivity()1205     ActivityRecord topRunningActivity() {
1206         return topRunningActivity(false /* focusableOnly */);
1207     }
1208 
1209     /**
1210      * Returns the top-most running activity, which the activity is non-finishing and ok to show
1211      * to the current user.
1212      *
1213      * @see ActivityRecord#canBeTopRunning()
1214      */
topRunningActivity(boolean focusableOnly)1215     ActivityRecord topRunningActivity(boolean focusableOnly) {
1216         // Split into 2 to avoid object creation due to variable capture.
1217         if (focusableOnly) {
1218             return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
1219         }
1220         return getActivity(ActivityRecord::canBeTopRunning);
1221     }
1222 
1223     /**
1224      * Reports non-finishing activity count including this TaskFragment's child embedded
1225      * TaskFragments' children activities.
1226      */
getNonFinishingActivityCount()1227     int getNonFinishingActivityCount() {
1228         final int[] runningActivityCount = new int[1];
1229         forAllActivities(a -> {
1230             if (!a.finishing) {
1231                 runningActivityCount[0]++;
1232             }
1233         });
1234         return runningActivityCount[0];
1235     }
1236 
1237     /**
1238      * Returns {@code true} if there's any non-finishing direct children activity, which is not
1239      * embedded in TaskFragments
1240      */
hasNonFinishingDirectActivity()1241     boolean hasNonFinishingDirectActivity() {
1242         for (int i = getChildCount() - 1; i >= 0; --i) {
1243             final ActivityRecord activity = getChildAt(i).asActivityRecord();
1244             if (activity != null && !activity.finishing) {
1245                 return true;
1246             }
1247         }
1248         return false;
1249     }
1250 
isTopActivityFocusable()1251     boolean isTopActivityFocusable() {
1252         final ActivityRecord r = topRunningActivity();
1253         return r != null ? r.isFocusable()
1254                 : (isFocusable() && getWindowConfiguration().canReceiveKeys());
1255     }
1256 
1257     /**
1258      * Returns the visibility state of this TaskFragment.
1259      *
1260      * @param starting The currently starting activity or null if there is none.
1261      */
1262     @TaskFragmentVisibility
getVisibility(ActivityRecord starting)1263     int getVisibility(ActivityRecord starting) {
1264         if (!isAttached() || isForceHidden()) {
1265             return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
1266         }
1267 
1268         if (isTopActivityLaunchedBehind()) {
1269             return TASK_FRAGMENT_VISIBILITY_VISIBLE;
1270         }
1271         final WindowContainer<?> parent = getParent();
1272         final Task thisTask = asTask();
1273         if (thisTask != null && parent.asTask() == null
1274                 && mTransitionController.isTransientVisible(thisTask)) {
1275             // Keep transient-hide root tasks visible. Non-root tasks still follow standard rule.
1276             return TASK_FRAGMENT_VISIBILITY_VISIBLE;
1277         }
1278 
1279         boolean gotTranslucentFullscreen = false;
1280         boolean gotTranslucentAdjacent = false;
1281         boolean shouldBeVisible = true;
1282 
1283         // This TaskFragment is only considered visible if all its parent TaskFragments are
1284         // considered visible, so check the visibility of all ancestor TaskFragment first.
1285         if (parent.asTaskFragment() != null) {
1286             final int parentVisibility = parent.asTaskFragment().getVisibility(starting);
1287             if (parentVisibility == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
1288                 // Can't be visible if parent isn't visible
1289                 return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
1290             } else if (parentVisibility == TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT) {
1291                 // Parent is behind a translucent container so the highest visibility this container
1292                 // can get is that.
1293                 gotTranslucentFullscreen = true;
1294             }
1295         }
1296 
1297         final List<TaskFragment> adjacentTaskFragments = new ArrayList<>();
1298         for (int i = parent.getChildCount() - 1; i >= 0; --i) {
1299             final WindowContainer other = parent.getChildAt(i);
1300             if (other == null) continue;
1301 
1302             final boolean hasRunningActivities = hasRunningActivity(other);
1303             if (other == this) {
1304                 if (!adjacentTaskFragments.isEmpty() && !gotTranslucentAdjacent) {
1305                     // The z-order of this TaskFragment is in middle of two adjacent TaskFragments
1306                     // and it cannot be visible if the TaskFragment on top is not translucent and
1307                     // is occluding this one.
1308                     mTmpRect.set(getBounds());
1309                     for (int j = adjacentTaskFragments.size() - 1; j >= 0; --j) {
1310                         final TaskFragment taskFragment = adjacentTaskFragments.get(j);
1311                         if (taskFragment.isAdjacentTo(this)) {
1312                             continue;
1313                         }
1314                         final boolean isOccluding = mTmpRect.intersect(taskFragment.getBounds())
1315                                 || taskFragment.forOtherAdjacentTaskFragments(adjacentTf -> {
1316                                     return mTmpRect.intersect(adjacentTf.getBounds());
1317                                 });
1318                         if (isOccluding) {
1319                             return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
1320                         }
1321                     }
1322                 }
1323                 // Should be visible if there is no other fragment occluding it, unless it doesn't
1324                 // have any running activities, not starting one and not home stack.
1325                 shouldBeVisible = hasRunningActivities
1326                         || (starting != null && starting.isDescendantOf(this))
1327                         || (isActivityTypeHome() && !isEmbedded());
1328                 break;
1329             }
1330 
1331             if (!hasRunningActivities) {
1332                 continue;
1333             }
1334 
1335             final int otherWindowingMode = other.getWindowingMode();
1336             if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN
1337                     || (otherWindowingMode != WINDOWING_MODE_PINNED && other.matchParentBounds())) {
1338                 if (isTranslucent(other, starting)) {
1339                     // Can be visible behind a translucent TaskFragment.
1340                     gotTranslucentFullscreen = true;
1341                     continue;
1342                 }
1343                 return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
1344             }
1345 
1346             final TaskFragment otherTaskFrag = other.asTaskFragment();
1347             if (otherTaskFrag != null && otherTaskFrag.hasAdjacentTaskFragment()) {
1348                 // For adjacent TaskFragments, we have assumptions that:
1349                 // 1. A set of adjacent TaskFragments always cover the entire Task window, so that
1350                 // if this TaskFragment is behind a set of opaque TaskFragments, then this
1351                 // TaskFragment is invisible.
1352                 // 2. Adjacent TaskFragments do not overlap, so that if this TaskFragment is behind
1353                 // any translucent TaskFragment in the adjacent set, then this TaskFragment is
1354                 // visible behind translucent.
1355                 final boolean hasTraversedAdj = otherTaskFrag.forOtherAdjacentTaskFragments(
1356                         adjacentTaskFragments::contains);
1357                 if (hasTraversedAdj) {
1358                     final boolean isTranslucent =
1359                             isBehindTransparentTaskFragment(otherTaskFrag, starting)
1360                                     || otherTaskFrag.forOtherAdjacentTaskFragments(
1361                                     (Predicate<TaskFragment>) tf ->
1362                                             isBehindTransparentTaskFragment(tf, starting));
1363                     if (isTranslucent) {
1364                         // Can be visible behind a translucent adjacent TaskFragments.
1365                         gotTranslucentFullscreen = true;
1366                         gotTranslucentAdjacent = true;
1367                         continue;
1368                     }
1369                     // Can not be visible behind adjacent TaskFragments.
1370                     return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
1371                 }
1372                 adjacentTaskFragments.add(otherTaskFrag);
1373             }
1374         }
1375 
1376         if (!shouldBeVisible) {
1377             return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
1378         }
1379 
1380         // Lastly - check if there is a translucent fullscreen TaskFragment on top.
1381         return gotTranslucentFullscreen
1382                 ? TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
1383                 : TASK_FRAGMENT_VISIBILITY_VISIBLE;
1384     }
1385 
isBehindTransparentTaskFragment( @onNull TaskFragment otherTf, @Nullable ActivityRecord starting)1386     private boolean isBehindTransparentTaskFragment(
1387             @NonNull TaskFragment otherTf, @Nullable ActivityRecord starting) {
1388         return otherTf.isTranslucent(starting) && getBounds().intersect(otherTf.getBounds());
1389     }
1390 
hasRunningActivity(WindowContainer wc)1391     private static boolean hasRunningActivity(WindowContainer wc) {
1392         if (wc.asTaskFragment() != null) {
1393             return wc.asTaskFragment().topRunningActivity() != null;
1394         }
1395         return wc.asActivityRecord() != null && !wc.asActivityRecord().finishing;
1396     }
1397 
isTranslucent(WindowContainer wc, ActivityRecord starting)1398     private static boolean isTranslucent(WindowContainer wc, ActivityRecord starting) {
1399         if (wc.asTaskFragment() != null) {
1400             return wc.asTaskFragment().isTranslucent(starting);
1401         } else if (wc.asActivityRecord() != null) {
1402             return !wc.asActivityRecord().occludesParent();
1403         }
1404         return false;
1405     }
1406 
1407 
isTopActivityLaunchedBehind()1408     private boolean isTopActivityLaunchedBehind() {
1409         final ActivityRecord top = topRunningActivity();
1410         return top != null && top.mLaunchTaskBehind;
1411     }
1412 
updateActivityVisibilities(@ullable ActivityRecord starting, boolean notifyClients)1413     final void updateActivityVisibilities(@Nullable ActivityRecord starting,
1414             boolean notifyClients) {
1415         mTaskSupervisor.beginActivityVisibilityUpdate();
1416         try {
1417             mEnsureActivitiesVisibleHelper.process(starting, notifyClients);
1418         } finally {
1419             mTaskSupervisor.endActivityVisibilityUpdate();
1420         }
1421     }
1422 
resumeTopActivity(ActivityRecord prev, ActivityOptions options, boolean skipPause)1423     final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
1424             boolean skipPause) {
1425         ActivityRecord next = topRunningActivity(true /* focusableOnly */);
1426         if (next == null || !next.canResumeByCompat()) {
1427             return false;
1428         }
1429 
1430         next.delayedResume = false;
1431 
1432         if (!skipPause && !mRootWindowContainer.allPausedActivitiesComplete()) {
1433             // If we aren't skipping pause, then we have to wait for currently pausing activities.
1434             ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: some activity pausing.");
1435             return false;
1436         }
1437 
1438         final TaskDisplayArea taskDisplayArea = getDisplayArea();
1439         // If the top activity is the resumed one, nothing to do.
1440         if (mResumedActivity == next && next.isState(RESUMED)
1441                 && taskDisplayArea.allResumedActivitiesComplete()) {
1442             // Ensure the visibility gets updated before execute app transition.
1443             taskDisplayArea.ensureActivitiesVisible(null /* starting */, true /* notifyClients */);
1444             // Make sure we have executed any pending transitions, since there
1445             // should be nothing left to do at this point.
1446             executeAppTransition(options);
1447 
1448             // In a multi-resumed environment, like in a freeform device, the top
1449             // activity can be resumed, but it might not be the focused app.
1450             // Set focused app when top activity is resumed. However, we shouldn't do it for a
1451             // same task because it can break focused state. (e.g. activity embedding)
1452             if (taskDisplayArea.inMultiWindowMode() && taskDisplayArea.mDisplayContent != null) {
1453                 final ActivityRecord focusedApp = taskDisplayArea.mDisplayContent.mFocusedApp;
1454                 if (focusedApp == null || focusedApp.getTask() != next.getTask()) {
1455                     taskDisplayArea.mDisplayContent.setFocusedApp(next);
1456                 }
1457             }
1458             ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity "
1459                     + "resumed %s", next);
1460             return false;
1461         }
1462 
1463         // If we are sleeping, and there is no resumed activity, and the top activity is paused,
1464         // well that is the state we want.
1465         if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
1466             // Make sure we have executed any pending transitions, since there
1467             // should be nothing left to do at this point.
1468             executeAppTransition(options);
1469             ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Going to sleep and"
1470                     + " all paused");
1471             return false;
1472         }
1473 
1474         // Make sure that the user who owns this activity is started.  If not,
1475         // we will just leave it as is because someone should be bringing
1476         // another user's activities to the top of the stack.
1477         if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {
1478             Slog.w(TAG, "Skipping resume of top activity " + next
1479                     + ": user " + next.mUserId + " is stopped");
1480             return false;
1481         }
1482 
1483         // The activity may be waiting for stop, but that is no longer
1484         // appropriate for it.
1485         mTaskSupervisor.mStoppingActivities.remove(next);
1486 
1487         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
1488 
1489         mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);
1490 
1491         ActivityRecord lastResumed = null;
1492         final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();
1493         if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTaskFragment().asTask()) {
1494             // So, why aren't we using prev here??? See the param comment on the method. prev
1495             // doesn't represent the last resumed activity. However, the last focus stack does if
1496             // it isn't null.
1497             lastResumed = lastFocusedRootTask.getTopResumedActivity();
1498         }
1499 
1500         boolean pausing = !skipPause && taskDisplayArea.pauseBackTasks(next);
1501         if (mResumedActivity != null) {
1502             ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s", mResumedActivity);
1503             pausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,
1504                     next, "resumeTopActivity");
1505         }
1506         if (pausing) {
1507             ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"
1508                     + " start pausing");
1509             // At this point we want to put the upcoming activity's process
1510             // at the top of the LRU list, since we know we will be needing it
1511             // very soon and it would be a waste to let it get killed if it
1512             // happens to be sitting towards the end.
1513             if (next.attachedToProcess()) {
1514                 next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
1515                         true /* activityChange */, false /* updateOomAdj */,
1516                         false /* addPendingTopUid */);
1517             } else if (!next.isProcessRunning()) {
1518                 // Since the start-process is asynchronous, if we already know the process of next
1519                 // activity isn't running, we can start the process earlier to save the time to wait
1520                 // for the current activity to be paused.
1521                 final boolean isTop = this == taskDisplayArea.getFocusedRootTask();
1522                 mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,
1523                         isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY
1524                                 : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);
1525             }
1526             if (lastResumed != null) {
1527                 lastResumed.setWillCloseOrEnterPip(true);
1528             }
1529             return true;
1530         } else if (mResumedActivity == next && next.isState(RESUMED)
1531                 && taskDisplayArea.allResumedActivitiesComplete()) {
1532             // It is possible for the activity to be resumed when we paused back stacks above if the
1533             // next activity doesn't have to wait for pause to complete.
1534             // So, nothing else to-do except:
1535             // Make sure we have executed any pending transitions, since there
1536             // should be nothing left to do at this point.
1537             executeAppTransition(options);
1538             ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity resumed "
1539                     + "(dontWaitForPause) %s", next);
1540             return true;
1541         }
1542 
1543         // If the most recent activity was noHistory but was only stopped rather
1544         // than stopped+finished because the device went to sleep, we need to make
1545         // sure to finish it as we're making a new activity topmost.
1546         if (shouldSleepActivities()) {
1547             mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next);
1548         }
1549 
1550         if (prev != null && prev != next && next.nowVisible) {
1551             // The next activity is already visible, so hide the previous
1552             // activity's windows right now so we can show the new one ASAP.
1553             // We only do this if the previous is finishing, which should mean
1554             // it is on top of the one being resumed so hiding it quickly
1555             // is good.  Otherwise, we want to do the normal route of allowing
1556             // the resumed activity to be shown so we can decide if the
1557             // previous should actually be hidden depending on whether the
1558             // new one is found to be full-screen or not.
1559             if (prev.finishing) {
1560                 prev.setVisibility(false);
1561                 if (DEBUG_SWITCH) {
1562                     Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev
1563                             + ", nowVisible=" + next.nowVisible);
1564                 }
1565             } else {
1566                 if (DEBUG_SWITCH) {
1567                     Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev
1568                             + ", nowVisible=" + next.nowVisible);
1569                 }
1570             }
1571         }
1572 
1573         try {
1574             mTaskSupervisor.getActivityMetricsLogger()
1575                     .notifyBeforePackageUnstopped(next.packageName);
1576             mAtmService.getPackageManagerInternalLocked().notifyComponentUsed(
1577                     next.packageName, next.mUserId,
1578                     next.packageName, next.toString()); /* TODO: Verify if correct userid */
1579         } catch (IllegalArgumentException e) {
1580             Slog.w(TAG, "Failed trying to unstop package "
1581                     + next.packageName + ": " + e);
1582         }
1583 
1584         // We are starting up the next activity, so tell the window manager
1585         // that the previous one will be hidden soon.  This way it can know
1586         // to ignore it when computing the desired screen orientation.
1587         boolean anim = true;
1588         final DisplayContent dc = taskDisplayArea.mDisplayContent;
1589         if (prev != null) {
1590             if (prev.finishing) {
1591                 if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {
1592                     anim = false;
1593                 }
1594                 prev.setVisibility(false);
1595             } else if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
1596                 anim = false;
1597             }
1598         } else if (mTaskSupervisor.mNoAnimActivities.contains(next)) {
1599             anim = false;
1600         }
1601 
1602         if (anim) {
1603             next.applyOptionsAnimation();
1604         } else {
1605             next.abortAndClearOptionsAnimation();
1606         }
1607 
1608         mTaskSupervisor.mNoAnimActivities.clear();
1609 
1610         if (next.attachedToProcess()) {
1611             if (DEBUG_SWITCH) {
1612                 Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.mAppStopped
1613                         + " visibleRequested=" + next.isVisibleRequested());
1614             }
1615 
1616             // If the previous activity is translucent, force a visibility update of
1617             // the next activity, so that it's added to WM's opening app list, and
1618             // transition animation can be set up properly.
1619             // For example, pressing Home button with a translucent activity in focus.
1620             // Launcher is already visible in this case. If we don't add it to opening
1621             // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
1622             // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
1623             final boolean lastActivityTranslucent = inMultiWindowMode()
1624                     || mLastPausedActivity != null && !mLastPausedActivity.occludesParent();
1625 
1626             // This activity is now becoming visible.
1627             if (!next.isVisibleRequested() || next.mAppStopped || lastActivityTranslucent) {
1628                 next.app.addToPendingTop();
1629                 next.setVisibility(true);
1630             }
1631 
1632             ActivityRecord lastResumedActivity =
1633                     lastFocusedRootTask == null ? null
1634                             : lastFocusedRootTask.getTopResumedActivity();
1635             final ActivityRecord.State lastState = next.getState();
1636 
1637             mAtmService.updateCpuStats();
1638 
1639             ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);
1640 
1641             next.setState(RESUMED, "resumeTopActivity");
1642 
1643             // Activity should also be visible if set mLaunchTaskBehind to true (see
1644             // ActivityRecord#shouldBeVisibleIgnoringKeyguard()).
1645             if (shouldBeVisible(next)) {
1646                 // We have special rotation behavior when here is some active activity that
1647                 // requests specific orientation or Keyguard is locked. Make sure all activity
1648                 // visibilities are set correctly as well as the transition is updated if needed
1649                 // to get the correct rotation behavior. Otherwise the following call to update
1650                 // the orientation may cause incorrect configurations delivered to client as a
1651                 // result of invisible window resize.
1652                 // TODO: Remove this once visibilities are set correctly immediately when
1653                 // starting an activity.
1654                 final int originalRelaunchingCount = next.mPendingRelaunchCount;
1655                 mRootWindowContainer.ensureVisibilityAndConfig(next, mDisplayContent,
1656                         false /* deferResume */);
1657                 if (next.mPendingRelaunchCount > originalRelaunchingCount) {
1658                     // The activity is scheduled to relaunch, then ResumeActivityItem will be also
1659                     // included (see ActivityRecord#relaunchActivityLocked) if it should resume.
1660                     next.completeResumeLocked();
1661                     return true;
1662                 }
1663             }
1664 
1665             final IApplicationThread appThread = next.app.getThread();
1666             // Deliver all pending results.
1667             final ArrayList<ResultInfo> a = next.results;
1668             if (a != null) {
1669                 final int size = a.size();
1670                 if (!next.finishing && size > 0) {
1671                     if (DEBUG_RESULTS) {
1672                         Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);
1673                     }
1674                     final ActivityResultItem item = new ActivityResultItem(next.token, a);
1675                     boolean isSuccessful;
1676                     try {
1677                         isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
1678                                 appThread, item);
1679                     } catch (RemoteException e) {
1680                         // TODO(b/323801078): remove Exception when cleanup
1681                         isSuccessful = false;
1682                     }
1683                     if (!isSuccessful) {
1684                         onResumeTopActivityRemoteFailure(lastState, next, lastResumedActivity,
1685                                 lastFocusedRootTask);
1686                         return true;
1687                     }
1688                 }
1689             }
1690 
1691             if (next.newIntents != null) {
1692                 final NewIntentItem item =
1693                         new NewIntentItem(next.token, next.newIntents, true /* resume */);
1694                 boolean isSuccessful;
1695                 try {
1696                     isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
1697                             appThread, item);
1698                 } catch (RemoteException e) {
1699                     // TODO(b/323801078): remove Exception when cleanup
1700                     isSuccessful = false;
1701                 }
1702                 if (!isSuccessful) {
1703                     onResumeTopActivityRemoteFailure(lastState, next, lastResumedActivity,
1704                             lastFocusedRootTask);
1705                     return true;
1706                 }
1707             }
1708 
1709             // Well the app will no longer be stopped.
1710             // Clear app token stopped state in window manager if needed.
1711             next.notifyAppResumed();
1712 
1713             EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
1714                     next.getTask().mTaskId, next.shortComponentName);
1715 
1716             mAtmService.getAppWarningsLocked().onResumeActivity(next);
1717             final int topProcessState = mAtmService.mTopProcessState;
1718             next.app.setPendingUiCleanAndForceProcessStateUpTo(topProcessState);
1719             next.abortAndClearOptionsAnimation();
1720             final ResumeActivityItem resumeActivityItem = new ResumeActivityItem(
1721                     next.token, topProcessState, dc.isNextTransitionForward(),
1722                     next.shouldSendCompatFakeFocus());
1723             boolean isSuccessful;
1724             try {
1725                 isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
1726                         appThread, resumeActivityItem);
1727             } catch (RemoteException e) {
1728                 // TODO(b/323801078): remove Exception when cleanup
1729                 isSuccessful = false;
1730             }
1731             if (!isSuccessful) {
1732                 onResumeTopActivityRemoteFailure(lastState, next, lastResumedActivity,
1733                         lastFocusedRootTask);
1734                 return true;
1735             }
1736 
1737             ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);
1738 
1739             next.completeResumeLocked();
1740         } else {
1741             // Whoops, need to restart this activity!
1742             if (!next.hasBeenLaunched) {
1743                 next.hasBeenLaunched = true;
1744             } else {
1745                 if (SHOW_APP_STARTING_PREVIEW) {
1746                     next.showStartingWindow(false /* taskSwich */);
1747                 }
1748                 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
1749             }
1750             ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);
1751             mTaskSupervisor.startSpecificActivity(next, true, true);
1752         }
1753 
1754         return true;
1755     }
1756 
1757     /** Likely app process has been killed. Needs to restart this activity. */
onResumeTopActivityRemoteFailure(@onNull ActivityRecord.State lastState, @NonNull ActivityRecord next, @Nullable ActivityRecord lastResumedActivity, @Nullable Task lastFocusedRootTask)1758     private void onResumeTopActivityRemoteFailure(@NonNull ActivityRecord.State lastState,
1759             @NonNull ActivityRecord next, @Nullable ActivityRecord lastResumedActivity,
1760             @Nullable Task lastFocusedRootTask) {
1761         ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "
1762                 + "%s", lastState, next);
1763         next.setState(lastState, "resumeTopActivityInnerLocked");
1764 
1765         // lastResumedActivity being non-null implies there is a lastStack present.
1766         if (lastResumedActivity != null) {
1767             lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
1768         }
1769 
1770         Slog.i(TAG, "Restarting because process died: " + next);
1771         if (!next.hasBeenLaunched) {
1772             next.hasBeenLaunched = true;
1773         } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null
1774                 && lastFocusedRootTask.isTopRootTaskInDisplayArea()) {
1775             next.showStartingWindow(false /* taskSwitch */);
1776         }
1777         mTaskSupervisor.startSpecificActivity(next, true, false);
1778     }
1779 
shouldSleepOrShutDownActivities()1780     boolean shouldSleepOrShutDownActivities() {
1781         return shouldSleepActivities() || mAtmService.mShuttingDown;
1782     }
1783 
1784     /**
1785      * Returns true if the TaskFragment should be visible.
1786      *
1787      * @param starting The currently starting activity or null if there is none.
1788      */
shouldBeVisible(ActivityRecord starting)1789     boolean shouldBeVisible(ActivityRecord starting) {
1790         return getVisibility(starting) != TASK_FRAGMENT_VISIBILITY_INVISIBLE;
1791     }
1792 
1793     /**
1794      * Returns {@code true} is the activity in this TaskFragment can be resumed.
1795      *
1796      * @param starting The currently starting activity or {@code null} if there is none.
1797      */
canBeResumed(@ullable ActivityRecord starting)1798     boolean canBeResumed(@Nullable ActivityRecord starting) {
1799         // No need to resume activity in TaskFragment that is not visible.
1800         return isTopActivityFocusable()
1801                 && getVisibility(starting) == TASK_FRAGMENT_VISIBILITY_VISIBLE;
1802     }
1803 
isFocusableAndVisible()1804     boolean isFocusableAndVisible() {
1805         return isTopActivityFocusable() && shouldBeVisible(null /* starting */);
1806     }
1807 
startPausing(boolean uiSleeping, ActivityRecord resuming, String reason)1808     final boolean startPausing(boolean uiSleeping, ActivityRecord resuming, String reason) {
1809         return startPausing(mTaskSupervisor.mUserLeaving, uiSleeping, resuming, reason);
1810     }
1811 
1812     /**
1813      * Start pausing the currently resumed activity.  It is an error to call this if there
1814      * is already an activity being paused or there is no resumed activity.
1815      *
1816      * @param userLeaving True if this should result in an onUserLeaving to the current activity.
1817      * @param uiSleeping True if this is happening with the user interface going to sleep (the
1818      * screen turning off).
1819      * @param resuming The activity we are currently trying to resume or null if this is not being
1820      *                 called as part of resuming the top activity, so we shouldn't try to instigate
1821      *                 a resume here if not null.
1822      * @param reason The reason of pausing the activity.
1823      * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
1824      * it to tell us when it is done.
1825      */
startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, String reason)1826     boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
1827             String reason) {
1828         if (!hasDirectChildActivities()) {
1829             return false;
1830         }
1831         if (mResumedActivity != null && !mResumedActivity.finishing
1832                 && mTransitionController.isTransientLaunch(mResumedActivity)) {
1833             // Even if the transient activity is occluded, defer pausing (addToStopping will still
1834             // be called) it until the transient transition is done. So the current resuming
1835             // activity won't need to wait for additional pause complete.
1836             ProtoLog.d(WM_DEBUG_STATES, "startPausing: Skipping pause for transient "
1837                             + "resumed activity=%s", mResumedActivity);
1838             return false;
1839         }
1840 
1841         ProtoLog.d(WM_DEBUG_STATES, "startPausing: taskFrag=%s mResumedActivity=%s", this,
1842                 mResumedActivity);
1843 
1844         if (mPausingActivity != null) {
1845             Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
1846                     + " state=" + mPausingActivity.getState());
1847             if (!shouldSleepActivities()) {
1848                 // Avoid recursion among check for sleep and complete pause during sleeping.
1849                 // Because activity will be paused immediately after resume, just let pause
1850                 // be completed by the order of activity paused from clients.
1851                 completePause(false, resuming);
1852             }
1853         }
1854         ActivityRecord prev = mResumedActivity;
1855 
1856         if (prev == null) {
1857             if (resuming == null) {
1858                 Slog.wtf(TAG, "Trying to pause when nothing is resumed");
1859                 mRootWindowContainer.resumeFocusedTasksTopActivities();
1860             }
1861             return false;
1862         }
1863 
1864         if (prev == resuming) {
1865             Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
1866             return false;
1867         }
1868 
1869         ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
1870         mPausingActivity = prev;
1871         mLastPausedActivity = prev;
1872         if (!prev.finishing && prev.isNoHistory()
1873                 && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
1874             mTaskSupervisor.mNoHistoryActivities.add(prev);
1875         }
1876         prev.setState(PAUSING, "startPausingLocked");
1877         prev.getTask().touchActiveTime();
1878 
1879         mAtmService.updateCpuStats();
1880 
1881         boolean pauseImmediately = false;
1882         boolean shouldAutoPip = false;
1883         if (resuming != null) {
1884             // We do not want to trigger auto-PiP upon launch of a translucent activity.
1885             final boolean resumingOccludesParent = resuming.occludesParent();
1886 
1887             if (ActivityTaskManagerService.isPip2ExperimentEnabled()) {
1888                 // If a new task is being launched, then mark the existing top activity as
1889                 // supporting picture-in-picture while pausing only if the starting activity
1890                 // would not be considered an overlay on top of the current activity
1891                 // (eg. not fullscreen, or the assistant)
1892                 Task.enableEnterPipOnTaskSwitch(prev, resuming.getTask(),
1893                         resuming, resuming.getOptions());
1894             }
1895 
1896             // Resuming the new resume activity only if the previous activity can't go into Pip
1897             // since we want to give Pip activities a chance to enter Pip before resuming the
1898             // next activity.
1899             final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
1900                     "shouldAutoPipWhilePausing", userLeaving);
1901             if (prev.supportsEnterPipOnTaskSwitch && userLeaving
1902                     && resumingOccludesParent && lastResumedCanPip
1903                     && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
1904                 shouldAutoPip = true;
1905             } else if (!lastResumedCanPip) {
1906                 // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
1907                 // activity to be paused.
1908                 pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
1909             } else {
1910                 // The previous activity may still enter PIP even though it did not allow auto-PIP.
1911             }
1912         }
1913 
1914         if (prev.attachedToProcess()) {
1915             if (shouldAutoPip && ActivityTaskManagerService.isPip2ExperimentEnabled()) {
1916                 prev.mPauseSchedulePendingForPip = true;
1917                 boolean willAutoPip = mAtmService.prepareAutoEnterPictureAndPictureMode(prev);
1918                 ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, requesting PIP mode "
1919                         + "via requestStartTransition(): %s, willAutoPip: %b", prev, willAutoPip);
1920             } else if (shouldAutoPip) {
1921                 prev.mPauseSchedulePendingForPip = true;
1922                 boolean didAutoPip = mAtmService.enterPictureInPictureMode(
1923                         prev, prev.pictureInPictureArgs, false /* fromClient */);
1924                 ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
1925                         + "directly: %s, didAutoPip: %b", prev, didAutoPip);
1926             } else {
1927                 schedulePauseActivity(prev, userLeaving, pauseImmediately,
1928                         false /* autoEnteringPip */, reason);
1929             }
1930         } else {
1931             mPausingActivity = null;
1932             mLastPausedActivity = null;
1933             mTaskSupervisor.mNoHistoryActivities.remove(prev);
1934         }
1935 
1936         // If we are not going to sleep, we want to ensure the device is
1937         // awake until the next activity is started.
1938         if (!uiSleeping && !mAtmService.isSleepingOrShuttingDownLocked()) {
1939             mTaskSupervisor.acquireLaunchWakelock();
1940         }
1941 
1942         // If already entered PIP mode, no need to keep pausing.
1943         if (mPausingActivity != null) {
1944             // Have the window manager pause its key dispatching until the new
1945             // activity has started.  If we're pausing the activity just because
1946             // the screen is being turned off and the UI is sleeping, don't interrupt
1947             // key dispatch; the same activity will pick it up again on wakeup.
1948             if (!uiSleeping) {
1949                 prev.pauseKeyDispatchingLocked();
1950             } else {
1951                 ProtoLog.v(WM_DEBUG_STATES, "Key dispatch not paused for screen off");
1952             }
1953 
1954             if (pauseImmediately) {
1955                 // If the caller said they don't want to wait for the pause, then complete
1956                 // the pause now.
1957                 completePause(false, resuming);
1958                 return false;
1959 
1960             } else {
1961                 prev.schedulePauseTimeout();
1962                 // All activities will be stopped when sleeping, don't need to wait for pause.
1963                 if (!uiSleeping) {
1964                     // Unset readiness since we now need to wait until this pause is complete.
1965                     mTransitionController.setReady(this, false /* ready */);
1966                 }
1967                 return true;
1968             }
1969 
1970         } else {
1971             // This activity either failed to schedule the pause or it entered PIP mode,
1972             // so just treat it as being paused now.
1973             ProtoLog.v(WM_DEBUG_STATES, "Activity not running or entered PiP, resuming next.");
1974             if (resuming == null) {
1975                 mRootWindowContainer.resumeFocusedTasksTopActivities();
1976             }
1977             return false;
1978         }
1979     }
1980 
schedulePauseActivity(ActivityRecord prev, boolean userLeaving, boolean pauseImmediately, boolean autoEnteringPip, String reason)1981     void schedulePauseActivity(ActivityRecord prev, boolean userLeaving,
1982             boolean pauseImmediately, boolean autoEnteringPip, String reason) {
1983         ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
1984         prev.mPauseSchedulePendingForPip = false;
1985         EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
1986                 prev.shortComponentName, "userLeaving=" + userLeaving, reason);
1987 
1988         final PauseActivityItem item = new PauseActivityItem(prev.token, prev.finishing,
1989                 userLeaving, pauseImmediately, autoEnteringPip);
1990         boolean isSuccessful;
1991         try {
1992             isSuccessful = mAtmService.getLifecycleManager().scheduleTransactionItem(
1993                     prev.app.getThread(), item);
1994         } catch (RemoteException e) {
1995             // TODO(b/323801078): remove Exception when cleanup
1996             // Ignore exception, if process died other code will cleanup.
1997             Slog.w(TAG, "Exception thrown during pause", e);
1998             isSuccessful = false;
1999         }
2000         if (!isSuccessful) {
2001             mPausingActivity = null;
2002             mLastPausedActivity = null;
2003             mTaskSupervisor.mNoHistoryActivities.remove(prev);
2004         }
2005     }
2006 
2007     @VisibleForTesting
completePause(boolean resumeNext, ActivityRecord resuming)2008     void completePause(boolean resumeNext, ActivityRecord resuming) {
2009         // Complete the pausing process of a pausing activity, so it doesn't make sense to
2010         // operate on non-leaf tasks.
2011         // warnForNonLeafTask("completePauseLocked");
2012 
2013         ActivityRecord prev = mPausingActivity;
2014         ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);
2015 
2016         if (prev != null) {
2017             prev.setWillCloseOrEnterPip(false);
2018             prev.supportsEnterPipOnTaskSwitch = false;
2019             final boolean wasStopping = prev.isState(STOPPING);
2020             prev.setState(PAUSED, "completePausedLocked");
2021             mPausingActivity = null;
2022             if (prev.finishing) {
2023                 // We will update the activity visibility later, no need to do in
2024                 // completeFinishing(). Updating visibility here might also making the next
2025                 // activities to be resumed, and could result in wrong app transition due to
2026                 // lack of previous activity information.
2027                 ProtoLog.v(WM_DEBUG_STATES, "Executing finish of activity: %s", prev);
2028                 prev = prev.completeFinishing(false /* updateVisibility */,
2029                         "completePausedLocked");
2030             } else if (prev.attachedToProcess()) {
2031                 ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
2032                                 + "wasStopping=%b visibleRequested=%b",  prev,  wasStopping,
2033                         prev.isVisibleRequested());
2034                 if (wasStopping) {
2035                     // We are also stopping, the stop request must have gone soon after the pause.
2036                     // We can't clobber it, because the stop confirmation will not be handled.
2037                     // We don't need to schedule another stop, we only need to let it happen.
2038                     prev.setState(STOPPING, "completePausedLocked");
2039                 } else if (!prev.isVisibleRequested() || shouldSleepOrShutDownActivities()) {
2040                     // Clear out any deferred client hide we might currently have.
2041                     prev.clearDeferHidingClient();
2042                     // If we were visible then resumeTopActivities will release resources before
2043                     // stopping.
2044                     prev.addToStopping(true /* scheduleIdle */, false /* idleDelayed */,
2045                             "completePauseLocked");
2046                 }
2047             } else {
2048                 ProtoLog.v(WM_DEBUG_STATES, "App died during pause, not stopping: %s", prev);
2049                 prev = null;
2050             }
2051         }
2052 
2053         if (resumeNext) {
2054             final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
2055             if (topRootTask != null && !topRootTask.shouldSleepOrShutDownActivities()) {
2056                 mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev);
2057             } else {
2058                 // checkReadyForSleep();
2059                 final ActivityRecord top =
2060                         topRootTask != null ? topRootTask.topRunningActivity() : null;
2061                 if (top == null || (prev != null && top != prev)) {
2062                     // If there are no more activities available to run, do resume anyway to start
2063                     // something. Also if the top activity on the root task is not the just paused
2064                     // activity, we need to go ahead and resume it to ensure we complete an
2065                     // in-flight app switch.
2066                     mRootWindowContainer.resumeFocusedTasksTopActivities();
2067                 }
2068             }
2069         }
2070 
2071         if (prev != null) {
2072             prev.resumeKeyDispatchingLocked();
2073         }
2074 
2075         mRootWindowContainer.ensureActivitiesVisible(resuming);
2076 
2077         // Notify when the task stack has changed, but only if visibilities changed (not just
2078         // focus). Also if there is an active root pinned task - we always want to notify it about
2079         // task stack changes, because its positioning may depend on it.
2080         if (mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause
2081                 || (getDisplayArea() != null && getDisplayArea().hasPinnedTask())) {
2082             mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
2083             mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
2084         }
2085     }
2086 
2087     @ActivityInfo.ScreenOrientation
2088     @Override
getOrientation(@ctivityInfo.ScreenOrientation int candidate)2089     int getOrientation(@ActivityInfo.ScreenOrientation int candidate) {
2090         if (shouldReportOrientationUnspecified()) {
2091             return SCREEN_ORIENTATION_UNSPECIFIED;
2092         }
2093         if (canSpecifyOrientation()) {
2094             return super.getOrientation(candidate);
2095         }
2096         return SCREEN_ORIENTATION_UNSET;
2097     }
2098 
2099     @ActivityInfo.ScreenOrientation
2100     @Override
getOverrideOrientation()2101     protected int getOverrideOrientation() {
2102         if (isEmbedded() && !isVisibleRequested()) {
2103             return SCREEN_ORIENTATION_UNSPECIFIED;
2104         }
2105         return super.getOverrideOrientation();
2106     }
2107 
2108     /**
2109      * Whether or not to allow this container to specify an app requested orientation.
2110      *
2111      * This is different from {@link #providesOrientation()} that
2112      * 1. The container may still provide an orientation even if it can't specify the app requested
2113      *    one, such as {@link #shouldReportOrientationUnspecified()}
2114      * 2. Even if the container can specify an app requested orientation, it may not be used by the
2115      *    parent container if it is {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
2116      */
canSpecifyOrientation()2117     boolean canSpecifyOrientation() {
2118         final int windowingMode = getWindowingMode();
2119         final int activityType = getActivityType();
2120         return windowingMode == WINDOWING_MODE_FULLSCREEN
2121                 || activityType == ACTIVITY_TYPE_HOME
2122                 || activityType == ACTIVITY_TYPE_RECENTS
2123                 || activityType == ACTIVITY_TYPE_ASSISTANT;
2124     }
2125 
2126     /**
2127      * Whether or not the parent container should use the orientation provided by this container
2128      * even if it is {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
2129      */
2130     @Override
providesOrientation()2131     boolean providesOrientation() {
2132         return super.providesOrientation() || shouldReportOrientationUnspecified();
2133     }
2134 
shouldReportOrientationUnspecified()2135     private boolean shouldReportOrientationUnspecified() {
2136         // Apps and their containers are not allowed to specify orientation from adjacent
2137         // TaskFragment.
2138         return hasAdjacentTaskFragment() && isVisibleRequested();
2139     }
2140 
2141     @Override
forAllTaskFragments(Consumer<TaskFragment> callback, boolean traverseTopToBottom)2142     void forAllTaskFragments(Consumer<TaskFragment> callback, boolean traverseTopToBottom) {
2143         super.forAllTaskFragments(callback, traverseTopToBottom);
2144         callback.accept(this);
2145     }
2146 
2147     @Override
forAllLeafTaskFragments(Consumer<TaskFragment> callback, boolean traverseTopToBottom)2148     void forAllLeafTaskFragments(Consumer<TaskFragment> callback, boolean traverseTopToBottom) {
2149         final int count = mChildren.size();
2150         boolean isLeafTaskFrag = true;
2151         if (traverseTopToBottom) {
2152             for (int i = count - 1; i >= 0; --i) {
2153                 final TaskFragment child = mChildren.get(i).asTaskFragment();
2154                 if (child != null) {
2155                     isLeafTaskFrag = false;
2156                     child.forAllLeafTaskFragments(callback, traverseTopToBottom);
2157                 }
2158             }
2159         } else {
2160             for (int i = 0; i < count; i++) {
2161                 final TaskFragment child = mChildren.get(i).asTaskFragment();
2162                 if (child != null) {
2163                     isLeafTaskFrag = false;
2164                     child.forAllLeafTaskFragments(callback, traverseTopToBottom);
2165                 }
2166             }
2167         }
2168         if (isLeafTaskFrag) callback.accept(this);
2169     }
2170 
2171     @Override
forAllLeafTaskFragments(Predicate<TaskFragment> callback)2172     boolean forAllLeafTaskFragments(Predicate<TaskFragment> callback) {
2173         boolean isLeafTaskFrag = true;
2174         for (int i = mChildren.size() - 1; i >= 0; --i) {
2175             final TaskFragment child = mChildren.get(i).asTaskFragment();
2176             if (child != null) {
2177                 isLeafTaskFrag = false;
2178                 if (child.forAllLeafTaskFragments(callback)) {
2179                     return true;
2180                 }
2181             }
2182         }
2183         if (isLeafTaskFrag) {
2184             return callback.test(this);
2185         }
2186         return false;
2187     }
2188 
addChild(ActivityRecord r)2189     void addChild(ActivityRecord r) {
2190         addChild(r, POSITION_TOP);
2191     }
2192 
2193     @Override
addChild(WindowContainer child, int index)2194     void addChild(WindowContainer child, int index) {
2195         ActivityRecord r = topRunningActivity();
2196         mClearedTaskForReuse = false;
2197         mClearedTaskFragmentForPip = false;
2198         mClearedForReorderActivityToFront = false;
2199 
2200         final ActivityRecord addingActivity = child.asActivityRecord();
2201         final boolean isAddingActivity = addingActivity != null;
2202         final Task task = isAddingActivity ? getTask() : null;
2203 
2204         // If this task had any activity before we added this one.
2205         boolean taskHadActivity = task != null && task.getTopMostActivity() != null;
2206         // getActivityType() looks at the top child, so we need to read the type before adding
2207         // a new child in case the new child is on top and UNDEFINED.
2208         final int activityType = task != null ? task.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
2209 
2210         super.addChild(child, index);
2211 
2212         if (isAddingActivity && task != null) {
2213             addingActivity.inHistory = true;
2214             task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
2215         }
2216 
2217         final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(addingActivity);
2218         if (hostProcess != null) {
2219             hostProcess.addEmbeddedActivity(addingActivity);
2220         }
2221     }
2222 
2223     @Override
onChildPositionChanged(WindowContainer child)2224     void onChildPositionChanged(WindowContainer child) {
2225         super.onChildPositionChanged(child);
2226 
2227         sendTaskFragmentInfoChanged();
2228     }
2229 
executeAppTransition(ActivityOptions options)2230     void executeAppTransition(ActivityOptions options) {
2231         mDisplayContent.executeAppTransition();
2232         ActivityOptions.abort(options);
2233     }
2234 
2235     @Override
canCreateRemoteAnimationTarget()2236     boolean canCreateRemoteAnimationTarget() {
2237         return true;
2238     }
2239 
shouldSleepActivities()2240     boolean shouldSleepActivities() {
2241         final DisplayContent dc = mDisplayContent;
2242         if (dc == null) {
2243             return mAtmService.isSleepingLocked();
2244         }
2245         if (!dc.isSleeping()) {
2246             return false;
2247         }
2248         // In case the unlocking order is keyguard-going-away -> screen-turning-on (display is
2249         // sleeping by screen-off-token which may be notified to release from power manager's
2250         // thread), keep the activities resume-able to avoid extra activity lifecycle when
2251         // performing keyguard-going-away. This only applies to default display because currently
2252         // the per-display keyguard-going-away state is assigned from a global signal.
2253         if (!dc.isDefaultDisplay || !dc.isKeyguardGoingAway()) {
2254             return true;
2255         }
2256         return !shouldBeVisible(null /* starting */);
2257     }
2258 
2259     @Override
resolveOverrideConfiguration(Configuration newParentConfig)2260     void resolveOverrideConfiguration(Configuration newParentConfig) {
2261         mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
2262         super.resolveOverrideConfiguration(newParentConfig);
2263         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
2264 
2265         if (mRelativeEmbeddedBounds != null && !mRelativeEmbeddedBounds.isEmpty()) {
2266             // For embedded TaskFragment, make sure the bounds is set based on the relative bounds.
2267             resolvedConfig.windowConfiguration.setBounds(translateRelativeBoundsToAbsoluteBounds(
2268                     mRelativeEmbeddedBounds, newParentConfig.windowConfiguration.getBounds()));
2269         }
2270         int windowingMode = resolvedConfig.windowConfiguration.getWindowingMode();
2271         final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2272 
2273         // Resolve override windowing mode to fullscreen for home task (even on freeform
2274         // display), or split-screen if in split-screen mode.
2275         if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
2276             windowingMode = WINDOWING_MODE_FULLSCREEN;
2277             resolvedConfig.windowConfiguration.setWindowingMode(windowingMode);
2278         }
2279 
2280         // Do not allow tasks not support multi window to be in a multi-window mode, unless it is in
2281         // pinned windowing mode.
2282         if (!supportsMultiWindow()) {
2283             final int candidateWindowingMode =
2284                     windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : parentWindowingMode;
2285             if (WindowConfiguration.inMultiWindowMode(candidateWindowingMode)
2286                     && candidateWindowingMode != WINDOWING_MODE_PINNED) {
2287                 resolvedConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
2288             }
2289         }
2290 
2291         final Task thisTask = asTask();
2292         if (thisTask != null) {
2293             thisTask.resolveLeafTaskOnlyOverrideConfigs(newParentConfig,
2294                     mTmpBounds /* previousBounds */);
2295         }
2296         computeConfigResourceOverrides(resolvedConfig, newParentConfig);
2297     }
2298 
supportsMultiWindow()2299     boolean supportsMultiWindow() {
2300         return supportsMultiWindowInDisplayArea(getDisplayArea());
2301     }
2302 
2303     /**
2304      * @return whether this task supports multi-window if it is in the given
2305      *         {@link TaskDisplayArea}.
2306      */
supportsMultiWindowInDisplayArea(@ullable TaskDisplayArea tda)2307     boolean supportsMultiWindowInDisplayArea(@Nullable TaskDisplayArea tda) {
2308         if (!mAtmService.mSupportsMultiWindow) {
2309             return false;
2310         }
2311         if (tda == null) {
2312             return false;
2313         }
2314         final Task task = getTask();
2315         if (task == null) {
2316             return false;
2317         }
2318         if (!task.isResizeable() && !tda.supportsNonResizableMultiWindow()) {
2319             // Not support non-resizable in multi window.
2320             return false;
2321         }
2322 
2323         final ActivityRecord rootActivity = task.getRootActivity();
2324         return tda.supportsActivityMinWidthHeightMultiWindow(mMinWidth, mMinHeight,
2325                 rootActivity != null ? rootActivity.info : null);
2326     }
2327 
getTaskId()2328     private int getTaskId() {
2329         return getTask() != null ? getTask().mTaskId : INVALID_TASK_ID;
2330     }
2331 
2332     static class ConfigOverrideHint {
2333         @Nullable DisplayInfo mTmpOverrideDisplayInfo;
2334         @Nullable AppCompatDisplayInsets mTmpCompatInsets;
2335         @Nullable Rect mParentAppBoundsOverride;
2336         @Nullable Rect mParentBoundsOverride;
2337         int mTmpOverrideConfigOrientation;
2338         boolean mUseOverrideInsetsForConfig;
2339 
resolveTmpOverrides(DisplayContent dc, Configuration parentConfig, boolean isFixedRotationTransforming, @Nullable Rect safeRegionBounds)2340         void resolveTmpOverrides(DisplayContent dc, Configuration parentConfig,
2341                 boolean isFixedRotationTransforming, @Nullable Rect safeRegionBounds) {
2342             mParentAppBoundsOverride = safeRegionBounds != null ? safeRegionBounds : new Rect(
2343                     parentConfig.windowConfiguration.getAppBounds());
2344             mParentBoundsOverride = safeRegionBounds != null ? safeRegionBounds : new Rect(
2345                     parentConfig.windowConfiguration.getBounds());
2346             mTmpOverrideConfigOrientation = parentConfig.orientation;
2347             Insets insets = Insets.NONE;
2348             if (safeRegionBounds != null) {
2349                 // Modify orientation based on the parent app bounds if safe region bounds are set.
2350                 mTmpOverrideConfigOrientation =
2351                         mParentAppBoundsOverride.height() >= mParentAppBoundsOverride.width()
2352                                 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
2353             } else if (mUseOverrideInsetsForConfig && dc != null
2354                     && !isFloating(parentConfig.windowConfiguration.getWindowingMode())) {
2355                 // Insets are decoupled from configuration by default from V+, use legacy
2356                 // compatibility behaviour for apps targeting SDK earlier than 35
2357                 // (see applySizeOverrideIfNeeded).
2358                 int rotation = parentConfig.windowConfiguration.getRotation();
2359                 if (rotation == ROTATION_UNDEFINED && !isFixedRotationTransforming) {
2360                     rotation = dc.getRotation();
2361                 }
2362                 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
2363                 final int dw = rotated ? dc.mBaseDisplayHeight : dc.mBaseDisplayWidth;
2364                 final int dh = rotated ? dc.mBaseDisplayWidth : dc.mBaseDisplayHeight;
2365                 DisplayPolicy.DecorInsets.Info decorInsets = dc.getDisplayPolicy()
2366                         .getDecorInsetsInfo(rotation, dw, dh);
2367                 final Rect stableBounds = decorInsets.mOverrideConfigFrame;
2368                 mTmpOverrideConfigOrientation = stableBounds.width() > stableBounds.height()
2369                         ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
2370                 insets = Insets.of(decorInsets.mOverrideNonDecorInsets);
2371             }
2372             mParentAppBoundsOverride.inset(insets);
2373         }
2374 
resetTmpOverrides()2375         void resetTmpOverrides() {
2376             mTmpOverrideDisplayInfo = null;
2377             mTmpCompatInsets = null;
2378             mTmpOverrideConfigOrientation = ORIENTATION_UNDEFINED;
2379         }
2380     }
2381 
computeConfigResourceOverrides(@onNull Configuration inOutConfig, @NonNull Configuration parentConfig)2382     void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2383             @NonNull Configuration parentConfig) {
2384         computeConfigResourceOverrides(inOutConfig, parentConfig, null /* configOverrideHint */);
2385     }
2386 
2387     /**
2388      * Forces the app bounds related configuration can be computed by
2389      * {@link #computeConfigResourceOverrides(Configuration, Configuration, ConfigOverrideHint)}.
2390      */
invalidateAppBoundsConfig(@onNull Configuration inOutConfig)2391     private static void invalidateAppBoundsConfig(@NonNull Configuration inOutConfig) {
2392         final Rect appBounds = inOutConfig.windowConfiguration.getAppBounds();
2393         if (appBounds != null) {
2394             appBounds.setEmpty();
2395         }
2396         inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
2397         inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
2398     }
2399 
2400     /**
2401      * Calculates configuration values used by the client to get resources. This should be run
2402      * using app-facing bounds (bounds unmodified by animations or transient interactions).
2403      *
2404      * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2405      * configuring an "inherit-bounds" window which means that all configuration settings would
2406      * just be inherited from the parent configuration.
2407      **/
computeConfigResourceOverrides(@onNull Configuration inOutConfig, @NonNull Configuration parentConfig, @Nullable ConfigOverrideHint overrideHint)2408     void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2409             @NonNull Configuration parentConfig, @Nullable ConfigOverrideHint overrideHint) {
2410         DisplayInfo overrideDisplayInfo = null;
2411         AppCompatDisplayInsets compatInsets = null;
2412         boolean useOverrideInsetsForConfig = false;
2413         if (overrideHint != null) {
2414             overrideDisplayInfo = overrideHint.mTmpOverrideDisplayInfo;
2415             compatInsets = overrideHint.mTmpCompatInsets;
2416             useOverrideInsetsForConfig = overrideHint.mUseOverrideInsetsForConfig;
2417             if (overrideDisplayInfo != null) {
2418                 // Make sure the screen related configs can be computed by the provided
2419                 // display info.
2420                 inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
2421             }
2422             if (overrideDisplayInfo != null || compatInsets != null) {
2423                 // Make sure the app bounds can be computed by the compat insets.
2424                 invalidateAppBoundsConfig(inOutConfig);
2425             }
2426         }
2427         int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2428         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2429             windowingMode = parentConfig.windowConfiguration.getWindowingMode();
2430         }
2431 
2432         float density = inOutConfig.densityDpi;
2433         if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2434             density = parentConfig.densityDpi;
2435         }
2436         density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
2437 
2438         // The bounds may have been overridden at this level. If the parent cannot cover these
2439         // bounds, the configuration is still computed according to the override bounds.
2440         final boolean insideParentBounds;
2441 
2442         final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
2443         final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
2444         if (resolvedBounds.isEmpty()) {
2445             mTmpFullBounds.set(parentBounds);
2446             insideParentBounds = true;
2447         } else {
2448             mTmpFullBounds.set(resolvedBounds);
2449             insideParentBounds = parentBounds.contains(resolvedBounds);
2450         }
2451 
2452         // Non-null compatibility insets means the activity prefers to keep its original size, so
2453         // out bounds doesn't need to be restricted by the parent or current display
2454         final boolean customContainerPolicy = compatInsets != null;
2455 
2456         Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2457         if (outAppBounds == null || outAppBounds.isEmpty()) {
2458             // App-bounds hasn't been overridden, so calculate a value for it.
2459             inOutConfig.windowConfiguration.setAppBounds(mTmpFullBounds);
2460             outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2461 
2462             // Floating tasks shouldn't be restricted by containing app bounds.
2463             if (!customContainerPolicy && !isFloating(windowingMode)) {
2464                 final Rect containingAppBounds;
2465                 if (insideParentBounds) {
2466                     containingAppBounds = useOverrideInsetsForConfig
2467                             ? overrideHint.mParentAppBoundsOverride
2468                             : parentConfig.windowConfiguration.getAppBounds();
2469                 } else {
2470                     // Restrict appBounds to display non-decor rather than parent because the
2471                     // override bounds are beyond the parent. Otherwise, it won't match the
2472                     // overridden bounds.
2473                     final TaskDisplayArea displayArea = getDisplayArea();
2474                     containingAppBounds = displayArea != null
2475                             ? displayArea.getWindowConfiguration().getAppBounds() : null;
2476                 }
2477                 if (containingAppBounds != null && !containingAppBounds.isEmpty()) {
2478                     outAppBounds.intersect(containingAppBounds);
2479                 }
2480             }
2481         }
2482 
2483         if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2484                 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2485             if (!customContainerPolicy && WindowConfiguration.isFloating(windowingMode)) {
2486                 mTmpNonDecorBounds.set(mTmpFullBounds);
2487                 mTmpStableBounds.set(mTmpFullBounds);
2488             } else if (!customContainerPolicy
2489                     && (overrideDisplayInfo != null || getDisplayContent() != null)) {
2490                 final DisplayInfo di = overrideDisplayInfo != null
2491                         ? overrideDisplayInfo
2492                         : getDisplayContent().getDisplayInfo();
2493 
2494                 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2495                 // area, i.e. the screen area without the system bars.
2496                 // The non decor inset are areas that could never be removed in Honeycomb. See
2497                 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
2498                 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di,
2499                         useOverrideInsetsForConfig);
2500             } else {
2501                 // Apply the given non-decor and stable insets to calculate the corresponding bounds
2502                 // for screen size of configuration.
2503                 int rotation = inOutConfig.windowConfiguration.getRotation();
2504                 if (rotation == ROTATION_UNDEFINED) {
2505                     rotation = parentConfig.windowConfiguration.getRotation();
2506                 }
2507                 if (rotation != ROTATION_UNDEFINED && customContainerPolicy) {
2508                     mTmpNonDecorBounds.set(mTmpFullBounds);
2509                     mTmpStableBounds.set(mTmpFullBounds);
2510                     compatInsets.getBoundsByRotation(mTmpBounds, rotation);
2511                     intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
2512                             compatInsets.mNonDecorInsets[rotation]);
2513                     intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
2514                             compatInsets.mStableInsets[rotation]);
2515                     outAppBounds.set(mTmpNonDecorBounds);
2516                 } else {
2517                     // Set to app bounds because it excludes decor insets.
2518                     mTmpNonDecorBounds.set(outAppBounds);
2519                     mTmpStableBounds.set(outAppBounds);
2520                 }
2521             }
2522 
2523             if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2524                 final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density + 0.5f);
2525                 inOutConfig.screenWidthDp = (insideParentBounds && !customContainerPolicy)
2526                         ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
2527                         : overrideScreenWidthDp;
2528             }
2529             if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2530                 final int overrideScreenHeightDp =
2531                         (int) (mTmpStableBounds.height() / density + 0.5f);
2532                 inOutConfig.screenHeightDp = (insideParentBounds && !customContainerPolicy)
2533                         ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
2534                         : overrideScreenHeightDp;
2535             }
2536 
2537             // TODO(b/238331848): Consider simplifying logic that computes smallestScreenWidthDp.
2538             if (inOutConfig.smallestScreenWidthDp
2539                     == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2540                 // When entering to or exiting from Pip, the PipTaskOrganizer will set the
2541                 // windowing mode of the activity in the task to WINDOWING_MODE_FULLSCREEN and
2542                 // temporarily set the bounds of the task to fullscreen size for transitioning.
2543                 // It will get the wrong value if the calculation is based on this temporary
2544                 // fullscreen bounds.
2545                 // We should just inherit the value from parent for this temporary state.
2546                 final boolean inPipTransition = windowingMode == WINDOWING_MODE_PINNED
2547                         && !mTmpFullBounds.isEmpty() && mTmpFullBounds.equals(parentBounds);
2548                 if (WindowConfiguration.isFloating(windowingMode) && !inPipTransition) {
2549                     // For floating tasks, calculate the smallest width from the bounds of the
2550                     // task, because they should not be affected by insets.
2551                     inOutConfig.smallestScreenWidthDp = (int) (0.5f
2552                             + Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
2553                 } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW && mIsEmbedded
2554                         && !resolvedBounds.equals(parentBounds)) {
2555                     // For embedded TFs, the smallest width should be updated. Otherwise, inherit
2556                     // from the parent task would result in applications loaded wrong resource.
2557                     inOutConfig.smallestScreenWidthDp =
2558                             Math.min(inOutConfig.screenWidthDp, inOutConfig.screenHeightDp);
2559                 }
2560                 // otherwise, it will just inherit
2561             }
2562         }
2563 
2564         if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
2565             inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
2566                     ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
2567         }
2568         if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2569             // For calculating screen layout, we need to use the non-decor inset screen area for the
2570             // calculation for compatibility reasons, i.e. screen area without system bars that
2571             // could never go away in Honeycomb.
2572             int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density + 0.5f);
2573             int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density + 0.5f);
2574             // Use overrides if provided. If both overrides are provided, mTmpNonDecorBounds is
2575             // undefined so it can't be used.
2576             if (inOutConfig.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2577                 compatScreenWidthDp = inOutConfig.screenWidthDp;
2578             }
2579             if (inOutConfig.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2580                 compatScreenHeightDp = inOutConfig.screenHeightDp;
2581             }
2582             // Reducing the screen layout starting from its parent config.
2583             inOutConfig.screenLayout = computeScreenLayout(parentConfig.screenLayout,
2584                     compatScreenWidthDp, compatScreenHeightDp);
2585         }
2586     }
2587 
2588     /**
2589      * Gets bounds with non-decor and stable insets applied respectively.
2590      *
2591      * If bounds overhangs the display, those edges will not get insets. See
2592      * {@link #intersectWithInsetsIfFits}
2593      *
2594      * @param outNonDecorBounds where to place bounds with non-decor insets applied.
2595      * @param outStableBounds where to place bounds with stable insets applied.
2596      * @param bounds the bounds to inset.
2597      * @param useLegacyInsetsForStableBounds {@code true} if we need to use the legacy insets frame
2598      *                for apps targeting U or before when calculating stable bounds.
2599      */
calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds, DisplayInfo displayInfo, boolean useLegacyInsetsForStableBounds)2600     void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
2601             DisplayInfo displayInfo, boolean useLegacyInsetsForStableBounds) {
2602         outNonDecorBounds.set(bounds);
2603         outStableBounds.set(bounds);
2604         if (mDisplayContent == null) {
2605             return;
2606         }
2607         mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
2608 
2609         final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
2610         final DisplayPolicy.DecorInsets.Info info = policy.getDecorInsetsInfo(
2611                 displayInfo.rotation, displayInfo.logicalWidth, displayInfo.logicalHeight);
2612         if (!useLegacyInsetsForStableBounds) {
2613             intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mConfigInsets);
2614             intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, info.mNonDecorInsets);
2615         } else {
2616             intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mOverrideConfigInsets);
2617             intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, info.mOverrideNonDecorInsets);
2618         }
2619     }
2620 
2621     /**
2622      * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
2623      * intersectBounds on a side, then the respective side will not be intersected.
2624      *
2625      * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
2626      * inset on that side is no-longer applicable. This scenario happens when a task's minimal
2627      * bounds are larger than the provided parent/display bounds.
2628      *
2629      * @param inOutBounds the bounds to intersect.
2630      * @param intersectBounds the bounds to intersect with.
2631      * @param intersectInsets insets to apply to intersectBounds before intersecting.
2632      */
intersectWithInsetsIfFits( Rect inOutBounds, Rect intersectBounds, Rect intersectInsets)2633     static void intersectWithInsetsIfFits(
2634             Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
2635         if (inOutBounds.right <= intersectBounds.right) {
2636             inOutBounds.right =
2637                     Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
2638         }
2639         if (inOutBounds.bottom <= intersectBounds.bottom) {
2640             inOutBounds.bottom =
2641                     Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
2642         }
2643         if (inOutBounds.left >= intersectBounds.left) {
2644             inOutBounds.left =
2645                     Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
2646         }
2647         if (inOutBounds.top >= intersectBounds.top) {
2648             inOutBounds.top =
2649                     Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
2650         }
2651     }
2652 
2653     @Override
getActivityType()2654     public int getActivityType() {
2655         final int applicationType = super.getActivityType();
2656         if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
2657             return applicationType;
2658         }
2659         final ActivityRecord activity = getTopMostActivity();
2660         return activity != null ? activity.getActivityType() : getTopChild().getActivityType();
2661     }
2662 
2663     @Override
onConfigurationChanged(Configuration newParentConfig)2664     public void onConfigurationChanged(Configuration newParentConfig) {
2665         super.onConfigurationChanged(newParentConfig);
2666         updateOrganizedTaskFragmentSurface();
2667         sendTaskFragmentInfoChanged();
2668     }
2669 
deferOrganizedTaskFragmentSurfaceUpdate()2670     void deferOrganizedTaskFragmentSurfaceUpdate() {
2671         mDelayOrganizedTaskFragmentSurfaceUpdate = true;
2672     }
2673 
continueOrganizedTaskFragmentSurfaceUpdate()2674     void continueOrganizedTaskFragmentSurfaceUpdate() {
2675         mDelayOrganizedTaskFragmentSurfaceUpdate = false;
2676         updateOrganizedTaskFragmentSurface();
2677     }
2678 
2679     /**
2680      * TaskFragmentOrganizer doesn't have access to the surface for security reasons, so we need to
2681      * update its surface on the server side if it is not collected for Shell or in pending
2682      * animation.
2683      */
updateOrganizedTaskFragmentSurface()2684     void updateOrganizedTaskFragmentSurface() {
2685         if (mDelayOrganizedTaskFragmentSurfaceUpdate || mTaskFragmentOrganizer == null) {
2686             return;
2687         }
2688         if (mTransitionController.isShellTransitionsEnabled()
2689                 && !mTransitionController.isCollecting(this)) {
2690             // TaskFragmentOrganizer doesn't have access to the surface for security reasons, so
2691             // update the surface here if it is not collected by Shell transition.
2692             updateOrganizedTaskFragmentSurfaceUnchecked();
2693         } else if (!mTransitionController.isShellTransitionsEnabled() && !isAnimating()) {
2694             // Update the surface here instead of in the organizer so that we can make sure
2695             // it can be synced with the surface freezer for legacy app transition.
2696             updateOrganizedTaskFragmentSurfaceUnchecked();
2697         }
2698     }
2699 
updateOrganizedTaskFragmentSurfaceUnchecked()2700     private void updateOrganizedTaskFragmentSurfaceUnchecked() {
2701         final SurfaceControl.Transaction t = getSyncTransaction();
2702         updateSurfacePosition(t);
2703         updateOrganizedTaskFragmentSurfaceSize(t, false /* forceUpdate */);
2704     }
2705 
2706     /** Updates the surface size so that the sub windows cannot be shown out of bounds. */
updateOrganizedTaskFragmentSurfaceSize(SurfaceControl.Transaction t, boolean forceUpdate)2707     private void updateOrganizedTaskFragmentSurfaceSize(SurfaceControl.Transaction t,
2708             boolean forceUpdate) {
2709         if (mTaskFragmentOrganizer == null) {
2710             // We only want to update for organized TaskFragment. Task will handle itself.
2711             return;
2712         }
2713         if (mSurfaceControl == null || mSurfaceAnimator.hasLeash()) {
2714             return;
2715         }
2716 
2717         // If this TaskFragment is closing while resizing, crop to the starting bounds instead.
2718         final Rect bounds = getBounds();
2719         final int width = bounds.width();
2720         final int height = bounds.height();
2721         if (!forceUpdate && width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
2722             return;
2723         }
2724         if (fillsParent()) {
2725             // Rely on parent's crop.
2726             t.setCrop(mSurfaceControl, null);
2727         } else {
2728             t.setWindowCrop(mSurfaceControl, width, height);
2729         }
2730         mLastSurfaceSize.set(width, height);
2731     }
2732 
2733     @Override
onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash)2734     public void onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash) {
2735         super.onAnimationLeashCreated(t, leash);
2736         // Reset surface bounds for animation. It will be taken care by the animation leash, and
2737         // reset again onAnimationLeashLost.
2738         if (mTaskFragmentOrganizer != null
2739                 && (mLastSurfaceSize.x != 0 || mLastSurfaceSize.y != 0)) {
2740             t.setWindowCrop(mSurfaceControl, 0, 0);
2741             final SurfaceControl.Transaction syncTransaction = getSyncTransaction();
2742             if (t != syncTransaction) {
2743                 // Avoid restoring to old window crop if the sync transaction is applied later.
2744                 syncTransaction.setWindowCrop(mSurfaceControl, 0, 0);
2745             }
2746             mLastSurfaceSize.set(0, 0);
2747         }
2748     }
2749 
2750     @Override
onAnimationLeashLost(SurfaceControl.Transaction t)2751     public void onAnimationLeashLost(SurfaceControl.Transaction t) {
2752         super.onAnimationLeashLost(t);
2753         // Update the surface bounds after animation.
2754         if (mTaskFragmentOrganizer != null) {
2755             updateOrganizedTaskFragmentSurfaceSize(t, true /* forceUpdate */);
2756         }
2757     }
2758 
2759     /**
2760      * Gets the relative bounds of this embedded TaskFragment. This should only be called on
2761      * embedded TaskFragment.
2762      */
2763     @NonNull
getRelativeEmbeddedBounds()2764     Rect getRelativeEmbeddedBounds() {
2765         if (mRelativeEmbeddedBounds == null) {
2766             throw new IllegalStateException("The TaskFragment is not embedded");
2767         }
2768         return mRelativeEmbeddedBounds;
2769     }
2770 
2771     /**
2772      * Translates the given relative bounds to screen space based on the given parent bounds.
2773      * When the relative bounds is outside of the parent bounds, it will be adjusted to fit the Task
2774      * bounds.
2775      */
translateRelativeBoundsToAbsoluteBounds(@onNull Rect relativeBounds, @NonNull Rect parentBounds)2776     Rect translateRelativeBoundsToAbsoluteBounds(@NonNull Rect relativeBounds,
2777             @NonNull Rect parentBounds) {
2778         if (relativeBounds.isEmpty()) {
2779             mTmpAbsBounds.setEmpty();
2780             return mTmpAbsBounds;
2781         }
2782         // Translate the relative bounds to absolute bounds.
2783         mTmpAbsBounds.set(relativeBounds);
2784         mTmpAbsBounds.offset(parentBounds.left, parentBounds.top);
2785 
2786         if (!isAllowedToBeEmbeddedInTrustedMode() && !parentBounds.contains(mTmpAbsBounds)) {
2787             // For untrusted embedding, we want to make sure the embedded bounds will never go
2788             // outside of the Task bounds.
2789             // We expect the organizer to update the bounds after receiving the Task bounds changed,
2790             // so skip trusted embedding to avoid unnecessary configuration change before organizer
2791             // requests a new bounds.
2792             // When the requested TaskFragment bounds is outside of Task bounds, try use the
2793             // intersection.
2794             // This can happen when the Task resized before the TaskFragmentOrganizer request.
2795             if (!mTmpAbsBounds.intersect(parentBounds)) {
2796                 // Use empty bounds to fill Task if there is no intersection.
2797                 mTmpAbsBounds.setEmpty();
2798             }
2799         }
2800         return mTmpAbsBounds;
2801     }
2802 
recomputeConfiguration()2803     void recomputeConfiguration() {
2804         onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
2805     }
2806 
2807     /**
2808      * Sets the relative bounds in parent coordinate for this embedded TaskFragment.
2809      * This will not override the requested bounds, and the actual bounds will be calculated in
2810      * {@link #resolveOverrideConfiguration}, so that it makes sure to record and use the relative
2811      * bounds that is set by the organizer until the organizer requests a new relative bounds.
2812      */
setRelativeEmbeddedBounds(@onNull Rect relativeEmbeddedBounds)2813     void setRelativeEmbeddedBounds(@NonNull Rect relativeEmbeddedBounds) {
2814         if (mRelativeEmbeddedBounds == null) {
2815             throw new IllegalStateException("The TaskFragment is not embedded");
2816         }
2817         if (mRelativeEmbeddedBounds.equals(relativeEmbeddedBounds)) {
2818             return;
2819         }
2820         mRelativeEmbeddedBounds.set(relativeEmbeddedBounds);
2821     }
2822 
2823     /**
2824      * Updates the record of relative bounds of this embedded TaskFragment, and checks whether we
2825      * should prepare a transition for the bounds change.
2826      */
shouldStartChangeTransition(@onNull Rect absStartBounds, @NonNull Rect relStartBounds)2827     boolean shouldStartChangeTransition(@NonNull Rect absStartBounds,
2828             @NonNull Rect relStartBounds) {
2829         if (mTaskFragmentOrganizer == null || !canStartChangeTransition()) {
2830             return false;
2831         }
2832 
2833         if (mTransitionController.isShellTransitionsEnabled()) {
2834             // For Shell transition, the change will be collected anyway, so only take snapshot when
2835             // the bounds are resized.
2836             final Rect endBounds = getConfiguration().windowConfiguration.getBounds();
2837             return endBounds.width() != absStartBounds.width()
2838                     || endBounds.height() != absStartBounds.height();
2839         } else {
2840             // For legacy transition, we need to trigger a change transition as long as the bounds
2841             // is changed, even if it is not resized.
2842             return !relStartBounds.equals(mRelativeEmbeddedBounds);
2843         }
2844     }
2845 
2846     @Override
canStartChangeTransition()2847     boolean canStartChangeTransition() {
2848         final Task task = getTask();
2849         // Skip change transition when the Task is drag resizing.
2850         return task != null && !task.isDragResizing() && super.canStartChangeTransition();
2851     }
2852 
2853     @Override
isSyncFinished(BLASTSyncEngine.SyncGroup group)2854     boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
2855         return super.isSyncFinished(group) && isReadyToTransit();
2856     }
2857 
2858     @Override
setSurfaceControl(SurfaceControl sc)2859     void setSurfaceControl(SurfaceControl sc) {
2860         super.setSurfaceControl(sc);
2861         if (mTaskFragmentOrganizer != null) {
2862             updateOrganizedTaskFragmentSurfaceUnchecked();
2863             // If the TaskFragmentOrganizer was set before we created the SurfaceControl, we need to
2864             // emit the callbacks now.
2865             sendTaskFragmentAppeared();
2866         }
2867     }
2868 
sendTaskFragmentInfoChanged()2869     void sendTaskFragmentInfoChanged() {
2870         if (mTaskFragmentOrganizer != null) {
2871             mTaskFragmentOrganizerController
2872                     .onTaskFragmentInfoChanged(mTaskFragmentOrganizer, this);
2873         }
2874     }
2875 
sendTaskFragmentParentInfoChanged()2876     void sendTaskFragmentParentInfoChanged() {
2877         final Task parentTask = getParent().asTask();
2878         if (mTaskFragmentOrganizer != null && parentTask != null) {
2879             mTaskFragmentOrganizerController
2880                     .onTaskFragmentParentInfoChanged(mTaskFragmentOrganizer, parentTask);
2881         }
2882     }
2883 
sendTaskFragmentAppeared()2884     private void sendTaskFragmentAppeared() {
2885         if (mTaskFragmentOrganizer != null) {
2886             mTaskFragmentOrganizerController.onTaskFragmentAppeared(mTaskFragmentOrganizer, this);
2887         }
2888     }
2889 
sendTaskFragmentVanished()2890     private void sendTaskFragmentVanished() {
2891         if (mTaskFragmentOrganizer != null) {
2892             mTaskFragmentOrganizerController.onTaskFragmentVanished(mTaskFragmentOrganizer, this);
2893         }
2894     }
2895 
2896     /**
2897      * Returns a {@link TaskFragmentInfo} with information from this TaskFragment. Should not be
2898      * called from {@link Task}.
2899      */
getTaskFragmentInfo()2900     TaskFragmentInfo getTaskFragmentInfo() {
2901         List<IBinder> childActivities = new ArrayList<>();
2902         List<IBinder> inRequestedTaskFragmentActivities = new ArrayList<>();
2903         for (int i = 0; i < getChildCount(); i++) {
2904             final WindowContainer<?> wc = getChildAt(i);
2905             final ActivityRecord ar = wc.asActivityRecord();
2906             if (mTaskFragmentOrganizerUid != INVALID_UID && ar != null
2907                     && ar.info.processName.equals(mTaskFragmentOrganizerProcessName)
2908                     && ar.getUid() == mTaskFragmentOrganizerUid && !ar.finishing) {
2909                 // Only includes Activities that belong to the organizer process for security.
2910                 childActivities.add(ar.token);
2911                 if (ar.mRequestedLaunchingTaskFragmentToken == mFragmentToken) {
2912                     inRequestedTaskFragmentActivities.add(ar.token);
2913                 }
2914             }
2915         }
2916         final Point positionInParent = new Point();
2917         getRelativePosition(positionInParent);
2918         return new TaskFragmentInfo(
2919                 mFragmentToken,
2920                 mRemoteToken.toWindowContainerToken(),
2921                 getConfiguration(),
2922                 getNonFinishingActivityCount(),
2923                 shouldBeVisible(null /* starting */),
2924                 childActivities,
2925                 inRequestedTaskFragmentActivities,
2926                 positionInParent,
2927                 mClearedTaskForReuse,
2928                 mClearedTaskFragmentForPip,
2929                 mClearedForReorderActivityToFront,
2930                 calculateMinDimension(),
2931                 isTopNonFinishingChild());
2932     }
2933 
isTopNonFinishingChild()2934     private boolean isTopNonFinishingChild() {
2935         final WindowContainer<?> parent = getParent();
2936         if (parent == null) {
2937             // Either the TaskFragment is not attached or is going to destroy. Return false.
2938             return false;
2939         }
2940         final ActivityRecord topNonFishingActivity = parent.getActivity(ar -> !ar.finishing);
2941         // If the parent's top non-finishing activity is this TaskFragment's, it means
2942         // this TaskFragment is the top non-finishing container of its parent.
2943         return topNonFishingActivity != null && topNonFishingActivity
2944                 .equals(getTopNonFinishingActivity());
2945     }
2946 
2947     /**
2948      * Calculates the minimum dimensions that this TaskFragment can be resized.
2949      * @see TaskFragmentInfo#getMinimumWidth()
2950      * @see TaskFragmentInfo#getMinimumHeight()
2951      */
calculateMinDimension()2952     Point calculateMinDimension() {
2953         final int[] maxMinWidth = new int[1];
2954         final int[] maxMinHeight = new int[1];
2955 
2956         forAllActivities(a -> {
2957             if (a.finishing) {
2958                 return;
2959             }
2960             final Point minDimensions = a.getMinDimensions();
2961             if (minDimensions == null) {
2962                 return;
2963             }
2964             maxMinWidth[0] = Math.max(maxMinWidth[0], minDimensions.x);
2965             maxMinHeight[0] = Math.max(maxMinHeight[0], minDimensions.y);
2966         });
2967         return new Point(maxMinWidth[0], maxMinHeight[0]);
2968     }
2969 
2970     @Nullable
getFragmentToken()2971     IBinder getFragmentToken() {
2972         return mFragmentToken;
2973     }
2974 
2975     @Nullable
getTaskFragmentOrganizer()2976     ITaskFragmentOrganizer getTaskFragmentOrganizer() {
2977         return mTaskFragmentOrganizer;
2978     }
2979 
2980     @Override
isOrganized()2981     boolean isOrganized() {
2982         return mTaskFragmentOrganizer != null;
2983     }
2984 
2985     /** Whether this is an organized {@link TaskFragment} and not a {@link Task}. */
isOrganizedTaskFragment()2986     final boolean isOrganizedTaskFragment() {
2987         return mTaskFragmentOrganizer != null;
2988     }
2989 
2990     /**
2991      * Whether this is an embedded {@link TaskFragment} that does not fill the parent {@link Task}.
2992      */
isEmbeddedWithBoundsOverride()2993     boolean isEmbeddedWithBoundsOverride() {
2994         if (!mIsEmbedded) {
2995             return false;
2996         }
2997         final Task task = getTask();
2998         if (task == null) {
2999             return false;
3000         }
3001         final Rect taskBounds = task.getBounds();
3002         final Rect taskFragBounds = getBounds();
3003         return !taskBounds.equals(taskFragBounds) && taskBounds.contains(taskFragBounds);
3004     }
3005 
3006     /** Whether the Task should be visible. */
isTaskVisibleRequested()3007     boolean isTaskVisibleRequested() {
3008         final Task task = getTask();
3009         return task != null && task.isVisibleRequested();
3010     }
3011 
isReadyToTransit()3012     boolean isReadyToTransit() {
3013         // We only wait when this is organized to give the organizer a chance to update.
3014         if (!isOrganizedTaskFragment()) {
3015             return true;
3016         }
3017         // We don't want to start the transition if the organized TaskFragment is empty, unless
3018         // it is requested to be removed or the mAllowTransitionWhenEmpty flag is true.
3019         if (getTopNonFinishingActivity() != null || mIsRemovalRequested
3020                 || mAllowTransitionWhenEmpty) {
3021             return true;
3022         }
3023         // Organizer shouldn't change embedded TaskFragment in PiP.
3024         if (isEmbeddedTaskFragmentInPip()) {
3025             return true;
3026         }
3027         // The TaskFragment becomes empty because the last running activity enters PiP when the Task
3028         // is minimized.
3029         if (mClearedTaskFragmentForPip && !isTaskVisibleRequested()) {
3030             return true;
3031         }
3032         return false;
3033     }
3034 
3035     @Override
canCustomizeAppTransition()3036     boolean canCustomizeAppTransition() {
3037         // This is only called when the app transition is going to be played by system server. In
3038         // this case, we should allow custom app transition for fullscreen embedded TaskFragment
3039         // just like Activity.
3040         return isEmbedded() && matchParentBounds();
3041     }
3042 
3043     /** Clear {@link #mLastPausedActivity} for all {@link TaskFragment} children */
clearLastPausedActivity()3044     void clearLastPausedActivity() {
3045         forAllTaskFragments(taskFragment -> taskFragment.mLastPausedActivity = null);
3046     }
3047 
3048     /**
3049      * Sets {@link #mMinWidth} and {@link #mMinWidth} to this TaskFragment.
3050      * It is usually set from the parent {@link Task} when adding the TaskFragment to the window
3051      * hierarchy.
3052      */
setMinDimensions(int minWidth, int minHeight)3053     void setMinDimensions(int minWidth, int minHeight) {
3054         if (asTask() != null) {
3055             throw new UnsupportedOperationException("This method must not be used to Task. The "
3056                     + " minimum dimension of Task should be passed from Task constructor.");
3057         }
3058         mMinWidth = minWidth;
3059         mMinHeight = minHeight;
3060     }
3061 
3062     /**
3063      * Whether this is an embedded TaskFragment in PIP Task. We don't allow any client config
3064      * override for such TaskFragment to prevent flight with PipTaskOrganizer.
3065      */
isEmbeddedTaskFragmentInPip()3066     boolean isEmbeddedTaskFragmentInPip() {
3067         return isOrganizedTaskFragment() && getTask() != null && getTask().inPinnedWindowingMode();
3068     }
3069 
shouldRemoveSelfOnLastChildRemoval()3070     boolean shouldRemoveSelfOnLastChildRemoval() {
3071         if (!mCreatedByOrganizer || mIsRemovalRequested) {
3072             return true;
3073         }
3074         // The TaskFragmentOrganizer may be killed while the embedded TaskFragments remains in WM
3075         // core. The embedded TaskFragment should still be removed when the child activities are
3076         // all gone (like package force-stopped).
3077         return mIsEmbedded && mTaskFragmentOrganizer == null;
3078     }
3079 
3080     /**
3081      * Returns whether this TaskFragment is going to be removed.
3082      */
isRemovalRequested()3083     boolean isRemovalRequested() {
3084         return mIsRemovalRequested;
3085     }
3086 
3087     @Override
removeChild(WindowContainer child)3088     void removeChild(WindowContainer child) {
3089         removeChild(child, true /* removeSelfIfPossible */);
3090     }
3091 
removeChild(WindowContainer child, boolean removeSelfIfPossible)3092     void removeChild(WindowContainer child, boolean removeSelfIfPossible) {
3093         super.removeChild(child);
3094         final ActivityRecord r = child.asActivityRecord();
3095         final WindowProcessController hostProcess = getOrganizerProcessIfDifferent(r);
3096         if (hostProcess != null) {
3097             hostProcess.removeEmbeddedActivity(r);
3098         }
3099         if (removeSelfIfPossible && shouldRemoveSelfOnLastChildRemoval() && !hasChild()) {
3100             removeImmediately("removeLastChild " + child);
3101         }
3102     }
3103 
3104     /**
3105      * Requests to remove this task fragment. If it doesn't have children, it is removed
3106      * immediately. Otherwise it will be removed until all activities are destroyed.
3107      *
3108      * @param withTransition Whether to use transition animation when removing activities. Set to
3109      *                       {@code false} if this is invisible to user, e.g. display removal.
3110      */
remove(boolean withTransition, String reason)3111     void remove(boolean withTransition, String reason) {
3112         if (!hasChild()) {
3113             removeImmediately(reason);
3114             return;
3115         }
3116         mIsRemovalRequested = true;
3117         // The task order may be changed by finishIfPossible() for adjusting focus if there are
3118         // nested tasks, so add all activities into a list to avoid missed removals.
3119         final ArrayList<ActivityRecord> removingActivities = new ArrayList<>();
3120         forAllActivities((r) -> {
3121             if (!r.finishing) {
3122                 removingActivities.add(r);
3123             }
3124         });
3125         for (int i = removingActivities.size() - 1; i >= 0; --i) {
3126             final ActivityRecord r = removingActivities.get(i);
3127             if (withTransition && r.isVisible()) {
3128                 r.finishIfPossible(reason, false /* oomAdj */);
3129             } else {
3130                 r.destroyIfPossible(reason);
3131             }
3132         }
3133     }
3134 
setDelayLastActivityRemoval(boolean delay)3135     void setDelayLastActivityRemoval(boolean delay) {
3136         if (!mIsEmbedded) {
3137             Slog.w(TAG, "Set delaying last activity removal on a non-embedded TF.");
3138         }
3139         mDelayLastActivityRemoval = delay;
3140     }
3141 
isDelayLastActivityRemoval()3142     boolean isDelayLastActivityRemoval() {
3143         return mDelayLastActivityRemoval;
3144     }
3145 
shouldDeferRemoval()3146     boolean shouldDeferRemoval() {
3147         if (!hasChild()) {
3148             return false;
3149         }
3150         return isExitAnimationRunningSelfOrChild();
3151     }
3152 
3153     @Override
handleCompleteDeferredRemoval()3154     boolean handleCompleteDeferredRemoval() {
3155         if (shouldDeferRemoval()) {
3156             return true;
3157         }
3158         return super.handleCompleteDeferredRemoval();
3159     }
3160 
3161     /** The overridden method must call {@link #removeImmediately()} instead of super. */
removeImmediately(String reason)3162     void removeImmediately(String reason) {
3163         Slog.d(TAG, "Remove task fragment: " + reason);
3164         removeImmediately();
3165     }
3166 
3167     @Override
removeImmediately()3168     void removeImmediately() {
3169         if (asTask() == null) {
3170             EventLogTags.writeWmTfRemoved(System.identityHashCode(this), getTaskId());
3171         }
3172         mIsRemovalRequested = false;
3173         removeFromAdjacentTaskFragments();
3174         cleanUpEmbeddedTaskFragment();
3175         final boolean shouldExecuteAppTransition =
3176                 mClearedTaskFragmentForPip && isTaskVisibleRequested();
3177         super.removeImmediately();
3178         sendTaskFragmentVanished();
3179         if (shouldExecuteAppTransition && mDisplayContent != null) {
3180             // When the Task is still visible, and the TaskFragment is removed because the last
3181             // running activity is reparenting to PiP, it is possible that no activity is getting
3182             // paused or resumed (having an embedded activity in split), thus we need to relayout
3183             // and execute it explicitly.
3184             mAtmService.addWindowLayoutReasons(
3185                     ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
3186             mDisplayContent.executeAppTransition();
3187         }
3188     }
3189 
3190     /** Called on remove to cleanup. */
cleanUpEmbeddedTaskFragment()3191     private void cleanUpEmbeddedTaskFragment() {
3192         if (!mIsEmbedded) {
3193             return;
3194         }
3195         mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this);
3196         final Task task = getTask();
3197         if (task == null) {
3198             return;
3199         }
3200         task.forAllLeafTaskFragments(taskFragment -> {
3201             if (taskFragment.getCompanionTaskFragment() == this) {
3202                 taskFragment.setCompanionTaskFragment(null /* companionTaskFragment */);
3203             }
3204         }, false /* traverseTopToBottom */);
3205     }
3206 
shouldBoostDimmer()3207     boolean shouldBoostDimmer() {
3208         if (asTask() != null || !isDimmingOnParentTask()) {
3209             // early return if not embedded or should not dim on parent Task.
3210             return false;
3211         }
3212 
3213         if (!hasAdjacentTaskFragment()) {
3214             // early return if no adjacent TF.
3215             return false;
3216         }
3217 
3218         final ArrayList<WindowContainer> siblings = getParent().mChildren;
3219         final int zOrder = siblings.indexOf(this);
3220         final boolean hasAdjacentOnTop = forOtherAdjacentTaskFragments(
3221                 tf -> siblings.indexOf(tf) > zOrder);
3222         if (!hasAdjacentOnTop) {
3223             // early return if this TF already has higher z-ordering.
3224             return false;
3225         }
3226 
3227         final ToBooleanFunction<WindowState> getDimBehindWindow =
3228                 (w) -> (w.mAttrs.flags & FLAG_DIM_BEHIND) != 0 && w.mActivityRecord != null
3229                         && w.mActivityRecord.isEmbedded() && (w.mActivityRecord.isVisibleRequested()
3230                         || w.mActivityRecord.isVisible());
3231         final boolean adjacentHasDimmingWindow = forOtherAdjacentTaskFragments(tf -> {
3232             return tf.forAllWindows(getDimBehindWindow, true);
3233         });
3234         if (adjacentHasDimmingWindow) {
3235             // early return if the adjacent Tf has a dimming window.
3236             return false;
3237         }
3238 
3239         // boost if there's an Activity window that has FLAG_DIM_BEHIND flag.
3240         return forAllWindows(getDimBehindWindow, true);
3241     }
3242 
3243     @Deprecated
3244     @Override
getDimmer()3245     Dimmer getDimmer() {
3246         // If this is in an embedded TaskFragment and we want the dim applies on the TaskFragment.
3247         if (mIsEmbedded && !isDimmingOnParentTask()) {
3248             return mDimmer;
3249         }
3250 
3251         return super.getDimmer();
3252     }
3253 
3254     /** Bounds to be used for dimming, as well as touch related tests. */
getDimBounds(@onNull Rect out)3255     void getDimBounds(@NonNull Rect out) {
3256         if (Flags.useTasksDimOnly() && mDimmer.hasDimState()) {
3257             out.set(mDimmer.getDimBounds());
3258         } else {
3259             if (mIsEmbedded && isDimmingOnParentTask() && getDimmer().getDimBounds() != null) {
3260                 // Return the task bounds if the dimmer is showing and should cover on the Task (not
3261                 // just on this embedded TaskFragment).
3262                 out.set(getTask().getBounds());
3263             } else {
3264                 out.set(getBounds());
3265             }
3266         }
3267     }
3268 
setEmbeddedDimArea(@mbeddedDimArea int embeddedDimArea)3269     void setEmbeddedDimArea(@EmbeddedDimArea int embeddedDimArea) {
3270         mEmbeddedDimArea = embeddedDimArea;
3271     }
3272 
setMoveToBottomIfClearWhenLaunch(boolean moveToBottomIfClearWhenLaunch)3273     void setMoveToBottomIfClearWhenLaunch(boolean moveToBottomIfClearWhenLaunch) {
3274         mMoveToBottomIfClearWhenLaunch = moveToBottomIfClearWhenLaunch;
3275     }
3276 
isMoveToBottomIfClearWhenLaunch()3277     boolean isMoveToBottomIfClearWhenLaunch() {
3278         return mMoveToBottomIfClearWhenLaunch;
3279     }
3280 
3281     @VisibleForTesting
isDimmingOnParentTask()3282     boolean isDimmingOnParentTask() {
3283         return mEmbeddedDimArea == EMBEDDED_DIM_AREA_PARENT_TASK;
3284     }
3285 
3286     @Override
prepareSurfaces()3287     void prepareSurfaces() {
3288         if (asTask() != null) {
3289             super.prepareSurfaces();
3290             return;
3291         }
3292 
3293         mDimmer.resetDimStates();
3294         super.prepareSurfaces();
3295 
3296         if (!Flags.useTasksDimOnly()) {
3297             final Rect dimBounds = mDimmer.getDimBounds();
3298             if (dimBounds != null) {
3299                 // Bounds need to be relative, as the dim layer is a child.
3300                 dimBounds.offsetTo(0 /* newLeft */, 0 /* newTop */);
3301                 if (mDimmer.updateDims(getSyncTransaction())) {
3302                     scheduleAnimation();
3303                 }
3304             }
3305         } else {
3306             if (mDimmer.updateDims(getSyncTransaction())) {
3307                 scheduleAnimation();
3308             }
3309         }
3310     }
3311 
3312     @Override
fillsParent()3313     boolean fillsParent() {
3314         // From the perspective of policy, we still want to report that this task fills parent
3315         // in fullscreen windowing mode even it doesn't match parent bounds because there will be
3316         // letterbox around its real content.
3317         return getWindowingMode() == WINDOWING_MODE_FULLSCREEN || matchParentBounds();
3318     }
3319 
3320     @Override
onChildVisibleRequestedChanged(@ullable WindowContainer child)3321     protected boolean onChildVisibleRequestedChanged(@Nullable WindowContainer child) {
3322         if (!super.onChildVisibleRequestedChanged(child)) return false;
3323         // Send the info changed to update the TaskFragment visibility.
3324         sendTaskFragmentInfoChanged();
3325         return true;
3326     }
3327 
3328     @Nullable
3329     @Override
getTaskFragment(Predicate<TaskFragment> callback)3330     TaskFragment getTaskFragment(Predicate<TaskFragment> callback) {
3331         final TaskFragment taskFragment = super.getTaskFragment(callback);
3332         if (taskFragment != null) {
3333             return taskFragment;
3334         }
3335         return callback.test(this) ? this : null;
3336     }
3337 
3338     /**
3339      * Moves the passed child to front
3340      * @return whether it was actually moved (vs already being top).
3341      */
moveChildToFront(WindowContainer newTop)3342     boolean moveChildToFront(WindowContainer newTop) {
3343         int origDist = getDistanceFromTop(newTop);
3344         positionChildAt(POSITION_TOP, newTop, false /* includeParents */);
3345         return getDistanceFromTop(newTop) != origDist;
3346     }
3347 
toFullString()3348     String toFullString() {
3349         final StringBuilder sb = new StringBuilder(128);
3350         sb.append(this);
3351         sb.setLength(sb.length() - 1); // Remove tail '}'.
3352         if (mTaskFragmentOrganizerUid != INVALID_UID) {
3353             sb.append(" organizerUid=");
3354             sb.append(mTaskFragmentOrganizerUid);
3355         }
3356         if (mTaskFragmentOrganizerProcessName != null) {
3357             sb.append(" organizerProc=");
3358             sb.append(mTaskFragmentOrganizerProcessName);
3359         }
3360         if (mAdjacentTaskFragments != null) {
3361             sb.append(" adjacent=");
3362             sb.append(mAdjacentTaskFragments);
3363         }
3364         sb.append('}');
3365         return sb.toString();
3366     }
3367 
3368     @Override
toString()3369     public String toString() {
3370         return "TaskFragment{" + Integer.toHexString(System.identityHashCode(this))
3371                 + " mode=" + WindowConfiguration.windowingModeToString(getWindowingMode()) + "}";
3372     }
3373 
dump(String prefix, FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, final boolean needSep, Runnable header)3374     boolean dump(String prefix, FileDescriptor fd, PrintWriter pw, boolean dumpAll,
3375             boolean dumpClient, String dumpPackage, final boolean needSep, Runnable header) {
3376         boolean printed = false;
3377         Runnable headerPrinter = () -> {
3378             if (needSep) {
3379                 pw.println();
3380             }
3381             if (header != null) {
3382                 header.run();
3383             }
3384 
3385             dumpInner(prefix, pw, dumpAll, dumpPackage);
3386         };
3387 
3388         if (dumpPackage == null) {
3389             // If we are not filtering by package, we want to print absolutely everything,
3390             // so always print the header even if there are no tasks/activities inside.
3391             headerPrinter.run();
3392             headerPrinter = null;
3393             printed = true;
3394         }
3395 
3396         for (int i = mChildren.size() - 1; i >= 0; --i) {
3397             WindowContainer child = mChildren.get(i);
3398             if (child.asTaskFragment() != null) {
3399                 printed |= child.asTaskFragment().dump(prefix + "  ", fd, pw, dumpAll,
3400                         dumpClient, dumpPackage, needSep, headerPrinter);
3401             } else if (child.asActivityRecord() != null) {
3402                 ActivityRecord.dumpActivity(fd, pw, i, child.asActivityRecord(), prefix + "  ",
3403                         "Hist ", true, !dumpAll, dumpClient, dumpPackage, false, headerPrinter,
3404                         getTask());
3405             }
3406         }
3407 
3408         return printed;
3409     }
3410 
dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage)3411     void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) {
3412         pw.print(prefix); pw.print("* "); pw.println(toFullString());
3413         final Rect bounds = getRequestedOverrideBounds();
3414         if (!bounds.isEmpty()) {
3415             pw.println(prefix + "  mBounds=" + bounds);
3416         }
3417         if (mIsRemovalRequested) {
3418             pw.println(prefix + "  mIsRemovalRequested=true");
3419         }
3420         if (dumpAll) {
3421             printThisActivity(pw, mLastPausedActivity, dumpPackage, false,
3422                     prefix + "  mLastPausedActivity: ", null);
3423         }
3424     }
3425 
3426     @Override
dump(PrintWriter pw, String prefix, boolean dumpAll)3427     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3428         super.dump(pw, prefix, dumpAll);
3429         pw.println(prefix + "bounds=" + getBounds().toShortString()
3430                 + (mIsolatedNav ? ", isolatedNav" : ""));
3431         final String doublePrefix = prefix + "  ";
3432         for (int i = mChildren.size() - 1; i >= 0; i--) {
3433             final WindowContainer<?> child = mChildren.get(i);
3434             final TaskFragment tf = child.asTaskFragment();
3435             pw.println(prefix + "* " + (tf != null ? tf.toFullString() : child));
3436             // Only dump non-activity because full activity info is already printed by
3437             // RootWindowContainer#dumpActivities.
3438             if (tf != null) {
3439                 child.dump(pw, doublePrefix, dumpAll);
3440             }
3441         }
3442     }
3443 
3444     @Override
writeIdentifierToProto(ProtoOutputStream proto, long fieldId)3445     void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
3446         final long token = proto.start(fieldId);
3447         proto.write(HASH_CODE, System.identityHashCode(this));
3448         final ActivityRecord topActivity = topRunningActivity();
3449         proto.write(USER_ID, topActivity != null ? topActivity.mUserId : USER_NULL);
3450         proto.write(TITLE, topActivity != null ? topActivity.intent.getComponent()
3451                 .flattenToShortString() : "TaskFragment");
3452         proto.end(token);
3453     }
3454 
3455     @Override
getProtoFieldId()3456     long getProtoFieldId() {
3457         return TASK_FRAGMENT;
3458     }
3459 
3460     @Override
dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTracingLogLevel int logLevel)3461     public void dumpDebug(ProtoOutputStream proto, long fieldId,
3462             @WindowTracingLogLevel int logLevel) {
3463         if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) {
3464             return;
3465         }
3466 
3467         final long token = proto.start(fieldId);
3468 
3469         super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
3470 
3471         proto.write(DISPLAY_ID, getDisplayId());
3472         proto.write(ACTIVITY_TYPE, getActivityType());
3473         proto.write(MIN_WIDTH, mMinWidth);
3474         proto.write(MIN_HEIGHT, mMinHeight);
3475 
3476         proto.end(token);
3477     }
3478 
3479     /** Set of {@link TaskFragment}s that are adjacent to each other. */
3480     static class AdjacentSet {
3481         private final ArraySet<TaskFragment> mAdjacentSet;
3482 
AdjacentSet(@onNull TaskFragment... taskFragments)3483         AdjacentSet(@NonNull TaskFragment... taskFragments) {
3484             this(new ArraySet<>(taskFragments));
3485         }
3486 
AdjacentSet(@onNull ArraySet<TaskFragment> taskFragments)3487         AdjacentSet(@NonNull ArraySet<TaskFragment> taskFragments) {
3488             final int size = taskFragments.size();
3489             if (size < 2) {
3490                 throw new IllegalArgumentException("Adjacent TaskFragments must contain at least"
3491                         + " two TaskFragments, but only " + size + " were provided.");
3492             }
3493             if (size > 2) {
3494                 for (int i = 0; i < size; i++) {
3495                     if (taskFragments.valueAt(i).asTask() == null) {
3496                         throw new IllegalArgumentException(
3497                                 "Not yet support 3+ adjacent for non-Task TFs");
3498                     }
3499                 }
3500             }
3501             mAdjacentSet = taskFragments;
3502         }
3503 
3504         /** Updates each {@link TaskFragment} in the set to be adjacent to each other. */
setAsAdjacent()3505         private void setAsAdjacent() {
3506             if (mAdjacentSet.isEmpty()
3507                     || equals(mAdjacentSet.valueAt(0).mAdjacentTaskFragments)) {
3508                 // No need to update if any TaskFragment in the set has already been updated to the
3509                 // same set.
3510                 return;
3511             }
3512             for (int i = mAdjacentSet.size() - 1; i >= 0; i--) {
3513                 final TaskFragment taskFragment = mAdjacentSet.valueAt(i);
3514                 taskFragment.removeFromAdjacentTaskFragments();
3515                 taskFragment.mAdjacentTaskFragments = this;
3516             }
3517         }
3518 
3519         /** Removes the {@link TaskFragment} from the adjacent set. */
remove(@onNull TaskFragment taskFragment)3520         private void remove(@NonNull TaskFragment taskFragment) {
3521             taskFragment.mAdjacentTaskFragments = null;
3522             taskFragment.mDelayLastActivityRemoval = false;
3523             mAdjacentSet.remove(taskFragment);
3524             if (mAdjacentSet.size() < 2) {
3525                 // To be considered as adjacent, there must be at least 2 TaskFragments in the set.
3526                 clear();
3527             }
3528         }
3529 
3530         /** Clears the adjacent relationship. */
clear()3531         private void clear() {
3532             for (int i = mAdjacentSet.size() - 1; i >= 0; i--) {
3533                 final TaskFragment taskFragment = mAdjacentSet.valueAt(i);
3534                 // Clear all reference.
3535                 taskFragment.mAdjacentTaskFragments = null;
3536                 taskFragment.mDelayLastActivityRemoval = false;
3537             }
3538             mAdjacentSet.clear();
3539         }
3540 
3541         /** Whether the {@link TaskFragment} is in this adjacent set. */
contains(@onNull TaskFragment taskFragment)3542         boolean contains(@NonNull TaskFragment taskFragment) {
3543             return mAdjacentSet.contains(taskFragment);
3544         }
3545 
3546         /**
3547          * Runs the callback on all adjacent TaskFragments. Skips the exclude one if not null.
3548          */
forAllTaskFragments(@onNull Consumer<TaskFragment> callback, @Nullable TaskFragment exclude)3549         void forAllTaskFragments(@NonNull Consumer<TaskFragment> callback,
3550                 @Nullable TaskFragment exclude) {
3551             for (int i = mAdjacentSet.size() - 1; i >= 0; i--) {
3552                 final TaskFragment taskFragment = mAdjacentSet.valueAt(i);
3553                 if (taskFragment != exclude) {
3554                     callback.accept(taskFragment);
3555                 }
3556             }
3557         }
3558 
3559         /**
3560          * Runs the callback on all adjacent TaskFragments until one returns {@code true}. Skips the
3561          * exclude one if not null.
3562          */
forAllTaskFragments(@onNull Predicate<TaskFragment> callback, @Nullable TaskFragment exclude)3563         boolean forAllTaskFragments(@NonNull Predicate<TaskFragment> callback,
3564                 @Nullable TaskFragment exclude) {
3565             for (int i = mAdjacentSet.size() - 1; i >= 0; i--) {
3566                 final TaskFragment taskFragment = mAdjacentSet.valueAt(i);
3567                 if (taskFragment == exclude) {
3568                     continue;
3569                 }
3570                 if (callback.test(taskFragment)) {
3571                     return true;
3572                 }
3573             }
3574             return false;
3575         }
3576 
size()3577         int size() {
3578             return mAdjacentSet.size();
3579         }
3580 
3581         @Override
equals(@ullable Object o)3582         public boolean equals(@Nullable Object o) {
3583             if (this == o) {
3584                 return true;
3585             }
3586             if (!(o instanceof AdjacentSet other)) {
3587                 return false;
3588             }
3589             return mAdjacentSet.equals(other.mAdjacentSet);
3590         }
3591 
3592         @Override
toString()3593         public String toString() {
3594             final StringBuilder sb = new StringBuilder();
3595             sb.append("AdjacentSet{");
3596             final int size = mAdjacentSet.size();
3597             for (int i = 0; i < size; i++) {
3598                 if (i != 0) {
3599                     sb.append(", ");
3600                 }
3601                 sb.append(mAdjacentSet.valueAt(i));
3602             }
3603             sb.append("}");
3604             return sb.toString();
3605         }
3606     }
3607 }
3608