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