Merge TaskStack and ActivityStack into one class (68/n)
Merge TaskStack and ActivityStack into one class.
Bug: 80414790
Test: Existing tests pass
Change-Id: I96fd5137cb868f277581b6c6d719d63fe2a8c677
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 51e7a01..2a06def 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1160,7 +1160,7 @@
this.task = task;
}
- TaskStack getStack() {
+ ActivityStack getStack() {
return task != null ? task.getTaskStack() : null;
}
@@ -1202,7 +1202,7 @@
} else if (mLastParent != null && mLastParent.getTaskStack() != null) {
task.getTaskStack().mExitingActivities.remove(this);
}
- final TaskStack stack = getStack();
+ final ActivityStack stack = getStack();
// If we reparent, make sure to remove ourselves from the old animation registry.
if (mAnimatingActivityRegistry != null) {
@@ -1266,7 +1266,7 @@
if (prevDc.mFocusedApp == this) {
prevDc.setFocusedApp(null);
- final TaskStack stack = dc.getTopStack();
+ final ActivityStack stack = dc.getTopStack();
if (stack != null) {
final Task task = stack.getTopChild();
if (task != null && task.getTopChild() == this) {
@@ -3024,7 +3024,7 @@
getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
}
- final TaskStack stack = getStack();
+ final ActivityStack stack = getStack();
if (delayed && !isEmpty()) {
// set the token aside because it has an active animation to be finished
ProtoLog.v(WM_DEBUG_ADD_REMOVE,
@@ -3754,7 +3754,7 @@
// Notify the pinned stack upon all windows drawn. If there was an animation in
// progress then this signal will resume that animation.
- final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+ final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
if (pinnedStack != null) {
pinnedStack.onAllWindowsDrawn();
}
@@ -5787,7 +5787,7 @@
getTransit(), task)) {
task.getBounds(mTmpRect);
} else {
- final TaskStack stack = getStack();
+ final ActivityStack stack = getStack();
if (stack == null) {
return;
}
@@ -6547,7 +6547,7 @@
void savePinnedStackBounds() {
// Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds
// for the next re-entry into PiP (assuming the activity is not hidden or destroyed)
- final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+ final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
if (pinnedStack == null) return;
final Rect stackBounds;
if (pinnedStack.lastAnimatingBoundsWasToFullscreen()) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index e22a6e2..c5c9391 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -16,12 +16,15 @@
package com.android.server.wm;
+import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
+import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -33,10 +36,17 @@
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.INVALID_DISPLAY;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
@@ -48,13 +58,10 @@
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
-import static com.android.server.am.ActivityStackProto.BOUNDS;
import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
import static com.android.server.am.ActivityStackProto.FULLSCREEN;
-import static com.android.server.am.ActivityStackProto.ID;
import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityStackProto.STACK;
-import static com.android.server.am.ActivityStackProto.TASKS;
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
@@ -97,8 +104,24 @@
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
+import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
+import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
+import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.RootActivityContainer.FindTaskResult;
+import static com.android.server.wm.StackProto.ADJUSTED_BOUNDS;
+import static com.android.server.wm.StackProto.ADJUSTED_FOR_IME;
+import static com.android.server.wm.StackProto.ADJUST_DIVIDER_AMOUNT;
+import static com.android.server.wm.StackProto.ADJUST_IME_AMOUNT;
+import static com.android.server.wm.StackProto.ANIMATING_BOUNDS;
+import static com.android.server.wm.StackProto.DEFER_REMOVAL;
+import static com.android.server.wm.StackProto.FILLS_PARENT;
+import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
+import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -111,6 +134,7 @@
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityController;
+import android.app.RemoteAction;
import android.app.ResultInfo;
import android.app.WindowConfiguration.ActivityType;
import android.app.WindowConfiguration.WindowingMode;
@@ -124,7 +148,9 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.Region;
import android.net.Uri;
import android.os.Binder;
import android.os.Debug;
@@ -138,17 +164,24 @@
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.util.ArraySet;
+import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
+import android.view.DisplayCutout;
+import android.view.DisplayInfo;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.logging.MetricsLoggerWrapper;
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.internal.policy.DockedDividerUtils;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService;
@@ -167,7 +200,8 @@
/**
* State and management of a single stack of activities.
*/
-class ActivityStack extends TaskStack {
+class ActivityStack extends WindowContainer<Task> implements BoundsAnimationTarget,
+ ConfigurationContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM;
private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
private static final String TAG_APP = TAG + POSTFIX_APP;
@@ -228,52 +262,12 @@
/** Stack is completely invisible. */
static final int STACK_VISIBILITY_INVISIBLE = 2;
- // TODO(display-unify): Remove after display unification.
- protected void onParentChanged(ActivityDisplay newParent, ActivityDisplay oldParent) {
- onParentChanged(
- newParent != null ? newParent.mDisplayContent : null,
- oldParent != null ? oldParent.mDisplayContent : null);
- }
+ /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
+ * restrict IME adjustment so that a min portion of top stack remains visible.*/
+ private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
- @Override
- protected void onParentChanged(
- ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- final ActivityDisplay display = newParent != null
- ? ((WindowContainer) newParent).getDisplayContent().mActivityDisplay : null;
- final ActivityDisplay oldDisplay = oldParent != null
- ? ((WindowContainer) oldParent).getDisplayContent().mActivityDisplay : null;
-
- mDisplayId = (display != null) ? display.mDisplayId : INVALID_DISPLAY;
- mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
-
- if (display != null) {
- // Rotations are relative to the display. This means if there are 2 displays rotated
- // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
- // from one to the other could look like a rotation change. To prevent this
- // apparent rotation change (and corresponding bounds rotation), pretend like our
- // current rotation is already the same as the new display.
- // Note, if ActivityStack or related logic ever gets nested, this logic will need
- // to move to onConfigurationChanged.
- getConfiguration().windowConfiguration.setRotation(
- display.getWindowConfiguration().getRotation());
- }
- super.onParentChanged(newParent, oldParent);
- if (display != null && inSplitScreenPrimaryWindowingMode()) {
- // If we created a docked stack we want to resize it so it resizes all other stacks
- // in the system.
- getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
- mTmpRect /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
- mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect,
- mTmpRect2, null, null, PRESERVE_WINDOWS);
- }
- mRootActivityContainer.updateUIDsPresentOnDisplay();
-
- // Resume next focusable stack after reparenting to another display if we aren't removing
- // the prevous display.
- if (oldDisplay != null && oldDisplay.isRemoving()) {
- postReparent();
- }
- }
+ /** Dimming amount for non-focused stack when stacks are IME-adjusted. */
+ private static final float IME_ADJUST_DIM_AMOUNT = 0.25f;
enum ActivityState {
INITIALIZING,
@@ -362,11 +356,71 @@
// Id of the previous display the stack was on.
int mPrevDisplayId = INVALID_DISPLAY;
+ /** Unique identifier */
+ final int mStackId;
+
+ /** For comparison with DisplayContent bounds. */
+ private Rect mTmpRect = new Rect();
+ private Rect mTmpRect2 = new Rect();
+ private Rect mTmpRect3 = new Rect();
+
+ /** For Pinned stack controlling. */
+ private Rect mTmpToBounds = new Rect();
+
+ /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
+ private final Rect mAdjustedBounds = new Rect();
+
+ /**
+ * Fully adjusted IME bounds. These are different from {@link #mAdjustedBounds} because they
+ * represent the state when the animation has ended.
+ */
+ private final Rect mFullyAdjustedImeBounds = new Rect();
+
+ /** ActivityRecords that are exiting, but still on screen for animations. */
+ final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
+
+ /** Detach this stack from its display when animation completes. */
+ // TODO: maybe tie this to WindowContainer#removeChild some how...
+ private boolean mDeferRemoval;
+
+ private final Rect mTmpAdjustedBounds = new Rect();
+ private boolean mAdjustedForIme;
+ private boolean mImeGoingAway;
+ private WindowState mImeWin;
+ private float mMinimizeAmount;
+ private float mAdjustImeAmount;
+ private float mAdjustDividerAmount;
+ private final int mDockedStackMinimizeThickness;
+
+ // If this is true, we are in the bounds animating mode. The task will be down or upscaled to
+ // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
+ // would otherwise apply while resizing, while resizing in the bounds animating mode.
+ private boolean mBoundsAnimating = false;
+ // Set when an animation has been requested but has not yet started from the UI thread. This is
+ // cleared when the animation actually starts.
+ private boolean mBoundsAnimatingRequested = false;
+ private boolean mBoundsAnimatingToFullscreen = false;
+ private boolean mCancelCurrentBoundsAnimation = false;
+ private Rect mBoundsAnimationTarget = new Rect();
+ private Rect mBoundsAnimationSourceHintBounds = new Rect();
+ private @BoundsAnimationController.AnimationType int mAnimationType;
+
+ Rect mPreAnimationBounds = new Rect();
+
+ private Dimmer mDimmer = new Dimmer(this);
+
+ /**
+ * For {@link #prepareSurfaces}.
+ */
+ private final Rect mTmpDimBoundsRect = new Rect();
+ private final Point mLastSurfaceSize = new Point();
+
+ private final AnimatingActivityRegistry mAnimatingActivityRegistry =
+ new AnimatingActivityRegistry();
+
/** Stores the override windowing-mode from before a transient mode change (eg. split) */
private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED;
- private final Rect mTmpRect = new Rect();
- private final Rect mTmpRect2 = new Rect();
private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic();
/** List for processing through a set of activities */
@@ -474,7 +528,12 @@
ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
int windowingMode, int activityType, boolean onTop) {
- super(supervisor.mService.mWindowManager, stackId);
+ super(supervisor.mService.mWindowManager);
+ mStackId = stackId;
+ mDockedStackMinimizeThickness =
+ supervisor.mService.mWindowManager.mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_minimize_thickness);
+ EventLog.writeEvent(com.android.server.EventLogTags.WM_STACK_CREATED, stackId);
mStackSupervisor = supervisor;
mService = supervisor.mService;
mRootActivityContainer = mService.mRootActivityContainer;
@@ -529,6 +588,27 @@
getBounds(newBounds);
super.onConfigurationChanged(newParentConfig);
+
+ // Only need to update surface size here since the super method will handle updating
+ // surface position.
+ updateSurfaceSize(getPendingTransaction());
+
+ if (mDisplayContent == null) {
+ return;
+ }
+
+ if (prevWindowingMode != getWindowingMode()) {
+ mDisplayContent.onStackWindowingModeChanged(this);
+
+ if (inSplitScreenSecondaryWindowingMode()) {
+ // When the stack is resized due to entering split screen secondary, offset the
+ // windows to compensate for the new stack position.
+ forAllWindows(w -> {
+ w.mWinAnimator.setOffsetPositionForStackResize(true);
+ }, true);
+ }
+ }
+
final ActivityDisplay display = getDisplay();
if (display == null ) {
return;
@@ -835,20 +915,6 @@
return mRootActivityContainer.getActivityDisplay(mDisplayId);
}
- void positionChildAtTop(Task child) {
- positionChildAtTop(child, true /* includingParents */);
- }
-
- private void positionChildAtBottom(Task child) {
- // If there are other focusable stacks on the display, the z-order of the display should not
- // be changed just because a task was placed at the bottom. E.g. if it is moving the topmost
- // task to bottom, the next focusable stack on the same display should be focused.
- final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack(
- child.getStack(), true /* ignoreCurrent */);
- positionChildAtBottom(child, nextFocusableStack == null /* includingParents */);
- child.updateTaskMovement(true);
- }
-
/**
* Defers updating the bounds of the stack. If the stack was resized/repositioned while
* deferring, the bounds will update in {@link #continueUpdateBounds()}.
@@ -4582,11 +4648,6 @@
// We only want to move the parents to the parents if we are creating this task at the
// top of its stack.
addChild(task, toTop ? MAX_VALUE : 0, showForAllUsers, toTop /*moveParents*/);
-
- if (toTop) {
- // TODO(stack-merge): figure-out a way to remove this call.
- positionChildAtTop(task);
- }
}
void positionChildAt(Task task, int position) {
@@ -4600,15 +4661,19 @@
final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
- // TODO(stack-merge): Can all of these be consolidated to just making the super call in the
- // else?
- if (position >= getChildCount()) {
- positionChildAtTop(task);
- } else if (position <= 0) {
- positionChildAtBottom(task);
- } else {
- super.positionChildAt(task, position);
+ boolean toTop = position >= getChildCount();
+ boolean includingParents = toTop || getDisplay().getNextFocusableStack(this,
+ true /* ignoreCurrent */) == null;
+ if (WindowManagerDebugConfig.DEBUG_STACK) {
+ Slog.i(TAG_WM, "positionChildAt: positioning task=" + task + " at " + position);
}
+ positionChildAt(position, task, includingParents);
+ task.updateTaskMovement(toTop);
+ if (getDisplayContent().mAppTransition.isTransitionSet()) {
+ task.setSendingToBottom(!toTop);
+ }
+ getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+
// TODO: Investigate if this random code is really needed.
if (task.voiceSession != null) {
@@ -4690,8 +4755,66 @@
return;
}
}
- super.animateResizePinnedStack(
- toBounds, sourceHintBounds, animationDuration, fromFullscreen);
+
+ // Get the from-bounds
+ final Rect fromBounds = new Rect();
+ getBounds(fromBounds);
+
+ // Get non-null fullscreen to-bounds for animating if the bounds are null
+ @BoundsAnimationController.SchedulePipModeChangedState int schedulePipModeChangedState =
+ NO_PIP_MODE_CHANGED_CALLBACKS;
+ final boolean toFullscreen = toBounds == null;
+ if (toFullscreen) {
+ if (fromFullscreen) {
+ throw new IllegalArgumentException("Should not defer scheduling PiP mode"
+ + " change on animation to fullscreen.");
+ }
+ schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
+
+ mWmService.getStackBounds(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mTmpToBounds);
+ if (!mTmpToBounds.isEmpty()) {
+ // If there is a fullscreen bounds, use that
+ toBounds = new Rect(mTmpToBounds);
+ } else {
+ // Otherwise, use the display bounds
+ toBounds = new Rect();
+ getDisplayContent().getBounds(toBounds);
+ }
+ } else if (fromFullscreen) {
+ schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
+ }
+
+ setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen);
+
+ final Rect finalToBounds = toBounds;
+ final @BoundsAnimationController.SchedulePipModeChangedState int
+ finalSchedulePipModeChangedState = schedulePipModeChangedState;
+ final DisplayContent displayContent = getDisplayContent();
+ @BoundsAnimationController.AnimationType int intendedAnimationType =
+ displayContent.mBoundsAnimationController.getAnimationType();
+ if (intendedAnimationType == FADE_IN) {
+ if (fromFullscreen) {
+ setPinnedStackAlpha(0f);
+ }
+ if (toBounds.width() == fromBounds.width()
+ && toBounds.height() == fromBounds.height()) {
+ intendedAnimationType = BoundsAnimationController.BOUNDS;
+ } else if (!fromFullscreen && !toBounds.equals(fromBounds)) {
+ // intendedAnimationType may have been reset at the end of RecentsAnimation,
+ // force it to BOUNDS type if we know for certain we're animating to
+ // a different bounds, especially for expand and collapse of PiP window.
+ intendedAnimationType = BoundsAnimationController.BOUNDS;
+ }
+ }
+
+ final @BoundsAnimationController.AnimationType int animationType = intendedAnimationType;
+ mCancelCurrentBoundsAnimation = false;
+ displayContent.mBoundsAnimationController.getHandler().post(() -> {
+ displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
+ finalToBounds, animationDuration, finalSchedulePipModeChangedState,
+ fromFullscreen, toFullscreen, animationType);
+ });
}
void dismissPip() {
@@ -4739,6 +4862,1580 @@
return mStackId;
}
+ Task findHomeTask() {
+ if (!isActivityTypeHome() || mChildren.isEmpty()) {
+ return null;
+ }
+ return mChildren.get(mChildren.size() - 1);
+ }
+
+ void prepareFreezingTaskBounds() {
+ for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
+ final Task task = mChildren.get(taskNdx);
+ task.prepareFreezingBounds();
+ }
+ }
+
+ /**
+ * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
+ * the normal task bounds.
+ *
+ * @param bounds The adjusted bounds.
+ */
+ private void setAdjustedBounds(Rect bounds) {
+ if (mAdjustedBounds.equals(bounds) && !isAnimatingForIme()) {
+ return;
+ }
+
+ mAdjustedBounds.set(bounds);
+ final boolean adjusted = !mAdjustedBounds.isEmpty();
+ Rect insetBounds = null;
+ if (adjusted && isAdjustedForMinimizedDockedStack()) {
+ insetBounds = getRawBounds();
+ } else if (adjusted && mAdjustedForIme) {
+ if (mImeGoingAway) {
+ insetBounds = getRawBounds();
+ } else {
+ insetBounds = mFullyAdjustedImeBounds;
+ }
+ }
+ alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : getRawBounds(), insetBounds);
+ mDisplayContent.setLayoutNeeded();
+
+ updateSurfaceBounds();
+ }
+
+ private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
+ if (matchParentBounds()) {
+ return;
+ }
+
+ final boolean alignBottom = mAdjustedForIme && getDockSide() == DOCKED_TOP;
+
+ // Update bounds of containing tasks.
+ for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
+ final Task task = mChildren.get(taskNdx);
+ task.alignToAdjustedBounds(adjustedBounds, tempInsetBounds, alignBottom);
+ }
+ }
+
+ @Override
+ public int setBounds(Rect bounds) {
+ return setBounds(getRequestedOverrideBounds(), bounds);
+ }
+
+ private int setBounds(Rect existing, Rect bounds) {
+ if (equivalentBounds(existing, bounds)) {
+ return BOUNDS_CHANGE_NONE;
+ }
+
+ final int result = super.setBounds(!inMultiWindowMode() ? null : bounds);
+
+ updateAdjustedBounds();
+
+ updateSurfaceBounds();
+ return result;
+ }
+
+ /** Bounds of the stack without adjusting for other factors in the system like visibility
+ * of docked stack.
+ * Most callers should be using {@link ConfigurationContainer#getRequestedOverrideBounds} a
+ * it takes into consideration other system factors. */
+ void getRawBounds(Rect out) {
+ out.set(getRawBounds());
+ }
+
+ private Rect getRawBounds() {
+ return super.getBounds();
+ }
+
+ @Override
+ public void getBounds(Rect bounds) {
+ bounds.set(getBounds());
+ }
+
+ @Override
+ public Rect getBounds() {
+ // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
+ // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
+ // stack is visible since it is already what we want to represent to the rest of the
+ // system.
+ if (!mAdjustedBounds.isEmpty()) {
+ return mAdjustedBounds;
+ } else {
+ return super.getBounds();
+ }
+ }
+
+ /**
+ * Sets the bounds animation target bounds ahead of an animation. This can't currently be done
+ * in onAnimationStart() since that is started on the UiThread.
+ */
+ private void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds,
+ boolean toFullscreen) {
+ if (mAnimationType == BoundsAnimationController.BOUNDS) {
+ mBoundsAnimatingRequested = true;
+ }
+ mBoundsAnimatingToFullscreen = toFullscreen;
+ if (destBounds != null) {
+ mBoundsAnimationTarget.set(destBounds);
+ } else {
+ mBoundsAnimationTarget.setEmpty();
+ }
+ if (sourceHintBounds != null) {
+ mBoundsAnimationSourceHintBounds.set(sourceHintBounds);
+ } else if (!mBoundsAnimating) {
+ // If the bounds are already animating, we don't want to reset the source hint. This is
+ // because the source hint is sent when starting the animation from the client that
+ // requested to enter pip. Other requests can adjust the pip bounds during an animation,
+ // but could accidentally reset the source hint bounds.
+ mBoundsAnimationSourceHintBounds.setEmpty();
+ }
+
+ mPreAnimationBounds.set(getRawBounds());
+ }
+
+ /**
+ * @return the final bounds for the bounds animation.
+ */
+ void getFinalAnimationBounds(Rect outBounds) {
+ outBounds.set(mBoundsAnimationTarget);
+ }
+
+ /**
+ * @return the final source bounds for the bounds animation.
+ */
+ void getFinalAnimationSourceHintBounds(Rect outBounds) {
+ outBounds.set(mBoundsAnimationSourceHintBounds);
+ }
+
+ /**
+ * @return the final animation bounds if the task stack is currently being animated, or the
+ * current stack bounds otherwise.
+ */
+ void getAnimationOrCurrentBounds(Rect outBounds) {
+ if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
+ getFinalAnimationBounds(outBounds);
+ return;
+ }
+ getBounds(outBounds);
+ }
+
+ /** Bounds of the stack with other system factors taken into consideration. */
+ void getDimBounds(Rect out) {
+ getBounds(out);
+ }
+
+ /**
+ * Updates the passed-in {@code inOutBounds} based on the current state of the
+ * pinned controller. This gets run *after* the override configuration is updated, so it's
+ * safe to rely on the controller's state in here (though eventually this dependence should
+ * be removed).
+ *
+ * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
+ * update pinned controller state.
+ *
+ * @param inOutBounds the bounds to update (both input and output).
+ * @return true if bounds were updated to some non-empty value.
+ */
+ boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) {
+ boolean animating = false;
+ if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
+ animating = true;
+ getFinalAnimationBounds(mTmpRect2);
+ } else {
+ mTmpRect2.set(inOutBounds);
+ }
+ boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+ mTmpRect2, mTmpRect3);
+ if (updated) {
+ inOutBounds.set(mTmpRect3);
+
+ // The final boundary is updated while there is an existing boundary animation. Let's
+ // cancel this animation to prevent the obsolete animation overwritten updated bounds.
+ if (animating && !inOutBounds.equals(mBoundsAnimationTarget)) {
+ final DisplayContent displayContent = getDisplayContent();
+ displayContent.mBoundsAnimationController.getHandler().post(() ->
+ displayContent.mBoundsAnimationController.cancel(this));
+ }
+ // Once we've set the bounds based on the rotation of the old bounds in the new
+ // orientation, clear the animation target bounds since they are obsolete, and
+ // cancel any currently running animations
+ mBoundsAnimationTarget.setEmpty();
+ mBoundsAnimationSourceHintBounds.setEmpty();
+ mCancelCurrentBoundsAnimation = true;
+ }
+ return updated;
+ }
+
+ /**
+ * Updates the passed-in {@code inOutBounds} based on the current state of the
+ * docked controller. This gets run *after* the override configuration is updated, so it's
+ * safe to rely on the controller's state in here (though eventually this dependence should
+ * be removed).
+ *
+ * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
+ * update docked controller state.
+ *
+ * @param parentConfig the parent configuration for reference.
+ * @param inOutBounds the bounds to update (both input and output).
+ */
+ void calculateDockedBoundsForConfigChange(Configuration parentConfig, Rect inOutBounds) {
+ final boolean primary =
+ getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+ repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
+ final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
+ snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
+ if (primary) {
+ final int newDockSide = getDockSide(parentConfig, inOutBounds);
+ // Update the dock create mode and clear the dock create bounds, these
+ // might change after a rotation and the original values will be invalid.
+ mWmService.setDockedStackCreateStateLocked(
+ (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
+ ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
+ : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
+ null);
+ mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
+ }
+ }
+
+ /**
+ * Some primary split screen sides are not allowed by the policy. This method queries the policy
+ * and moves the primary stack around if needed.
+ *
+ * @param parentConfig the configuration of the stack's parent.
+ * @param primary true if adjusting the primary docked stack, false for secondary.
+ * @param inOutBounds the bounds of the stack to adjust.
+ */
+ void repositionSplitScreenStackAfterRotation(Configuration parentConfig, boolean primary,
+ Rect inOutBounds) {
+ final int dockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds);
+ final int otherDockSide = DockedDividerUtils.invertDockSide(dockSide);
+ final int primaryDockSide = primary ? dockSide : otherDockSide;
+ if (mDisplayContent.getDockedDividerController()
+ .canPrimaryStackDockTo(primaryDockSide,
+ parentConfig.windowConfiguration.getBounds(),
+ parentConfig.windowConfiguration.getRotation())) {
+ return;
+ }
+ final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
+ switch (otherDockSide) {
+ case DOCKED_LEFT:
+ int movement = inOutBounds.left;
+ inOutBounds.left -= movement;
+ inOutBounds.right -= movement;
+ break;
+ case DOCKED_RIGHT:
+ movement = parentBounds.right - inOutBounds.right;
+ inOutBounds.left += movement;
+ inOutBounds.right += movement;
+ break;
+ case DOCKED_TOP:
+ movement = inOutBounds.top;
+ inOutBounds.top -= movement;
+ inOutBounds.bottom -= movement;
+ break;
+ case DOCKED_BOTTOM:
+ movement = parentBounds.bottom - inOutBounds.bottom;
+ inOutBounds.top += movement;
+ inOutBounds.bottom += movement;
+ break;
+ }
+ }
+
+ /**
+ * Snaps the bounds after rotation to the closest snap target for the docked stack.
+ */
+ void snapDockedStackAfterRotation(Configuration parentConfig, DisplayCutout displayCutout,
+ Rect outBounds) {
+
+ // Calculate the current position.
+ final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth();
+ final int dockSide = getDockSide(parentConfig, outBounds);
+ final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
+ dockSide, dividerSize);
+ final int displayWidth = parentConfig.windowConfiguration.getBounds().width();
+ final int displayHeight = parentConfig.windowConfiguration.getBounds().height();
+
+ // Snap the position to a target.
+ final int rotation = parentConfig.windowConfiguration.getRotation();
+ final int orientation = parentConfig.orientation;
+ mDisplayContent.getDisplayPolicy().getStableInsetsLw(rotation, displayWidth, displayHeight,
+ displayCutout, outBounds);
+ final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
+ mWmService.mContext.getResources(), displayWidth, displayHeight,
+ dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
+ getDockSide(), isMinimizedDockAndHomeStackResizable());
+ final DividerSnapAlgorithm.SnapTarget target =
+ algorithm.calculateNonDismissingSnapTarget(dividerPosition);
+
+ // Recalculate the bounds based on the position of the target.
+ DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
+ outBounds, displayWidth, displayHeight,
+ dividerSize);
+ }
+
+ /**
+ * Put a Task in this stack. Used for adding only.
+ * When task is added to top of the stack, the entire branch of the hierarchy (including stack
+ * and display) will be brought to top.
+ * @param task The task to add.
+ * @param position Target position to add the task to.
+ * @param showForAllUsers Whether to show the task regardless of the current user.
+ */
+ void addChild(Task task, int position, boolean showForAllUsers, boolean moveParents) {
+ // Add child task.
+ addChild(task, null);
+
+ // Move child to a proper position, as some restriction for position might apply.
+ position = positionChildAt(
+ position, task, moveParents /* includingParents */, showForAllUsers);
+ }
+
+ @Override
+ void addChild(Task task, int position) {
+ addChild(task, position, task.showForAllUsers(), false /* includingParents */);
+ }
+
+ void positionChildAtTop(Task child) {
+ if (child == null) {
+ // TODO: Fix the call-points that cause this to happen.
+ return;
+ }
+
+ positionChildAt(POSITION_TOP, child, true /* includingParents */);
+ child.updateTaskMovement(true);
+
+ final DisplayContent displayContent = getDisplayContent();
+ if (displayContent.mAppTransition.isTransitionSet()) {
+ child.setSendingToBottom(false);
+ }
+ displayContent.layoutAndAssignWindowLayersIfNeeded();
+ }
+
+ private void positionChildAtBottom(Task child) {
+ // If there are other focusable stacks on the display, the z-order of the display should not
+ // be changed just because a task was placed at the bottom. E.g. if it is moving the topmost
+ // task to bottom, the next focusable stack on the same display should be focused.
+ final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack(
+ child.getStack(), true /* ignoreCurrent */);
+ positionChildAtBottom(child, nextFocusableStack == null /* includingParents */);
+ child.updateTaskMovement(true);
+ }
+
+ @VisibleForTesting
+ void positionChildAtBottom(Task child, boolean includingParents) {
+ if (child == null) {
+ // TODO: Fix the call-points that cause this to happen.
+ return;
+ }
+
+ positionChildAt(POSITION_BOTTOM, child, includingParents);
+
+ if (getDisplayContent().mAppTransition.isTransitionSet()) {
+ child.setSendingToBottom(true);
+ }
+ getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+ }
+
+ @Override
+ void positionChildAt(int position, Task child, boolean includingParents) {
+ positionChildAt(position, child, includingParents, child.showForAllUsers());
+ }
+
+ /**
+ * Overridden version of {@link ActivityStack#positionChildAt(int, Task, boolean)}. Used in
+ * {@link ActivityStack#addChild(Task, int, boolean showForAllUsers, boolean)}, as it can
+ * receive showForAllUsers param from {@link ActivityRecord} instead of
+ * {@link Task#showForAllUsers()}.
+ */
+ private int positionChildAt(int position, Task child, boolean includingParents,
+ boolean showForAllUsers) {
+ final int targetPosition = findPositionForTask(child, position, showForAllUsers);
+ super.positionChildAt(targetPosition, child, includingParents);
+
+ // Log positioning.
+ if (DEBUG_TASK_MOVEMENT) {
+ Slog.d(TAG_WM, "positionTask: task=" + this + " position=" + position);
+ }
+
+ final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
+ EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop,
+ targetPosition);
+
+ return targetPosition;
+ }
+
+ @Override
+ void onChildPositionChanged(WindowContainer child) {
+ if (!mChildren.contains(child)) {
+ return;
+ }
+
+ final Task task = (Task) child;
+ final boolean isTop = getTopChild() == task;
+ task.updateTaskMovement(isTop);
+ if (isTop) {
+ final DisplayContent displayContent = getDisplayContent();
+ if (displayContent.mAppTransition.isTransitionSet()) {
+ task.setSendingToBottom(false);
+ }
+ displayContent.layoutAndAssignWindowLayersIfNeeded();
+ }
+ }
+
+ // TODO(display-unify): Remove after display unification.
+ protected void onParentChanged(ActivityDisplay newParent, ActivityDisplay oldParent) {
+ onParentChanged(
+ newParent != null ? newParent.mDisplayContent : null,
+ oldParent != null ? oldParent.mDisplayContent : null);
+ }
+
+ @Override
+ protected void onParentChanged(
+ ConfigurationContainer newParent, ConfigurationContainer oldParent) {
+ final ActivityDisplay display = newParent != null
+ ? ((WindowContainer) newParent).getDisplayContent().mActivityDisplay : null;
+ final ActivityDisplay oldDisplay = oldParent != null
+ ? ((WindowContainer) oldParent).getDisplayContent().mActivityDisplay : null;
+
+ mDisplayId = (display != null) ? display.mDisplayId : INVALID_DISPLAY;
+ mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
+
+ if (display != null) {
+ // Rotations are relative to the display. This means if there are 2 displays rotated
+ // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
+ // from one to the other could look like a rotation change. To prevent this
+ // apparent rotation change (and corresponding bounds rotation), pretend like our
+ // current rotation is already the same as the new display.
+ // Note, if ActivityStack or related logic ever gets nested, this logic will need
+ // to move to onConfigurationChanged.
+ getConfiguration().windowConfiguration.setRotation(
+ display.getWindowConfiguration().getRotation());
+ }
+ super.onParentChanged(newParent, oldParent);
+ if (getParent() == null && mDisplayContent != null) {
+ EventLog.writeEvent(com.android.server.EventLogTags.WM_STACK_REMOVED, mStackId);
+
+ mDisplayContent = null;
+ mWmService.mWindowPlacerLocked.requestTraversal();
+ }
+ if (display != null && inSplitScreenPrimaryWindowingMode()) {
+ // If we created a docked stack we want to resize it so it resizes all other stacks
+ // in the system.
+ getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
+ mTmpRect /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
+ mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect,
+ mTmpRect2, null, null, PRESERVE_WINDOWS);
+ }
+ mRootActivityContainer.updateUIDsPresentOnDisplay();
+
+ // Resume next focusable stack after reparenting to another display if we aren't removing
+ // the prevous display.
+ if (oldDisplay != null && oldDisplay.isRemoving()) {
+ postReparent();
+ }
+ }
+
+ void reparent(DisplayContent newParent, boolean onTop) {
+ // Real parent of stack is within display object, so we have to delegate re-parenting there.
+ newParent.moveStackToDisplay(this, onTop);
+ }
+
+ // TODO: We should really have users as a window container in the hierarchy so that we don't
+ // have to do complicated things like we are doing in this method.
+ int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers) {
+ final boolean canShowTask =
+ showForAllUsers || mWmService.isCurrentProfileLocked(task.mUserId);
+
+ final int stackSize = mChildren.size();
+ int minPosition = 0;
+ int maxPosition = stackSize - 1;
+
+ if (canShowTask) {
+ minPosition = computeMinPosition(minPosition, stackSize);
+ } else {
+ maxPosition = computeMaxPosition(maxPosition);
+ }
+
+ // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
+ if (targetPosition == POSITION_BOTTOM && minPosition == 0) {
+ return POSITION_BOTTOM;
+ } else if (targetPosition == POSITION_TOP && maxPosition == (stackSize - 1)) {
+ return POSITION_TOP;
+ }
+ // Reset position based on minimum/maximum possible positions.
+ return Math.min(Math.max(targetPosition, minPosition), maxPosition);
+ }
+
+ /** Calculate the minimum possible position for a task that can be shown to the user.
+ * The minimum position will be above all other tasks that can't be shown.
+ * @param minPosition The minimum position the caller is suggesting.
+ * We will start adjusting up from here.
+ * @param size The size of the current task list.
+ */
+ private int computeMinPosition(int minPosition, int size) {
+ while (minPosition < size) {
+ final Task tmpTask = mChildren.get(minPosition);
+ final boolean canShowTmpTask =
+ tmpTask.showForAllUsers()
+ || mWmService.isCurrentProfileLocked(tmpTask.mUserId);
+ if (canShowTmpTask) {
+ break;
+ }
+ minPosition++;
+ }
+ return minPosition;
+ }
+
+ /** Calculate the maximum possible position for a task that can't be shown to the user.
+ * The maximum position will be below all other tasks that can be shown.
+ * @param maxPosition The maximum position the caller is suggesting.
+ * We will start adjusting down from here.
+ */
+ private int computeMaxPosition(int maxPosition) {
+ while (maxPosition > 0) {
+ final Task tmpTask = mChildren.get(maxPosition);
+ final boolean canShowTmpTask =
+ tmpTask.showForAllUsers()
+ || mWmService.isCurrentProfileLocked(tmpTask.mUserId);
+ if (!canShowTmpTask) {
+ break;
+ }
+ maxPosition--;
+ }
+ return maxPosition;
+ }
+
+ private void updateSurfaceBounds() {
+ updateSurfaceSize(getPendingTransaction());
+ updateSurfacePosition();
+ scheduleAnimation();
+ }
+
+ /**
+ * Calculate an amount by which to expand the stack bounds in each direction.
+ * Used to make room for shadows in the pinned windowing mode.
+ */
+ int getStackOutset() {
+ DisplayContent displayContent = getDisplayContent();
+ if (inPinnedWindowingMode() && displayContent != null) {
+ final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
+
+ // We multiply by two to match the client logic for converting view elevation
+ // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
+ return (int) Math.ceil(
+ mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, displayMetrics)
+ * 2);
+ }
+ return 0;
+ }
+
+ @Override
+ void getRelativeDisplayedPosition(Point outPos) {
+ super.getRelativeDisplayedPosition(outPos);
+ final int outset = getStackOutset();
+ outPos.x -= outset;
+ outPos.y -= outset;
+ }
+
+ private void updateSurfaceSize(SurfaceControl.Transaction transaction) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+
+ final Rect stackBounds = getDisplayedBounds();
+ int width = stackBounds.width();
+ int height = stackBounds.height();
+
+ final int outset = getStackOutset();
+ width += 2 * outset;
+ height += 2 * outset;
+
+ if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
+ return;
+ }
+ transaction.setWindowCrop(mSurfaceControl, width, height);
+ mLastSurfaceSize.set(width, height);
+ }
+
+ @VisibleForTesting
+ Point getLastSurfaceSize() {
+ return mLastSurfaceSize;
+ }
+
+ @Override
+ void onDisplayChanged(DisplayContent dc) {
+ super.onDisplayChanged(dc);
+ updateSurfaceBounds();
+ }
+
+ /**
+ * Determines the stack and task bounds of the other stack when in docked mode. The current task
+ * bounds is passed in but depending on the stack, the task and stack must match. Only in
+ * minimized mode with resizable launcher, the other stack ignores calculating the stack bounds
+ * and uses the task bounds passed in as the stack and task bounds, otherwise the stack bounds
+ * is calculated and is also used for its task bounds.
+ * If any of the out bounds are empty, it represents default bounds
+ *
+ * @param currentTempTaskBounds the current task bounds of the other stack
+ * @param outStackBounds the calculated stack bounds of the other stack
+ * @param outTempTaskBounds the calculated task bounds of the other stack
+ */
+ void getStackDockedModeBounds(Rect dockedBounds,
+ Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds) {
+ final Configuration parentConfig = getParent().getConfiguration();
+ outTempTaskBounds.setEmpty();
+
+ if (dockedBounds == null || dockedBounds.isEmpty()) {
+ // Calculate the primary docked bounds.
+ final boolean dockedOnTopOrLeft = mWmService.mDockedStackCreateMode
+ == SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+ getStackDockedModeBounds(parentConfig,
+ true /* primary */, outStackBounds, dockedBounds,
+ mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
+ return;
+ }
+ final int dockedSide = getDockSide(parentConfig, dockedBounds);
+
+ // When the home stack is resizable, should always have the same stack and task bounds
+ if (isActivityTypeHome()) {
+ final Task homeTask = findHomeTask();
+ if (homeTask == null || homeTask.isResizeable()) {
+ // Calculate the home stack bounds when in docked mode and the home stack is
+ // resizeable.
+ getDisplayContent().mDividerControllerLocked
+ .getHomeStackBoundsInDockedMode(parentConfig,
+ dockedSide, outStackBounds);
+ } else {
+ // Home stack isn't resizeable, so don't specify stack bounds.
+ outStackBounds.setEmpty();
+ }
+
+ outTempTaskBounds.set(outStackBounds);
+ return;
+ }
+
+ // When minimized state, the stack bounds for all non-home and docked stack bounds should
+ // match the passed task bounds
+ if (isMinimizedDockAndHomeStackResizable() && currentTempTaskBounds != null) {
+ outStackBounds.set(currentTempTaskBounds);
+ return;
+ }
+
+ if (dockedSide == DOCKED_INVALID) {
+ // Not sure how you got here...Only thing we can do is return current bounds.
+ Slog.e(TAG_WM, "Failed to get valid docked side for docked stack");
+ outStackBounds.set(getRawBounds());
+ return;
+ }
+
+ final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
+ getStackDockedModeBounds(parentConfig,
+ false /* primary */, outStackBounds, dockedBounds,
+ mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
+ }
+
+ /**
+ * Outputs the bounds a stack should be given the presence of a docked stack on the display.
+ * @param parentConfig The parent configuration.
+ * @param primary {@code true} if getting the primary stack bounds.
+ * @param outBounds Output bounds that should be used for the stack.
+ * @param dockedBounds Bounds of the docked stack.
+ * @param dockDividerWidth We need to know the width of the divider make to the output bounds
+ * close to the side of the dock.
+ * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
+ */
+ private void getStackDockedModeBounds(Configuration parentConfig, boolean primary,
+ Rect outBounds, Rect dockedBounds, int dockDividerWidth,
+ boolean dockOnTopOrLeft) {
+ final Rect displayRect = parentConfig.windowConfiguration.getBounds();
+ final boolean splitHorizontally = displayRect.width() > displayRect.height();
+
+ outBounds.set(displayRect);
+ if (primary) {
+ if (mWmService.mDockedStackCreateBounds != null) {
+ outBounds.set(mWmService.mDockedStackCreateBounds);
+ return;
+ }
+
+ // The initial bounds of the docked stack when it is created about half the screen space
+ // and its bounds can be adjusted after that. The bounds of all other stacks are
+ // adjusted to occupy whatever screen space the docked stack isn't occupying.
+ final DisplayCutout displayCutout = mDisplayContent.getDisplayInfo().displayCutout;
+ mDisplayContent.getDisplayPolicy().getStableInsetsLw(
+ parentConfig.windowConfiguration.getRotation(),
+ displayRect.width(), displayRect.height(), displayCutout, mTmpRect2);
+ final int position = new DividerSnapAlgorithm(mWmService.mContext.getResources(),
+ displayRect.width(),
+ displayRect.height(),
+ dockDividerWidth,
+ parentConfig.orientation == ORIENTATION_PORTRAIT,
+ mTmpRect2).getMiddleTarget().position;
+
+ if (dockOnTopOrLeft) {
+ if (splitHorizontally) {
+ outBounds.right = position;
+ } else {
+ outBounds.bottom = position;
+ }
+ } else {
+ if (splitHorizontally) {
+ outBounds.left = position + dockDividerWidth;
+ } else {
+ outBounds.top = position + dockDividerWidth;
+ }
+ }
+ return;
+ }
+
+ // Other stacks occupy whatever space is left by the docked stack.
+ if (!dockOnTopOrLeft) {
+ if (splitHorizontally) {
+ outBounds.right = dockedBounds.left - dockDividerWidth;
+ } else {
+ outBounds.bottom = dockedBounds.top - dockDividerWidth;
+ }
+ } else {
+ if (splitHorizontally) {
+ outBounds.left = dockedBounds.right + dockDividerWidth;
+ } else {
+ outBounds.top = dockedBounds.bottom + dockDividerWidth;
+ }
+ }
+ DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
+ }
+
+ void resetDockedStackToMiddle() {
+ if (!inSplitScreenPrimaryWindowingMode()) {
+ throw new IllegalStateException("Not a docked stack=" + this);
+ }
+
+ mWmService.mDockedStackCreateBounds = null;
+
+ final Rect bounds = new Rect();
+ final Rect tempBounds = new Rect();
+ getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
+ bounds, tempBounds);
+ mStackSupervisor.resizeDockedStackLocked(bounds, null /* tempTaskBounds */,
+ null /* tempTaskInsetBounds */, null /* tempOtherTaskBounds */,
+ null /* tempOtherTaskInsetBounds */, false /* preserveWindows */,
+ false /* deferResume */);
+ }
+
+ @Override
+ void removeIfPossible() {
+ if (isAnimating(TRANSITION | CHILDREN)) {
+ mDeferRemoval = true;
+ return;
+ }
+ removeImmediately();
+ }
+
+ /**
+ * Adjusts the stack bounds if the IME is visible.
+ *
+ * @param imeWin The IME window.
+ * @param keepLastAmount Use {@code true} to keep the last adjusted amount from
+ * {@link DockedStackDividerController} for adjusting the stack bounds,
+ * Use {@code false} to reset adjusted amount as 0.
+ * @see #updateAdjustForIme(float, float, boolean)
+ */
+ void setAdjustedForIme(WindowState imeWin, boolean keepLastAmount) {
+ mImeWin = imeWin;
+ mImeGoingAway = false;
+ if (!mAdjustedForIme || keepLastAmount) {
+ mAdjustedForIme = true;
+ DockedStackDividerController controller = getDisplayContent().mDividerControllerLocked;
+ final float adjustImeAmount = keepLastAmount ? controller.mLastAnimationProgress : 0f;
+ final float adjustDividerAmount = keepLastAmount ? controller.mLastDividerProgress : 0f;
+ updateAdjustForIme(adjustImeAmount, adjustDividerAmount, true /* force */);
+ }
+ }
+
+ boolean isAdjustedForIme() {
+ return mAdjustedForIme;
+ }
+
+ boolean isAnimatingForIme() {
+ return mImeWin != null && mImeWin.isAnimatingLw();
+ }
+
+ /**
+ * Update the stack's bounds (crop or position) according to the IME window's
+ * current position. When IME window is animated, the bottom stack is animated
+ * together to track the IME window's current position, and the top stack is
+ * cropped as necessary.
+ *
+ * @return true if a traversal should be performed after the adjustment.
+ */
+ boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
+ if (adjustAmount != mAdjustImeAmount
+ || adjustDividerAmount != mAdjustDividerAmount || force) {
+ mAdjustImeAmount = adjustAmount;
+ mAdjustDividerAmount = adjustDividerAmount;
+ updateAdjustedBounds();
+ return isVisible();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Resets the adjustment after it got adjusted for the IME.
+ * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
+ * animations; otherwise, set flag and animates the window away together
+ * with IME window.
+ */
+ void resetAdjustedForIme(boolean adjustBoundsNow) {
+ if (adjustBoundsNow) {
+ mImeWin = null;
+ mImeGoingAway = false;
+ mAdjustImeAmount = 0f;
+ mAdjustDividerAmount = 0f;
+ if (!mAdjustedForIme) {
+ return;
+ }
+ mAdjustedForIme = false;
+ updateAdjustedBounds();
+ mWmService.setResizeDimLayer(false, getWindowingMode(), 1.0f);
+ } else {
+ mImeGoingAway |= mAdjustedForIme;
+ }
+ }
+
+ /**
+ * Sets the amount how much we currently minimize our stack.
+ *
+ * @param minimizeAmount The amount, between 0 and 1.
+ * @return Whether the amount has changed and a layout is needed.
+ */
+ boolean setAdjustedForMinimizedDock(float minimizeAmount) {
+ if (minimizeAmount != mMinimizeAmount) {
+ mMinimizeAmount = minimizeAmount;
+ updateAdjustedBounds();
+ return isVisible();
+ } else {
+ return false;
+ }
+ }
+
+ boolean shouldIgnoreInput() {
+ return isAdjustedForMinimizedDockedStack()
+ || (inSplitScreenPrimaryWindowingMode() && isMinimizedDockAndHomeStackResizable());
+ }
+
+ /**
+ * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
+ * to the list of to be drawn windows the service is waiting for.
+ */
+ void beginImeAdjustAnimation() {
+ for (int j = mChildren.size() - 1; j >= 0; j--) {
+ final Task task = mChildren.get(j);
+ if (task.hasContentToDisplay()) {
+ task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
+ task.setWaitingForDrawnIfResizingChanged();
+ }
+ }
+ }
+
+ /**
+ * Resets the resizing state of all windows.
+ */
+ void endImeAdjustAnimation() {
+ for (int j = mChildren.size() - 1; j >= 0; j--) {
+ mChildren.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
+ }
+ }
+
+ int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
+ return displayContentRect.top + (int)
+ ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN);
+ }
+
+ private boolean adjustForIME(final WindowState imeWin) {
+ // To prevent task stack resize animation may flicking when playing app transition
+ // animation & IME window enter animation in parallel, we need to make sure app
+ // transition is done and then adjust task size for IME, skip the new adjusted frame when
+ // app transition is still running.
+ if (getDisplayContent().mAppTransition.isRunning()) {
+ return false;
+ }
+
+ final int dockedSide = getDockSide();
+ final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
+ if (imeWin == null || !dockedTopOrBottom) {
+ return false;
+ }
+
+ final Rect displayStableRect = mTmpRect;
+ final Rect contentBounds = mTmpRect2;
+
+ // Calculate the content bounds excluding the area occupied by IME
+ getDisplayContent().getStableRect(displayStableRect);
+ contentBounds.set(displayStableRect);
+ int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
+
+ imeTop += imeWin.getGivenContentInsetsLw().top;
+ if (contentBounds.bottom > imeTop) {
+ contentBounds.bottom = imeTop;
+ }
+
+ final int yOffset = displayStableRect.bottom - contentBounds.bottom;
+
+ final int dividerWidth =
+ getDisplayContent().mDividerControllerLocked.getContentWidth();
+ final int dividerWidthInactive =
+ getDisplayContent().mDividerControllerLocked.getContentWidthInactive();
+
+ if (dockedSide == DOCKED_TOP) {
+ // If this stack is docked on top, we make it smaller so the bottom stack is not
+ // occluded by IME. We shift its bottom up by the height of the IME, but
+ // leaves at least 30% of the top stack visible.
+ final int minTopStackBottom =
+ getMinTopStackBottom(displayStableRect, getRawBounds().bottom);
+ final int bottom = Math.max(
+ getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive,
+ minTopStackBottom);
+ mTmpAdjustedBounds.set(getRawBounds());
+ mTmpAdjustedBounds.bottom = (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount)
+ * getRawBounds().bottom);
+ mFullyAdjustedImeBounds.set(getRawBounds());
+ } else {
+ // When the stack is on bottom and has no focus, it's only adjusted for divider width.
+ final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
+
+ // When the stack is on bottom and has focus, it needs to be moved up so as to
+ // not occluded by IME, and at the same time adjusted for divider width.
+ // We try to move it up by the height of the IME window, but only to the extent
+ // that leaves at least 30% of the top stack visible.
+ // 'top' is where the top of bottom stack will move to in this case.
+ final int topBeforeImeAdjust =
+ getRawBounds().top - dividerWidth + dividerWidthInactive;
+ final int minTopStackBottom =
+ getMinTopStackBottom(displayStableRect,
+ getRawBounds().top - dividerWidth);
+ final int top = Math.max(
+ getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive);
+
+ mTmpAdjustedBounds.set(getRawBounds());
+ // Account for the adjustment for IME and divider width separately.
+ // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
+ // and dividerWidthDelta is due to divider width change only.
+ mTmpAdjustedBounds.top =
+ getRawBounds().top + (int) (mAdjustImeAmount * (top - topBeforeImeAdjust)
+ + mAdjustDividerAmount * dividerWidthDelta);
+ mFullyAdjustedImeBounds.set(getRawBounds());
+ mFullyAdjustedImeBounds.top = top;
+ mFullyAdjustedImeBounds.bottom = top + getRawBounds().height();
+ }
+ return true;
+ }
+
+ private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
+ final int dockSide = getDockSide();
+ if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
+ return false;
+ }
+
+ if (dockSide == DOCKED_TOP) {
+ mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
+ int topInset = mTmpRect.top;
+ mTmpAdjustedBounds.set(getRawBounds());
+ mTmpAdjustedBounds.bottom = (int) (minimizeAmount * topInset + (1 - minimizeAmount)
+ * getRawBounds().bottom);
+ } else if (dockSide == DOCKED_LEFT) {
+ mTmpAdjustedBounds.set(getRawBounds());
+ final int width = getRawBounds().width();
+ mTmpAdjustedBounds.right =
+ (int) (minimizeAmount * mDockedStackMinimizeThickness
+ + (1 - minimizeAmount) * getRawBounds().right);
+ mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
+ } else if (dockSide == DOCKED_RIGHT) {
+ mTmpAdjustedBounds.set(getRawBounds());
+ mTmpAdjustedBounds.left =
+ (int) (minimizeAmount * (getRawBounds().right - mDockedStackMinimizeThickness)
+ + (1 - minimizeAmount) * getRawBounds().left);
+ }
+ return true;
+ }
+
+ private boolean isMinimizedDockAndHomeStackResizable() {
+ return mDisplayContent.mDividerControllerLocked.isMinimizedDock()
+ && mDisplayContent.mDividerControllerLocked.isHomeStackResizable();
+ }
+
+ /**
+ * @return the distance in pixels how much the stack gets minimized from it's original size
+ */
+ int getMinimizeDistance() {
+ final int dockSide = getDockSide();
+ if (dockSide == DOCKED_INVALID) {
+ return 0;
+ }
+
+ if (dockSide == DOCKED_TOP) {
+ mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
+ int topInset = mTmpRect.top;
+ return getRawBounds().bottom - topInset;
+ } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
+ return getRawBounds().width() - mDockedStackMinimizeThickness;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Updates the adjustment depending on it's current state.
+ */
+ private void updateAdjustedBounds() {
+ boolean adjust = false;
+ if (mMinimizeAmount != 0f) {
+ adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
+ } else if (mAdjustedForIme) {
+ adjust = adjustForIME(mImeWin);
+ }
+ if (!adjust) {
+ mTmpAdjustedBounds.setEmpty();
+ }
+ setAdjustedBounds(mTmpAdjustedBounds);
+
+ final boolean isImeTarget = (mWmService.getImeFocusStackLocked() == this);
+ if (mAdjustedForIme && adjust && !isImeTarget) {
+ final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
+ * IME_ADJUST_DIM_AMOUNT;
+ mWmService.setResizeDimLayer(true, getWindowingMode(), alpha);
+ }
+ }
+
+ void applyAdjustForImeIfNeeded(Task task) {
+ if (mMinimizeAmount != 0f || !mAdjustedForIme || mAdjustedBounds.isEmpty()) {
+ return;
+ }
+
+ final Rect insetBounds = mImeGoingAway ? getRawBounds() : mFullyAdjustedImeBounds;
+ task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP);
+ mDisplayContent.setLayoutNeeded();
+ }
+
+
+ boolean isAdjustedForMinimizedDockedStack() {
+ return mMinimizeAmount != 0f;
+ }
+
+ /**
+ * @return {@code true} if we have a {@link Task} that is animating (currently only used for the
+ * recents animation); {@code false} otherwise.
+ */
+ boolean isTaskAnimating() {
+ for (int j = mChildren.size() - 1; j >= 0; j--) {
+ final Task task = mChildren.get(j);
+ if (task.isTaskAnimating()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+ pw.println(prefix + "mStackId=" + mStackId);
+ pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
+ pw.println(prefix + "mBounds=" + getRawBounds().toShortString());
+ if (mMinimizeAmount != 0f) {
+ pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount);
+ }
+ if (mAdjustedForIme) {
+ pw.println(prefix + "mAdjustedForIme=true");
+ pw.println(prefix + "mAdjustImeAmount=" + mAdjustImeAmount);
+ pw.println(prefix + "mAdjustDividerAmount=" + mAdjustDividerAmount);
+ }
+ if (!mAdjustedBounds.isEmpty()) {
+ pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
+ }
+ for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
+ mChildren.get(taskNdx).dump(pw, prefix + " ", dumpAll);
+ }
+ if (!mExitingActivities.isEmpty()) {
+ pw.println();
+ pw.println(" Exiting application tokens:");
+ for (int i = mExitingActivities.size() - 1; i >= 0; i--) {
+ WindowToken token = mExitingActivities.get(i);
+ pw.print(" Exiting App #"); pw.print(i);
+ pw.print(' '); pw.print(token);
+ pw.println(':');
+ token.dump(pw, " ", dumpAll);
+ }
+ }
+ mAnimatingActivityRegistry.dump(pw, "AnimatingApps:", prefix);
+ }
+
+ @Override
+ boolean fillsParent() {
+ return matchParentBounds();
+ }
+
+ String getName() {
+ return toShortString();
+ }
+
+ public String toShortString() {
+ return "Stack=" + mStackId;
+ }
+
+ /**
+ * For docked workspace (or workspace that's side-by-side to the docked), provides
+ * information which side of the screen was the dock anchored.
+ */
+ int getDockSide() {
+ return getDockSide(mDisplayContent.getConfiguration(), getRawBounds());
+ }
+
+ int getDockSideForDisplay(DisplayContent dc) {
+ return getDockSide(dc, dc.getConfiguration(), getRawBounds());
+ }
+
+ int getDockSide(Configuration parentConfig, Rect bounds) {
+ if (mDisplayContent == null) {
+ return DOCKED_INVALID;
+ }
+ return getDockSide(mDisplayContent, parentConfig, bounds);
+ }
+
+ private int getDockSide(DisplayContent dc, Configuration parentConfig, Rect bounds) {
+ return dc.getDockedDividerController().getDockSide(bounds,
+ parentConfig.windowConfiguration.getBounds(),
+ parentConfig.orientation, parentConfig.windowConfiguration.getRotation());
+ }
+
+ boolean hasTaskForUser(int userId) {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final Task task = mChildren.get(i);
+ if (task.mUserId == userId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void findTaskForResizePoint(int x, int y, int delta,
+ DisplayContent.TaskForResizePointSearchResult results) {
+ if (!getWindowConfiguration().canResizeTask()) {
+ results.searchDone = true;
+ return;
+ }
+
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final Task task = mChildren.get(i);
+ if (task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ results.searchDone = true;
+ return;
+ }
+
+ // We need to use the task's dim bounds (which is derived from the visible bounds of
+ // its apps windows) for any touch-related tests. Can't use the task's original
+ // bounds because it might be adjusted to fit the content frame. One example is when
+ // the task is put to top-left quadrant, the actual visible area would not start at
+ // (0,0) after it's adjusted for the status bar.
+ task.getDimBounds(mTmpRect);
+ mTmpRect.inset(-delta, -delta);
+ if (mTmpRect.contains(x, y)) {
+ mTmpRect.inset(delta, delta);
+
+ results.searchDone = true;
+
+ if (!mTmpRect.contains(x, y)) {
+ results.taskForResize = task;
+ return;
+ }
+ // User touched inside the task. No need to look further,
+ // focus transfer will be handled in ACTION_UP.
+ return;
+ }
+ }
+ }
+
+ void setTouchExcludeRegion(Task focusedTask, int delta, Region touchExcludeRegion,
+ Rect contentRect, Rect postExclude) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final Task task = mChildren.get(i);
+ ActivityRecord topVisibleActivity = task.getTopVisibleActivity();
+ if (topVisibleActivity == null || !topVisibleActivity.hasContentToDisplay()) {
+ continue;
+ }
+
+ /**
+ * Exclusion region is the region that TapDetector doesn't care about.
+ * Here we want to remove all non-focused tasks from the exclusion region.
+ * We also remove the outside touch area for resizing for all freeform
+ * tasks (including the focused).
+ *
+ * We save the focused task region once we find it, and add it back at the end.
+ *
+ * If the task is home stack and it is resizable in the minimized state, we want to
+ * exclude the docked stack from touch so we need the entire screen area and not just a
+ * small portion which the home stack currently is resized to.
+ */
+
+ if (task.isActivityTypeHome() && isMinimizedDockAndHomeStackResizable()) {
+ mDisplayContent.getBounds(mTmpRect);
+ } else {
+ task.getDimBounds(mTmpRect);
+ }
+
+ if (task == focusedTask) {
+ // Add the focused task rect back into the exclude region once we are done
+ // processing stacks.
+ postExclude.set(mTmpRect);
+ }
+
+ final boolean isFreeformed = task.inFreeformWindowingMode();
+ if (task != focusedTask || isFreeformed) {
+ if (isFreeformed) {
+ // If the task is freeformed, enlarge the area to account for outside
+ // touch area for resize.
+ mTmpRect.inset(-delta, -delta);
+ // Intersect with display content rect. If we have system decor (status bar/
+ // navigation bar), we want to exclude that from the tap detection.
+ // Otherwise, if the app is partially placed under some system button (eg.
+ // Recents, Home), pressing that button would cause a full series of
+ // unwanted transfer focus/resume/pause, before we could go home.
+ mTmpRect.intersect(contentRect);
+ }
+ touchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
+ }
+ }
+ }
+
+ public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
+ // Hold the lock since this is called from the BoundsAnimator running on the UiThread
+ synchronized (mWmService.mGlobalLock) {
+ if (mCancelCurrentBoundsAnimation) {
+ return false;
+ }
+ }
+
+ try {
+ mWmService.mActivityTaskManager.resizePinnedStack(stackBounds, tempTaskBounds);
+ } catch (RemoteException e) {
+ // I don't believe you.
+ }
+ return true;
+ }
+
+ void onAllWindowsDrawn() {
+ if (!mBoundsAnimating && !mBoundsAnimatingRequested) {
+ return;
+ }
+
+ getDisplayContent().mBoundsAnimationController.onAllWindowsDrawn();
+ }
+
+ @Override // AnimatesBounds
+ public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate,
+ @BoundsAnimationController.AnimationType int animationType) {
+ // Hold the lock since this is called from the BoundsAnimator running on the UiThread
+ synchronized (mWmService.mGlobalLock) {
+ if (!isAttached()) {
+ // Don't run the animation if the stack is already detached
+ return false;
+ }
+
+ if (animationType == BoundsAnimationController.BOUNDS) {
+ mBoundsAnimatingRequested = false;
+ mBoundsAnimating = true;
+ }
+ mAnimationType = animationType;
+
+ // If we are changing UI mode, as in the PiP to fullscreen
+ // transition, then we need to wait for the window to draw.
+ if (schedulePipModeChangedCallback) {
+ forAllWindows((w) -> {
+ w.mWinAnimator.resetDrawState();
+ }, false /* traverseTopToBottom */);
+ }
+ }
+
+ if (inPinnedWindowingMode()) {
+ try {
+ mWmService.mActivityTaskManager.notifyPinnedStackAnimationStarted();
+ } catch (RemoteException e) {
+ // I don't believe you...
+ }
+
+ if ((schedulePipModeChangedCallback || animationType == FADE_IN)) {
+ // We need to schedule the PiP mode change before the animation up. It is possible
+ // in this case for the animation down to not have been completed, so always
+ // force-schedule and update to the client to ensure that it is notified that it
+ // is no longer in picture-in-picture mode
+ updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate);
+ }
+ }
+ return true;
+ }
+
+ @Override // AnimatesBounds
+ public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
+ boolean moveToFullscreen) {
+ synchronized (mWmService.mGlobalLock) {
+ if (inPinnedWindowingMode()) {
+ // Update to the final bounds if requested. This is done here instead of in the
+ // bounds animator to allow us to coordinate this after we notify the PiP mode
+ // changed
+
+ if (schedulePipModeChangedCallback) {
+ // We need to schedule the PiP mode change after the animation down, so use the
+ // final bounds
+ updatePictureInPictureModeForPinnedStackAnimation(mBoundsAnimationTarget,
+ false /* forceUpdate */);
+ }
+
+ if (mAnimationType == BoundsAnimationController.FADE_IN) {
+ setPinnedStackAlpha(1f);
+ mWmService.mAtmService.notifyPinnedStackAnimationEnded();
+ return;
+ }
+
+ if (finalStackSize != null && !mCancelCurrentBoundsAnimation) {
+ setPinnedStackSize(finalStackSize, null);
+ } else {
+ // We have been canceled, so the final stack size is null, still run the
+ // animation-end logic
+ onPipAnimationEndResize();
+ }
+
+ mWmService.mAtmService.notifyPinnedStackAnimationEnded();
+ if (moveToFullscreen) {
+ ((ActivityStack) this).dismissPip();
+ }
+ } else {
+ // No PiP animation, just run the normal animation-end logic
+ onPipAnimationEndResize();
+ }
+ }
+ }
+
+ /**
+ * Sets the current picture-in-picture aspect ratio.
+ */
+ void setPictureInPictureAspectRatio(float aspectRatio) {
+ if (!mWmService.mAtmService.mSupportsPictureInPicture) {
+ return;
+ }
+
+ final DisplayContent displayContent = getDisplayContent();
+ if (displayContent == null) {
+ return;
+ }
+
+ if (!inPinnedWindowingMode()) {
+ return;
+ }
+
+ final PinnedStackController pinnedStackController =
+ getDisplayContent().getPinnedStackController();
+
+ if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) {
+ return;
+ }
+
+ // Notify the pinned stack controller about aspect ratio change.
+ // This would result a callback delivered from SystemUI to WM to start animation,
+ // if the bounds are ought to be altered due to aspect ratio change.
+ pinnedStackController.setAspectRatio(
+ pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
+ ? aspectRatio : -1f);
+ }
+
+ /**
+ * Sets the current picture-in-picture actions.
+ */
+ void setPictureInPictureActions(List<RemoteAction> actions) {
+ if (!mWmService.mAtmService.mSupportsPictureInPicture) {
+ return;
+ }
+
+ if (!inPinnedWindowingMode()) {
+ return;
+ }
+
+ getDisplayContent().getPinnedStackController().setActions(actions);
+ }
+
+ /** Called immediately prior to resizing the tasks at the end of the pinned stack animation. */
+ void onPipAnimationEndResize() {
+ mBoundsAnimating = false;
+ for (int i = 0; i < mChildren.size(); i++) {
+ final Task t = mChildren.get(i);
+ t.clearPreserveNonFloatingState();
+ }
+ mWmService.requestTraversal();
+ }
+
+ @Override
+ public boolean shouldDeferStartOnMoveToFullscreen() {
+ synchronized (mWmService.mGlobalLock) {
+ if (!isAttached()) {
+ // Unnecessary to pause the animation because the stack is detached.
+ return false;
+ }
+
+ // Workaround for the recents animation -- normally we need to wait for the new activity
+ // to show before starting the PiP animation, but because we start and show the home
+ // activity early for the recents animation prior to the PiP animation starting, there
+ // is no subsequent all-drawn signal. In this case, we can skip the pause when the home
+ // stack is already visible and drawn.
+ final ActivityStack homeStack = mDisplayContent.getHomeStack();
+ if (homeStack == null) {
+ return true;
+ }
+ final Task homeTask = homeStack.getTopChild();
+ if (homeTask == null) {
+ return true;
+ }
+ final ActivityRecord homeApp = homeTask.getTopVisibleActivity();
+ if (!homeTask.isVisible() || homeApp == null) {
+ return true;
+ }
+ return !homeApp.allDrawn;
+ }
+ }
+
+ /**
+ * @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen
+ * bounds and we have a deferred PiP mode changed callback set with the animation.
+ */
+ public boolean deferScheduleMultiWindowModeChanged() {
+ if (inPinnedWindowingMode()) {
+ // For the pinned stack, the deferring of the multi-window mode changed is tied to the
+ // transition animation into picture-in-picture, and is called once the animation
+ // completes, or is interrupted in a way that would leave the stack in a non-fullscreen
+ // state.
+ // @see BoundsAnimationController
+ // @see BoundsAnimationControllerTests
+ return (mBoundsAnimatingRequested || mBoundsAnimating);
+ }
+ return false;
+ }
+
+ public boolean isForceScaled() {
+ return mBoundsAnimating;
+ }
+
+ public boolean isAnimatingBounds() {
+ return mBoundsAnimating;
+ }
+
+ public boolean lastAnimatingBoundsWasToFullscreen() {
+ return mBoundsAnimatingToFullscreen;
+ }
+
+ public boolean isAnimatingBoundsToFullscreen() {
+ return isAnimatingBounds() && lastAnimatingBoundsWasToFullscreen();
+ }
+
+ public boolean pinnedStackResizeDisallowed() {
+ if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
+ return true;
+ }
+ return false;
+ }
+
+ /** Returns true if a removal action is still being deferred. */
+ boolean checkCompleteDeferredRemoval() {
+ if (isAnimating(TRANSITION | CHILDREN)) {
+ return true;
+ }
+ if (mDeferRemoval) {
+ removeImmediately();
+ }
+
+ return super.checkCompleteDeferredRemoval();
+ }
+
+ @Override
+ int getOrientation() {
+ return (canSpecifyOrientation()) ? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
+ }
+
+ private boolean canSpecifyOrientation() {
+ final int windowingMode = getWindowingMode();
+ final int activityType = getActivityType();
+ return windowingMode == WINDOWING_MODE_FULLSCREEN
+ || activityType == ACTIVITY_TYPE_HOME
+ || activityType == ACTIVITY_TYPE_RECENTS
+ || activityType == ACTIVITY_TYPE_ASSISTANT;
+ }
+
+ @Override
+ Dimmer getDimmer() {
+ return mDimmer;
+ }
+
+ @Override
+ void prepareSurfaces() {
+ mDimmer.resetDimStates();
+ super.prepareSurfaces();
+ getDimBounds(mTmpDimBoundsRect);
+
+ // Bounds need to be relative, as the dim layer is a child.
+ mTmpDimBoundsRect.offsetTo(0, 0);
+ if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
+ scheduleAnimation();
+ }
+ }
+
+ @Override
+ public boolean setPinnedStackAlpha(float alpha) {
+ // Hold the lock since this is called from the BoundsAnimator running on the UiThread
+ synchronized (mWmService.mGlobalLock) {
+ final SurfaceControl sc = getSurfaceControl();
+ if (sc == null || !sc.isValid()) {
+ // If the stack is already removed, don't bother updating any stack animation
+ return false;
+ }
+ getPendingTransaction().setAlpha(sc, mCancelCurrentBoundsAnimation ? 1 : alpha);
+ scheduleAnimation();
+ return !mCancelCurrentBoundsAnimation;
+ }
+ }
+
+ public DisplayInfo getDisplayInfo() {
+ return mDisplayContent.getDisplayInfo();
+ }
+
+ void dim(float alpha) {
+ mDimmer.dimAbove(getPendingTransaction(), alpha);
+ scheduleAnimation();
+ }
+
+ void stopDimming() {
+ mDimmer.stopDim(getPendingTransaction());
+ scheduleAnimation();
+ }
+
+ AnimatingActivityRegistry getAnimatingActivityRegistry() {
+ return mAnimatingActivityRegistry;
+ }
+
+ @Override
+ void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
+ Rect outSurfaceInsets) {
+ final Task task = getTopChild();
+ if (task != null) {
+ task.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
+ } else {
+ super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
+ }
+ }
+
+ @Override
+ RemoteAnimationTarget createRemoteAnimationTarget(
+ RemoteAnimationController.RemoteAnimationRecord record) {
+ final Task task = getTopChild();
+ return task != null ? task.createRemoteAnimationTarget(record) : null;
+ }
+
@Override
public String toString() {
return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
@@ -4782,10 +6479,10 @@
@WindowTraceLogLevel int logLevel) {
final long token = proto.start(fieldId);
writeToProtoInnerStackOnly(proto, STACK, logLevel);
- proto.write(ID, mStackId);
+ proto.write(com.android.server.am.ActivityStackProto.ID, mStackId);
for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
final Task task = getChildAt(taskNdx);
- task.writeToProto(proto, TASKS, logLevel);
+ task.writeToProto(proto, com.android.server.am.ActivityStackProto.TASKS, logLevel);
}
if (mResumedActivity != null) {
mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
@@ -4793,11 +6490,36 @@
proto.write(DISPLAY_ID, mDisplayId);
if (!matchParentBounds()) {
final Rect bounds = getRequestedOverrideBounds();
- bounds.writeToProto(proto, BOUNDS);
+ bounds.writeToProto(proto, com.android.server.am.ActivityStackProto.BOUNDS);
}
// TODO: Remove, no longer needed with windowingMode.
proto.write(FULLSCREEN, matchParentBounds());
proto.end(token);
}
+
+ // TODO(proto-merge): Remove once protos for ActivityStack and TaskStack are merged.
+ void writeToProtoInnerStackOnly(ProtoOutputStream proto, long fieldId,
+ @WindowTraceLogLevel int logLevel) {
+ if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
+ return;
+ }
+
+ final long token = proto.start(fieldId);
+ super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
+ proto.write(StackProto.ID, mStackId);
+ for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
+ mChildren.get(taskNdx).writeToProtoInnerTaskOnly(proto, StackProto.TASKS, logLevel);
+ }
+ proto.write(FILLS_PARENT, matchParentBounds());
+ getRawBounds().writeToProto(proto, StackProto.BOUNDS);
+ proto.write(DEFER_REMOVAL, mDeferRemoval);
+ proto.write(MINIMIZE_AMOUNT, mMinimizeAmount);
+ proto.write(ADJUSTED_FOR_IME, mAdjustedForIme);
+ proto.write(ADJUST_IME_AMOUNT, mAdjustImeAmount);
+ proto.write(ADJUST_DIVIDER_AMOUNT, mAdjustDividerAmount);
+ mAdjustedBounds.writeToProto(proto, ADJUSTED_BOUNDS);
+ proto.write(ANIMATING_BOUNDS, mBoundsAnimating);
+ proto.end(token);
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index e94ac4c..3c6faff0 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1708,15 +1708,6 @@
return;
}
- // It is possible for the bounds animation from the WM to call this but be delayed by
- // another AM call that is holding the AMS lock. In such a case, the pinnedBounds may be
- // incorrect if AMS.resizeStackWithBoundsFromWindowManager() is already called while waiting
- // for the AMS lock to be freed. So check and make sure these bounds are still good.
- // TODO(stack-merge): Is this still relevant?
- if (stack.pinnedStackResizeDisallowed()) {
- return;
- }
-
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizePinnedStack");
mService.deferWindowLayout();
try {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e78e302..98949cb 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -556,9 +556,9 @@
// Last systemUiVisibility we dispatched to windows.
private int mLastDispatchedSystemUiVisibility = 0;
- private final ArrayList<TaskStack> mTmpAlwaysOnTopStacks = new ArrayList<>();
- private final ArrayList<TaskStack> mTmpNormalStacks = new ArrayList<>();
- private final ArrayList<TaskStack> mTmpHomeStacks = new ArrayList<>();
+ private final ArrayList<ActivityStack> mTmpAlwaysOnTopStacks = new ArrayList<>();
+ private final ArrayList<ActivityStack> mTmpNormalStacks = new ArrayList<>();
+ private final ArrayList<ActivityStack> mTmpHomeStacks = new ArrayList<>();
/** Corner radius that windows should have in order to match the display. */
private final float mWindowCornerRadius;
@@ -1801,15 +1801,15 @@
return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
}
- TaskStack getHomeStack() {
+ ActivityStack getHomeStack() {
return mTaskStackContainers.getHomeStack();
}
/**
* @return The primary split-screen stack, but only if it is visible, and {@code null} otherwise.
*/
- TaskStack getSplitScreenPrimaryStack() {
- TaskStack stack = mTaskStackContainers.getSplitScreenPrimaryStack();
+ ActivityStack getSplitScreenPrimaryStack() {
+ ActivityStack stack = mTaskStackContainers.getSplitScreenPrimaryStack();
return (stack != null && stack.isVisible()) ? stack : null;
}
@@ -1821,11 +1821,11 @@
* Like {@link #getSplitScreenPrimaryStack}, but also returns the stack if it's currently
* not visible.
*/
- TaskStack getSplitScreenPrimaryStackIgnoringVisibility() {
+ ActivityStack getSplitScreenPrimaryStackIgnoringVisibility() {
return mTaskStackContainers.getSplitScreenPrimaryStack();
}
- TaskStack getPinnedStack() {
+ ActivityStack getPinnedStack() {
return mTaskStackContainers.getPinnedStack();
}
@@ -1837,7 +1837,7 @@
* Returns the topmost stack on the display that is compatible with the input windowing mode.
* Null is no compatible stack on the display.
*/
- TaskStack getTopStackInWindowingMode(int windowingMode) {
+ ActivityStack getTopStackInWindowingMode(int windowingMode) {
return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
}
@@ -1845,17 +1845,17 @@
* Returns the topmost stack on the display that is compatible with the input windowing mode and
* activity type. Null is no compatible stack on the display.
*/
- TaskStack getStack(int windowingMode, int activityType) {
+ ActivityStack getStack(int windowingMode, int activityType) {
return mTaskStackContainers.getStack(windowingMode, activityType);
}
@VisibleForTesting
- WindowList<TaskStack> getStacks() {
+ WindowList<ActivityStack> getStacks() {
return mTaskStackContainers.mChildren;
}
@VisibleForTesting
- TaskStack getTopStack() {
+ ActivityStack getTopStack() {
return mTaskStackContainers.getTopStack();
}
@@ -1863,7 +1863,7 @@
return mTaskStackContainers.getVisibleTasks();
}
- void onStackWindowingModeChanged(TaskStack stack) {
+ void onStackWindowingModeChanged(ActivityStack stack) {
mTaskStackContainers.onStackWindowingModeChanged(stack);
}
@@ -2207,17 +2207,17 @@
out.set(mDisplayFrames.mStable);
}
- void setStackOnDisplay(TaskStack stack, int position) {
+ void setStackOnDisplay(ActivityStack stack, int position) {
if (DEBUG_STACK) Slog.d(TAG_WM, "Set stack=" + stack + " on displayId=" + mDisplayId);
mTaskStackContainers.addChild(stack, position);
}
- void moveStackToDisplay(TaskStack stack, boolean onTop) {
+ void moveStackToDisplay(ActivityStack stack, boolean onTop) {
stack.reparent(mTaskStackContainers, onTop ? POSITION_TOP: POSITION_BOTTOM);
}
// TODO(display-unify): No longer needed then.
- void removeStackFromDisplay(TaskStack stack) {
+ void removeStackFromDisplay(ActivityStack stack) {
mTaskStackContainers.removeChild(stack);
}
@@ -2250,7 +2250,7 @@
getParent().positionChildAt(position, this, includingParents);
}
- void positionStackAt(int position, TaskStack child, boolean includingParents) {
+ void positionStackAt(int position, ActivityStack child, boolean includingParents) {
mTaskStackContainers.positionChildAt(position, child, includingParents);
layoutAndAssignWindowLayersIfNeeded();
}
@@ -2284,7 +2284,7 @@
final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
mTmpTaskForResizePointSearchResult.reset();
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(stackNdx);
if (!stack.getWindowConfiguration().canResizeTask()) {
return null;
}
@@ -2307,7 +2307,7 @@
mTmpRect2.setEmpty();
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0;
--stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(stackNdx);
stack.setTouchExcludeRegion(focusedTask, delta, mTouchExcludeRegion,
mDisplayFrames.mContent, mTmpRect2);
}
@@ -2437,7 +2437,7 @@
boolean updated = false;
for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(i);
if (stack == null || !stack.isAdjustedForIme()) {
continue;
}
@@ -2466,7 +2466,7 @@
boolean clearImeAdjustAnimation() {
boolean changed = false;
for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(i);
if (stack != null && stack.isAdjustedForIme()) {
stack.resetAdjustedForIme(true /* adjustBoundsNow */);
changed = true;
@@ -2477,7 +2477,7 @@
void beginImeAdjustAnimation() {
for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(i);
if (stack.isVisible() && stack.isAdjustedForIme()) {
stack.beginImeAdjustAnimation();
}
@@ -2488,10 +2488,10 @@
final WindowState imeWin = mInputMethodWindow;
final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
&& !mDividerControllerLocked.isImeHideRequested();
- final TaskStack dockedStack = getSplitScreenPrimaryStack();
+ final ActivityStack dockedStack = getSplitScreenPrimaryStack();
final boolean dockVisible = dockedStack != null;
final Task topDockedTask = dockVisible ? dockedStack.getTopChild() : null;
- final TaskStack imeTargetStack = mWmService.getImeFocusStackLocked();
+ final ActivityStack imeTargetStack = mWmService.getImeFocusStackLocked();
final int imeDockSide = (dockVisible && imeTargetStack != null) ?
imeTargetStack.getDockSide() : DOCKED_INVALID;
final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
@@ -2515,7 +2515,7 @@
if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(i);
final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)
&& stack.inSplitScreenWindowingMode()) {
@@ -2528,7 +2528,7 @@
imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
} else {
for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(i);
stack.resetAdjustedForIme(!dockVisible);
}
mDividerControllerLocked.setAdjustedForIme(
@@ -2539,7 +2539,7 @@
void prepareFreezingTaskBounds() {
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(stackNdx);
stack.prepareFreezingTaskBounds();
}
}
@@ -2620,7 +2620,7 @@
super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
proto.write(ID, mDisplayId);
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(stackNdx);
stack.writeToProtoInnerStackOnly(proto, STACKS, logLevel);
}
mDividerControllerLocked.writeToProto(proto, DOCKED_STACK_DIVIDER_CONTROLLER);
@@ -2735,7 +2735,7 @@
pw.println();
pw.println(prefix + "Application tokens in top down Z order:");
for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(stackNdx);
stack.dump(pw, prefix + " ", dumpAll);
}
@@ -2765,15 +2765,15 @@
pw.println();
// Dump stack references
- final TaskStack homeStack = getHomeStack();
+ final ActivityStack homeStack = getHomeStack();
if (homeStack != null) {
pw.println(prefix + "homeStack=" + homeStack.getName());
}
- final TaskStack pinnedStack = getPinnedStack();
+ final ActivityStack pinnedStack = getPinnedStack();
if (pinnedStack != null) {
pw.println(prefix + "pinnedStack=" + pinnedStack.getName());
}
- final TaskStack splitScreenPrimaryStack = getSplitScreenPrimaryStack();
+ final ActivityStack splitScreenPrimaryStack = getSplitScreenPrimaryStack();
if (splitScreenPrimaryStack != null) {
pw.println(prefix + "splitScreenPrimaryStack=" + splitScreenPrimaryStack.getName());
}
@@ -2806,7 +2806,7 @@
/** Returns true if the stack in the windowing mode is visible. */
boolean isStackVisible(int windowingMode) {
- final TaskStack stack = getTopStackInWindowingMode(windowingMode);
+ final ActivityStack stack = getTopStackInWindowingMode(windowingMode);
return stack != null && stack.isVisible();
}
@@ -3911,7 +3911,7 @@
* Window container class that contains all containers on this display relating to Apps.
* I.e Activities.
*/
- private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
+ private final class TaskStackContainers extends DisplayChildWindowContainer<ActivityStack> {
/**
* A control placed at the appropriate level for transitions to occur.
*/
@@ -3936,9 +3936,9 @@
// Cached reference to some special stacks we tend to get a lot so we don't need to loop
// through the list to find them.
- private TaskStack mHomeStack = null;
- private TaskStack mPinnedStack = null;
- private TaskStack mSplitScreenPrimaryStack = null;
+ private ActivityStack mHomeStack = null;
+ private ActivityStack mPinnedStack = null;
+ private ActivityStack mSplitScreenPrimaryStack = null;
TaskStackContainers(WindowManagerService service) {
super(service);
@@ -3954,7 +3954,7 @@
* Returns the topmost stack on the display that is compatible with the input windowing mode
* and activity type. Null is no compatible stack on the display.
*/
- TaskStack getStack(int windowingMode, int activityType) {
+ ActivityStack getStack(int windowingMode, int activityType) {
if (activityType == ACTIVITY_TYPE_HOME) {
return mHomeStack;
}
@@ -3964,7 +3964,7 @@
return mSplitScreenPrimaryStack;
}
for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
- final TaskStack stack = mTaskStackContainers.getChildAt(i);
+ final ActivityStack stack = mTaskStackContainers.getChildAt(i);
if (activityType == ACTIVITY_TYPE_UNDEFINED
&& windowingMode == stack.getWindowingMode()) {
// Passing in undefined type means we want to match the topmost stack with the
@@ -3979,23 +3979,23 @@
}
@VisibleForTesting
- TaskStack getTopStack() {
+ ActivityStack getTopStack() {
return mTaskStackContainers.getChildCount() > 0
? mTaskStackContainers.getChildAt(mTaskStackContainers.getChildCount() - 1) : null;
}
- TaskStack getHomeStack() {
+ ActivityStack getHomeStack() {
if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
}
return mHomeStack;
}
- TaskStack getPinnedStack() {
+ ActivityStack getPinnedStack() {
return mPinnedStack;
}
- TaskStack getSplitScreenPrimaryStack() {
+ ActivityStack getSplitScreenPrimaryStack() {
return mSplitScreenPrimaryStack;
}
@@ -4009,7 +4009,7 @@
return visibleTasks;
}
- void onStackWindowingModeChanged(TaskStack stack) {
+ void onStackWindowingModeChanged(ActivityStack stack) {
removeStackReferenceIfNeeded(stack);
addStackReferenceIfNeeded(stack);
if (stack == mPinnedStack && getTopStack() != stack) {
@@ -4018,7 +4018,7 @@
}
}
- private void addStackReferenceIfNeeded(TaskStack stack) {
+ private void addStackReferenceIfNeeded(ActivityStack stack) {
if (stack.isActivityTypeHome()) {
if (mHomeStack != null) {
throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
@@ -4046,7 +4046,7 @@
}
}
- private void removeStackReferenceIfNeeded(TaskStack stack) {
+ private void removeStackReferenceIfNeeded(ActivityStack stack) {
if (stack == mHomeStack) {
mHomeStack = null;
} else if (stack == mPinnedStack) {
@@ -4061,14 +4061,13 @@
}
@Override
- void addChild(TaskStack stack, int position) {
+ void addChild(ActivityStack stack, int position) {
addStackReferenceIfNeeded(stack);
position = findPositionForStack(position, stack, true /* adding */);
super.addChild(stack, position);
if (mActivityDisplay != null) {
- // TODO(stack-merge): Remove cast.
- mActivityDisplay.addChild((ActivityStack) stack, position, true /*fromDc*/);
+ mActivityDisplay.addChild(stack, position, true /*fromDc*/);
}
// The reparenting case is handled in WindowContainer.
@@ -4079,11 +4078,10 @@
}
@Override
- protected void removeChild(TaskStack stack) {
+ protected void removeChild(ActivityStack stack) {
super.removeChild(stack);
if (mActivityDisplay != null) {
- // TODO(stack-merge): Remove cast.
- mActivityDisplay.onChildRemoved((ActivityStack) stack);
+ mActivityDisplay.onChildRemoved(stack);
}
removeStackReferenceIfNeeded(stack);
}
@@ -4095,7 +4093,7 @@
}
@Override
- void positionChildAt(int position, TaskStack child, boolean includingParents) {
+ void positionChildAt(int position, ActivityStack child, boolean includingParents) {
if (child.getWindowConfiguration().isAlwaysOnTop()
&& position != POSITION_TOP) {
// This stack is always-on-top, override the default behavior.
@@ -4134,7 +4132,8 @@
* @param adding Flag indicates whether we're adding a new stack or positioning an existing.
* @return The proper position for the stack.
*/
- private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) {
+ private int findPositionForStack(int requestedPosition, ActivityStack stack,
+ boolean adding) {
if (stack.inPinnedWindowingMode()) {
return POSITION_TOP;
}
@@ -4316,7 +4315,7 @@
assignStackOrdering(t);
for (int i = 0; i < mChildren.size(); i++) {
- final TaskStack s = mChildren.get(i);
+ final ActivityStack s = mChildren.get(i);
s.assignChildLayers(t);
}
}
@@ -4329,7 +4328,7 @@
mTmpHomeStacks.clear();
mTmpNormalStacks.clear();
for (int i = 0; i < mChildren.size(); ++i) {
- final TaskStack s = mChildren.get(i);
+ final ActivityStack s = mChildren.get(i);
if (s.isAlwaysOnTop()) {
mTmpAlwaysOnTopStacks.add(s);
} else if (s.isActivityTypeHome()) {
@@ -4349,7 +4348,7 @@
int layerForSplitScreenDividerAnchor = layer++;
int layerForAnimationLayer = layer++;
for (int i = 0; i < mTmpNormalStacks.size(); i++) {
- final TaskStack s = mTmpNormalStacks.get(i);
+ final ActivityStack s = mTmpNormalStacks.get(i);
s.assignLayer(t, layer++);
if (s.inSplitScreenWindowingMode()) {
// The split screen divider anchor is located above the split screen window.
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index b454922..07d5094 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -140,7 +140,7 @@
float mLastDividerProgress;
private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4];
private boolean mImeHideRequested;
- private TaskStack mDimmedStack;
+ private ActivityStack mDimmedStack;
DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
mService = service;
@@ -255,7 +255,7 @@
}
boolean isHomeStackResizable() {
- final TaskStack homeStack = mDisplayContent.getHomeStack();
+ final ActivityStack homeStack = mDisplayContent.getHomeStack();
if (homeStack == null) {
return false;
}
@@ -371,7 +371,7 @@
if (mWindow == null) {
return;
}
- TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
+ ActivityStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
// If the stack is invisible, we policy force hide it in WindowAnimator.shouldForceHide
final boolean visible = stack != null;
@@ -415,7 +415,7 @@
}
void positionDockedStackedDivider(Rect frame) {
- TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
+ ActivityStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
if (stack == null) {
// Unfortunately we might end up with still having a divider, even though the underlying
// stack was already removed. This is because we are on AM thread and the removal of the
@@ -523,7 +523,8 @@
// If a primary stack was just created, it will not have access to display content at
// this point so pass it from here to get a valid dock side.
- final TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
+ final ActivityStack stack =
+ mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
mOriginalDockedSide = stack.getDockSideForDisplay(mDisplayContent);
return;
}
@@ -558,7 +559,7 @@
boolean isHomeStackResizable) {
long animDuration = 0;
if (animate) {
- final TaskStack stack =
+ final ActivityStack stack =
mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
final long transitionDuration = isAnimationMaximizing()
? mDisplayContent.mAppTransition.getLastClipRevealTransitionDuration()
@@ -629,10 +630,10 @@
*/
void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) {
// TODO: Maybe only allow split-screen windowing modes?
- final TaskStack stack = targetWindowingMode != WINDOWING_MODE_UNDEFINED
+ final ActivityStack stack = targetWindowingMode != WINDOWING_MODE_UNDEFINED
? mDisplayContent.getTopStackInWindowingMode(targetWindowingMode)
: null;
- final TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStack();
+ final ActivityStack dockedStack = mDisplayContent.getSplitScreenPrimaryStack();
boolean visibleAndValid = visible && stack != null && dockedStack != null;
// Ensure an old dim that was shown for the docked stack divider is removed so we don't end
@@ -703,7 +704,7 @@
if (mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility() == null) {
return;
}
- final TaskStack homeStack = mDisplayContent.getHomeStack();
+ final ActivityStack homeStack = mDisplayContent.getHomeStack();
if (homeStack == null) {
return;
}
@@ -717,7 +718,7 @@
if (mMinimizedDock && mService.mKeyguardOrAodShowingOnDefaultDisplay) {
return;
}
- final TaskStack topSecondaryStack = mDisplayContent.getTopStackInWindowingMode(
+ final ActivityStack topSecondaryStack = mDisplayContent.getTopStackInWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController();
final boolean minimizedForRecentsAnimation = recentsAnim != null &&
@@ -872,7 +873,7 @@
}
private boolean setMinimizedDockedStack(boolean minimized) {
- final TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
+ final ActivityStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
notifyDockedStackMinimizedChanged(minimized, false /* animate */, isHomeStackResizable());
return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f);
}
@@ -922,7 +923,7 @@
}
private boolean animateForMinimizedDockedStack(long now) {
- final TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
+ final ActivityStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
if (!mAnimationStarted) {
mAnimationStarted = true;
mAnimationStartTime = now;
@@ -956,7 +957,7 @@
/**
* Gets the amount how much to minimize a stack depending on the interpolated fraction t.
*/
- private float getMinimizeAmount(TaskStack stack, float t) {
+ private float getMinimizeAmount(ActivityStack stack, float t) {
final float naturalAmount = getInterpolatedAnimationValue(t);
if (isAnimationMaximizing()) {
return adjustMaximizeAmount(stack, t, naturalAmount);
@@ -971,7 +972,7 @@
* transition so we don't create a visible "hole", but only if both the clip reveal and the
* docked stack divider start from about the same portion on the screen.
*/
- private float adjustMaximizeAmount(TaskStack stack, float t, float naturalAmount) {
+ private float adjustMaximizeAmount(ActivityStack stack, float t, float naturalAmount) {
if (mMaximizeMeetFraction == 1f) {
return naturalAmount;
}
@@ -987,7 +988,7 @@
* Retrieves the animation fraction at which the docked stack has to meet the clip reveal
* edge. See {@link #adjustMaximizeAmount}.
*/
- private float getClipRevealMeetFraction(TaskStack stack) {
+ private float getClipRevealMeetFraction(ActivityStack stack) {
if (!isAnimationMaximizing() || stack == null ||
!mDisplayContent.mAppTransition.hadClipRevealAnimation()) {
return 1f;
diff --git a/services/core/java/com/android/server/wm/DragResizeMode.java b/services/core/java/com/android/server/wm/DragResizeMode.java
index c0bf1e8..71beb50 100644
--- a/services/core/java/com/android/server/wm/DragResizeMode.java
+++ b/services/core/java/com/android/server/wm/DragResizeMode.java
@@ -35,7 +35,7 @@
*/
static final int DRAG_RESIZE_MODE_DOCKED_DIVIDER = 1;
- static boolean isModeAllowedForStack(TaskStack stack, int mode) {
+ static boolean isModeAllowedForStack(ActivityStack stack, int mode) {
switch (mode) {
case DRAG_RESIZE_MODE_FREEFORM:
return stack.getWindowingMode() == WINDOWING_MODE_FREEFORM;
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 6cb1e76..a5b1fda 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -140,7 +140,7 @@
public void startAnimation(Rect destinationBounds, Rect sourceRectHint,
int animationDuration) {
synchronized (mService.mGlobalLock) {
- final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+ final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
pinnedStack.animateResizePinnedStack(destinationBounds,
sourceRectHint, animationDuration, true /* fromFullscreen */);
}
@@ -468,7 +468,7 @@
}
try {
final Rect animatingBounds = new Rect();
- final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
+ final ActivityStack pinnedStack = mDisplayContent.getPinnedStack();
if (pinnedStack != null) {
pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 7a3e43b..282144e 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -366,7 +366,7 @@
// Make leashes for each of the visible/target tasks and add it to the recents animation to
// be started
final ArrayList<Task> visibleTasks = mDisplayContent.getVisibleTasks();
- final TaskStack targetStack = mDisplayContent.getStack(WINDOWING_MODE_UNDEFINED,
+ final ActivityStack targetStack = mDisplayContent.getStack(WINDOWING_MODE_UNDEFINED,
targetActivityType);
if (targetStack != null) {
for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
@@ -410,7 +410,8 @@
}
// Save the minimized home height
- final TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
+ final ActivityStack dockedStack =
+ mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
mDisplayContent.getDockedDividerController().getHomeStackBoundsInDockedMode(
mDisplayContent.getConfiguration(),
dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(),
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 149bcfb..f33a0eb 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -412,10 +412,10 @@
}
}
- TaskStack getStack(int windowingMode, int activityType) {
+ ActivityStack getStack(int windowingMode, int activityType) {
for (int i = mChildren.size() - 1; i >= 0; i--) {
final DisplayContent dc = mChildren.get(i);
- final TaskStack stack = dc.getStack(windowingMode, activityType);
+ final ActivityStack stack = dc.getStack(windowingMode, activityType);
if (stack != null) {
return stack;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 60b7ac0..eec51a6 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -935,7 +935,6 @@
@Override
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- // TODO(stack-merge): Remove casts after object merge.
final ActivityStack oldStack = ((ActivityStack) oldParent);
final ActivityStack newStack = ((ActivityStack) newParent);
@@ -2238,8 +2237,8 @@
return getTaskStack() != null ? getTaskStack().getDisplayContent() : null;
}
- TaskStack getTaskStack() {
- return (TaskStack) getParent();
+ ActivityStack getTaskStack() {
+ return (ActivityStack) getParent();
}
int getAdjustedAddPosition(ActivityRecord r, int suggestedPosition) {
@@ -2305,13 +2304,12 @@
}
// TODO: Consolidate this with Task.reparent()
- void reparent(TaskStack stack, int position, boolean moveParents, String reason) {
+ void reparent(ActivityStack stack, int position, boolean moveParents, String reason) {
if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
+ " from stack=" + getTaskStack());
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask");
- // TODO(stack-merge): Remove cast.
- final ActivityStack prevStack = (ActivityStack) getTaskStack();
+ final ActivityStack prevStack = getTaskStack();
final boolean wasTopFocusedStack =
mAtmService.mRootActivityContainer.isTopDisplayFocusedStack(prevStack);
final ActivityDisplay prevStackDisplay = prevStack.getDisplay();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
deleted file mode 100644
index ec627c8..0000000
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ /dev/null
@@ -1,1816 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
-import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.DOCKED_BOTTOM;
-import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_RIGHT;
-import static android.view.WindowManager.DOCKED_TOP;
-
-import static com.android.server.wm.BoundsAnimationController.FADE_IN;
-import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
-import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
-import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
-import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
-import static com.android.server.wm.StackProto.ADJUSTED_BOUNDS;
-import static com.android.server.wm.StackProto.ADJUSTED_FOR_IME;
-import static com.android.server.wm.StackProto.ADJUST_DIVIDER_AMOUNT;
-import static com.android.server.wm.StackProto.ADJUST_IME_AMOUNT;
-import static com.android.server.wm.StackProto.ANIMATING_BOUNDS;
-import static com.android.server.wm.StackProto.BOUNDS;
-import static com.android.server.wm.StackProto.DEFER_REMOVAL;
-import static com.android.server.wm.StackProto.FILLS_PARENT;
-import static com.android.server.wm.StackProto.ID;
-import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
-import static com.android.server.wm.StackProto.TASKS;
-import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
-import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
-import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
-import android.app.RemoteAction;
-import android.content.res.Configuration;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.os.RemoteException;
-import android.util.DisplayMetrics;
-import android.util.EventLog;
-import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
-import android.view.DisplayCutout;
-import android.view.DisplayInfo;
-import android.view.RemoteAnimationTarget;
-import android.view.SurfaceControl;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.policy.DividerSnapAlgorithm;
-import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
-import com.android.internal.policy.DockedDividerUtils;
-import com.android.server.EventLogTags;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-public class TaskStack extends WindowContainer<Task> implements
- BoundsAnimationTarget, ConfigurationContainerListener {
- /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
- * restrict IME adjustment so that a min portion of top stack remains visible.*/
- private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
-
- /** Dimming amount for non-focused stack when stacks are IME-adjusted. */
- private static final float IME_ADJUST_DIM_AMOUNT = 0.25f;
-
- /** Unique identifier */
- final int mStackId;
-
- /** For comparison with DisplayContent bounds. */
- private Rect mTmpRect = new Rect();
- private Rect mTmpRect2 = new Rect();
- private Rect mTmpRect3 = new Rect();
-
- /** For Pinned stack controlling. */
- private Rect mTmpToBounds = new Rect();
-
- /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
- private final Rect mAdjustedBounds = new Rect();
-
- /**
- * Fully adjusted IME bounds. These are different from {@link #mAdjustedBounds} because they
- * represent the state when the animation has ended.
- */
- private final Rect mFullyAdjustedImeBounds = new Rect();
-
- /** ActivityRecords that are exiting, but still on screen for animations. */
- final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
-
- /** Detach this stack from its display when animation completes. */
- // TODO: maybe tie this to WindowContainer#removeChild some how...
- private boolean mDeferRemoval;
-
- private final Rect mTmpAdjustedBounds = new Rect();
- private boolean mAdjustedForIme;
- private boolean mImeGoingAway;
- private WindowState mImeWin;
- private float mMinimizeAmount;
- private float mAdjustImeAmount;
- private float mAdjustDividerAmount;
- private final int mDockedStackMinimizeThickness;
-
- // If this is true, we are in the bounds animating mode. The task will be down or upscaled to
- // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
- // would otherwise apply while resizing, while resizing in the bounds animating mode.
- private boolean mBoundsAnimating = false;
- // Set when an animation has been requested but has not yet started from the UI thread. This is
- // cleared when the animation actually starts.
- private boolean mBoundsAnimatingRequested = false;
- private boolean mBoundsAnimatingToFullscreen = false;
- private boolean mCancelCurrentBoundsAnimation = false;
- private Rect mBoundsAnimationTarget = new Rect();
- private Rect mBoundsAnimationSourceHintBounds = new Rect();
- private @BoundsAnimationController.AnimationType int mAnimationType;
-
- Rect mPreAnimationBounds = new Rect();
-
- private Dimmer mDimmer = new Dimmer(this);
-
- /**
- * For {@link #prepareSurfaces}.
- */
- private final Rect mTmpDimBoundsRect = new Rect();
- private final Point mLastSurfaceSize = new Point();
-
- private final AnimatingActivityRegistry mAnimatingActivityRegistry =
- new AnimatingActivityRegistry();
-
- TaskStack(WindowManagerService service, int stackId) {
- super(service);
- mStackId = stackId;
- mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_minimize_thickness);
- EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
- }
-
- Task findHomeTask() {
- if (!isActivityTypeHome() || mChildren.isEmpty()) {
- return null;
- }
- return mChildren.get(mChildren.size() - 1);
- }
-
- void prepareFreezingTaskBounds() {
- for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
- final Task task = mChildren.get(taskNdx);
- task.prepareFreezingBounds();
- }
- }
-
- /**
- * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
- * the normal task bounds.
- *
- * @param bounds The adjusted bounds.
- */
- private void setAdjustedBounds(Rect bounds) {
- if (mAdjustedBounds.equals(bounds) && !isAnimatingForIme()) {
- return;
- }
-
- mAdjustedBounds.set(bounds);
- final boolean adjusted = !mAdjustedBounds.isEmpty();
- Rect insetBounds = null;
- if (adjusted && isAdjustedForMinimizedDockedStack()) {
- insetBounds = getRawBounds();
- } else if (adjusted && mAdjustedForIme) {
- if (mImeGoingAway) {
- insetBounds = getRawBounds();
- } else {
- insetBounds = mFullyAdjustedImeBounds;
- }
- }
- alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : getRawBounds(), insetBounds);
- mDisplayContent.setLayoutNeeded();
-
- updateSurfaceBounds();
- }
-
- private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
- if (matchParentBounds()) {
- return;
- }
-
- final boolean alignBottom = mAdjustedForIme && getDockSide() == DOCKED_TOP;
-
- // Update bounds of containing tasks.
- for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
- final Task task = mChildren.get(taskNdx);
- task.alignToAdjustedBounds(adjustedBounds, tempInsetBounds, alignBottom);
- }
- }
-
- @Override
- public int setBounds(Rect bounds) {
- return setBounds(getRequestedOverrideBounds(), bounds);
- }
-
- private int setBounds(Rect existing, Rect bounds) {
- if (equivalentBounds(existing, bounds)) {
- return BOUNDS_CHANGE_NONE;
- }
-
- final int result = super.setBounds(!inMultiWindowMode() ? null : bounds);
-
- updateAdjustedBounds();
-
- updateSurfaceBounds();
- return result;
- }
-
- /** Bounds of the stack without adjusting for other factors in the system like visibility
- * of docked stack.
- * Most callers should be using {@link ConfigurationContainer#getRequestedOverrideBounds} a
- * it takes into consideration other system factors. */
- void getRawBounds(Rect out) {
- out.set(getRawBounds());
- }
-
- private Rect getRawBounds() {
- return super.getBounds();
- }
-
- @Override
- public void getBounds(Rect bounds) {
- bounds.set(getBounds());
- }
-
- @Override
- public Rect getBounds() {
- // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
- // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
- // stack is visible since it is already what we want to represent to the rest of the
- // system.
- if (!mAdjustedBounds.isEmpty()) {
- return mAdjustedBounds;
- } else {
- return super.getBounds();
- }
- }
-
- /**
- * Sets the bounds animation target bounds ahead of an animation. This can't currently be done
- * in onAnimationStart() since that is started on the UiThread.
- */
- private void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds,
- boolean toFullscreen) {
- if (mAnimationType == BoundsAnimationController.BOUNDS) {
- mBoundsAnimatingRequested = true;
- }
- mBoundsAnimatingToFullscreen = toFullscreen;
- if (destBounds != null) {
- mBoundsAnimationTarget.set(destBounds);
- } else {
- mBoundsAnimationTarget.setEmpty();
- }
- if (sourceHintBounds != null) {
- mBoundsAnimationSourceHintBounds.set(sourceHintBounds);
- } else if (!mBoundsAnimating) {
- // If the bounds are already animating, we don't want to reset the source hint. This is
- // because the source hint is sent when starting the animation from the client that
- // requested to enter pip. Other requests can adjust the pip bounds during an animation,
- // but could accidentally reset the source hint bounds.
- mBoundsAnimationSourceHintBounds.setEmpty();
- }
-
- mPreAnimationBounds.set(getRawBounds());
- }
-
- /**
- * @return the final bounds for the bounds animation.
- */
- void getFinalAnimationBounds(Rect outBounds) {
- outBounds.set(mBoundsAnimationTarget);
- }
-
- /**
- * @return the final source bounds for the bounds animation.
- */
- void getFinalAnimationSourceHintBounds(Rect outBounds) {
- outBounds.set(mBoundsAnimationSourceHintBounds);
- }
-
- /**
- * @return the final animation bounds if the task stack is currently being animated, or the
- * current stack bounds otherwise.
- */
- void getAnimationOrCurrentBounds(Rect outBounds) {
- if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
- getFinalAnimationBounds(outBounds);
- return;
- }
- getBounds(outBounds);
- }
-
- /** Bounds of the stack with other system factors taken into consideration. */
- void getDimBounds(Rect out) {
- getBounds(out);
- }
-
- /**
- * Updates the passed-in {@code inOutBounds} based on the current state of the
- * pinned controller. This gets run *after* the override configuration is updated, so it's
- * safe to rely on the controller's state in here (though eventually this dependence should
- * be removed).
- *
- * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
- * update pinned controller state.
- *
- * @param inOutBounds the bounds to update (both input and output).
- * @return true if bounds were updated to some non-empty value.
- */
- boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) {
- boolean animating = false;
- if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
- animating = true;
- getFinalAnimationBounds(mTmpRect2);
- } else {
- mTmpRect2.set(inOutBounds);
- }
- boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
- mTmpRect2, mTmpRect3);
- if (updated) {
- inOutBounds.set(mTmpRect3);
-
- // The final boundary is updated while there is an existing boundary animation. Let's
- // cancel this animation to prevent the obsolete animation overwritten updated bounds.
- if (animating && !inOutBounds.equals(mBoundsAnimationTarget)) {
- final DisplayContent displayContent = getDisplayContent();
- displayContent.mBoundsAnimationController.getHandler().post(() ->
- displayContent.mBoundsAnimationController.cancel(this));
- }
- // Once we've set the bounds based on the rotation of the old bounds in the new
- // orientation, clear the animation target bounds since they are obsolete, and
- // cancel any currently running animations
- mBoundsAnimationTarget.setEmpty();
- mBoundsAnimationSourceHintBounds.setEmpty();
- mCancelCurrentBoundsAnimation = true;
- }
- return updated;
- }
-
- /**
- * Updates the passed-in {@code inOutBounds} based on the current state of the
- * docked controller. This gets run *after* the override configuration is updated, so it's
- * safe to rely on the controller's state in here (though eventually this dependence should
- * be removed).
- *
- * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
- * update docked controller state.
- *
- * @param parentConfig the parent configuration for reference.
- * @param inOutBounds the bounds to update (both input and output).
- */
- void calculateDockedBoundsForConfigChange(Configuration parentConfig, Rect inOutBounds) {
- final boolean primary =
- getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
- repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
- final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
- snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
- if (primary) {
- final int newDockSide = getDockSide(parentConfig, inOutBounds);
- // Update the dock create mode and clear the dock create bounds, these
- // might change after a rotation and the original values will be invalid.
- mWmService.setDockedStackCreateStateLocked(
- (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
- ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
- : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
- null);
- mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
- }
- }
-
- /**
- * Some primary split screen sides are not allowed by the policy. This method queries the policy
- * and moves the primary stack around if needed.
- *
- * @param parentConfig the configuration of the stack's parent.
- * @param primary true if adjusting the primary docked stack, false for secondary.
- * @param inOutBounds the bounds of the stack to adjust.
- */
- void repositionSplitScreenStackAfterRotation(Configuration parentConfig, boolean primary,
- Rect inOutBounds) {
- final int dockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds);
- final int otherDockSide = DockedDividerUtils.invertDockSide(dockSide);
- final int primaryDockSide = primary ? dockSide : otherDockSide;
- if (mDisplayContent.getDockedDividerController()
- .canPrimaryStackDockTo(primaryDockSide,
- parentConfig.windowConfiguration.getBounds(),
- parentConfig.windowConfiguration.getRotation())) {
- return;
- }
- final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
- switch (otherDockSide) {
- case DOCKED_LEFT:
- int movement = inOutBounds.left;
- inOutBounds.left -= movement;
- inOutBounds.right -= movement;
- break;
- case DOCKED_RIGHT:
- movement = parentBounds.right - inOutBounds.right;
- inOutBounds.left += movement;
- inOutBounds.right += movement;
- break;
- case DOCKED_TOP:
- movement = inOutBounds.top;
- inOutBounds.top -= movement;
- inOutBounds.bottom -= movement;
- break;
- case DOCKED_BOTTOM:
- movement = parentBounds.bottom - inOutBounds.bottom;
- inOutBounds.top += movement;
- inOutBounds.bottom += movement;
- break;
- }
- }
-
- /**
- * Snaps the bounds after rotation to the closest snap target for the docked stack.
- */
- void snapDockedStackAfterRotation(Configuration parentConfig, DisplayCutout displayCutout,
- Rect outBounds) {
-
- // Calculate the current position.
- final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth();
- final int dockSide = getDockSide(parentConfig, outBounds);
- final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
- dockSide, dividerSize);
- final int displayWidth = parentConfig.windowConfiguration.getBounds().width();
- final int displayHeight = parentConfig.windowConfiguration.getBounds().height();
-
- // Snap the position to a target.
- final int rotation = parentConfig.windowConfiguration.getRotation();
- final int orientation = parentConfig.orientation;
- mDisplayContent.getDisplayPolicy().getStableInsetsLw(rotation, displayWidth, displayHeight,
- displayCutout, outBounds);
- final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
- mWmService.mContext.getResources(), displayWidth, displayHeight,
- dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
- getDockSide(), isMinimizedDockAndHomeStackResizable());
- final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
-
- // Recalculate the bounds based on the position of the target.
- DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
- outBounds, displayWidth, displayHeight,
- dividerSize);
- }
-
- /**
- * Put a Task in this stack. Used for adding only.
- * When task is added to top of the stack, the entire branch of the hierarchy (including stack
- * and display) will be brought to top.
- * @param task The task to add.
- * @param position Target position to add the task to.
- * @param showForAllUsers Whether to show the task regardless of the current user.
- */
- void addChild(Task task, int position, boolean showForAllUsers, boolean moveParents) {
- // Add child task.
- addChild(task, null);
-
- // Move child to a proper position, as some restriction for position might apply.
- position = positionChildAt(
- position, task, moveParents /* includingParents */, showForAllUsers);
- // TODO: Feels like this should go in TaskRecord#onParentChanged
- final boolean toTop = position >= getChildCount();
- task.updateTaskMovement(toTop);
- }
-
- @Override
- void addChild(Task task, int position) {
- addChild(task, position, task.showForAllUsers(), false /* includingParents */);
- }
-
- void positionChildAt(Task child, int position) {
- if (DEBUG_STACK) {
- Slog.i(TAG_WM, "positionChildAt: positioning task=" + child + " at " + position);
- }
- if (child == null) {
- if (DEBUG_STACK) {
- Slog.i(TAG_WM, "positionChildAt: could not find task=" + this);
- }
- return;
- }
- positionChildAt(position, child, false /* includingParents */);
- child.updateTaskMovement(true);
- getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
-
- void positionChildAtTop(Task child, boolean includingParents) {
- if (child == null) {
- // TODO: Fix the call-points that cause this to happen.
- return;
- }
-
- positionChildAt(POSITION_TOP, child, includingParents);
- child.updateTaskMovement(true);
-
- final DisplayContent displayContent = getDisplayContent();
- if (displayContent.mAppTransition.isTransitionSet()) {
- child.setSendingToBottom(false);
- }
- displayContent.layoutAndAssignWindowLayersIfNeeded();
- }
-
- void positionChildAtBottom(Task child, boolean includingParents) {
- if (child == null) {
- // TODO: Fix the call-points that cause this to happen.
- return;
- }
-
- positionChildAt(POSITION_BOTTOM, child, includingParents);
-
- if (getDisplayContent().mAppTransition.isTransitionSet()) {
- child.setSendingToBottom(true);
- }
- getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
-
- @Override
- void positionChildAt(int position, Task child, boolean includingParents) {
- positionChildAt(position, child, includingParents, child.showForAllUsers());
- }
-
- /**
- * Overridden version of {@link TaskStack#positionChildAt(int, Task, boolean)}. Used in
- * {@link TaskStack#addChild(Task, int, boolean showForAllUsers, boolean)}, as it can receive
- * showForAllUsers param from {@link ActivityRecord} instead of {@link Task#showForAllUsers()}.
- */
- private int positionChildAt(int position, Task child, boolean includingParents,
- boolean showForAllUsers) {
- final int targetPosition = findPositionForTask(child, position, showForAllUsers);
- super.positionChildAt(targetPosition, child, includingParents);
-
- // Log positioning.
- if (DEBUG_TASK_MOVEMENT)
- Slog.d(TAG_WM, "positionTask: task=" + this + " position=" + position);
-
- final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
- EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
-
- return targetPosition;
- }
-
- @Override
- void onChildPositionChanged(WindowContainer child) {
- if (mChildren.contains(child)) {
- ((Task) child).updateTaskMovement(getTopChild() == child);
- }
- }
-
- void reparent(DisplayContent newParent, boolean onTop) {
- // Real parent of stack is within display object, so we have to delegate re-parenting there.
- newParent.moveStackToDisplay(this, onTop);
- }
-
- // TODO: We should really have users as a window container in the hierarchy so that we don't
- // have to do complicated things like we are doing in this method.
- int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers) {
- final boolean canShowTask =
- showForAllUsers || mWmService.isCurrentProfileLocked(task.mUserId);
-
- final int stackSize = mChildren.size();
- int minPosition = 0;
- int maxPosition = stackSize - 1;
-
- if (canShowTask) {
- minPosition = computeMinPosition(minPosition, stackSize);
- } else {
- maxPosition = computeMaxPosition(maxPosition);
- }
-
- // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
- if (targetPosition == POSITION_BOTTOM && minPosition == 0) {
- return POSITION_BOTTOM;
- } else if (targetPosition == POSITION_TOP && maxPosition == (stackSize - 1)) {
- return POSITION_TOP;
- }
- // Reset position based on minimum/maximum possible positions.
- return Math.min(Math.max(targetPosition, minPosition), maxPosition);
- }
-
- /** Calculate the minimum possible position for a task that can be shown to the user.
- * The minimum position will be above all other tasks that can't be shown.
- * @param minPosition The minimum position the caller is suggesting.
- * We will start adjusting up from here.
- * @param size The size of the current task list.
- */
- private int computeMinPosition(int minPosition, int size) {
- while (minPosition < size) {
- final Task tmpTask = mChildren.get(minPosition);
- final boolean canShowTmpTask =
- tmpTask.showForAllUsers()
- || mWmService.isCurrentProfileLocked(tmpTask.mUserId);
- if (canShowTmpTask) {
- break;
- }
- minPosition++;
- }
- return minPosition;
- }
-
- /** Calculate the maximum possible position for a task that can't be shown to the user.
- * The maximum position will be below all other tasks that can be shown.
- * @param maxPosition The maximum position the caller is suggesting.
- * We will start adjusting down from here.
- */
- private int computeMaxPosition(int maxPosition) {
- while (maxPosition > 0) {
- final Task tmpTask = mChildren.get(maxPosition);
- final boolean canShowTmpTask =
- tmpTask.showForAllUsers()
- || mWmService.isCurrentProfileLocked(tmpTask.mUserId);
- if (!canShowTmpTask) {
- break;
- }
- maxPosition--;
- }
- return maxPosition;
- }
-
- @Override
- public void onConfigurationChanged(Configuration newParentConfig) {
- final int prevWindowingMode = getWindowingMode();
- super.onConfigurationChanged(newParentConfig);
-
- // Only need to update surface size here since the super method will handle updating
- // surface position.
- updateSurfaceSize(getPendingTransaction());
- final int windowingMode = getWindowingMode();
-
- if (mDisplayContent == null) {
- return;
- }
-
- if (prevWindowingMode != windowingMode) {
- mDisplayContent.onStackWindowingModeChanged(this);
-
- if (inSplitScreenSecondaryWindowingMode()) {
- // When the stack is resized due to entering split screen secondary, offset the
- // windows to compensate for the new stack position.
- forAllWindows(w -> {
- w.mWinAnimator.setOffsetPositionForStackResize(true);
- }, true);
- }
- }
- }
-
- private void updateSurfaceBounds() {
- updateSurfaceSize(getPendingTransaction());
- updateSurfacePosition();
- scheduleAnimation();
- }
-
- /**
- * Calculate an amount by which to expand the stack bounds in each direction.
- * Used to make room for shadows in the pinned windowing mode.
- */
- int getStackOutset() {
- DisplayContent displayContent = getDisplayContent();
- if (inPinnedWindowingMode() && displayContent != null) {
- final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
-
- // We multiply by two to match the client logic for converting view elevation
- // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
- return (int)Math.ceil(mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP,
- displayMetrics) * 2);
- }
- return 0;
- }
-
- @Override
- void getRelativeDisplayedPosition(Point outPos) {
- super.getRelativeDisplayedPosition(outPos);
- final int outset = getStackOutset();
- outPos.x -= outset;
- outPos.y -= outset;
- }
-
- private void updateSurfaceSize(SurfaceControl.Transaction transaction) {
- if (mSurfaceControl == null) {
- return;
- }
-
- final Rect stackBounds = getDisplayedBounds();
- int width = stackBounds.width();
- int height = stackBounds.height();
-
- final int outset = getStackOutset();
- width += 2*outset;
- height += 2*outset;
-
- if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
- return;
- }
- transaction.setWindowCrop(mSurfaceControl, width, height);
- mLastSurfaceSize.set(width, height);
- }
-
- @VisibleForTesting
- Point getLastSurfaceSize() {
- return mLastSurfaceSize;
- }
-
- @Override
- void onDisplayChanged(DisplayContent dc) {
- super.onDisplayChanged(dc);
- updateSurfaceBounds();
- }
-
- /**
- * Determines the stack and task bounds of the other stack when in docked mode. The current task
- * bounds is passed in but depending on the stack, the task and stack must match. Only in
- * minimized mode with resizable launcher, the other stack ignores calculating the stack bounds
- * and uses the task bounds passed in as the stack and task bounds, otherwise the stack bounds
- * is calculated and is also used for its task bounds.
- * If any of the out bounds are empty, it represents default bounds
- *
- * @param currentTempTaskBounds the current task bounds of the other stack
- * @param outStackBounds the calculated stack bounds of the other stack
- * @param outTempTaskBounds the calculated task bounds of the other stack
- */
- void getStackDockedModeBounds(Rect dockedBounds,
- Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds) {
- final Configuration parentConfig = getParent().getConfiguration();
- outTempTaskBounds.setEmpty();
-
- if (dockedBounds == null || dockedBounds.isEmpty()) {
- // Calculate the primary docked bounds.
- final boolean dockedOnTopOrLeft = mWmService.mDockedStackCreateMode
- == SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
- getStackDockedModeBounds(parentConfig,
- true /* primary */, outStackBounds, dockedBounds,
- mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
- return;
- }
- final int dockedSide = getDockSide(parentConfig, dockedBounds);
-
- // When the home stack is resizable, should always have the same stack and task bounds
- if (isActivityTypeHome()) {
- final Task homeTask = findHomeTask();
- if (homeTask == null || homeTask.isResizeable()) {
- // Calculate the home stack bounds when in docked mode and the home stack is
- // resizeable.
- getDisplayContent().mDividerControllerLocked
- .getHomeStackBoundsInDockedMode(parentConfig,
- dockedSide, outStackBounds);
- } else {
- // Home stack isn't resizeable, so don't specify stack bounds.
- outStackBounds.setEmpty();
- }
-
- outTempTaskBounds.set(outStackBounds);
- return;
- }
-
- // When minimized state, the stack bounds for all non-home and docked stack bounds should
- // match the passed task bounds
- if (isMinimizedDockAndHomeStackResizable() && currentTempTaskBounds != null) {
- outStackBounds.set(currentTempTaskBounds);
- return;
- }
-
- if (dockedSide == DOCKED_INVALID) {
- // Not sure how you got here...Only thing we can do is return current bounds.
- Slog.e(TAG_WM, "Failed to get valid docked side for docked stack");
- outStackBounds.set(getRawBounds());
- return;
- }
-
- final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
- getStackDockedModeBounds(parentConfig,
- false /* primary */, outStackBounds, dockedBounds,
- mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
- }
-
- /**
- * Outputs the bounds a stack should be given the presence of a docked stack on the display.
- * @param parentConfig The parent configuration.
- * @param primary {@code true} if getting the primary stack bounds.
- * @param outBounds Output bounds that should be used for the stack.
- * @param dockedBounds Bounds of the docked stack.
- * @param dockDividerWidth We need to know the width of the divider make to the output bounds
- * close to the side of the dock.
- * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
- */
- private void getStackDockedModeBounds(Configuration parentConfig, boolean primary,
- Rect outBounds, Rect dockedBounds, int dockDividerWidth,
- boolean dockOnTopOrLeft) {
- final Rect displayRect = parentConfig.windowConfiguration.getBounds();
- final boolean splitHorizontally = displayRect.width() > displayRect.height();
-
- outBounds.set(displayRect);
- if (primary) {
- if (mWmService.mDockedStackCreateBounds != null) {
- outBounds.set(mWmService.mDockedStackCreateBounds);
- return;
- }
-
- // The initial bounds of the docked stack when it is created about half the screen space
- // and its bounds can be adjusted after that. The bounds of all other stacks are
- // adjusted to occupy whatever screen space the docked stack isn't occupying.
- final DisplayCutout displayCutout = mDisplayContent.getDisplayInfo().displayCutout;
- mDisplayContent.getDisplayPolicy().getStableInsetsLw(
- parentConfig.windowConfiguration.getRotation(),
- displayRect.width(), displayRect.height(), displayCutout, mTmpRect2);
- final int position = new DividerSnapAlgorithm(mWmService.mContext.getResources(),
- displayRect.width(),
- displayRect.height(),
- dockDividerWidth,
- parentConfig.orientation == ORIENTATION_PORTRAIT,
- mTmpRect2).getMiddleTarget().position;
-
- if (dockOnTopOrLeft) {
- if (splitHorizontally) {
- outBounds.right = position;
- } else {
- outBounds.bottom = position;
- }
- } else {
- if (splitHorizontally) {
- outBounds.left = position + dockDividerWidth;
- } else {
- outBounds.top = position + dockDividerWidth;
- }
- }
- return;
- }
-
- // Other stacks occupy whatever space is left by the docked stack.
- if (!dockOnTopOrLeft) {
- if (splitHorizontally) {
- outBounds.right = dockedBounds.left - dockDividerWidth;
- } else {
- outBounds.bottom = dockedBounds.top - dockDividerWidth;
- }
- } else {
- if (splitHorizontally) {
- outBounds.left = dockedBounds.right + dockDividerWidth;
- } else {
- outBounds.top = dockedBounds.bottom + dockDividerWidth;
- }
- }
- DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
- }
-
- void resetDockedStackToMiddle() {
- if (!inSplitScreenPrimaryWindowingMode()) {
- throw new IllegalStateException("Not a docked stack=" + this);
- }
-
- mWmService.mDockedStackCreateBounds = null;
-
- final Rect bounds = new Rect();
- final Rect tempBounds = new Rect();
- getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
- bounds, tempBounds);
- // TODO(stack-merge): remove cast.
- ((ActivityStack) this).mStackSupervisor.resizeDockedStackLocked(bounds,
- null /* tempTaskBounds */,
- null /* tempTaskInsetBounds */, null /* tempOtherTaskBounds */,
- null /* tempOtherTaskInsetBounds */, false /* preserveWindows */,
- false /* deferResume */);
- }
-
- @Override
- void removeIfPossible() {
- if (isAnimating(TRANSITION | CHILDREN)) {
- mDeferRemoval = true;
- return;
- }
- removeImmediately();
- }
-
- @Override
- // TODO(stack-merge): This is mostly taking care of the case where the stask is removing from
- // the display, so we should probably consolidate it there instead.
- void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- super.onParentChanged(newParent, oldParent);
-
- if (getParent() != null || mDisplayContent == null) {
- return;
- }
-
- EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
-
- mDisplayContent = null;
- mWmService.mWindowPlacerLocked.requestTraversal();
- }
-
- /**
- * Adjusts the stack bounds if the IME is visible.
- *
- * @param imeWin The IME window.
- * @param keepLastAmount Use {@code true} to keep the last adjusted amount from
- * {@link DockedStackDividerController} for adjusting the stack bounds,
- * Use {@code false} to reset adjusted amount as 0.
- * @see #updateAdjustForIme(float, float, boolean)
- */
- void setAdjustedForIme(WindowState imeWin, boolean keepLastAmount) {
- mImeWin = imeWin;
- mImeGoingAway = false;
- if (!mAdjustedForIme || keepLastAmount) {
- mAdjustedForIme = true;
- DockedStackDividerController controller = getDisplayContent().mDividerControllerLocked;
- final float adjustImeAmount = keepLastAmount ? controller.mLastAnimationProgress : 0f;
- final float adjustDividerAmount = keepLastAmount ? controller.mLastDividerProgress : 0f;
- updateAdjustForIme(adjustImeAmount, adjustDividerAmount, true /* force */);
- }
- }
-
- boolean isAdjustedForIme() {
- return mAdjustedForIme;
- }
-
- boolean isAnimatingForIme() {
- return mImeWin != null && mImeWin.isAnimatingLw();
- }
-
- /**
- * Update the stack's bounds (crop or position) according to the IME window's
- * current position. When IME window is animated, the bottom stack is animated
- * together to track the IME window's current position, and the top stack is
- * cropped as necessary.
- *
- * @return true if a traversal should be performed after the adjustment.
- */
- boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
- if (adjustAmount != mAdjustImeAmount
- || adjustDividerAmount != mAdjustDividerAmount || force) {
- mAdjustImeAmount = adjustAmount;
- mAdjustDividerAmount = adjustDividerAmount;
- updateAdjustedBounds();
- return isVisible();
- } else {
- return false;
- }
- }
-
- /**
- * Resets the adjustment after it got adjusted for the IME.
- * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
- * animations; otherwise, set flag and animates the window away together
- * with IME window.
- */
- void resetAdjustedForIme(boolean adjustBoundsNow) {
- if (adjustBoundsNow) {
- mImeWin = null;
- mImeGoingAway = false;
- mAdjustImeAmount = 0f;
- mAdjustDividerAmount = 0f;
- if (!mAdjustedForIme) {
- return;
- }
- mAdjustedForIme = false;
- updateAdjustedBounds();
- mWmService.setResizeDimLayer(false, getWindowingMode(), 1.0f);
- } else {
- mImeGoingAway |= mAdjustedForIme;
- }
- }
-
- /**
- * Sets the amount how much we currently minimize our stack.
- *
- * @param minimizeAmount The amount, between 0 and 1.
- * @return Whether the amount has changed and a layout is needed.
- */
- boolean setAdjustedForMinimizedDock(float minimizeAmount) {
- if (minimizeAmount != mMinimizeAmount) {
- mMinimizeAmount = minimizeAmount;
- updateAdjustedBounds();
- return isVisible();
- } else {
- return false;
- }
- }
-
- boolean shouldIgnoreInput() {
- return isAdjustedForMinimizedDockedStack() ||
- (inSplitScreenPrimaryWindowingMode() && isMinimizedDockAndHomeStackResizable());
- }
-
- /**
- * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
- * to the list of to be drawn windows the service is waiting for.
- */
- void beginImeAdjustAnimation() {
- for (int j = mChildren.size() - 1; j >= 0; j--) {
- final Task task = mChildren.get(j);
- if (task.hasContentToDisplay()) {
- task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
- task.setWaitingForDrawnIfResizingChanged();
- }
- }
- }
-
- /**
- * Resets the resizing state of all windows.
- */
- void endImeAdjustAnimation() {
- for (int j = mChildren.size() - 1; j >= 0; j--) {
- mChildren.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
- }
- }
-
- int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
- return displayContentRect.top + (int)
- ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN);
- }
-
- private boolean adjustForIME(final WindowState imeWin) {
- // To prevent task stack resize animation may flicking when playing app transition
- // animation & IME window enter animation in parallel, we need to make sure app
- // transition is done and then adjust task size for IME, skip the new adjusted frame when
- // app transition is still running.
- if (getDisplayContent().mAppTransition.isRunning()) {
- return false;
- }
-
- final int dockedSide = getDockSide();
- final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
- if (imeWin == null || !dockedTopOrBottom) {
- return false;
- }
-
- final Rect displayStableRect = mTmpRect;
- final Rect contentBounds = mTmpRect2;
-
- // Calculate the content bounds excluding the area occupied by IME
- getDisplayContent().getStableRect(displayStableRect);
- contentBounds.set(displayStableRect);
- int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
-
- imeTop += imeWin.getGivenContentInsetsLw().top;
- if (contentBounds.bottom > imeTop) {
- contentBounds.bottom = imeTop;
- }
-
- final int yOffset = displayStableRect.bottom - contentBounds.bottom;
-
- final int dividerWidth =
- getDisplayContent().mDividerControllerLocked.getContentWidth();
- final int dividerWidthInactive =
- getDisplayContent().mDividerControllerLocked.getContentWidthInactive();
-
- if (dockedSide == DOCKED_TOP) {
- // If this stack is docked on top, we make it smaller so the bottom stack is not
- // occluded by IME. We shift its bottom up by the height of the IME, but
- // leaves at least 30% of the top stack visible.
- final int minTopStackBottom =
- getMinTopStackBottom(displayStableRect, getRawBounds().bottom);
- final int bottom = Math.max(
- getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive,
- minTopStackBottom);
- mTmpAdjustedBounds.set(getRawBounds());
- mTmpAdjustedBounds.bottom = (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount)
- * getRawBounds().bottom);
- mFullyAdjustedImeBounds.set(getRawBounds());
- } else {
- // When the stack is on bottom and has no focus, it's only adjusted for divider width.
- final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
-
- // When the stack is on bottom and has focus, it needs to be moved up so as to
- // not occluded by IME, and at the same time adjusted for divider width.
- // We try to move it up by the height of the IME window, but only to the extent
- // that leaves at least 30% of the top stack visible.
- // 'top' is where the top of bottom stack will move to in this case.
- final int topBeforeImeAdjust =
- getRawBounds().top - dividerWidth + dividerWidthInactive;
- final int minTopStackBottom =
- getMinTopStackBottom(displayStableRect,
- getRawBounds().top - dividerWidth);
- final int top = Math.max(
- getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive);
-
- mTmpAdjustedBounds.set(getRawBounds());
- // Account for the adjustment for IME and divider width separately.
- // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
- // and dividerWidthDelta is due to divider width change only.
- mTmpAdjustedBounds.top = getRawBounds().top +
- (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) +
- mAdjustDividerAmount * dividerWidthDelta);
- mFullyAdjustedImeBounds.set(getRawBounds());
- mFullyAdjustedImeBounds.top = top;
- mFullyAdjustedImeBounds.bottom = top + getRawBounds().height();
- }
- return true;
- }
-
- private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
- final int dockSide = getDockSide();
- if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
- return false;
- }
-
- if (dockSide == DOCKED_TOP) {
- mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
- int topInset = mTmpRect.top;
- mTmpAdjustedBounds.set(getRawBounds());
- mTmpAdjustedBounds.bottom = (int) (minimizeAmount * topInset + (1 - minimizeAmount)
- * getRawBounds().bottom);
- } else if (dockSide == DOCKED_LEFT) {
- mTmpAdjustedBounds.set(getRawBounds());
- final int width = getRawBounds().width();
- mTmpAdjustedBounds.right =
- (int) (minimizeAmount * mDockedStackMinimizeThickness
- + (1 - minimizeAmount) * getRawBounds().right);
- mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
- } else if (dockSide == DOCKED_RIGHT) {
- mTmpAdjustedBounds.set(getRawBounds());
- mTmpAdjustedBounds.left = (int) (minimizeAmount *
- (getRawBounds().right - mDockedStackMinimizeThickness)
- + (1 - minimizeAmount) * getRawBounds().left);
- }
- return true;
- }
-
- private boolean isMinimizedDockAndHomeStackResizable() {
- return mDisplayContent.mDividerControllerLocked.isMinimizedDock()
- && mDisplayContent.mDividerControllerLocked.isHomeStackResizable();
- }
-
- /**
- * @return the distance in pixels how much the stack gets minimized from it's original size
- */
- int getMinimizeDistance() {
- final int dockSide = getDockSide();
- if (dockSide == DOCKED_INVALID) {
- return 0;
- }
-
- if (dockSide == DOCKED_TOP) {
- mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
- int topInset = mTmpRect.top;
- return getRawBounds().bottom - topInset;
- } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
- return getRawBounds().width() - mDockedStackMinimizeThickness;
- } else {
- return 0;
- }
- }
-
- /**
- * Updates the adjustment depending on it's current state.
- */
- private void updateAdjustedBounds() {
- boolean adjust = false;
- if (mMinimizeAmount != 0f) {
- adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
- } else if (mAdjustedForIme) {
- adjust = adjustForIME(mImeWin);
- }
- if (!adjust) {
- mTmpAdjustedBounds.setEmpty();
- }
- setAdjustedBounds(mTmpAdjustedBounds);
-
- final boolean isImeTarget = (mWmService.getImeFocusStackLocked() == this);
- if (mAdjustedForIme && adjust && !isImeTarget) {
- final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
- * IME_ADJUST_DIM_AMOUNT;
- mWmService.setResizeDimLayer(true, getWindowingMode(), alpha);
- }
- }
-
- void applyAdjustForImeIfNeeded(Task task) {
- if (mMinimizeAmount != 0f || !mAdjustedForIme || mAdjustedBounds.isEmpty()) {
- return;
- }
-
- final Rect insetBounds = mImeGoingAway ? getRawBounds() : mFullyAdjustedImeBounds;
- task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP);
- mDisplayContent.setLayoutNeeded();
- }
-
-
- boolean isAdjustedForMinimizedDockedStack() {
- return mMinimizeAmount != 0f;
- }
-
- /**
- * @return {@code true} if we have a {@link Task} that is animating (currently only used for the
- * recents animation); {@code false} otherwise.
- */
- boolean isTaskAnimating() {
- for (int j = mChildren.size() - 1; j >= 0; j--) {
- final Task task = mChildren.get(j);
- if (task.isTaskAnimating()) {
- return true;
- }
- }
- return false;
- }
-
- // TODO(proto-merge): Remove once protos for ActivityStack and TaskStack are merged.
- void writeToProtoInnerStackOnly(ProtoOutputStream proto, long fieldId,
- @WindowTraceLogLevel int logLevel) {
- if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
- return;
- }
-
- final long token = proto.start(fieldId);
- super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
- proto.write(ID, mStackId);
- for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
- mChildren.get(taskNdx).writeToProtoInnerTaskOnly(proto, TASKS, logLevel);
- }
- proto.write(FILLS_PARENT, matchParentBounds());
- getRawBounds().writeToProto(proto, BOUNDS);
- proto.write(DEFER_REMOVAL, mDeferRemoval);
- proto.write(MINIMIZE_AMOUNT, mMinimizeAmount);
- proto.write(ADJUSTED_FOR_IME, mAdjustedForIme);
- proto.write(ADJUST_IME_AMOUNT, mAdjustImeAmount);
- proto.write(ADJUST_DIVIDER_AMOUNT, mAdjustDividerAmount);
- mAdjustedBounds.writeToProto(proto, ADJUSTED_BOUNDS);
- proto.write(ANIMATING_BOUNDS, mBoundsAnimating);
- proto.end(token);
- }
-
- @Override
- void dump(PrintWriter pw, String prefix, boolean dumpAll) {
- pw.println(prefix + "mStackId=" + mStackId);
- pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
- pw.println(prefix + "mBounds=" + getRawBounds().toShortString());
- if (mMinimizeAmount != 0f) {
- pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount);
- }
- if (mAdjustedForIme) {
- pw.println(prefix + "mAdjustedForIme=true");
- pw.println(prefix + "mAdjustImeAmount=" + mAdjustImeAmount);
- pw.println(prefix + "mAdjustDividerAmount=" + mAdjustDividerAmount);
- }
- if (!mAdjustedBounds.isEmpty()) {
- pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
- }
- for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
- mChildren.get(taskNdx).dump(pw, prefix + " ", dumpAll);
- }
- if (!mExitingActivities.isEmpty()) {
- pw.println();
- pw.println(" Exiting application tokens:");
- for (int i = mExitingActivities.size() - 1; i >= 0; i--) {
- WindowToken token = mExitingActivities.get(i);
- pw.print(" Exiting App #"); pw.print(i);
- pw.print(' '); pw.print(token);
- pw.println(':');
- token.dump(pw, " ", dumpAll);
- }
- }
- mAnimatingActivityRegistry.dump(pw, "AnimatingApps:", prefix);
- }
-
- @Override
- boolean fillsParent() {
- return matchParentBounds();
- }
-
- String getName() {
- return toShortString();
- }
-
- public String toShortString() {
- return "Stack=" + mStackId;
- }
-
- /**
- * For docked workspace (or workspace that's side-by-side to the docked), provides
- * information which side of the screen was the dock anchored.
- */
- int getDockSide() {
- return getDockSide(mDisplayContent.getConfiguration(), getRawBounds());
- }
-
- int getDockSideForDisplay(DisplayContent dc) {
- return getDockSide(dc, dc.getConfiguration(), getRawBounds());
- }
-
- int getDockSide(Configuration parentConfig, Rect bounds) {
- if (mDisplayContent == null) {
- return DOCKED_INVALID;
- }
- return getDockSide(mDisplayContent, parentConfig, bounds);
- }
-
- private int getDockSide(DisplayContent dc, Configuration parentConfig, Rect bounds) {
- return dc.getDockedDividerController().getDockSide(bounds,
- parentConfig.windowConfiguration.getBounds(),
- parentConfig.orientation, parentConfig.windowConfiguration.getRotation());
- }
-
- boolean hasTaskForUser(int userId) {
- for (int i = mChildren.size() - 1; i >= 0; i--) {
- final Task task = mChildren.get(i);
- if (task.mUserId == userId) {
- return true;
- }
- }
- return false;
- }
-
- void findTaskForResizePoint(int x, int y, int delta,
- DisplayContent.TaskForResizePointSearchResult results) {
- if (!getWindowConfiguration().canResizeTask()) {
- results.searchDone = true;
- return;
- }
-
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task task = mChildren.get(i);
- if (task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
- results.searchDone = true;
- return;
- }
-
- // We need to use the task's dim bounds (which is derived from the visible bounds of
- // its apps windows) for any touch-related tests. Can't use the task's original
- // bounds because it might be adjusted to fit the content frame. One example is when
- // the task is put to top-left quadrant, the actual visible area would not start at
- // (0,0) after it's adjusted for the status bar.
- task.getDimBounds(mTmpRect);
- mTmpRect.inset(-delta, -delta);
- if (mTmpRect.contains(x, y)) {
- mTmpRect.inset(delta, delta);
-
- results.searchDone = true;
-
- if (!mTmpRect.contains(x, y)) {
- results.taskForResize = task;
- return;
- }
- // User touched inside the task. No need to look further,
- // focus transfer will be handled in ACTION_UP.
- return;
- }
- }
- }
-
- void setTouchExcludeRegion(Task focusedTask, int delta, Region touchExcludeRegion,
- Rect contentRect, Rect postExclude) {
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task task = mChildren.get(i);
- ActivityRecord topVisibleActivity = task.getTopVisibleActivity();
- if (topVisibleActivity == null || !topVisibleActivity.hasContentToDisplay()) {
- continue;
- }
-
- /**
- * Exclusion region is the region that TapDetector doesn't care about.
- * Here we want to remove all non-focused tasks from the exclusion region.
- * We also remove the outside touch area for resizing for all freeform
- * tasks (including the focused).
- *
- * We save the focused task region once we find it, and add it back at the end.
- *
- * If the task is home stack and it is resizable in the minimized state, we want to
- * exclude the docked stack from touch so we need the entire screen area and not just a
- * small portion which the home stack currently is resized to.
- */
-
- if (task.isActivityTypeHome() && isMinimizedDockAndHomeStackResizable()) {
- mDisplayContent.getBounds(mTmpRect);
- } else {
- task.getDimBounds(mTmpRect);
- }
-
- if (task == focusedTask) {
- // Add the focused task rect back into the exclude region once we are done
- // processing stacks.
- postExclude.set(mTmpRect);
- }
-
- final boolean isFreeformed = task.inFreeformWindowingMode();
- if (task != focusedTask || isFreeformed) {
- if (isFreeformed) {
- // If the task is freeformed, enlarge the area to account for outside
- // touch area for resize.
- mTmpRect.inset(-delta, -delta);
- // Intersect with display content rect. If we have system decor (status bar/
- // navigation bar), we want to exclude that from the tap detection.
- // Otherwise, if the app is partially placed under some system button (eg.
- // Recents, Home), pressing that button would cause a full series of
- // unwanted transfer focus/resume/pause, before we could go home.
- mTmpRect.intersect(contentRect);
- }
- touchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
- }
- }
- }
-
- public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
- // Hold the lock since this is called from the BoundsAnimator running on the UiThread
- synchronized (mWmService.mGlobalLock) {
- if (mCancelCurrentBoundsAnimation) {
- return false;
- }
- }
-
- try {
- mWmService.mActivityTaskManager.resizePinnedStack(stackBounds, tempTaskBounds);
- } catch (RemoteException e) {
- // I don't believe you.
- }
- return true;
- }
-
- void onAllWindowsDrawn() {
- if (!mBoundsAnimating && !mBoundsAnimatingRequested) {
- return;
- }
-
- getDisplayContent().mBoundsAnimationController.onAllWindowsDrawn();
- }
-
- @Override // AnimatesBounds
- public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate,
- @BoundsAnimationController.AnimationType int animationType) {
- // Hold the lock since this is called from the BoundsAnimator running on the UiThread
- synchronized (mWmService.mGlobalLock) {
- if (!isAttached()) {
- // Don't run the animation if the stack is already detached
- return false;
- }
-
- if (animationType == BoundsAnimationController.BOUNDS) {
- mBoundsAnimatingRequested = false;
- mBoundsAnimating = true;
- }
- mAnimationType = animationType;
-
- // If we are changing UI mode, as in the PiP to fullscreen
- // transition, then we need to wait for the window to draw.
- if (schedulePipModeChangedCallback) {
- forAllWindows((w) -> { w.mWinAnimator.resetDrawState(); },
- false /* traverseTopToBottom */);
- }
- }
-
- if (inPinnedWindowingMode()) {
- try {
- mWmService.mActivityTaskManager.notifyPinnedStackAnimationStarted();
- } catch (RemoteException e) {
- // I don't believe you...
- }
-
- if ((schedulePipModeChangedCallback || animationType == FADE_IN)) {
- // We need to schedule the PiP mode change before the animation up. It is possible
- // in this case for the animation down to not have been completed, so always
- // force-schedule and update to the client to ensure that it is notified that it
- // is no longer in picture-in-picture mode
- // TODO(stack-merge): Remove cast.
- ((ActivityStack) this).updatePictureInPictureModeForPinnedStackAnimation(null,
- forceUpdate);
- }
- }
- return true;
- }
-
- @Override // AnimatesBounds
- public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
- boolean moveToFullscreen) {
- synchronized (mWmService.mGlobalLock) {
- if (inPinnedWindowingMode()) {
- // Update to the final bounds if requested. This is done here instead of in the
- // bounds animator to allow us to coordinate this after we notify the PiP mode changed
-
- if (schedulePipModeChangedCallback) {
- // We need to schedule the PiP mode change after the animation down, so use the
- // final bounds
- // TODO(stack-merge): Remove cast.
- ((ActivityStack) this).updatePictureInPictureModeForPinnedStackAnimation(
- mBoundsAnimationTarget, false /* forceUpdate */);
- }
-
- if (mAnimationType == BoundsAnimationController.FADE_IN) {
- setPinnedStackAlpha(1f);
- mWmService.mAtmService.notifyPinnedStackAnimationEnded();
- return;
- }
-
- if (finalStackSize != null && !mCancelCurrentBoundsAnimation) {
- setPinnedStackSize(finalStackSize, null);
- } else {
- // We have been canceled, so the final stack size is null, still run the
- // animation-end logic
- onPipAnimationEndResize();
- }
-
- mWmService.mAtmService.notifyPinnedStackAnimationEnded();
- if (moveToFullscreen) {
- ((ActivityStack) this).dismissPip();
- }
- } else {
- // No PiP animation, just run the normal animation-end logic
- onPipAnimationEndResize();
- }
- }
- }
-
- /**
- * Animates the pinned stack.
- */
- void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds,
- int animationDuration, boolean fromFullscreen) {
- if (!inPinnedWindowingMode()) {
- return;
- }
- // Get the from-bounds
- final Rect fromBounds = new Rect();
- getBounds(fromBounds);
-
- // Get non-null fullscreen to-bounds for animating if the bounds are null
- @SchedulePipModeChangedState int schedulePipModeChangedState =
- NO_PIP_MODE_CHANGED_CALLBACKS;
- final boolean toFullscreen = toBounds == null;
- if (toFullscreen) {
- if (fromFullscreen) {
- throw new IllegalArgumentException("Should not defer scheduling PiP mode"
- + " change on animation to fullscreen.");
- }
- schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
-
- mWmService.getStackBounds(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mTmpToBounds);
- if (!mTmpToBounds.isEmpty()) {
- // If there is a fullscreen bounds, use that
- toBounds = new Rect(mTmpToBounds);
- } else {
- // Otherwise, use the display bounds
- toBounds = new Rect();
- getDisplayContent().getBounds(toBounds);
- }
- } else if (fromFullscreen) {
- schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
- }
-
- setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen);
-
- final Rect finalToBounds = toBounds;
- final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
- schedulePipModeChangedState;
- final DisplayContent displayContent = getDisplayContent();
- @BoundsAnimationController.AnimationType int intendedAnimationType =
- displayContent.mBoundsAnimationController.getAnimationType();
- if (intendedAnimationType == FADE_IN) {
- if (fromFullscreen) {
- setPinnedStackAlpha(0f);
- }
- if (toBounds.width() == fromBounds.width()
- && toBounds.height() == fromBounds.height()) {
- intendedAnimationType = BoundsAnimationController.BOUNDS;
- } else if (!fromFullscreen && !toBounds.equals(fromBounds)) {
- // intendedAnimationType may have been reset at the end of RecentsAnimation,
- // force it to BOUNDS type if we know for certain we're animating to
- // a different bounds, especially for expand and collapse of PiP window.
- intendedAnimationType = BoundsAnimationController.BOUNDS;
- }
- }
-
- final @BoundsAnimationController.AnimationType int animationType = intendedAnimationType;
- mCancelCurrentBoundsAnimation = false;
- displayContent.mBoundsAnimationController.getHandler().post(() -> {
- displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
- finalToBounds, animationDuration, finalSchedulePipModeChangedState,
- fromFullscreen, toFullscreen, animationType);
- });
- }
-
- /**
- * Sets the current picture-in-picture aspect ratio.
- */
- void setPictureInPictureAspectRatio(float aspectRatio) {
- if (!mWmService.mAtmService.mSupportsPictureInPicture) {
- return;
- }
-
- final DisplayContent displayContent = getDisplayContent();
- if (displayContent == null) {
- return;
- }
-
- if (!inPinnedWindowingMode()) {
- return;
- }
-
- final PinnedStackController pinnedStackController =
- getDisplayContent().getPinnedStackController();
-
- if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) {
- return;
- }
-
- // Notify the pinned stack controller about aspect ratio change.
- // This would result a callback delivered from SystemUI to WM to start animation,
- // if the bounds are ought to be altered due to aspect ratio change.
- pinnedStackController.setAspectRatio(
- pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
- ? aspectRatio : -1f);
- }
-
- /**
- * Sets the current picture-in-picture actions.
- */
- void setPictureInPictureActions(List<RemoteAction> actions) {
- if (!mWmService.mAtmService.mSupportsPictureInPicture) {
- return;
- }
-
- if (!inPinnedWindowingMode()) {
- return;
- }
-
- getDisplayContent().getPinnedStackController().setActions(actions);
- }
-
- /** Called immediately prior to resizing the tasks at the end of the pinned stack animation. */
- void onPipAnimationEndResize() {
- mBoundsAnimating = false;
- for (int i = 0; i < mChildren.size(); i++) {
- final Task t = mChildren.get(i);
- t.clearPreserveNonFloatingState();
- }
- mWmService.requestTraversal();
- }
-
- @Override
- public boolean shouldDeferStartOnMoveToFullscreen() {
- synchronized (mWmService.mGlobalLock) {
- if (!isAttached()) {
- // Unnecessary to pause the animation because the stack is detached.
- return false;
- }
-
- // Workaround for the recents animation -- normally we need to wait for the new activity
- // to show before starting the PiP animation, but because we start and show the home
- // activity early for the recents animation prior to the PiP animation starting, there
- // is no subsequent all-drawn signal. In this case, we can skip the pause when the home
- // stack is already visible and drawn.
- final TaskStack homeStack = mDisplayContent.getHomeStack();
- if (homeStack == null) {
- return true;
- }
- final Task homeTask = homeStack.getTopChild();
- if (homeTask == null) {
- return true;
- }
- final ActivityRecord homeApp = homeTask.getTopVisibleActivity();
- if (!homeTask.isVisible() || homeApp == null) {
- return true;
- }
- return !homeApp.allDrawn;
- }
- }
-
- /**
- * @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen
- * bounds and we have a deferred PiP mode changed callback set with the animation.
- */
- public boolean deferScheduleMultiWindowModeChanged() {
- if (inPinnedWindowingMode()) {
- // For the pinned stack, the deferring of the multi-window mode changed is tied to the
- // transition animation into picture-in-picture, and is called once the animation
- // completes, or is interrupted in a way that would leave the stack in a non-fullscreen
- // state.
- // @see BoundsAnimationController
- // @see BoundsAnimationControllerTests
- return (mBoundsAnimatingRequested || mBoundsAnimating);
- }
- return false;
- }
-
- public boolean isForceScaled() {
- return mBoundsAnimating;
- }
-
- public boolean isAnimatingBounds() {
- return mBoundsAnimating;
- }
-
- public boolean lastAnimatingBoundsWasToFullscreen() {
- return mBoundsAnimatingToFullscreen;
- }
-
- public boolean isAnimatingBoundsToFullscreen() {
- return isAnimatingBounds() && lastAnimatingBoundsWasToFullscreen();
- }
-
- public boolean pinnedStackResizeDisallowed() {
- if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
- return true;
- }
- return false;
- }
-
- /** Returns true if a removal action is still being deferred. */
- boolean checkCompleteDeferredRemoval() {
- if (isAnimating(TRANSITION | CHILDREN)) {
- return true;
- }
- if (mDeferRemoval) {
- removeImmediately();
- }
-
- return super.checkCompleteDeferredRemoval();
- }
-
- @Override
- int getOrientation() {
- return (canSpecifyOrientation()) ? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
- }
-
- private boolean canSpecifyOrientation() {
- final int windowingMode = getWindowingMode();
- final int activityType = getActivityType();
- return windowingMode == WINDOWING_MODE_FULLSCREEN
- || activityType == ACTIVITY_TYPE_HOME
- || activityType == ACTIVITY_TYPE_RECENTS
- || activityType == ACTIVITY_TYPE_ASSISTANT;
- }
-
- @Override
- Dimmer getDimmer() {
- return mDimmer;
- }
-
- @Override
- void prepareSurfaces() {
- mDimmer.resetDimStates();
- super.prepareSurfaces();
- getDimBounds(mTmpDimBoundsRect);
-
- // Bounds need to be relative, as the dim layer is a child.
- mTmpDimBoundsRect.offsetTo(0, 0);
- if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
- scheduleAnimation();
- }
- }
-
- @Override
- public boolean setPinnedStackAlpha(float alpha) {
- // Hold the lock since this is called from the BoundsAnimator running on the UiThread
- synchronized (mWmService.mGlobalLock) {
- final SurfaceControl sc = getSurfaceControl();
- if (sc == null || !sc.isValid()) {
- // If the stack is already removed, don't bother updating any stack animation
- return false;
- }
- getPendingTransaction().setAlpha(sc, mCancelCurrentBoundsAnimation ? 1 : alpha);
- scheduleAnimation();
- return !mCancelCurrentBoundsAnimation;
- }
- }
-
- public DisplayInfo getDisplayInfo() {
- return mDisplayContent.getDisplayInfo();
- }
-
- void dim(float alpha) {
- mDimmer.dimAbove(getPendingTransaction(), alpha);
- scheduleAnimation();
- }
-
- void stopDimming() {
- mDimmer.stopDim(getPendingTransaction());
- scheduleAnimation();
- }
-
- AnimatingActivityRegistry getAnimatingActivityRegistry() {
- return mAnimatingActivityRegistry;
- }
-
- @Override
- void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
- Rect outSurfaceInsets) {
- final Task task = getTopChild();
- if (task != null) {
- task.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
- } else {
- super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
- }
- }
-
- @Override
- RemoteAnimationTarget createRemoteAnimationTarget(
- RemoteAnimationController.RemoteAnimationRecord record) {
- final Task task = getTopChild();
- return task != null ? task.createRemoteAnimationTarget(record) : null;
- }
-}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index cf3e2bb..3a6f1a4 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -92,16 +92,16 @@
private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
- /** Animation layer that happens above all animating {@link TaskStack}s. */
+ /** Animation layer that happens above all animating {@link ActivityStack}s. */
static final int ANIMATION_LAYER_STANDARD = 0;
- /** Animation layer that happens above all {@link TaskStack}s. */
+ /** Animation layer that happens above all {@link ActivityStack}s. */
static final int ANIMATION_LAYER_BOOSTED = 1;
/**
* Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
* activities and all activities that are being controlled by the recents animation. This
- * layer is generally below all {@link TaskStack}s.
+ * layer is generally below all {@link ActivityStack}s.
*/
static final int ANIMATION_LAYER_HOME = 2;
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index 9fe4760..4f7662d 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -61,7 +61,7 @@
public final Rect mParentFrame = new Rect();
/**
- * The entire screen area of the {@link TaskStack} this window is in. Usually equal to the
+ * The entire screen area of the {@link ActivityStack} this window is in. Usually equal to the
* screen area of the device.
*
* TODO(b/111611553): The name is unclear and most likely should be swapped with
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9bdf010..482f95e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1940,7 +1940,7 @@
// re-factor.
activity.firstWindowDrawn = false;
activity.clearAllDrawn();
- final TaskStack stack = activity.getStack();
+ final ActivityStack stack = activity.getStack();
if (stack != null) {
stack.mExitingActivities.remove(activity);
}
@@ -2769,7 +2769,7 @@
@Override
public void getStackBounds(int windowingMode, int activityType, Rect bounds) {
synchronized (mGlobalLock) {
- final TaskStack stack = mRoot.getStack(windowingMode, activityType);
+ final ActivityStack stack = mRoot.getStack(windowingMode, activityType);
if (stack != null) {
stack.getBounds(bounds);
return;
@@ -3223,7 +3223,7 @@
// Notify whether the docked stack exists for the current user
final DisplayContent displayContent = getDefaultDisplayContentLocked();
- final TaskStack stack =
+ final ActivityStack stack =
displayContent.getSplitScreenPrimaryStackIgnoringVisibility();
displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(
stack != null && stack.hasTaskForUser(newUserId));
@@ -4423,7 +4423,7 @@
return mRoot.getTopFocusedDisplayContent().mCurrentFocus;
}
- TaskStack getImeFocusStackLocked() {
+ ActivityStack getImeFocusStackLocked() {
// Don't use mCurrentFocus.getStack() because it returns home stack for system windows.
// Also don't use mInputMethodTarget's stack, because some window with FLAG_NOT_FOCUSABLE
// and FLAG_ALT_FOCUSABLE_IM flags both set might be set to IME target so they're moved
@@ -6483,7 +6483,7 @@
@Override
public int getDockedStackSide() {
synchronized (mGlobalLock) {
- final TaskStack dockedStack = getDefaultDisplayContentLocked()
+ final ActivityStack dockedStack = getDefaultDisplayContentLocked()
.getSplitScreenPrimaryStackIgnoringVisibility();
return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
}
@@ -7737,7 +7737,7 @@
return;
}
- final TaskStack stack = task.getTaskStack();
+ final ActivityStack stack = task.getTaskStack();
// We ignore home stack since we don't want home stack to move to front when touched.
// Specifically, in freeform we don't want tapping on home to cause the freeform apps to go
// behind home. See b/117376413
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4047bdd..8a6512d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1006,7 +1006,7 @@
}
}
- final TaskStack stack = getStack();
+ final ActivityStack stack = getStack();
if (inPinnedWindowingMode() && stack != null
&& stack.lastAnimatingBoundsWasToFullscreen()) {
// PIP edge case: When going from pinned to fullscreen, we apply a
@@ -1419,7 +1419,7 @@
return mActivityRecord != null ? mActivityRecord.getTask() : null;
}
- TaskStack getStack() {
+ ActivityStack getStack() {
Task task = getTask();
if (task != null) {
if (task.getTaskStack() != null) {
@@ -1442,7 +1442,7 @@
bounds.setEmpty();
mTmpRect.setEmpty();
if (intersectWithStackBounds) {
- final TaskStack stack = task.getTaskStack();
+ final ActivityStack stack = task.getTaskStack();
if (stack != null) {
stack.getDimBounds(mTmpRect);
} else {
@@ -2150,7 +2150,7 @@
return false;
}
- final TaskStack stack = getStack();
+ final ActivityStack stack = getStack();
if (stack != null && stack.shouldIgnoreInput()) {
// Ignore when the stack shouldn't receive input event.
// (i.e. the minimized stack in split screen mode.)
@@ -2555,7 +2555,7 @@
// just in case they have the divider at an unstable position. Better
// also reset drag resizing state, because the owner can't do it
// anymore.
- final TaskStack stack =
+ final ActivityStack stack =
dc.getSplitScreenPrimaryStackIgnoringVisibility();
if (stack != null) {
stack.resetDockedStackToMiddle();
@@ -3152,7 +3152,7 @@
return;
}
- final TaskStack stack = task.getTaskStack();
+ final ActivityStack stack = task.getTaskStack();
if (stack == null) {
return;
}
@@ -3166,7 +3166,7 @@
return;
}
- final TaskStack stack = task.getTaskStack();
+ final ActivityStack stack = task.getTaskStack();
if (stack == null) {
return;
}
@@ -3417,7 +3417,7 @@
}
private int getStackId() {
- final TaskStack stack = getStack();
+ final ActivityStack stack = getStack();
if (stack == null) {
return INVALID_STACK_ID;
}
@@ -3648,7 +3648,7 @@
@Override
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
- final TaskStack stack = getStack();
+ final ActivityStack stack = getStack();
pw.print(prefix + "mDisplayId=" + getDisplayId());
if (stack != null) {
pw.print(" stackId=" + stack.mStackId);
@@ -5098,7 +5098,7 @@
outPoint.offset(-parentBounds.left, -parentBounds.top);
}
- TaskStack stack = getStack();
+ ActivityStack stack = getStack();
// If we have stack outsets, that means the top-left
// will be outset, and we need to inset ourselves
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a853828..94aff7b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1016,7 +1016,7 @@
mSurfaceController.deferTransactionUntil(mSurfaceController.mSurfaceControl,
mWin.getFrameNumber());
} else {
- final TaskStack stack = mWin.getStack();
+ final ActivityStack stack = mWin.getStack();
mTmpPos.x = 0;
mTmpPos.y = 0;
if (stack != null) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
index b6eaab7..c6203c5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
@@ -37,7 +37,7 @@
import org.mockito.MockitoAnnotations;
/**
- * Tests for the {@link TaskStack} class.
+ * Tests for the {@link ActivityStack} class.
*
* Build/Install/Run:
* atest FrameworksServicesTests:AnimatingActivityRegistryTest
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 6ee9621..fc94c5e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -28,7 +28,6 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import android.graphics.Rect;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
@@ -55,7 +54,7 @@
@RunWith(WindowTestRunner.class)
public class AppChangeTransitionTests extends WindowTestsBase {
- private TaskStack mStack;
+ private ActivityStack mStack;
private Task mTask;
private ActivityRecord mActivity;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
index 8617fb2..dbf61db 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -68,8 +68,8 @@
@Test
public void testStackPositionChildAt() {
// Test that always-on-top stack can't be moved to position other than top.
- final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
- final TaskStack stack2 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
final WindowContainer taskStackContainer = stack1.getParent();
@@ -93,7 +93,7 @@
@Test
public void testStackPositionBelowPinnedStack() {
// Test that no stack can be above pinned stack.
- final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
final WindowContainer taskStackContainer = stack1.getParent();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 40ce363..5877041 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -41,7 +41,7 @@
import org.junit.runner.RunWith;
/**
- * Tests for the {@link TaskStack} class.
+ * Tests for the {@link ActivityStack} class.
*
* Build/Install/Run:
* atest WmTests:TaskStackTests
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 0b7cbce..f443255 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -261,7 +261,7 @@
// minimized and home stack is resizable, so that we should ignore input for the stack.
final DockedStackDividerController controller =
mDisplayContent.getDockedDividerController();
- final TaskStack stack = createTaskStackOnDisplay(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
+ final ActivityStack stack = createTaskStackOnDisplay(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
ACTIVITY_TYPE_STANDARD, mDisplayContent);
spyOn(appWindow);
spyOn(controller);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index a7a78e1..0da9dc4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -41,7 +41,6 @@
import static org.mockito.Mockito.mock;
import android.content.Context;
-import android.content.res.Configuration;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
@@ -314,7 +313,7 @@
}
}
- /** Creates a {@link TaskStack} and adds it to the specified {@link DisplayContent}. */
+ /** Creates a {@link ActivityStack} and adds it to the specified {@link DisplayContent}. */
ActivityStack createTaskStackOnDisplay(DisplayContent dc) {
return createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, dc);
}