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