Remove StackWindowController and StackWindowListener (46/n)
TaskStack and ActivityStack hold each other as a member. ActivityStack
will create TaskStack while constructing.
Moved all pinned specific stack into general one.
PinnedStackWindowController, PinnedActivityStack are removed.
Test: go/wm-smoke
Test: atest WmTests
Bug: 80414790
Change-Id: I63e3ec429576ec62960d0280b048883a8ed5145c
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 1f638c7..0616846 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -278,12 +278,12 @@
}
// Since positionChildAt() is called during the creation process of pinned stacks,
- // ActivityStack#getWindowContainerController() can be null. In this special case,
+ // ActivityStack#getStack() can be null. In this special case,
// since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(),
// we don't have to call WindowContainerController#positionChildAt() here.
- if (stack.getWindowContainerController() != null && mDisplayContent != null) {
+ if (stack.getTaskStack() != null && mDisplayContent != null) {
mDisplayContent.positionStackAt(insertPosition,
- stack.getWindowContainerController().mContainer, includingParents);
+ stack.getTaskStack(), includingParents);
}
if (!wasContained) {
stack.setParent(this);
@@ -450,13 +450,12 @@
@VisibleForTesting
<T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
int stackId, boolean onTop) {
- if (windowingMode == WINDOWING_MODE_PINNED) {
- return (T) new PinnedActivityStack(this, stackId,
- mRootActivityContainer.mStackSupervisor, onTop);
+ if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
+ throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
+ + "activity type.");
}
return (T) new ActivityStack(this, stackId,
- mRootActivityContainer.mStackSupervisor, windowingMode, activityType,
- onTop);
+ mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop);
}
/**
@@ -1019,8 +1018,8 @@
return mSplitScreenPrimaryStack != null;
}
- PinnedActivityStack getPinnedStack() {
- return (PinnedActivityStack) mPinnedStack;
+ ActivityStack getPinnedStack() {
+ return mPinnedStack;
}
boolean hasPinnedStack() {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 4d7de90..891c3da 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -114,6 +114,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;
@@ -173,8 +174,7 @@
/**
* State and management of a single stack of activities.
*/
-class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
- implements StackWindowListener {
+class ActivityStack extends ConfigurationContainer {
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;
@@ -297,8 +297,7 @@
static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
final ActivityTaskManagerService mService;
- private final WindowManagerService mWindowManager;
- T mWindowContainerController;
+ final WindowManagerService mWindowManager;
/**
* The back history of all previous (and possibly still
@@ -397,6 +396,9 @@
static final int DESTROY_ACTIVITIES_MSG = FIRST_ACTIVITY_STACK_MSG + 5;
static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 6;
+ // TODO: remove after unification.
+ TaskStack mTaskStack;
+
private static class ScheduleDestroyArgs {
final WindowProcessController mOwner;
final String mReason;
@@ -495,21 +497,30 @@
// stacks on a wrong display.
mDisplayId = display.mDisplayId;
setActivityType(activityType);
- mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
- mTmpRect2);
+ createTaskStack(display.mDisplayId, onTop, mTmpRect2);
setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
true /* creating */);
display.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
}
- T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
- return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds,
- mRootActivityContainer.mWindowManager);
+ void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
+ final DisplayContent dc = mWindowManager.mRoot.getDisplayContent(displayId);
+ if (dc == null) {
+ throw new IllegalArgumentException("Trying to add stackId=" + mStackId
+ + " to unknown displayId=" + displayId);
+ }
+ mTaskStack = new TaskStack(mWindowManager, mStackId, this);
+ dc.setStackOnDisplay(mStackId, onTop, mTaskStack);
+ if (mTaskStack.matchParentBounds()) {
+ outBounds.setEmpty();
+ } else {
+ mTaskStack.getRawBounds(outBounds);
+ }
}
- T getWindowContainerController() {
- return mWindowContainerController;
+ TaskStack getTaskStack() {
+ return mTaskStack;
}
/**
@@ -553,6 +564,9 @@
if (display == null) {
return;
}
+ if (getTaskStack() == null) {
+ return;
+ }
// Update bounds if applicable
boolean hasNewOverrideBounds = false;
@@ -560,8 +574,7 @@
if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
// Pinned calculation already includes rotation
mTmpRect2.set(mTmpRect);
- hasNewOverrideBounds = getWindowContainerController().mContainer
- .calculatePinnedBoundsForConfigChange(mTmpRect2);
+ hasNewOverrideBounds = getTaskStack().calculatePinnedBoundsForConfigChange(mTmpRect2);
} else {
final int newRotation = getWindowConfiguration().getRotation();
if (!matchParentBounds()) {
@@ -588,7 +601,7 @@
|| getRequestedOverrideWindowingMode()
== WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
mTmpRect2.set(mTmpRect);
- getWindowContainerController().mContainer
+ getTaskStack()
.calculateDockedBoundsForConfigChange(newParentConfig, mTmpRect2);
hasNewOverrideBounds = true;
}
@@ -786,7 +799,11 @@
mTmpRect2.setEmpty();
if (windowingMode != WINDOWING_MODE_FULLSCREEN) {
- mWindowContainerController.getRawBounds(mTmpRect2);
+ if (mTaskStack.matchParentBounds()) {
+ mTmpRect2.setEmpty();
+ } else {
+ mTaskStack.getRawBounds(mTmpRect2);
+ }
}
if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) {
@@ -843,7 +860,12 @@
// Reparent the window container before we try to update the position when adding it to
// the new display below
mTmpRect2.setEmpty();
- mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
+ if (mTaskStack == null) {
+ // TODO: Remove after unification.
+ Log.w(TAG, "Task stack is not valid when reparenting.");
+ } else {
+ mTaskStack.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
+ }
setBounds(mTmpRect2.isEmpty() ? null : mTmpRect2);
activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
if (!displayRemoved) {
@@ -876,8 +898,10 @@
/** Removes the stack completely. Also calls WindowManager to do the same on its side. */
void remove() {
removeFromDisplay();
- mWindowContainerController.removeContainer();
- mWindowContainerController = null;
+ if (mTaskStack != null) {
+ mTaskStack.removeIfPossible();
+ mTaskStack = null;
+ }
onParentChanged();
}
@@ -890,26 +914,35 @@
*/
void getStackDockedModeBounds(Rect dockedBounds, Rect currentTempTaskBounds,
Rect outStackBounds, Rect outTempTaskBounds) {
- mWindowContainerController.getStackDockedModeBounds(getParent().getConfiguration(),
- dockedBounds, currentTempTaskBounds,
- outStackBounds, outTempTaskBounds);
+ if (mTaskStack != null) {
+ mTaskStack.getStackDockedModeBoundsLocked(getParent().getConfiguration(), dockedBounds,
+ currentTempTaskBounds, outStackBounds, outTempTaskBounds);
+ } else {
+ outStackBounds.setEmpty();
+ outTempTaskBounds.setEmpty();
+ }
}
void prepareFreezingTaskBounds() {
- mWindowContainerController.prepareFreezingTaskBounds();
+ if (mTaskStack != null) {
+ // TODO: This cannot be false after unification.
+ mTaskStack.prepareFreezingTaskBounds();
+ }
}
void getWindowContainerBounds(Rect outBounds) {
- if (mWindowContainerController != null) {
- mWindowContainerController.getBounds(outBounds);
+ if (mTaskStack != null) {
+ mTaskStack.getBounds(outBounds);
return;
}
outBounds.setEmpty();
}
void positionChildWindowContainerAtTop(TaskRecord child) {
- mWindowContainerController.positionChildAtTop(child.getTask(),
- true /* includingParents */);
+ if (mTaskStack != null) {
+ // TODO: Remove after unification. This cannot be false after that.
+ mTaskStack.positionChildAtTop(child.getTask(), true /* includingParents */);
+ }
}
void positionChildWindowContainerAtBottom(TaskRecord child) {
@@ -918,14 +951,27 @@
// task to bottom, the next focusable stack on the same display should be focused.
final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack(
child.getStack(), true /* ignoreCurrent */);
- mWindowContainerController.positionChildAtBottom(child.getTask(),
- nextFocusableStack == null /* includingParents */);
+ if (mTaskStack != null) {
+ // TODO: Remove after unification. This cannot be false after that.
+ mTaskStack.positionChildAtBottom(child.getTask(),
+ nextFocusableStack == null /* includingParents */);
+ }
}
/**
* Returns whether to defer the scheduling of the multi-window mode.
*/
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
+ if (getTaskStack() == null) return false;
+ return getTaskStack().deferScheduleMultiWindowModeChanged();
+ }
return false;
}
@@ -2994,7 +3040,10 @@
position = getAdjustedPositionForTask(task, position, null /* starting */);
mTaskHistory.remove(task);
mTaskHistory.add(position, task);
- mWindowContainerController.positionChildAt(task.getTask(), position);
+ if (mTaskStack != null) {
+ // TODO: this could not be false after unification.
+ mTaskStack.positionChildAt(task.getTask(), position);
+ }
updateTaskMovement(task, true);
}
@@ -4909,8 +4958,7 @@
}
// TODO: Figure-out a way to consolidate with resize() method below.
- @Override
- public void requestResize(Rect bounds) {
+ void requestResize(Rect bounds) {
mService.resizeStack(mStackId, bounds,
true /* allowResizeInDockedMode */, false /* preserveWindows */,
false /* animate */, -1 /* animationDuration */);
@@ -4948,7 +4996,8 @@
}
void onPipAnimationEndResize() {
- mWindowContainerController.onPipAnimationEndResize();
+ if (mTaskStack == null) return;
+ mTaskStack.onPipAnimationEndResize();
}
@@ -5494,6 +5543,65 @@
}
}
+
+ Rect getDefaultPictureInPictureBounds(float aspectRatio) {
+ if (getTaskStack() == null) return null;
+ return getTaskStack().getPictureInPictureBounds(aspectRatio, null /* currentStackBounds */);
+ }
+
+ void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
+ boolean fromFullscreen) {
+ if (!inPinnedWindowingMode()) return;
+ if (skipResizeAnimation(toBounds == null /* toFullscreen */)) {
+ mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
+ } else {
+ if (getTaskStack() == null) return;
+ getTaskStack().animateResizePinnedStack(toBounds, sourceHintBounds,
+ animationDuration, fromFullscreen);
+ }
+ }
+
+ private boolean skipResizeAnimation(boolean toFullscreen) {
+ if (!toFullscreen) {
+ return false;
+ }
+ final Configuration parentConfig = getParent().getConfiguration();
+ final ActivityRecord top = topRunningNonOverlayTaskActivity();
+ return top != null && !top.isConfigurationCompatible(parentConfig);
+ }
+
+ void setPictureInPictureAspectRatio(float aspectRatio) {
+ if (getTaskStack() == null) return;
+ getTaskStack().setPictureInPictureAspectRatio(aspectRatio);
+ }
+
+ void setPictureInPictureActions(List<RemoteAction> actions) {
+ if (getTaskStack() == null) return;
+ getTaskStack().setPictureInPictureActions(actions);
+ }
+
+ boolean isAnimatingBoundsToFullscreen() {
+ if (getTaskStack() == null) return false;
+ return getTaskStack().isAnimatingBoundsToFullscreen();
+ }
+
+ public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds,
+ boolean forceUpdate) {
+ // It is guaranteed that the activities requiring the update will be in the pinned stack at
+ // this point (either reparented before the animation into PiP, or before reparenting after
+ // the animation out of PiP)
+ synchronized (mService.mGlobalLock) {
+ if (!isAttached()) {
+ return;
+ }
+ ArrayList<TaskRecord> tasks = getAllTasks();
+ for (int i = 0; i < tasks.size(); i++) {
+ mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds,
+ forceUpdate);
+ }
+ }
+ }
+
public int getStackId() {
return mStackId;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a50ae84..a4cda5a 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1674,8 +1674,8 @@
}
void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
- // TODO(multi-display): Pinned stack display should be passed in.
- final PinnedActivityStack stack =
+ // TODO(multi-display): The display containing the stack should be passed in.
+ final ActivityStack stack =
mRootActivityContainer.getDefaultDisplay().getPinnedStack();
if (stack == null) {
Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
@@ -1686,7 +1686,7 @@
// 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.
- final PinnedStackWindowController stackController = stack.getWindowContainerController();
+ final TaskStack stackController = stack.getTaskStack();
if (stackController.pinnedStackResizeDisallowed()) {
return;
}
@@ -1730,15 +1730,14 @@
* invisible as well and added to the stopping list. After which we process the
* stopping list by handling the idle.
*/
- final PinnedActivityStack pinnedStack = (PinnedActivityStack) stack;
- pinnedStack.mForceHidden = true;
- pinnedStack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
- pinnedStack.mForceHidden = false;
+ stack.mForceHidden = true;
+ stack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+ stack.mForceHidden = false;
activityIdleInternalLocked(null, false /* fromTimeout */,
true /* processPausingActivites */, null /* configuration */);
// Move all the tasks to the bottom of the fullscreen stack
- moveTasksToFullscreenStackLocked(pinnedStack, !ON_TOP);
+ moveTasksToFullscreenStackLocked(stack, !ON_TOP);
} else {
for (int i = tasks.size() - 1; i >= 0; i--) {
removeTaskByIdLocked(tasks.get(i).taskId, true /* killProcess */,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index e82e748..fe5bc25 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -82,13 +82,10 @@
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HOME_PROC;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.LAUNCHING_ACTIVITY;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto
- .PREVIOUS_PROC_VISIBLE_TIME_MS;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
- .MODE;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
- .PACKAGE;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -245,7 +242,6 @@
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.server.appop.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -261,6 +257,7 @@
import com.android.server.am.PendingIntentController;
import com.android.server.am.PendingIntentRecord;
import com.android.server.am.UserState;
+import com.android.server.appop.AppOpsService;
import com.android.server.firewall.IntentFirewall;
import com.android.server.pm.UserManagerService;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -2407,7 +2404,7 @@
try {
synchronized (mGlobalLock) {
if (animate) {
- final PinnedActivityStack stack = mRootActivityContainer.getStack(stackId);
+ final ActivityStack stack = mRootActivityContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
return;
@@ -3712,7 +3709,7 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final PinnedActivityStack stack =
+ final ActivityStack stack =
mRootActivityContainer.getDefaultDisplay().getPinnedStack();
if (stack == null) {
Slog.w(TAG, "dismissPip: pinned stack not found.");
@@ -3834,9 +3831,8 @@
// If we are animating to fullscreen then we have already dispatched the PIP mode
// changed, so we should reflect that check here as well.
- final PinnedActivityStack stack = r.getActivityStack();
- final PinnedStackWindowController windowController = stack.getWindowContainerController();
- return !windowController.mContainer.isAnimatingBoundsToFullscreen();
+ final TaskStack taskStack = r.getActivityStack().getTaskStack();
+ return !taskStack.isAnimatingBoundsToFullscreen();
}
@Override
@@ -3870,7 +3866,7 @@
r.pictureInPictureArgs.getSourceRectHint());
mRootActivityContainer.moveActivityToPinnedStack(
r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
- final PinnedActivityStack stack = r.getActivityStack();
+ final ActivityStack stack = r.getActivityStack();
stack.setPictureInPictureAspectRatio(aspectRatio);
stack.setPictureInPictureActions(actions);
MetricsLoggerWrapper.logPictureInPictureEnter(mContext, r.appInfo.uid,
@@ -3914,7 +3910,7 @@
// If the activity is already in picture-in-picture, update the pinned stack now
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP
- final PinnedActivityStack stack = r.getActivityStack();
+ final ActivityStack stack = r.getActivityStack();
if (!stack.isAnimatingBoundsToFullscreen()) {
stack.setPictureInPictureAspectRatio(
r.pictureInPictureArgs.getAspectRatio());
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 740d472..50311c2 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2307,13 +2307,12 @@
out.set(mDisplayFrames.mStable);
}
- TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) {
- if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
- + mDisplayId);
+ void setStackOnDisplay(int stackId, boolean onTop, TaskStack stack) {
+ if (DEBUG_STACK) {
+ Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" + mDisplayId);
+ }
- final TaskStack stack = new TaskStack(mWmService, stackId, controller);
mTaskStackContainers.addStackToDisplay(stack, onTop);
- return stack;
}
void moveStackToDisplay(TaskStack stack, boolean onTop) {
@@ -4015,7 +4014,6 @@
/**
* Adds the stack to this container.
- * @see DisplayContent#createStack(int, boolean, StackWindowController)
*/
void addStackToDisplay(TaskStack stack, boolean onTop) {
addStackReferenceIfNeeded(stack);
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index 3062d34..86dc66d 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -221,7 +221,7 @@
}
private boolean saveTaskToLaunchParam(TaskRecord task, PersistableLaunchParams params) {
- final ActivityStack<?> stack = task.getStack();
+ final ActivityStack stack = task.getStack();
final int displayId = stack.mDisplayId;
final ActivityDisplay display =
mSupervisor.mRootActivityContainer.getActivityDisplay(displayId);
diff --git a/services/core/java/com/android/server/wm/PinnedActivityStack.java b/services/core/java/com/android/server/wm/PinnedActivityStack.java
deleted file mode 100644
index 2a05af4..0000000
--- a/services/core/java/com/android/server/wm/PinnedActivityStack.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 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.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-
-import android.app.RemoteAction;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * State and management of the pinned stack of activities.
- */
-class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
- implements PinnedStackWindowListener {
-
- PinnedActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
- boolean onTop) {
- super(display, stackId, supervisor, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, onTop);
- }
-
- @Override
- PinnedStackWindowController createStackWindowController(int displayId, boolean onTop,
- Rect outBounds) {
- return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds,
- mRootActivityContainer.mWindowManager);
- }
-
- Rect getDefaultPictureInPictureBounds(float aspectRatio) {
- return getWindowContainerController().getPictureInPictureBounds(aspectRatio,
- null /* currentStackBounds */);
- }
-
- void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
- boolean fromFullscreen) {
- if (skipResizeAnimation(toBounds == null /* toFullscreen */)) {
- mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
- } else {
- getWindowContainerController().animateResizePinnedStack(toBounds, sourceHintBounds,
- animationDuration, fromFullscreen);
- }
- }
-
- private boolean skipResizeAnimation(boolean toFullscreen) {
- if (!toFullscreen) {
- return false;
- }
- final Configuration parentConfig = getParent().getConfiguration();
- final ActivityRecord top = topRunningNonOverlayTaskActivity();
- return top != null && !top.isConfigurationCompatible(parentConfig);
- }
-
- void setPictureInPictureAspectRatio(float aspectRatio) {
- getWindowContainerController().setPictureInPictureAspectRatio(aspectRatio);
- }
-
- void setPictureInPictureActions(List<RemoteAction> actions) {
- getWindowContainerController().setPictureInPictureActions(actions);
- }
-
- boolean isAnimatingBoundsToFullscreen() {
- return getWindowContainerController().mContainer.isAnimatingBoundsToFullscreen();
- }
-
- /**
- * Returns whether to defer the scheduling of the multi-window mode.
- */
- boolean deferScheduleMultiWindowModeChanged() {
- // 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 mWindowContainerController.deferScheduleMultiWindowModeChanged();
- }
-
- public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds,
- boolean forceUpdate) {
- // It is guaranteed that the activities requiring the update will be in the pinned stack at
- // this point (either reparented before the animation into PiP, or before reparenting after
- // the animation out of PiP)
- synchronized (mService.mGlobalLock) {
- if (!isAttached()) {
- return;
- }
- ArrayList<TaskRecord> tasks = getAllTasks();
- for (int i = 0; i < tasks.size(); i++ ) {
- mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds,
- forceUpdate);
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
deleted file mode 100644
index 518e39b..0000000
--- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2017 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.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-
-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 android.app.RemoteAction;
-import android.graphics.Rect;
-
-import java.util.List;
-
-/**
- * Controller for the pinned stack container. See {@link StackWindowController}.
- */
-public class PinnedStackWindowController extends StackWindowController {
-
- private Rect mTmpFromBounds = new Rect();
- private Rect mTmpToBounds = new Rect();
-
- public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener,
- int displayId, boolean onTop, Rect outBounds, WindowManagerService service) {
- super(stackId, listener, displayId, onTop, outBounds, service);
- }
-
- /**
- * @return the {@param currentStackBounds} transformed to the give {@param aspectRatio}. If
- * {@param currentStackBounds} is null, then the {@param aspectRatio} is applied to the
- * default bounds.
- */
- public Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
- synchronized (mGlobalLock) {
- if (!mService.mSupportsPictureInPicture || mContainer == null) {
- return null;
- }
-
- final DisplayContent displayContent = mContainer.getDisplayContent();
- if (displayContent == null) {
- return null;
- }
-
- final PinnedStackController pinnedStackController =
- displayContent.getPinnedStackController();
- if (stackBounds == null) {
- // Calculate the aspect ratio bounds from the default bounds
- stackBounds = pinnedStackController.getDefaultOrLastSavedBounds();
- }
-
- if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
- return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio,
- true /* useCurrentMinEdgeSize */);
- } else {
- return stackBounds;
- }
- }
- }
-
- /**
- * Animates the pinned stack.
- */
- public void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds,
- int animationDuration, boolean fromFullscreen) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- throw new IllegalArgumentException("Pinned stack container not found :(");
- }
-
- // Get the from-bounds
- final Rect fromBounds = new Rect();
- mContainer.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;
-
- mService.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();
- mContainer.getDisplayContent().getBounds(toBounds);
- }
- } else if (fromFullscreen) {
- schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
- }
-
- mContainer.setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen);
-
- final Rect finalToBounds = toBounds;
- final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
- schedulePipModeChangedState;
- final DisplayContent displayContent = mContainer.getDisplayContent();
- displayContent.mBoundsAnimationController.getHandler().post(() -> {
- if (mContainer == null) {
- return;
- }
- displayContent.mBoundsAnimationController.animateBounds(mContainer, fromBounds,
- finalToBounds, animationDuration, finalSchedulePipModeChangedState,
- fromFullscreen, toFullscreen);
- });
- }
- }
-
- /**
- * Sets the current picture-in-picture aspect ratio.
- */
- public void setPictureInPictureAspectRatio(float aspectRatio) {
- synchronized (mGlobalLock) {
- if (!mService.mSupportsPictureInPicture || mContainer == null) {
- return;
- }
-
- final PinnedStackController pinnedStackController =
- mContainer.getDisplayContent().getPinnedStackController();
-
- if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) {
- mContainer.getAnimationOrCurrentBounds(mTmpFromBounds);
- mTmpToBounds.set(mTmpFromBounds);
- getPictureInPictureBounds(aspectRatio, mTmpToBounds);
- if (!mTmpToBounds.equals(mTmpFromBounds)) {
- animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */,
- -1 /* duration */, false /* fromFullscreen */);
- }
- pinnedStackController.setAspectRatio(
- pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
- ? aspectRatio : -1f);
- }
- }
- }
-
- /**
- * Sets the current picture-in-picture actions.
- */
- public void setPictureInPictureActions(List<RemoteAction> actions) {
- synchronized (mGlobalLock) {
- if (!mService.mSupportsPictureInPicture || mContainer == null) {
- return;
- }
-
- mContainer.getDisplayContent().getPinnedStackController().setActions(actions);
- }
- }
-
- /**
- * @return whether the multi-window mode change should be deferred as a part of a transition
- * from fullscreen to non-fullscreen bounds.
- */
- public boolean deferScheduleMultiWindowModeChanged() {
- synchronized (mGlobalLock) {
- return mContainer.deferScheduleMultiWindowModeChanged();
- }
- }
-
- /**
- * @return whether the stack can be resized from the bounds animation.
- */
- public boolean pinnedStackResizeDisallowed() {
- synchronized (mGlobalLock) {
- return mContainer.pinnedStackResizeDisallowed();
- }
- }
-
- /**
- * The following calls are made from WM to AM.
- */
-
- /** Calls directly into activity manager so window manager lock shouldn't held. */
- public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds,
- boolean forceUpdate) {
- if (mListener != null) {
- PinnedStackWindowListener listener = (PinnedStackWindowListener) mListener;
- listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds,
- forceUpdate);
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
deleted file mode 100644
index 33e8a60..0000000
--- a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.graphics.Rect;
-
-/**
- * Interface used by the creator of {@link PinnedStackWindowController} to listen to changes with
- * the stack container.
- */
-public interface PinnedStackWindowListener extends StackWindowListener {
-
- /**
- * Called when the stack container pinned stack animation will change the picture-in-picture
- * mode. This is a direct call into ActivityManager.
- */
- default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds,
- boolean forceUpdate) {}
-}
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index f55c7c9..55554a7 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -955,7 +955,7 @@
mWindowManager.deferSurfaceLayout();
final ActivityDisplay display = r.getActivityStack().getDisplay();
- PinnedActivityStack stack = display.getPinnedStack();
+ ActivityStack stack = display.getPinnedStack();
// This will clear the pinned stack by moving an existing task to the full screen stack,
// ensuring only one task is present.
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
deleted file mode 100644
index ada807b..0000000
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2016 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 com.android.server.wm.WindowContainer.POSITION_BOTTOM;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Slog;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Controller for the stack container. This is created by activity manager to link activity stacks
- * to the stack container they use in window manager.
- *
- * Test class: {@link StackWindowControllerTests}
- */
-public class StackWindowController
- extends WindowContainerController<TaskStack, StackWindowListener> {
-
- private final int mStackId;
-
- private final H mHandler;
-
- final Rect mTmpBounds = new Rect();
-
- public StackWindowController(int stackId, StackWindowListener listener, int displayId,
- boolean onTop, Rect outBounds) {
- this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
- }
-
- @VisibleForTesting
- public StackWindowController(int stackId, StackWindowListener listener,
- int displayId, boolean onTop, Rect outBounds, WindowManagerService service) {
- super(listener, service);
- mStackId = stackId;
- mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
-
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
- if (dc == null) {
- throw new IllegalArgumentException("Trying to add stackId=" + stackId
- + " to unknown displayId=" + displayId);
- }
-
- dc.createStack(stackId, onTop, this);
- getRawBounds(outBounds);
- }
-
- @Override
- public void removeContainer() {
- if (mContainer != null) {
- mContainer.removeIfPossible();
- super.removeContainer();
- }
- }
-
- void reparent(int displayId, Rect outStackBounds, boolean onTop) {
- if (mContainer == null) {
- throw new IllegalArgumentException("Trying to move unknown stackId=" + mStackId
- + " to displayId=" + displayId);
- }
-
- final DisplayContent targetDc = mRoot.getDisplayContent(displayId);
- if (targetDc == null) {
- throw new IllegalArgumentException("Trying to move stackId=" + mStackId
- + " to unknown displayId=" + displayId);
- }
-
- targetDc.moveStackToDisplay(mContainer, onTop);
- getRawBounds(outStackBounds);
- }
-
- 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;
- }
- if (mContainer == null) {
- if (DEBUG_STACK) {
- Slog.i(TAG_WM, "positionChildAt: could not find stack for task=" + mContainer);
- }
- return;
- }
- child.positionAt(position);
- mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
-
- void positionChildAtTop(Task child, boolean includingParents) {
- if (child == null) {
- // TODO: Fix the call-points that cause this to happen.
- return;
- }
-
- mContainer.positionChildAt(POSITION_TOP, child, includingParents);
-
- final DisplayContent displayContent = mContainer.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;
- }
-
- mContainer.positionChildAt(POSITION_BOTTOM, child, includingParents);
-
- if (mContainer.getDisplayContent().mAppTransition.isTransitionSet()) {
- child.setSendingToBottom(true);
- }
- mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
-
- /**
- * Re-sizes a stack and its containing tasks.
- *
- * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
- * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
- * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id.
- */
- public void resize(Rect bounds, SparseArray<Rect> taskBounds,
- SparseArray<Rect> taskTempInsetBounds) {
- if (mContainer == null) {
- throw new IllegalArgumentException("resizeStack: stack " + this + " not found.");
- }
- // We might trigger a configuration change. Save the current task bounds for freezing.
- mContainer.prepareFreezingTaskBounds();
- if (mContainer.setBounds(bounds, taskBounds, taskTempInsetBounds)
- && mContainer.isVisible()) {
- mContainer.getDisplayContent().setLayoutNeeded();
- mService.mWindowPlacerLocked.performSurfacePlacement();
- }
- }
-
- public void onPipAnimationEndResize() {
- mContainer.onPipAnimationEndResize();
- }
-
- /**
- * @see TaskStack.getStackDockedModeBoundsLocked(ConfigurationContainer, Rect, Rect, Rect)
- */
- public void getStackDockedModeBounds(Configuration parentConfig, Rect dockedBounds,
- Rect currentTempTaskBounds,
- Rect outStackBounds, Rect outTempTaskBounds) {
- if (mContainer != null) {
- mContainer.getStackDockedModeBoundsLocked(parentConfig, dockedBounds,
- currentTempTaskBounds, outStackBounds, outTempTaskBounds);
- return;
- }
- outStackBounds.setEmpty();
- outTempTaskBounds.setEmpty();
- }
-
- public void prepareFreezingTaskBounds() {
- if (mContainer == null) {
- throw new IllegalArgumentException("prepareFreezingTaskBounds: stack " + this
- + " not found.");
- }
- mContainer.prepareFreezingTaskBounds();
- }
-
- public void getRawBounds(Rect outBounds) {
- if (mContainer.matchParentBounds()) {
- outBounds.setEmpty();
- } else {
- mContainer.getRawBounds(outBounds);
- }
- }
-
- public void getBounds(Rect outBounds) {
- if (mContainer != null) {
- mContainer.getBounds(outBounds);
- return;
- }
- outBounds.setEmpty();
- }
-
- void requestResize(Rect bounds) {
- mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
- }
-
- @Override
- public String toString() {
- return "{StackWindowController stackId=" + mStackId + "}";
- }
-
- private static final class H extends Handler {
-
- static final int REQUEST_RESIZE = 0;
-
- private final WeakReference<StackWindowController> mController;
-
- H(WeakReference<StackWindowController> controller, Looper looper) {
- super(looper);
- mController = controller;
- }
-
- @Override
- public void handleMessage(Message msg) {
- final StackWindowController controller = mController.get();
- final StackWindowListener listener = (controller != null)
- ? controller.mListener : null;
- if (listener == null) {
- return;
- }
- switch (msg.what) {
- case REQUEST_RESIZE:
- listener.requestResize((Rect) msg.obj);
- break;
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/services/core/java/com/android/server/wm/StackWindowListener.java
deleted file mode 100644
index c763c17..0000000
--- a/services/core/java/com/android/server/wm/StackWindowListener.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.graphics.Rect;
-
-/**
- * Interface used by the creator of {@link StackWindowController} to listen to changes with
- * the stack container.
- */
-public interface StackWindowListener extends WindowContainerListener {
-
- /** Called when the stack container would like its controller to resize. */
- void requestResize(Rect bounds);
-}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d334bd2..a7dd55b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -209,26 +209,14 @@
super.removeImmediately();
}
- void reparent(StackWindowController stackController, int position, boolean moveParents) {
- if (DEBUG_STACK) {
- Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
- + " to stack=" + stackController + " at " + position);
- }
- final TaskStack stack = stackController.mContainer;
- if (stack == null) {
- throw new IllegalArgumentException("reparent: could not find stack="
- + stackController);
- }
- reparent(stack, position, moveParents);
- getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
-
-
void reparent(TaskStack stack, int position, boolean moveParents) {
if (stack == mStack) {
throw new IllegalArgumentException(
"task=" + this + " already child of stack=" + mStack);
}
+ if (stack == null) {
+ throw new IllegalArgumentException("reparent: could not find stack.");
+ }
if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
+ " from stack=" + mStack);
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask");
@@ -254,6 +242,7 @@
onDisplayChanged(displayContent);
prevDisplayContent.setLayoutNeeded();
}
+ getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
/** @see ActivityTaskManagerService#positionTaskInStack(int, int, int). */
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 6acd864..f3050a9 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -709,7 +709,7 @@
final List<TaskRecord> tasksToCheck = new ArrayList<>();
for (int i = 0; i < display.getChildCount(); ++i) {
- ActivityStack<?> stack = display.getChildAt(i);
+ final ActivityStack stack = display.getChildAt(i);
if (!stack.inFreeformWindowingMode()) {
continue;
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index e944858..69dcaf4 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -455,17 +455,10 @@
}
final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
- final StackWindowController stackController = getStack().getWindowContainerController();
+ final TaskStack stack = getStack().getTaskStack();
- if (DEBUG_STACK) {
- Slog.i(TAG_WM, "TaskRecord: taskId=" + taskId
- + " stack=" + stackController + " bounds=" + bounds);
- }
-
- final TaskStack stack = stackController.mContainer;
if (stack == null) {
- throw new IllegalArgumentException("TaskRecord: invalid stack="
- + stackController);
+ throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack);
}
EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
mTask = new Task(taskId, stack, userId, mService.mWindowManager, mResizeMode,
@@ -742,7 +735,7 @@
// Must reparent first in window manager to avoid a situation where AM can delete the
// we are coming from in WM before we reparent because it became empty.
- mTask.reparent(toStack.getWindowContainerController(), position,
+ mTask.reparent(toStack.getTaskStack(), position,
moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index ee74bdf..8ed7d04 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -21,6 +21,7 @@
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;
@@ -33,6 +34,10 @@
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
+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;
@@ -47,10 +52,12 @@
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.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.CallSuper;
+import android.app.RemoteAction;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
@@ -71,9 +78,10 @@
import com.android.server.EventLogTags;
import java.io.PrintWriter;
+import java.util.List;
public class TaskStack extends WindowContainer<Task> implements
- BoundsAnimationTarget {
+ 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;
@@ -93,6 +101,10 @@
private Rect mTmpRect2 = new Rect();
private Rect mTmpRect3 = new Rect();
+ /** For Pinned stack controlling. */
+ private Rect mTmpFromBounds = new Rect();
+ private Rect mTmpToBounds = new Rect();
+
/** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
private final Rect mAdjustedBounds = new Rect();
@@ -141,6 +153,9 @@
private Dimmer mDimmer = new Dimmer(this);
+ // TODO: remove after unification.
+ ActivityStack mActivityStack;
+
/**
* For {@link #prepareSurfaces}.
*/
@@ -150,10 +165,11 @@
private final AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry =
new AnimatingAppWindowTokenRegistry();
- TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
+ TaskStack(WindowManagerService service, int stackId, ActivityStack activityStack) {
super(service);
mStackId = stackId;
- setController(controller);
+ mActivityStack = activityStack;
+ activityStack.registerConfigurationChangeListener(this);
mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_minimize_thickness);
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
@@ -572,6 +588,49 @@
positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers);
}
+ 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;
+ }
+ child.positionAt(position);
+ 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);
+
+ 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());
@@ -596,6 +655,21 @@
EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
}
+ void reparent(int displayId, Rect outStackBounds, boolean onTop) {
+ final DisplayContent targetDc = mWmService.mRoot.getDisplayContent(displayId);
+ if (targetDc == null) {
+ throw new IllegalArgumentException("Trying to move stackId=" + mStackId
+ + " to unknown displayId=" + displayId);
+ }
+
+ targetDc.moveStackToDisplay(this, onTop);
+ if (matchParentBounds()) {
+ outStackBounds.setEmpty();
+ } else {
+ getRawBounds(outStackBounds);
+ }
+ }
+
// 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.
private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
@@ -725,6 +799,23 @@
}
/**
+ * Re-sizes a stack and its containing tasks.
+ *
+ * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
+ * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
+ * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id.
+ */
+ void resize(Rect bounds, SparseArray<Rect> taskBounds,
+ SparseArray<Rect> taskTempInsetBounds) {
+ // We might trigger a configuration change. Save the current task bounds for freezing.
+ prepareFreezingTaskBounds();
+ if (setBounds(bounds, taskBounds, taskTempInsetBounds) && isVisible()) {
+ getDisplayContent().setLayoutNeeded();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ }
+
+ /**
* Calculate an amount by which to expand the stack bounds in each direction.
* Used to make room for shadows in the pinned windowing mode.
*/
@@ -929,12 +1020,7 @@
(dockedStack == null || dockedStack == this) ? null : dockedStack.getRawBounds();
getStackDockedModeBoundsLocked(mDisplayContent.getConfiguration(), dockedBounds,
null /* currentTempTaskBounds */, bounds, tempBounds);
- getController().requestResize(bounds);
- }
-
- @Override
- StackWindowController getController() {
- return (StackWindowController) super.getController();
+ mActivityStack.requestResize(bounds);
}
@Override
@@ -947,6 +1033,14 @@
}
@Override
+ void removeImmediately() {
+ if (mActivityStack != null) {
+ mActivityStack.unregisterConfigurationChangeListener(this);
+ }
+ super.removeImmediately();
+ }
+
+ @Override
void onParentSet() {
super.onParentSet();
@@ -1572,14 +1666,13 @@
// I don't believe you...
}
- final PinnedStackWindowController controller =
- (PinnedStackWindowController) getController();
- if (schedulePipModeChangedCallback && controller != null) {
+ if (schedulePipModeChangedCallback && mActivityStack != null) {
// 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
- controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate);
+ mActivityStack.updatePictureInPictureModeForPinnedStackAnimation(null,
+ forceUpdate);
}
}
return true;
@@ -1592,12 +1685,10 @@
// 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
- final PinnedStackWindowController controller =
- (PinnedStackWindowController) getController();
- if (schedulePipModeChangedCallback && controller != null) {
+ if (schedulePipModeChangedCallback) {
// We need to schedule the PiP mode change after the animation down, so use the
// final bounds
- controller.updatePictureInPictureModeForPinnedStackAnimation(
+ mActivityStack.updatePictureInPictureModeForPinnedStackAnimation(
mBoundsAnimationTarget, false /* forceUpdate */);
}
@@ -1624,6 +1715,135 @@
}
}
+ /**
+ * @return the current stack bounds transformed to the given {@param aspectRatio}. If
+ * the default bounds is {@code null}, then the {@param aspectRatio} is applied to the
+ * default bounds.
+ */
+ Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
+ if (!mWmService.mSupportsPictureInPicture) {
+ return null;
+ }
+
+ final DisplayContent displayContent = getDisplayContent();
+ if (displayContent == null) {
+ return null;
+ }
+
+ if (!inPinnedWindowingMode()) {
+ return null;
+ }
+
+ final PinnedStackController pinnedStackController =
+ displayContent.getPinnedStackController();
+ if (stackBounds == null) {
+ // Calculate the aspect ratio bounds from the default bounds
+ stackBounds = pinnedStackController.getDefaultOrLastSavedBounds();
+ }
+
+ if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
+ return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio,
+ true /* useCurrentMinEdgeSize */);
+ } else {
+ return stackBounds;
+ }
+ }
+
+ /**
+ * 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();
+ displayContent.mBoundsAnimationController.getHandler().post(() -> {
+ displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
+ finalToBounds, animationDuration, finalSchedulePipModeChangedState,
+ fromFullscreen, toFullscreen);
+ });
+ }
+
+ /**
+ * Sets the current picture-in-picture aspect ratio.
+ */
+ void setPictureInPictureAspectRatio(float aspectRatio) {
+ if (!mWmService.mSupportsPictureInPicture) {
+ return;
+ }
+
+ if (!inPinnedWindowingMode()) {
+ return;
+ }
+
+ final PinnedStackController pinnedStackController =
+ getDisplayContent().getPinnedStackController();
+
+ if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) {
+ return;
+ }
+ getAnimationOrCurrentBounds(mTmpFromBounds);
+ mTmpToBounds.set(mTmpFromBounds);
+ getPictureInPictureBounds(aspectRatio, mTmpToBounds);
+ if (!mTmpToBounds.equals(mTmpFromBounds)) {
+ animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */,
+ -1 /* duration */, false /* fromFullscreen */);
+ }
+ pinnedStackController.setAspectRatio(
+ pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
+ ? aspectRatio : -1f);
+ }
+
+ /**
+ * Sets the current picture-in-picture actions.
+ */
+ void setPictureInPictureActions(List<RemoteAction> actions) {
+ if (!mWmService.mSupportsPictureInPicture) {
+ return;
+ }
+
+ if (!inPinnedWindowingMode()) {
+ return;
+ }
+
+ getDisplayContent().getPinnedStackController().setActions(actions);
+ }
+
@Override
public boolean isAttached() {
synchronized (mWmService.mGlobalLock) {