blob: d73cb50fe107f962ac298222e0317c77bef277e8 [file] [log] [blame]
Wale Ogunwaled63594a2016-07-18 07:48:30 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.wm;
18
Jorim Jaggi612bb882017-05-16 17:11:18 +020019import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
20import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080022import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
23import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
24import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
25import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
26import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
lumark19a5d2e2019-10-11 16:19:30 +080027import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Vishnu Nair04ab4392018-01-10 11:00:06 -080028import static android.view.SurfaceControl.Transaction;
Louis Chang7501e332018-08-20 13:08:39 +080029
lumark19a5d2e2019-10-11 16:19:30 +080030import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
31import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
32import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
lumark9bca6b42019-10-17 18:35:22 +080033import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
34import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
35import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070036import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
37import static com.android.server.wm.WindowContainerProto.ORIENTATION;
38import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
39import static com.android.server.wm.WindowContainerProto.VISIBLE;
Louis Chang7501e332018-08-20 13:08:39 +080040import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
41import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
42import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
lumark19a5d2e2019-10-11 16:19:30 +080043import static com.android.server.wm.WindowManagerService.logWithStack;
Yunfan Chen87b5a242019-10-01 17:53:59 +090044import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
lumark19a5d2e2019-10-11 16:19:30 +080045import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Jorim Jaggi612bb882017-05-16 17:11:18 +020046
Wale Ogunwaled63594a2016-07-18 07:48:30 -070047import android.annotation.CallSuper;
Jorim Jaggi391790622018-04-18 15:30:44 +020048import android.annotation.IntDef;
Garfield Tan90b04282018-12-11 14:04:42 -080049import android.annotation.Nullable;
Jorim Jaggi391790622018-04-18 15:30:44 +020050import android.app.WindowConfiguration;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080051import android.content.pm.ActivityInfo;
Andrii Kulian441e4492016-09-29 15:25:00 -070052import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080053import android.graphics.Point;
54import android.graphics.Rect;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080055import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -080056import android.os.IBinder;
lumark19a5d2e2019-10-11 16:19:30 +080057import android.os.Trace;
58import android.util.Pair;
Vishnu Nair04ab4392018-01-10 11:00:06 -080059import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010060import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080061import android.util.proto.ProtoOutputStream;
lumark19a5d2e2019-10-11 16:19:30 +080062import android.view.DisplayInfo;
Robert Carrb1579c82017-09-05 14:54:47 -070063import android.view.MagnificationSpec;
lumark19a5d2e2019-10-11 16:19:30 +080064import android.view.RemoteAnimationTarget;
Robert Carrb1579c82017-09-05 14:54:47 -070065import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010066import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070067import android.view.SurfaceSession;
lumark19a5d2e2019-10-11 16:19:30 +080068import android.view.WindowManager;
69import android.view.animation.Animation;
Garfield Tan2f145f22018-11-01 15:27:03 -070070
Evan Rosky65dffa62019-02-04 14:09:53 -080071import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggia5e10572017-11-15 14:36:26 +010072import com.android.internal.util.ToBooleanFunction;
Yunfan Chen87b5a242019-10-01 17:53:59 +090073import com.android.server.policy.WindowManagerPolicy;
lumark19a5d2e2019-10-11 16:19:30 +080074import com.android.server.protolog.common.ProtoLog;
Jorim Jaggia5e10572017-11-15 14:36:26 +010075import com.android.server.wm.SurfaceAnimator.Animatable;
Garfield Tan2f145f22018-11-01 15:27:03 -070076
Jorim Jaggia5e10572017-11-15 14:36:26 +010077import java.io.PrintWriter;
Yunfan Chen87b5a242019-10-01 17:53:59 +090078import java.util.ArrayList;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070079import java.util.Comparator;
80import java.util.LinkedList;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070081import java.util.function.Consumer;
Wale Ogunwaledfbeed72019-11-20 08:57:39 -080082import java.util.function.Function;
Wale Ogunwaled1880962016-11-08 10:31:59 -080083import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070084
85/**
86 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -070087 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -070088 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
89 * changes are made to this class.
90 */
Wale Ogunwale98d62312017-07-12 09:24:56 -070091class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Jorim Jaggia5e10572017-11-15 14:36:26 +010092 implements Comparable<WindowContainer>, Animatable {
93
94 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070095
Louis Changdc077272019-11-12 16:52:56 +080096 /** Animation layer that happens above all animating {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +020097 static final int ANIMATION_LAYER_STANDARD = 0;
98
Louis Changdc077272019-11-12 16:52:56 +080099 /** Animation layer that happens above all {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200100 static final int ANIMATION_LAYER_BOOSTED = 1;
101
102 /**
103 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
Winson Chung732446a2018-09-19 13:15:17 -0700104 * activities and all activities that are being controlled by the recents animation. This
Louis Changdc077272019-11-12 16:52:56 +0800105 * layer is generally below all {@link ActivityStack}s.
Jorim Jaggi391790622018-04-18 15:30:44 +0200106 */
107 static final int ANIMATION_LAYER_HOME = 2;
108
109 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
110 ANIMATION_LAYER_STANDARD,
111 ANIMATION_LAYER_BOOSTED,
112 ANIMATION_LAYER_HOME,
113 })
114 @interface AnimationLayer {}
115
Andrii Kuliand2765632016-12-12 22:26:34 -0800116 static final int POSITION_TOP = Integer.MAX_VALUE;
117 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
118
Andrii Kulian441e4492016-09-29 15:25:00 -0700119 /**
120 * The parent of this window container.
121 * For removing or setting new parent {@link #setParent} should be used, because it also
122 * performs configuration updates based on new parent's settings.
123 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100124 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700125
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200126 // Set to true when we are performing a reparenting operation so we only send one
127 // onParentChanged() notification.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700128 boolean mReparenting;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200129
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700130 // List of children for this window container. List is in z-order as the children appear on
131 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +0200132 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700133
Wale Ogunwale51362492016-09-08 17:49:17 -0700134 // The specified orientation for this window container.
135 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
136
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800137 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
138 new Pools.SynchronizedPool<>(3);
139
Tiger Huanged6794e2019-05-07 20:07:59 +0800140 // The display this window container is on.
141 protected DisplayContent mDisplayContent;
142
Robert Carrb1579c82017-09-05 14:54:47 -0700143 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100144 private int mLastLayer = 0;
145 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700146
Tiger Huanged6794e2019-05-07 20:07:59 +0800147 // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
148 private final Transaction mPendingTransaction;
149
Robert Carrb1579c82017-09-05 14:54:47 -0700150 /**
Yunfan Chen87b5a242019-10-01 17:53:59 +0900151 * Windows that clients are waiting to have drawn.
152 */
153 final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
154
155 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700156 * Applied as part of the animation pass in "prepareSurfaces".
157 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100158 protected final SurfaceAnimator mSurfaceAnimator;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800159 protected final WindowManagerService mWmService;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100160
chaviwe07246a2017-12-12 16:18:29 -0800161 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800162 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800163
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100164 /** Total number of elements in this subtree, including our own hierarchy element. */
165 private int mTreeWeight = 1;
166
chaviw7f1fa992018-01-10 13:52:12 -0800167 /**
Vishnu Nairddd80742018-08-21 14:12:46 -0700168 * Indicates whether we are animating and have committed the transaction to reparent our
chaviw7f1fa992018-01-10 13:52:12 -0800169 * surface to the animation leash
170 */
171 private boolean mCommittedReparentToAnimationLeash;
172
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800173 private final Configuration mTmpConfig = new Configuration();
174
lumark9bca6b42019-10-17 18:35:22 +0800175 /** Interface for {@link #isAnimating} to check which cases for the container is animating. */
176 public interface AnimationFlags {
177 /**
178 * A bit flag indicates that {@link #isAnimating} should also return {@code true}
179 * even though the container is not yet animating, but the window container or its
180 * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition}
181 * that is pending so an animation starts soon.
182 */
183 int TRANSITION = 1;
184
185 /**
186 * A bit flag indicates that {@link #isAnimating} should also check if one of the
187 * ancestors of the container are animating in addition to the container itself.
188 */
189 int PARENTS = 2;
190
191 /**
192 * A bit flag indicates that {@link #isAnimating} should also check if one of the
193 * descendants of the container are animating in addition to the container itself.
194 */
195 int CHILDREN = 4;
196 }
197
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200198 /**
199 * Callback which is triggered while changing the parent, after setting up the surface but
200 * before asking the parent to assign child layers.
201 */
202 interface PreAssignChildLayersCallback {
203 void onPreAssignChildLayers();
204 }
205
lumark19a5d2e2019-10-11 16:19:30 +0800206 /**
207 * True if this an AppWindowToken and the activity which created this was launched with
208 * ActivityOptions.setLaunchTaskBehind.
209 *
210 * TODO(b/142617871): We run a special animation when the activity was launched with that
211 * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly
212 * selected to suppress an animation, and remove this flag.
213 */
214 boolean mLaunchTaskBehind;
215
216 /**
217 * If we are running an animation, this determines the transition type. Must be one of
218 * {@link AppTransition#TransitionFlags}.
219 */
220 int mTransit;
221
222 /**
223 * If we are running an animation, this determines the flags during this animation. Must be a
224 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
225 */
226 int mTransitFlags;
227
228 /** Whether this container should be boosted at the top of all its siblings. */
229 @VisibleForTesting boolean mNeedsZBoost;
230
231 /** Layer used to constrain the animation to a container's stack bounds. */
232 SurfaceControl mAnimationBoundsLayer;
233
234 /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */
235 boolean mNeedsAnimationBoundsLayer;
236
237 /**
238 * This gets used during some open/close transitions as well as during a change transition
239 * where it represents the starting-state snapshot.
240 */
lumarkbc0032a2019-11-01 21:38:13 +0800241 WindowContainerThumbnail mThumbnail;
lumark19a5d2e2019-10-11 16:19:30 +0800242 final Rect mTransitStartRect = new Rect();
243 final Point mTmpPoint = new Point();
244 protected final Rect mTmpRect = new Rect();
245 final Rect mTmpPrevBounds = new Rect();
246
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800247 WindowContainer(WindowManagerService wms) {
248 mWmService = wms;
Vishnu Nair33197392019-08-30 10:29:37 -0700249 mPendingTransaction = wms.mTransactionFactory.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800250 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100251 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800252
Wale Ogunwale98d62312017-07-12 09:24:56 -0700253 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700254 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700255 return mParent;
256 }
257
Wale Ogunwale98d62312017-07-12 09:24:56 -0700258 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700259 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700260 return mChildren.size();
261 }
262
263 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700264 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700265 return mChildren.get(index);
266 }
267
chaviwe07246a2017-12-12 16:18:29 -0800268 @Override
269 public void onConfigurationChanged(Configuration newParentConfig) {
270 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800271 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800272 scheduleAnimation();
273 }
274
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200275 void reparent(WindowContainer newParent, int position) {
276 if (newParent == null) {
277 throw new IllegalArgumentException("reparent: can't reparent to null " + this);
278 }
279
280 final WindowContainer oldParent = mParent;
281 if (mParent == newParent) {
282 throw new IllegalArgumentException("WC=" + this + " already child of " + mParent);
283 }
284
285 // The display object before reparenting as that might lead to old parent getting removed
286 // from the display if it no longer has any child.
287 final DisplayContent prevDc = oldParent.getDisplayContent();
288 final DisplayContent dc = newParent.getDisplayContent();
289
290 mReparenting = true;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700291 oldParent.removeChild(this);
Louis Chang2453d062019-11-19 22:30:48 +0800292 newParent.addChild(this, position);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200293 mReparenting = false;
294
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200295 // Relayout display(s)
296 dc.setLayoutNeeded();
297 if (prevDc != dc) {
298 onDisplayChanged(dc);
299 prevDc.setLayoutNeeded();
300 }
301 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700302
303 // Send onParentChanged notification here is we disabled sending it in setParent for
304 // reparenting case.
305 onParentChanged(newParent, oldParent);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200306 }
307
Jorim Jaggia5e10572017-11-15 14:36:26 +0100308 final protected void setParent(WindowContainer<WindowContainer> parent) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200309 final WindowContainer oldParent = mParent;
Andrii Kulian441e4492016-09-29 15:25:00 -0700310 mParent = parent;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800311
312 if (mParent != null) {
313 mParent.onChildAdded(this);
314 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200315 if (!mReparenting) {
316 onParentChanged(mParent, oldParent);
317 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800318 }
319
320 /**
321 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
322 * Supposed to be overridden and contain actions that should be executed after parent was set.
323 */
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800324 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200325 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
326 onParentChanged(newParent, oldParent, null);
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200327 }
328
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200329 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
330 PreAssignChildLayersCallback callback) {
331 super.onParentChanged(newParent, oldParent);
Robert Carrb1579c82017-09-05 14:54:47 -0700332 if (mParent == null) {
333 return;
334 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100335
Robert Carrb1579c82017-09-05 14:54:47 -0700336 if (mSurfaceControl == null) {
337 // If we don't yet have a surface, but we now have a parent, we should
338 // build a surface.
339 mSurfaceControl = makeSurface().build();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700340 getPendingTransaction().show(mSurfaceControl);
Evan Roskyb1ea7ca2018-04-05 17:17:35 -0700341 updateSurfacePosition();
Robert Carrb1579c82017-09-05 14:54:47 -0700342 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100343 // If we have a surface but a new parent, we just need to perform a reparent. Go through
344 // surface animator such that hierarchy is preserved when animating, i.e.
345 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
346 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100347 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700348 }
349
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200350 if (callback != null) {
351 callback.onPreAssignChildLayers();
352 }
353
Robert Carrb1579c82017-09-05 14:54:47 -0700354 // Either way we need to ask the parent to assign us a Z-order.
355 mParent.assignChildLayers();
356 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700357 }
358
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700359 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100360 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
361 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700362
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700363 /**
364 * Adds the input window container has a child of this container in order based on the input
365 * comparator.
366 * @param child The window container to add as a child of this window container.
367 * @param comparator Comparator to use in determining the position the child should be added to.
368 * If null, the child will be added to the top.
369 */
370 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700371 protected void addChild(E child, Comparator<E> comparator) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700372 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700373 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700374 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700375 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700376 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700377
Andrii Kulianb94292e2016-10-19 13:30:58 -0700378 int positionToAdd = -1;
379 if (comparator != null) {
380 final int count = mChildren.size();
381 for (int i = 0; i < count; i++) {
382 if (comparator.compare(child, mChildren.get(i)) < 0) {
383 positionToAdd = i;
384 break;
385 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700386 }
387 }
388
Andrii Kulianb94292e2016-10-19 13:30:58 -0700389 if (positionToAdd == -1) {
390 mChildren.add(child);
391 } else {
392 mChildren.add(positionToAdd, child);
393 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100394
Andrii Kulianb94292e2016-10-19 13:30:58 -0700395 // Set the parent after we've actually added a child in case a subclass depends on this.
396 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700397 }
398
Wale Ogunwalef6192862016-09-10 13:42:30 -0700399 /** Adds the input window container has a child of this container at the input index. */
400 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800401 void addChild(E child, int index) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700402 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700403 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700404 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800405 + " can't add to container=" + getName()
406 + "\n callers=" + Debug.getCallers(15, "\n"));
Wale Ogunwalef6192862016-09-10 13:42:30 -0700407 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900408
409 if ((index < 0 && index != POSITION_BOTTOM)
410 || (index > mChildren.size() && index != POSITION_TOP)) {
411 throw new IllegalArgumentException("addChild: invalid position=" + index
412 + ", children number=" + mChildren.size());
413 }
414
415 if (index == POSITION_TOP) {
416 index = mChildren.size();
417 } else if (index == POSITION_BOTTOM) {
418 index = 0;
419 }
420
Wale Ogunwalef6192862016-09-10 13:42:30 -0700421 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100422
Andrii Kulianb94292e2016-10-19 13:30:58 -0700423 // Set the parent after we've actually added a child in case a subclass depends on this.
424 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700425 }
426
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100427 private void onChildAdded(WindowContainer child) {
428 mTreeWeight += child.mTreeWeight;
429 WindowContainer parent = getParent();
430 while (parent != null) {
431 parent.mTreeWeight += child.mTreeWeight;
432 parent = parent.getParent();
433 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200434 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100435 }
436
Wale Ogunwalef6192862016-09-10 13:42:30 -0700437 /**
438 * Removes the input child container from this container which is its parent.
439 *
440 * @return True if the container did contain the input child and it was detached.
441 */
442 @CallSuper
443 void removeChild(E child) {
444 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100445 onChildRemoved(child);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700446 if (!child.mReparenting) {
447 child.setParent(null);
448 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700449 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700450 throw new IllegalArgumentException("removeChild: container=" + child.getName()
451 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700452 }
453 }
454
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100455 private void onChildRemoved(WindowContainer child) {
456 mTreeWeight -= child.mTreeWeight;
457 WindowContainer parent = getParent();
458 while (parent != null) {
459 parent.mTreeWeight -= child.mTreeWeight;
460 parent = parent.getParent();
461 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200462 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100463 }
464
Wale Ogunwale571771c2016-08-26 13:18:50 -0700465 /**
466 * Removes this window container and its children with no regard for what else might be going on
467 * in the system. For example, the container will be removed during animation if this method is
468 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
469 * which allows the system to defer removal until a suitable time.
470 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700471 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700472 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700473 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100474 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700475 child.removeImmediately();
476 // Need to do this after calling remove on the child because the child might try to
477 // remove/detach itself from its parent which will cause an exception if we remove
478 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100479 if (mChildren.remove(child)) {
480 onChildRemoved(child);
481 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700482 }
483
Robert Carrb1579c82017-09-05 14:54:47 -0700484 if (mSurfaceControl != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800485 getPendingTransaction().remove(mSurfaceControl);
chaviw6728e2f2018-03-19 15:58:04 -0700486
487 // Merge to parent transaction to ensure the transactions on this WindowContainer are
488 // applied in native even if WindowContainer is removed.
489 if (mParent != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800490 mParent.getPendingTransaction().merge(getPendingTransaction());
chaviw6728e2f2018-03-19 15:58:04 -0700491 }
492
Robert Carrb1579c82017-09-05 14:54:47 -0700493 mSurfaceControl = null;
Garfield Tan265ab91a2019-11-12 16:30:49 -0800494 mLastSurfacePosition.set(0, 0);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000495 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700496 }
497
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700498 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700499 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700500 }
501 }
502
503 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100504 * @return The index of this element in the hierarchy tree in prefix order.
505 */
506 int getPrefixOrderIndex() {
507 if (mParent == null) {
508 return 0;
509 }
510 return mParent.getPrefixOrderIndex(this);
511 }
512
513 private int getPrefixOrderIndex(WindowContainer child) {
514 int order = 0;
515 for (int i = 0; i < mChildren.size(); i++) {
516 final WindowContainer childI = mChildren.get(i);
517 if (child == childI) {
518 break;
519 }
520 order += childI.mTreeWeight;
521 }
522 if (mParent != null) {
523 order += mParent.getPrefixOrderIndex(this);
524 }
525
526 // We also need to count ourselves.
527 order++;
528 return order;
529 }
530
531 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700532 * Removes this window container and its children taking care not to remove them during a
533 * critical stage in the system. For example, some containers will not be removed during
534 * animation if this method is called.
535 */
536 // TODO: figure-out implementation that works best for this.
537 // E.g. when do we remove from parent list? maybe not...
538 void removeIfPossible() {
539 for (int i = mChildren.size() - 1; i >= 0; --i) {
540 final WindowContainer wc = mChildren.get(i);
541 wc.removeIfPossible();
542 }
543 }
544
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700545 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000546 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700547 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000548 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700549 if (current == child || current.hasChild(child)) {
550 return true;
551 }
552 }
553 return false;
554 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700555
Andrii Kulian441e4492016-09-29 15:25:00 -0700556 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800557 * Move a child from it's current place in siblings list to the specified position,
558 * with an option to move all its parents to top.
559 * @param position Target position to move the child to.
560 * @param child Child to move to selected position.
561 * @param includingParents Flag indicating whether we need to move the entire branch of the
562 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
563 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
564 * this flag will do nothing.
565 */
566 @CallSuper
567 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800568
569 if (child.getParent() != this) {
570 throw new IllegalArgumentException("removeChild: container=" + child.getName()
571 + " is not a child of container=" + getName()
572 + " current parent=" + child.getParent());
573 }
574
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800575 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800576 position = POSITION_TOP;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700577 } else if (position <= 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800578 position = POSITION_BOTTOM;
579 }
580
581 switch (position) {
582 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800583 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800584 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200585 mChildren.add(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200586 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800587 }
588 if (includingParents && getParent() != null) {
589 getParent().positionChildAt(POSITION_TOP, this /* child */,
590 true /* includingParents */);
591 }
592 break;
593 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800594 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800595 mChildren.remove(child);
596 mChildren.addFirst(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200597 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800598 }
599 if (includingParents && getParent() != null) {
600 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
601 true /* includingParents */);
602 }
603 break;
604 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800605 // TODO: Removing the child before reinserting requires the caller to provide a
606 // position that takes into account the removed child (if the index of the
607 // child < position, then the position should be adjusted). We should consider
608 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800609 mChildren.remove(child);
610 mChildren.add(position, child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200611 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800612 }
613 }
614
615 /**
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800616 * Notify that a child's position has changed. Possible changes are adding or removing a child.
617 */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200618 void onChildPositionChanged(WindowContainer child) { }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800619
620 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700621 * Update override configuration and recalculate full config.
Evan Roskydfe3da72018-10-26 17:21:06 -0700622 * @see #mRequestedOverrideConfiguration
Andrii Kulian441e4492016-09-29 15:25:00 -0700623 * @see #mFullConfiguration
624 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700625 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700626 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800627 // We must diff before the configuration is applied so that we can capture the change
628 // against the existing bounds.
Evan Roskydfe3da72018-10-26 17:21:06 -0700629 final int diff = diffRequestedOverrideBounds(
630 overrideConfiguration.windowConfiguration.getBounds());
631 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700632 if (mParent != null) {
633 mParent.onDescendantOverrideConfigurationChanged();
634 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800635
636 if (diff == BOUNDS_CHANGE_NONE) {
637 return;
638 }
639
640 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
641 onResize();
642 } else {
643 onMovedByResize();
644 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700645 }
646
647 /**
648 * Notify that a descendant's overrideConfiguration has changed.
649 */
650 void onDescendantOverrideConfigurationChanged() {
651 if (mParent != null) {
652 mParent.onDescendantOverrideConfigurationChanged();
653 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700654 }
655
656 /**
Garfield Tan2f145f22018-11-01 15:27:03 -0700657 * Notify that the display this container is on has changed. This could be either this container
658 * is moved to a new display, or some configurations on the display it is on changes.
659 *
660 * @param dc The display this container is on after changes.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700661 */
662 void onDisplayChanged(DisplayContent dc) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800663 mDisplayContent = dc;
664 if (dc != null && dc != this) {
665 dc.getPendingTransaction().merge(mPendingTransaction);
666 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700667 for (int i = mChildren.size() - 1; i >= 0; --i) {
668 final WindowContainer child = mChildren.get(i);
669 child.onDisplayChanged(dc);
670 }
671 }
672
Tiger Huanged6794e2019-05-07 20:07:59 +0800673 DisplayContent getDisplayContent() {
674 return mDisplayContent;
675 }
676
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700677 void setWaitingForDrawnIfResizingChanged() {
678 for (int i = mChildren.size() - 1; i >= 0; --i) {
679 final WindowContainer wc = mChildren.get(i);
680 wc.setWaitingForDrawnIfResizingChanged();
681 }
682 }
683
684 void onResize() {
685 for (int i = mChildren.size() - 1; i >= 0; --i) {
686 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800687 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700688 }
689 }
690
Bryce Leed92ae482018-01-22 13:56:23 -0800691 void onParentResize() {
692 // In the case this container has specified its own bounds, a parent resize will not
693 // affect its bounds. Any relevant changes will be propagated through changes to the
694 // Configuration override.
695 if (hasOverrideBounds()) {
696 return;
697 }
698
699 // Default implementation is to treat as resize on self.
700 onResize();
701 }
702
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700703 void onMovedByResize() {
704 for (int i = mChildren.size() - 1; i >= 0; --i) {
705 final WindowContainer wc = mChildren.get(i);
706 wc.onMovedByResize();
707 }
708 }
709
710 void resetDragResizingChangeReported() {
711 for (int i = mChildren.size() - 1; i >= 0; --i) {
712 final WindowContainer wc = mChildren.get(i);
713 wc.resetDragResizingChangeReported();
714 }
715 }
716
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700717 void forceWindowsScaleableInTransaction(boolean force) {
718 for (int i = mChildren.size() - 1; i >= 0; --i) {
719 final WindowContainer wc = mChildren.get(i);
720 wc.forceWindowsScaleableInTransaction(force);
721 }
722 }
723
Jorim Jaggia5e10572017-11-15 14:36:26 +0100724 /**
lumark9bca6b42019-10-17 18:35:22 +0800725 * @return {@code true} when this container or its related containers are running an
726 * animation, {@code false} otherwise.
727 *
728 * By default this predicate only checks if this container itself is actually running an
729 * animation, but you can extend the check target over its relatives, or relax the condition
730 * so that this can return {@code true} if an animation starts soon by giving a combination
731 * of {@link #AnimationFlags}.
732 *
733 * Note that you can give a combination of bitmask flags to specify targets and condition for
734 * checking animating status.
735 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
736 * container itself or one of its parents is running an animation or waiting for an app
737 * transition.
738 *
739 * Note that TRANSITION propagates to parents and children as well.
740 *
741 * {@see AnimationFlags#TRANSITION}
742 * {@see AnimationFlags#PARENTS}
743 * {@see AnimationFlags#CHILDREN}
Jorim Jaggia5e10572017-11-15 14:36:26 +0100744 */
lumark9bca6b42019-10-17 18:35:22 +0800745 final boolean isAnimating(int flags) {
746 if (mSurfaceAnimator.isAnimating()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100747 return true;
748 }
lumark9bca6b42019-10-17 18:35:22 +0800749 if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
750 return true;
751 }
752 if ((flags & PARENTS) != 0) {
753 final WindowContainer parent = getParent();
754 if (parent != null && parent.isAnimating(flags & ~CHILDREN)) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700755 return true;
756 }
757 }
lumark9bca6b42019-10-17 18:35:22 +0800758 if ((flags & CHILDREN) != 0) {
759 for (int i = 0; i < mChildren.size(); ++i) {
760 final WindowContainer wc = mChildren.get(i);
761 if (wc.isAnimating(flags & ~PARENTS)) {
762 return true;
763 }
764 }
765 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700766 return false;
767 }
768
Jorim Jaggia5e10572017-11-15 14:36:26 +0100769 /**
lumark9bca6b42019-10-17 18:35:22 +0800770 * @return {@code true} when the container is waiting the app transition start, {@code false}
771 * otherwise.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100772 */
lumark9bca6b42019-10-17 18:35:22 +0800773 boolean isWaitingForTransitionStart() {
774 return false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100775 }
776
777 /**
lumark9bca6b42019-10-17 18:35:22 +0800778 * @return {@code true} if in this subtree of the hierarchy we have an
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800779 * {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200780 */
lumark9bca6b42019-10-17 18:35:22 +0800781 boolean isAppTransitioning() {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800782 return getActivity(app -> app.isAnimating(TRANSITION)) != null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200783 }
784
785 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100786 * @return Whether our own container running an animation at the moment.
787 */
lumark9bca6b42019-10-17 18:35:22 +0800788 final boolean isAnimating() {
789 return isAnimating(0 /* self only */);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100790 }
791
lumark19a5d2e2019-10-11 16:19:30 +0800792 /**
793 * @return {@code true} if the container is in changing app transition.
794 */
795 boolean isChangingAppTransition() {
796 return false;
797 }
798
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700799 void sendAppVisibilityToClients() {
800 for (int i = mChildren.size() - 1; i >= 0; --i) {
801 final WindowContainer wc = mChildren.get(i);
802 wc.sendAppVisibilityToClients();
803 }
804 }
805
Wale Ogunwale44f21802016-09-02 12:49:48 -0700806 /**
807 * Returns true if the container or one of its children as some content it can display or wants
808 * to display (e.g. app views or saved surface).
809 *
810 * NOTE: While this method will return true if the there is some content to display, it doesn't
811 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
812 * visible.
813 */
814 boolean hasContentToDisplay() {
815 for (int i = mChildren.size() - 1; i >= 0; --i) {
816 final WindowContainer wc = mChildren.get(i);
817 if (wc.hasContentToDisplay()) {
818 return true;
819 }
820 }
821 return false;
822 }
823
824 /**
825 * Returns true if the container or one of its children is considered visible from the
826 * WindowManager perspective which usually means valid surface and some other internal state
827 * are true.
828 *
829 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
830 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
831 * the container has any content to display.
832 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700833 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700834 // TODO: Will this be more correct if it checks the visibility of its parents?
835 // It depends...For example, Tasks and Stacks are only visible if there children are visible
836 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800837 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700838 for (int i = mChildren.size() - 1; i >= 0; --i) {
839 final WindowContainer wc = mChildren.get(i);
840 if (wc.isVisible()) {
841 return true;
842 }
843 }
844 return false;
845 }
846
Bryce Lee00d586d2017-07-28 20:48:43 -0700847 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700848 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700849 */
850 boolean isOnTop() {
851 return getParent().getTopChild() == this && getParent().isOnTop();
852 }
853
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100854 /** Returns the top child container. */
855 E getTopChild() {
856 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700857 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700858
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700859 /** Returns true if there is still a removal being deferred */
860 boolean checkCompleteDeferredRemoval() {
861 boolean stillDeferringRemoval = false;
862
863 for (int i = mChildren.size() - 1; i >= 0; --i) {
864 final WindowContainer wc = mChildren.get(i);
865 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
866 }
867
868 return stillDeferringRemoval;
869 }
870
871 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700872 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700873 for (int i = mChildren.size() - 1; i >= 0; --i) {
874 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700875 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700876 }
877 }
878
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700879 void onAppTransitionDone() {
880 for (int i = mChildren.size() - 1; i >= 0; --i) {
881 final WindowContainer wc = mChildren.get(i);
882 wc.onAppTransitionDone();
883 }
884 }
885
Garfield Tan90b04282018-12-11 14:04:42 -0800886 /**
887 * Called when this container or one of its descendants changed its requested orientation, and
888 * wants this container to handle it or pass it to its parent.
889 *
890 * @param freezeDisplayToken freeze this app window token if display needs to freeze
891 * @param requestingContainer the container which orientation request has changed
892 * @return {@code true} if handled; {@code false} otherwise.
893 */
894 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
895 @Nullable ConfigurationContainer requestingContainer) {
896 final WindowContainer parent = getParent();
897 if (parent == null) {
898 return false;
899 }
900 return parent.onDescendantOrientationChanged(freezeDisplayToken,
901 requestingContainer);
902 }
903
904 /**
Garfield Tan49dae102019-02-04 09:51:59 -0800905 * Check if this container or its parent will handle orientation changes from descendants. It's
906 * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
907 * ConfigurationContainer)} in the sense that the return value of this method tells if this
908 * container or its parent will handle the request eventually, while the return value of the
909 * other method is if it handled the request synchronously.
910 *
911 * @return {@code true} if it handles or will handle orientation change in the future; {@code
912 * false} if it won't handle the change at anytime.
913 */
914 boolean handlesOrientationChangeFromDescendant() {
915 final WindowContainer parent = getParent();
916 return parent != null && parent.handlesOrientationChangeFromDescendant();
917 }
918
919 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800920 * Get the configuration orientation by the requested screen orientation
921 * ({@link ActivityInfo.ScreenOrientation}) of this activity.
922 *
923 * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
924 * {@link Configuration#ORIENTATION_PORTRAIT},
925 * {@link Configuration#ORIENTATION_UNDEFINED}).
926 */
927 int getRequestedConfigurationOrientation() {
928 if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
929 // NOSENSOR means the display's "natural" orientation, so return that.
930 if (mDisplayContent != null) {
931 return mDisplayContent.getNaturalOrientation();
932 }
933 } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
934 // LOCKED means the activity's orientation remains unchanged, so return existing value.
935 return getConfiguration().orientation;
936 } else if (isFixedOrientationLandscape(mOrientation)) {
937 return ORIENTATION_LANDSCAPE;
938 } else if (isFixedOrientationPortrait(mOrientation)) {
939 return ORIENTATION_PORTRAIT;
940 }
941 return ORIENTATION_UNDEFINED;
942 }
943
944 /**
Garfield Tan90b04282018-12-11 14:04:42 -0800945 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
946 * parameters.
947 *
948 * @param orientation the specified orientation.
949 */
Wale Ogunwale51362492016-09-08 17:49:17 -0700950 void setOrientation(int orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -0800951 setOrientation(orientation, null /* freezeDisplayToken */,
952 null /* ActivityRecord */);
953 }
954
955 /**
956 * Sets the specified orientation of this container. It percolates this change upward along the
957 * hierarchy to let each level of the hierarchy a chance to respond to it.
958 *
959 * @param orientation the specified orientation. Needs to be one of {@link
960 * android.content.pm.ActivityInfo.ScreenOrientation}.
961 * @param freezeDisplayToken uses this token to freeze display if orientation change is not
962 * done. Display will not be frozen if this is {@code null}, which
963 * should only happen in tests.
964 * @param requestingContainer the container which orientation request has changed. Mostly used
965 * to ensure it gets correct configuration.
966 */
967 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
968 @Nullable ConfigurationContainer requestingContainer) {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700969 if (mOrientation == orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -0800970 return;
971 }
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700972
973 mOrientation = orientation;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800974 final int configOrientation = getRequestedConfigurationOrientation();
975 if (getRequestedOverrideConfiguration().orientation != configOrientation) {
976 mTmpConfig.setTo(getRequestedOverrideConfiguration());
977 mTmpConfig.orientation = configOrientation;
978 onRequestedOverrideConfigurationChanged(mTmpConfig);
979 }
980
Garfield Tan90b04282018-12-11 14:04:42 -0800981 final WindowContainer parent = getParent();
982 if (parent != null) {
983 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
984 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700985 }
986
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700987 int getOrientation() {
988 return getOrientation(mOrientation);
989 }
990
Wale Ogunwale51362492016-09-08 17:49:17 -0700991 /**
992 * Returns the specified orientation for this window container or one of its children is there
993 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
994 * specification is set.
995 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
996 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700997 *
998 * @param candidate The current orientation candidate that will be returned if we don't find a
999 * better match.
1000 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -07001001 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001002 int getOrientation(int candidate) {
Bryce Leea163b762017-01-24 11:05:01 -08001003 if (!fillsParent()) {
1004 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -07001005 return SCREEN_ORIENTATION_UNSET;
1006 }
1007
Bryce Leea163b762017-01-24 11:05:01 -08001008 // The container fills its parent so we can use it orientation if it has one
1009 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -07001010 // specified and fall back on this container's unset or unspecified value as a candidate
1011 // if none of the children have a better candidate for the orientation.
1012 if (mOrientation != SCREEN_ORIENTATION_UNSET
1013 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1014 return mOrientation;
1015 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001016
1017 for (int i = mChildren.size() - 1; i >= 0; --i) {
1018 final WindowContainer wc = mChildren.get(i);
1019
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001020 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
1021 // SCREEN_ORIENTATION_UNSPECIFIED?
1022 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
1023 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -07001024 if (orientation == SCREEN_ORIENTATION_BEHIND) {
1025 // container wants us to use the orientation of the container behind it. See if we
1026 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
1027 // look behind this container.
1028 candidate = orientation;
1029 continue;
1030 }
1031
1032 if (orientation == SCREEN_ORIENTATION_UNSET) {
1033 continue;
1034 }
1035
1036 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1037 // Use the orientation if the container fills its parent or requested an explicit
1038 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
1039 return orientation;
1040 }
1041 }
1042
1043 return candidate;
1044 }
1045
1046 /**
1047 * Returns true if this container is opaque and fills all the space made available by its parent
1048 * container.
1049 *
1050 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
1051 * this is just a signal from the client to window manager stating its intent, but not what it
1052 * actually does.
1053 */
1054 boolean fillsParent() {
1055 return false;
1056 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001057
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001058 // TODO: Users would have their own window containers under the display container?
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001059 void switchUser(int userId) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001060 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001061 mChildren.get(i).switchUser(userId);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001062 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001063 }
1064
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001065 /**
1066 * For all windows at or below this container call the callback.
1067 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
1068 * stops the search if {@link ToBooleanFunction#apply} returns true.
1069 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
1070 * z-order, else from bottom-to-top.
1071 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -08001072 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001073 */
1074 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001075 if (traverseTopToBottom) {
1076 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001077 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1078 return true;
1079 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001080 }
1081 } else {
1082 final int count = mChildren.size();
1083 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001084 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1085 return true;
1086 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001087 }
1088 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001089 return false;
1090 }
1091
1092 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001093 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
1094 forAllWindows(wrapper, traverseTopToBottom);
1095 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001096 }
1097
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001098 boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001099 return forAllActivities(callback, true /*traverseTopToBottom*/);
1100 }
1101
1102 boolean forAllActivities(
1103 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
1104 if (traverseTopToBottom) {
1105 for (int i = mChildren.size() - 1; i >= 0; --i) {
1106 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
1107 }
1108 } else {
1109 final int count = mChildren.size();
1110 for (int i = 0; i < count; i++) {
1111 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
lumark9bca6b42019-10-17 18:35:22 +08001112 }
lumark588a3e82018-07-20 18:53:54 +08001113 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001114
lumark9bca6b42019-10-17 18:35:22 +08001115 return false;
lumark588a3e82018-07-20 18:53:54 +08001116 }
1117
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001118 void forAllActivities(Consumer<ActivityRecord> callback) {
1119 forAllActivities(callback, true /*traverseTopToBottom*/);
1120 }
1121
1122 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
1123 if (traverseTopToBottom) {
1124 for (int i = mChildren.size() - 1; i >= 0; --i) {
1125 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1126 }
1127 } else {
1128 final int count = mChildren.size();
1129 for (int i = 0; i < count; i++) {
1130 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1131 }
1132 }
1133 }
1134
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001135 /**
1136 * Process all activities in this branch of the tree.
1137 *
1138 * @param callback Called for each activity found.
1139 * @param boundary We don't return activities via {@param callback} until we get to this node in
1140 * the tree.
1141 * @param includeBoundary If the boundary from be processed to return activities.
1142 * @param traverseTopToBottom direction to traverse the tree.
1143 * @return {@code true} if we ended the search before reaching the end of the tree.
1144 */
1145 final boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1146 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1147 return forAllActivities(
1148 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1149 }
1150
1151 private boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1152 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1153 boolean[] boundaryFound) {
1154 if (traverseTopToBottom) {
1155 for (int i = mChildren.size() - 1; i >= 0; --i) {
1156 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1157 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1158 return true;
1159 }
1160 }
1161 } else {
1162 final int count = mChildren.size();
1163 for (int i = 0; i < count; i++) {
1164 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1165 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1166 return true;
1167 }
1168 }
1169 }
1170
1171 return false;
1172 }
1173
1174 private boolean processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback,
1175 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1176 boolean[] boundaryFound, WindowContainer wc) {
1177 if (wc == boundary) {
1178 boundaryFound[0] = true;
1179 if (!includeBoundary) return false;
1180 }
1181
1182 if (boundaryFound[0]) {
1183 return wc.forAllActivities(callback, traverseTopToBottom);
1184 }
1185
1186 return wc.forAllActivities(
1187 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1188 }
1189
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001190 /** @return {@code true} if this node or any of its children contains an activity. */
1191 boolean hasActivity() {
1192 for (int i = mChildren.size() - 1; i >= 0; --i) {
1193 if (mChildren.get(i).hasActivity()) {
1194 return true;
1195 }
1196 }
1197 return false;
1198 }
1199
1200 ActivityRecord getActivity(Predicate<ActivityRecord> callback) {
1201 return getActivity(callback, true /*traverseTopToBottom*/);
1202 }
1203
1204 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001205 return getActivity(callback, traverseTopToBottom, null /*boundary*/);
1206 }
1207
1208 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
1209 WindowContainer boundary) {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001210 if (traverseTopToBottom) {
1211 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001212 final WindowContainer wc = mChildren.get(i);
1213 if (wc == boundary) return null;
1214
1215 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001216 if (r != null) {
1217 return r;
1218 }
1219 }
1220 } else {
1221 final int count = mChildren.size();
1222 for (int i = 0; i < count; i++) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001223 final WindowContainer wc = mChildren.get(i);
1224 if (wc == boundary) return null;
1225
1226 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001227 if (r != null) {
1228 return r;
1229 }
1230 }
1231 }
1232
1233 return null;
1234 }
1235
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001236 /**
1237 * Gets an activity in a branch of the tree.
1238 *
1239 * @param callback called to test if this is the activity that should be returned.
1240 * @param boundary We don't return activities via {@param callback} until we get to this node in
1241 * the tree.
1242 * @param includeBoundary If the boundary from be processed to return activities.
1243 * @param traverseTopToBottom direction to traverse the tree.
1244 * @return The activity if found or null.
1245 */
1246 final ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1247 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1248 return getActivity(
1249 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1250 }
1251
1252 private ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1253 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1254 boolean[] boundaryFound) {
1255 if (traverseTopToBottom) {
1256 for (int i = mChildren.size() - 1; i >= 0; --i) {
1257 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1258 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1259 if (r != null) {
1260 return r;
1261 }
1262 }
1263 } else {
1264 final int count = mChildren.size();
1265 for (int i = 0; i < count; i++) {
1266 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1267 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1268 if (r != null) {
1269 return r;
1270 }
1271 }
1272 }
1273
1274 return null;
1275 }
1276
1277 private ActivityRecord processGetActivityWithBoundary(Predicate<ActivityRecord> callback,
1278 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1279 boolean[] boundaryFound, WindowContainer wc) {
1280 if (wc == boundary || boundary == null) {
1281 boundaryFound[0] = true;
1282 if (!includeBoundary) return null;
1283 }
1284
1285 if (boundaryFound[0]) {
1286 return wc.getActivity(callback, traverseTopToBottom);
1287 }
1288
1289 return wc.getActivity(
1290 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1291 }
1292
1293 ActivityRecord getActivityAbove(ActivityRecord r) {
1294 return getActivity((above) -> true, r,
1295 false /*includeBoundary*/, false /*traverseTopToBottom*/);
1296 }
1297
1298 ActivityRecord getActivityBelow(ActivityRecord r) {
1299 return getActivity((below) -> true, r,
1300 false /*includeBoundary*/, true /*traverseTopToBottom*/);
1301 }
1302
1303 ActivityRecord getBottomMostActivity() {
1304 return getActivity((r) -> true, false /*traverseTopToBottom*/);
1305 }
1306
1307 ActivityRecord getTopMostActivity() {
1308 return getActivity((r) -> true, true /*traverseTopToBottom*/);
1309 }
1310
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001311 ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
1312 // Break down into 4 calls to avoid object creation due to capturing input params.
1313 if (includeFinishing) {
1314 if (includeOverlays) {
1315 return getActivity((r) -> true);
1316 }
1317 return getActivity((r) -> !r.mTaskOverlay);
1318 } else if (includeOverlays) {
1319 return getActivity((r) -> !r.finishing);
1320 }
1321
1322 return getActivity((r) -> !r.finishing && !r.mTaskOverlay);
1323 }
1324
Winson Chungd5852192019-09-06 17:20:28 -07001325 void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
1326 for (int i = mChildren.size() - 1; i >= 0; --i) {
1327 mChildren.get(i).forAllWallpaperWindows(callback);
1328 }
1329 }
1330
Jorim Jaggi51304d72017-05-17 17:25:32 +02001331 /**
1332 * For all tasks at or below this container call the callback.
1333 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001334 * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and
1335 * stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
1336 */
1337 boolean forAllTasks(Function<Task, Boolean> callback) {
1338 for (int i = mChildren.size() - 1; i >= 0; --i) {
1339 if (mChildren.get(i).forAllTasks(callback)) {
1340 return true;
1341 }
1342 }
1343 return false;
1344 }
1345
1346 /**
1347 * For all tasks at or below this container call the callback.
1348 *
Jorim Jaggi51304d72017-05-17 17:25:32 +02001349 * @param callback Callback to be called for every task.
1350 */
1351 void forAllTasks(Consumer<Task> callback) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001352 forAllTasks(callback, true /*traverseTopToBottom*/);
1353 }
1354
1355 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
1356 final int count = mChildren.size();
1357 if (traverseTopToBottom) {
1358 for (int i = count - 1; i >= 0; --i) {
1359 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1360 }
1361 } else {
1362 for (int i = 0; i < count; i++) {
1363 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1364 }
Jorim Jaggi51304d72017-05-17 17:25:32 +02001365 }
1366 }
1367
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001368 Task getTaskAbove(Task t) {
1369 return getTask(
1370 (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/);
1371 }
1372
1373 Task getTaskBelow(Task t) {
1374 return getTask((below) -> true, t, false /*includeBoundary*/, true /*traverseTopToBottom*/);
1375 }
1376
1377 Task getBottomMostTask() {
1378 return getTask((t) -> true, false /*traverseTopToBottom*/);
1379 }
1380
1381 Task getTopMostTask() {
1382 return getTask((t) -> true, true /*traverseTopToBottom*/);
1383 }
1384
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001385 Task getTask(Predicate<Task> callback) {
1386 return getTask(callback, true /*traverseTopToBottom*/);
1387 }
1388
1389 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
1390 if (traverseTopToBottom) {
1391 for (int i = mChildren.size() - 1; i >= 0; --i) {
1392 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1393 if (t != null) {
1394 return t;
1395 }
1396 }
1397 } else {
1398 final int count = mChildren.size();
1399 for (int i = 0; i < count; i++) {
1400 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1401 if (t != null) {
1402 return t;
1403 }
1404 }
1405 }
1406
1407 return null;
1408 }
1409
lumarkbc0032a2019-11-01 21:38:13 +08001410 /**
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001411 * Gets an task in a branch of the tree.
lumarkbc0032a2019-11-01 21:38:13 +08001412 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001413 * @param callback called to test if this is the task that should be returned.
1414 * @param boundary We don't return tasks via {@param callback} until we get to this node in
1415 * the tree.
1416 * @param includeBoundary If the boundary from be processed to return tasks.
1417 * @param traverseTopToBottom direction to traverse the tree.
1418 * @return The task if found or null.
lumarkbc0032a2019-11-01 21:38:13 +08001419 */
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001420 final Task getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary,
1421 boolean traverseTopToBottom) {
1422 return getTask(callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1423 }
1424
1425 private Task getTask(Predicate<Task> callback,
1426 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1427 boolean[] boundaryFound) {
1428 if (traverseTopToBottom) {
1429 for (int i = mChildren.size() - 1; i >= 0; --i) {
1430 final Task t = processGetTaskWithBoundary(callback, boundary,
1431 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1432 if (t != null) {
1433 return t;
1434 }
1435 }
1436 } else {
1437 final int count = mChildren.size();
1438 for (int i = 0; i < count; i++) {
1439 final Task t = processGetTaskWithBoundary(callback, boundary,
1440 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1441 if (t != null) {
1442 return t;
1443 }
lumarkbc0032a2019-11-01 21:38:13 +08001444 }
1445 }
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001446
1447 return null;
1448 }
1449
1450 private Task processGetTaskWithBoundary(Predicate<Task> callback,
1451 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1452 boolean[] boundaryFound, WindowContainer wc) {
1453 if (wc == boundary || boundary == null) {
1454 boundaryFound[0] = true;
1455 if (!includeBoundary) return null;
1456 }
1457
1458 if (boundaryFound[0]) {
1459 return wc.getTask(callback, traverseTopToBottom);
1460 }
1461
1462 return wc.getTask(
1463 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
lumarkbc0032a2019-11-01 21:38:13 +08001464 }
1465
Wale Ogunwaled1880962016-11-08 10:31:59 -08001466 WindowState getWindow(Predicate<WindowState> callback) {
1467 for (int i = mChildren.size() - 1; i >= 0; --i) {
1468 final WindowState w = mChildren.get(i).getWindow(callback);
1469 if (w != null) {
1470 return w;
1471 }
1472 }
1473
1474 return null;
1475 }
1476
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001477 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -07001478 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
1479 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001480 */
1481 @Override
1482 public int compareTo(WindowContainer other) {
1483 if (this == other) {
1484 return 0;
1485 }
1486
1487 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +02001488 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001489 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
1490 }
1491
1492 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
1493 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001494 try {
1495 getParents(thisParentChain);
1496 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001497
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001498 // Find the common ancestor of both containers.
1499 WindowContainer commonAncestor = null;
1500 WindowContainer thisTop = thisParentChain.peekLast();
1501 WindowContainer otherTop = otherParentChain.peekLast();
1502 while (thisTop != null && otherTop != null && thisTop == otherTop) {
1503 commonAncestor = thisParentChain.removeLast();
1504 otherParentChain.removeLast();
1505 thisTop = thisParentChain.peekLast();
1506 otherTop = otherParentChain.peekLast();
1507 }
1508
1509 // Containers don't belong to the same hierarchy???
1510 if (commonAncestor == null) {
1511 throw new IllegalArgumentException("No in the same hierarchy this="
1512 + thisParentChain + " other=" + otherParentChain);
1513 }
1514
1515 // Children are always considered greater than their parents, so if one of the containers
1516 // we are comparing it the parent of the other then whichever is the child is greater.
1517 if (commonAncestor == this) {
1518 return -1;
1519 } else if (commonAncestor == other) {
1520 return 1;
1521 }
1522
1523 // The position of the first non-common ancestor in the common ancestor list determines
1524 // which is greater the which.
1525 final WindowList<WindowContainer> list = commonAncestor.mChildren;
1526 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
1527 ? 1 : -1;
1528 } finally {
1529 mTmpChain1.clear();
1530 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001531 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001532 }
1533
1534 private void getParents(LinkedList<WindowContainer> parents) {
1535 parents.clear();
1536 WindowContainer current = this;
1537 do {
1538 parents.addLast(current);
1539 current = current.mParent;
1540 } while (current != null);
1541 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001542
Robert Carrb1579c82017-09-05 14:54:47 -07001543 SurfaceControl.Builder makeSurface() {
1544 final WindowContainer p = getParent();
1545 return p.makeChildSurface(this);
1546 }
1547
Robert Carrf59b8dd2017-10-02 18:58:36 -07001548 /**
1549 * @param child The WindowContainer this child surface is for, or null if the Surface
1550 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
1551 */
Robert Carrb1579c82017-09-05 14:54:47 -07001552 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1553 final WindowContainer p = getParent();
1554 // Give the parent a chance to set properties. In hierarchy v1 we rely
1555 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -08001556 return p.makeChildSurface(child)
1557 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -07001558 }
Robert Carrdea7bf42019-04-04 12:02:51 -07001559 /*
1560 * @return The SurfaceControl parent for this containers SurfaceControl.
1561 * The SurfaceControl must be valid if non-null.
1562 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001563 @Override
1564 public SurfaceControl getParentSurfaceControl() {
1565 final WindowContainer parent = getParent();
1566 if (parent == null) {
1567 return null;
1568 }
1569 return parent.getSurfaceControl();
1570 }
1571
Robert Carrb1579c82017-09-05 14:54:47 -07001572 /**
1573 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1574 */
1575 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +09001576 if (mSurfaceControl == null) {
1577 return false;
1578 }
1579
Robert Carrb1579c82017-09-05 14:54:47 -07001580 for (int i = 0; i < mChildren.size(); i++) {
1581 if (!mChildren.get(i).shouldMagnify()) {
1582 return false;
1583 }
1584 }
1585 return true;
1586 }
1587
1588 SurfaceSession getSession() {
1589 if (getParent() != null) {
1590 return getParent().getSession();
1591 }
1592 return null;
1593 }
1594
1595 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001596 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1597 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001598 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001599 mLastLayer = layer;
1600 mLastRelativeToLayer = null;
1601 }
1602 }
1603
1604 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1605 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1606 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001607 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001608 mLastLayer = layer;
1609 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -07001610 }
1611 }
1612
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001613 protected void setLayer(Transaction t, int layer) {
1614
1615 // Route through surface animator to accommodate that our surface control might be
1616 // attached to the leash, and leash is attached to parent container.
1617 mSurfaceAnimator.setLayer(t, layer);
1618 }
1619
1620 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1621
1622 // Route through surface animator to accommodate that our surface control might be
1623 // attached to the leash, and leash is attached to parent container.
1624 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1625 }
1626
1627 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1628 mSurfaceAnimator.reparent(t, newParent);
1629 }
1630
Robert Carrb1579c82017-09-05 14:54:47 -07001631 void assignChildLayers(Transaction t) {
1632 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -07001633
1634 // We use two passes as a way to promote children which
1635 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001636 for (int j = 0; j < mChildren.size(); ++j) {
1637 final WindowContainer wc = mChildren.get(j);
1638 wc.assignChildLayers(t);
1639 if (!wc.needsZBoost()) {
1640 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001641 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001642 }
1643 for (int j = 0; j < mChildren.size(); ++j) {
1644 final WindowContainer wc = mChildren.get(j);
1645 if (wc.needsZBoost()) {
1646 wc.assignLayer(t, layer++);
1647 }
Robert Carrb1579c82017-09-05 14:54:47 -07001648 }
1649 }
1650
1651 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001652 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001653 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001654 }
1655
1656 boolean needsZBoost() {
1657 for (int i = 0; i < mChildren.size(); i++) {
1658 if (mChildren.get(i).needsZBoost()) {
1659 return true;
1660 }
1661 }
1662 return false;
1663 }
1664
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001665 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001666 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001667 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001668 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001669 * @param proto Stream to write the WindowContainer object to.
1670 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
Nataniel Borges023ecb52019-01-16 14:15:43 -08001671 * @param logLevel Determines the amount of data to be written to the Protobuf.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001672 * @hide
1673 */
1674 @CallSuper
1675 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -08001676 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -08001677 @WindowTraceLogLevel int logLevel) {
1678 boolean isVisible = isVisible();
1679 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1680 return;
1681 }
1682
Adrian Roos4921ccf2017-09-28 16:54:06 +02001683 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08001684 super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001685 proto.write(ORIENTATION, mOrientation);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001686 proto.write(VISIBLE, isVisible);
1687 if (mSurfaceAnimator.isAnimating()) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001688 mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001689 }
Adrian Roos4921ccf2017-09-28 16:54:06 +02001690 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001691 }
1692
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001693 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1694 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1695 if (wrapper == null) {
1696 wrapper = new ForAllWindowsConsumerWrapper();
1697 }
1698 wrapper.setConsumer(consumer);
1699 return wrapper;
1700 }
1701
1702 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1703
1704 private Consumer<WindowState> mConsumer;
1705
1706 void setConsumer(Consumer<WindowState> consumer) {
1707 mConsumer = consumer;
1708 }
1709
1710 @Override
1711 public boolean apply(WindowState w) {
1712 mConsumer.accept(w);
1713 return false;
1714 }
1715
1716 void release() {
1717 mConsumer = null;
1718 mConsumerWrapperPool.release(this);
1719 }
1720 }
Robert Carrb1579c82017-09-05 14:54:47 -07001721
1722 // TODO(b/68336570): Should this really be on WindowContainer since it
1723 // can only be used on the top-level nodes that aren't animated?
1724 // (otherwise we would be fighting other callers of setMatrix).
1725 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1726 if (shouldMagnify()) {
1727 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1728 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
1729 } else {
1730 for (int i = 0; i < mChildren.size(); i++) {
1731 mChildren.get(i).applyMagnificationSpec(t, spec);
1732 }
1733 }
1734 }
1735
Robert Carrb1579c82017-09-05 14:54:47 -07001736 void prepareSurfaces() {
chaviw7f1fa992018-01-10 13:52:12 -08001737 // If a leash has been set when the transaction was committed, then the leash reparent has
1738 // been committed.
1739 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001740 for (int i = 0; i < mChildren.size(); i++) {
1741 mChildren.get(i).prepareSurfaces();
1742 }
1743 }
1744
1745 /**
chaviw7f1fa992018-01-10 13:52:12 -08001746 * @return true if the reparent to animation leash transaction has been committed, false
1747 * otherwise.
1748 */
1749 boolean hasCommittedReparentToAnimationLeash() {
1750 return mCommittedReparentToAnimationLeash;
1751 }
1752
1753 /**
Tiger Huanged6794e2019-05-07 20:07:59 +08001754 * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
1755 * will be applied.
Robert Carrb1579c82017-09-05 14:54:47 -07001756 */
1757 void scheduleAnimation() {
1758 if (mParent != null) {
1759 mParent.scheduleAnimation();
1760 }
1761 }
1762
Robert Carrdea7bf42019-04-04 12:02:51 -07001763 /**
1764 * @return The SurfaceControl for this container.
1765 * The SurfaceControl must be valid if non-null.
1766 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001767 @Override
1768 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001769 return mSurfaceControl;
1770 }
1771
Jorim Jaggia5e10572017-11-15 14:36:26 +01001772 @Override
1773 public Transaction getPendingTransaction() {
Tiger Huanged6794e2019-05-07 20:07:59 +08001774 final DisplayContent displayContent = getDisplayContent();
1775 if (displayContent != null && displayContent != this) {
1776 return displayContent.getPendingTransaction();
1777 }
1778 // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
1779 // let the caller to save the surface operations within the local mPendingTransaction.
1780 // If this is not a DisplayContent, we will merge it to the pending transaction of its
1781 // display once it attaches to it.
Robert Carrf59b8dd2017-10-02 18:58:36 -07001782 return mPendingTransaction;
1783 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001784
1785 /**
1786 * Starts an animation on the container.
1787 *
1788 * @param anim The animation to run.
1789 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1790 * some point but the meaning is too weird to work for all containers.
1791 */
1792 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
1793 if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim);
1794
1795 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1796 // the moment this doesn't work for all animatable window containers.
1797 mSurfaceAnimator.startAnimation(t, anim, hidden);
1798 }
1799
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001800 void transferAnimation(WindowContainer from) {
1801 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1802 }
1803
Jorim Jaggia5e10572017-11-15 14:36:26 +01001804 void cancelAnimation() {
1805 mSurfaceAnimator.cancelAnimation();
1806 }
1807
1808 @Override
1809 public Builder makeAnimationLeash() {
1810 return makeSurface();
1811 }
1812
Jorim Jaggi596a1992017-12-29 14:48:02 +01001813 @Override
1814 public SurfaceControl getAnimationLeashParent() {
1815 return getParentSurfaceControl();
1816 }
1817
chaviw23ee71c2017-12-18 11:29:41 -08001818 /**
1819 * @return The layer on which all app animations are happening.
1820 */
Jorim Jaggi391790622018-04-18 15:30:44 +02001821 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08001822 final WindowContainer parent = getParent();
1823 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02001824 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08001825 }
1826 return null;
1827 }
1828
lumark19a5d2e2019-10-11 16:19:30 +08001829 // TODO: Remove this and use #getBounds() instead once we set an app transition animation
1830 // on TaskStack.
1831 Rect getAnimationBounds(int appStackClipMode) {
1832 return getBounds();
1833 }
1834
1835 /**
1836 * Applies the app transition animation according the given the layout properties in the
1837 * window hierarchy.
1838 *
1839 * @param lp The layout parameters of the window.
1840 * @param transit The app transition type indicates what kind of transition to be applied.
1841 * @param enter Whether the app transition is entering transition or not.
1842 * @param isVoiceInteraction Whether the container is participating in voice interaction or not.
1843 *
1844 * @return {@code true} when the container applied the app transition, {@code false} if the
1845 * app transition is disabled or skipped.
1846 *
1847 * @see #getAnimationAdapter
1848 */
1849 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
1850 boolean isVoiceInteraction) {
1851 if (mWmService.mDisableTransitionAnimation) {
1852 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1853 "applyAnimation: transition animation is disabled or skipped. "
1854 + "container=%s", this);
1855 cancelAnimation();
1856 return false;
1857 }
1858
1859 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
1860 // to animate and it can cause strange artifacts when we unfreeze the display if some
1861 // different animation is running.
1862 try {
1863 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
1864 if (okToAnimate()) {
lumarkbc0032a2019-11-01 21:38:13 +08001865 final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
1866 transit, enter, isVoiceInteraction);
lumark19a5d2e2019-10-11 16:19:30 +08001867 AnimationAdapter adapter = adapters.first;
1868 AnimationAdapter thumbnailAdapter = adapters.second;
1869 if (adapter != null) {
1870 startAnimation(getPendingTransaction(), adapter, !isVisible());
1871 if (adapter.getShowWallpaper()) {
1872 mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
1873 }
1874 if (thumbnailAdapter != null) {
1875 mThumbnail.startAnimation(
1876 getPendingTransaction(), thumbnailAdapter, !isVisible());
1877 }
1878 }
1879 } else {
1880 cancelAnimation();
1881 }
1882 } finally {
1883 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
1884 }
1885
1886 return isAnimating();
1887 }
1888
1889 /**
1890 * Gets the {@link AnimationAdapter} according the given window layout properties in the window
1891 * hierarchy.
1892 *
1893 * @return The return value will always contain two elements, one for normal animations and the
1894 * other for thumbnail animation, both can be {@code null}.
1895 *
1896 * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord
1897 * @See LocalAnimationAdapter
1898 */
1899 Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
1900 int transit, boolean enter, boolean isVoiceInteraction) {
1901 final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;
1902 final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();
1903
1904 // Separate position and size for use in animators.
1905 mTmpRect.set(getAnimationBounds(appStackClipMode));
1906 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
1907 mTmpRect.offsetTo(0, 0);
1908
1909 final RemoteAnimationController controller =
1910 getDisplayContent().mAppTransition.getRemoteAnimationController();
1911 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
1912 && isChangingAppTransition();
1913
1914 // Delaying animation start isn't compatible with remote animations at all.
1915 if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
1916 final RemoteAnimationController.RemoteAnimationRecord adapters =
1917 controller.createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
1918 (isChanging ? mTransitStartRect : null));
1919 resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
1920 } else if (isChanging) {
1921 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
1922 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
1923 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
1924
lumarkbc0032a2019-11-01 21:38:13 +08001925 final AnimationAdapter adapter = new LocalAnimationAdapter(
lumark19a5d2e2019-10-11 16:19:30 +08001926 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, displayInfo,
1927 durationScale, true /* isAppAnimation */, false /* isThumbnail */),
1928 getSurfaceAnimationRunner());
1929
lumarkbc0032a2019-11-01 21:38:13 +08001930 final AnimationAdapter thumbnailAdapter = mThumbnail != null
1931 ? new LocalAnimationAdapter(new WindowChangeAnimationSpec(mTransitStartRect,
1932 mTmpRect, displayInfo, durationScale, true /* isAppAnimation */,
1933 true /* isThumbnail */), getSurfaceAnimationRunner())
1934 : null;
lumark19a5d2e2019-10-11 16:19:30 +08001935 resultAdapters = new Pair<>(adapter, thumbnailAdapter);
1936 mTransit = transit;
1937 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
1938 } else {
1939 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
1940 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
1941
1942 if (a != null) {
1943 // Only apply corner radius to animation if we're not in multi window mode.
1944 // We don't want rounded corners when in pip or split screen.
1945 final float windowCornerRadius = !inMultiWindowMode()
1946 ? getDisplayContent().getWindowCornerRadius()
1947 : 0;
1948 AnimationAdapter adapter = new LocalAnimationAdapter(
1949 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
1950 getDisplayContent().mAppTransition.canSkipFirstFrame(),
1951 appStackClipMode, true /* isAppAnimation */, windowCornerRadius),
1952 getSurfaceAnimationRunner());
1953
1954 resultAdapters = new Pair<>(adapter, null);
1955 mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP;
1956 mTransit = transit;
1957 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
1958 } else {
1959 resultAdapters = new Pair<>(null, null);
1960 }
1961 }
1962 return resultAdapters;
1963 }
1964
1965 final SurfaceAnimationRunner getSurfaceAnimationRunner() {
1966 return mWmService.mSurfaceAnimationRunner;
1967 }
1968
1969 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
1970 boolean isVoiceInteraction) {
1971 final DisplayContent displayContent = getDisplayContent();
1972 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
1973 final int width = displayInfo.appWidth;
1974 final int height = displayInfo.appHeight;
1975 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);
1976
1977 // Determine the visible rect to calculate the thumbnail clip with
1978 // getAnimationFrames.
1979 final Rect frame = new Rect(0, 0, width, height);
1980 final Rect displayFrame = new Rect(0, 0,
1981 displayInfo.logicalWidth, displayInfo.logicalHeight);
1982 final Rect insets = new Rect();
1983 final Rect stableInsets = new Rect();
1984 final Rect surfaceInsets = new Rect();
1985 getAnimationFrames(frame, insets, stableInsets, surfaceInsets);
1986
1987 if (mLaunchTaskBehind) {
1988 // Differentiate the two animations. This one which is briefly on the screen
1989 // gets the !enter animation, and the other one which remains on the
1990 // screen gets the enter animation. Both appear in the mOpeningApps set.
1991 enter = false;
1992 }
1993 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
1994 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
1995 + "surfaceInsets=%s",
1996 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
1997 final Configuration displayConfig = displayContent.getConfiguration();
1998 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
1999 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2000 surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
2001 if (a != null) {
2002 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2003 final int containingWidth = frame.width();
2004 final int containingHeight = frame.height();
2005 a.initialize(containingWidth, containingHeight, width, height);
2006 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
2007 }
2008 return a;
2009 }
2010
2011 RemoteAnimationTarget createRemoteAnimationTarget(
2012 RemoteAnimationController.RemoteAnimationRecord record) {
2013 return null;
2014 }
2015
2016 boolean okToDisplay() {
2017 return mDisplayContent != null && mDisplayContent.okToDisplay();
2018 }
2019
2020 boolean okToAnimate() {
2021 return mDisplayContent != null && mDisplayContent.okToAnimate();
2022 }
2023
Jorim Jaggia5e10572017-11-15 14:36:26 +01002024 @Override
2025 public void commitPendingTransaction() {
2026 scheduleAnimation();
2027 }
2028
Robert Carr2f8aa392018-01-31 14:46:51 -08002029 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01002030 final WindowContainer parent = getParent();
2031 if (parent != null) {
2032 parent.assignChildLayers(t);
2033 }
2034 }
2035
2036 @Override
2037 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002038 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01002039 reassignLayer(t);
2040 }
2041
2042 @Override
lumarkf6f34942019-04-29 16:56:50 +08002043 public void onAnimationLeashLost(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002044 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01002045 reassignLayer(t);
2046 }
2047
2048 /**
2049 * Called when an animation has finished running.
2050 */
2051 protected void onAnimationFinished() {
chaviwccd5d502019-02-22 13:30:31 -08002052 mWmService.onAnimationFinished();
Jorim Jaggia5e10572017-11-15 14:36:26 +01002053 }
2054
2055 /**
2056 * @return The currently running animation, if any, or {@code null} otherwise.
2057 */
2058 AnimationAdapter getAnimation() {
2059 return mSurfaceAnimator.getAnimation();
2060 }
2061
2062 /**
2063 * @see SurfaceAnimator#startDelayingAnimationStart
2064 */
2065 void startDelayingAnimationStart() {
2066 mSurfaceAnimator.startDelayingAnimationStart();
2067 }
2068
2069 /**
2070 * @see SurfaceAnimator#endDelayingAnimationStart
2071 */
2072 void endDelayingAnimationStart() {
2073 mSurfaceAnimator.endDelayingAnimationStart();
2074 }
2075
2076 @Override
2077 public int getSurfaceWidth() {
2078 return mSurfaceControl.getWidth();
2079 }
2080
2081 @Override
2082 public int getSurfaceHeight() {
2083 return mSurfaceControl.getHeight();
2084 }
2085
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002086 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01002087 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2088 if (mSurfaceAnimator.isAnimating()) {
2089 pw.print(prefix); pw.println("ContainerAnimator:");
2090 mSurfaceAnimator.dump(pw, prefix + " ");
2091 }
2092 }
chaviwe07246a2017-12-12 16:18:29 -08002093
chaviw2f0567b2018-01-29 16:22:02 -08002094 void updateSurfacePosition() {
chaviwe07246a2017-12-12 16:18:29 -08002095 if (mSurfaceControl == null) {
2096 return;
2097 }
2098
Evan Roskyed6767f2018-10-26 17:21:06 -07002099 getRelativeDisplayedPosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08002100 if (mTmpPos.equals(mLastSurfacePosition)) {
2101 return;
2102 }
2103
chaviw2f0567b2018-01-29 16:22:02 -08002104 getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08002105 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08002106 }
2107
Evan Rosky65dffa62019-02-04 14:09:53 -08002108 @VisibleForTesting
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002109 Point getLastSurfacePosition() {
2110 return mLastSurfacePosition;
2111 }
2112
Evan Roskyed6767f2018-10-26 17:21:06 -07002113 /**
2114 * Displayed bounds specify where to display this container at. It differs from bounds during
2115 * certain operations (like animation or interactive dragging).
2116 *
2117 * @return the bounds to display this container at.
2118 */
2119 Rect getDisplayedBounds() {
2120 return getBounds();
2121 }
2122
lumark19a5d2e2019-10-11 16:19:30 +08002123 /**
2124 * The {@code outFrame} retrieved by this method specifies where the animation will finish
2125 * the entrance animation, as the next frame will display the window at these coordinates. In
2126 * case of exit animation, this is where the animation will start, as the frame before the
2127 * animation is displaying the window at these bounds.
2128 *
2129 * @param outFrame The bounds where entrance animation finishes or exit animation starts.
2130 * @param outInsets Insets that are covered by system windows.
2131 * @param outStableInsets Insets that determine the area covered by the stable system windows.
2132 * @param outSurfaceInsets Positive insets between the drawing surface and window content.
2133 */
2134 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2135 Rect outSurfaceInsets) {
2136 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2137 outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight);
2138 outInsets.setEmpty();
2139 outStableInsets.setEmpty();
2140 outSurfaceInsets.setEmpty();
2141 }
2142
Evan Roskyed6767f2018-10-26 17:21:06 -07002143 void getRelativeDisplayedPosition(Point outPos) {
2144 final Rect dispBounds = getDisplayedBounds();
2145 outPos.set(dispBounds.left, dispBounds.top);
chaviwe07246a2017-12-12 16:18:29 -08002146 final WindowContainer parent = getParent();
2147 if (parent != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002148 final Rect parentBounds = parent.getDisplayedBounds();
chaviwe07246a2017-12-12 16:18:29 -08002149 outPos.offset(-parentBounds.left, -parentBounds.top);
2150 }
2151 }
chaviw2fb06bc2018-01-19 17:09:15 -08002152
Yunfan Chen87b5a242019-10-01 17:53:59 +09002153 void waitForAllWindowsDrawn() {
2154 final WindowManagerPolicy policy = mWmService.mPolicy;
2155 forAllWindows(w -> {
2156 final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
Garfield Tane8d84ab2019-10-11 09:49:40 -07002157 if (w.isVisibleLw() && (w.mActivityRecord != null || keyguard)) {
Yunfan Chen87b5a242019-10-01 17:53:59 +09002158 w.mWinAnimator.mDrawState = DRAW_PENDING;
2159 // Force add to mResizingWindows.
2160 w.resetLastContentInsets();
2161 mWaitingForDrawn.add(w);
2162 }
2163 }, true /* traverseTopToBottom */);
2164 }
2165
chaviw2fb06bc2018-01-19 17:09:15 -08002166 Dimmer getDimmer() {
2167 if (mParent == null) {
2168 return null;
2169 }
2170 return mParent.getDimmer();
2171 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07002172}