Animate pinned stack resizing.
This introduces animating of stack bounds within window manager
module. It also uses this type of animation when moving an activity from
fullscreen stack to pinned stack.
Bug: 25672053
Change-Id: I75914a685d10021f8a7535b47ef12b6920b3fd5e
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 72e8c3b..d45bc5d 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -47,7 +47,6 @@
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
-import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -79,7 +78,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashSet;
import java.util.List;
public class Am extends BaseCommand {
@@ -159,6 +157,7 @@
" am stack start <DISPLAY_ID> <INTENT>\n" +
" am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
" am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
+ " am stack resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
" am stack resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]\n" +
" am stack size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]\n" +
" am stack move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
@@ -1688,6 +1687,9 @@
case "resize":
runStackResize();
break;
+ case "resize-animated":
+ runStackResizeAnimated();
+ break;
case "resize-docked-stack":
runStackResizeDocked();
break;
@@ -1756,7 +1758,18 @@
System.err.println("Error: invalid input bounds");
return;
}
- resizeStack(stackId, bounds, 0);
+ resizeStack(stackId, bounds, 0, false);
+ }
+
+ private void runStackResizeAnimated() throws Exception {
+ String stackIdStr = nextArgRequired();
+ int stackId = Integer.valueOf(stackIdStr);
+ final Rect bounds = getBounds();
+ if (bounds == null) {
+ System.err.println("Error: invalid input bounds");
+ return;
+ }
+ resizeStack(stackId, bounds, 0, true);
}
private void runStackResizeDocked() throws Exception {
@@ -1773,14 +1786,15 @@
}
}
- private void resizeStack(int stackId, Rect bounds, int delayMs) throws Exception {
+ private void resizeStack(int stackId, Rect bounds, int delayMs, boolean animate)
+ throws Exception {
if (bounds == null) {
showError("Error: invalid input bounds");
return;
}
try {
- mAm.resizeStack(stackId, bounds, false);
+ mAm.resizeStack(stackId, bounds, false, false, animate);
Thread.sleep(delayMs);
} catch (RemoteException e) {
showError("Error: resizing stack " + e);
@@ -1894,7 +1908,7 @@
maxChange = Math.min(stepSize, currentPoint - minPoint);
currentPoint -= maxChange;
setBoundsSide(bounds, side, currentPoint);
- resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+ resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
}
System.out.println("Growing docked stack side=" + side);
@@ -1902,7 +1916,7 @@
maxChange = Math.min(stepSize, maxPoint - currentPoint);
currentPoint += maxChange;
setBoundsSide(bounds, side, currentPoint);
- resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+ resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
}
System.out.println("Back to Original size side=" + side);
@@ -1910,7 +1924,7 @@
maxChange = Math.min(stepSize, currentPoint - startPoint);
currentPoint -= maxChange;
setBoundsSide(bounds, side, currentPoint);
- resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+ resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 420bf31..90feab4 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -564,8 +564,7 @@
* there isn't a display gap.
*/
public static boolean preserveWindowOnTaskMove(int stackId) {
- return stackId == FULLSCREEN_WORKSPACE_STACK_ID
- || stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID;
+ return stackId == FULLSCREEN_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
}
/**
@@ -616,6 +615,14 @@
public static boolean keepVisibleDeadAppWindowOnScreen(int stackId) {
return stackId != PINNED_STACK_ID;
}
+
+ /**
+ * Returns true if the backdrop on the client side should match the frame of the window.
+ * Returns false, if the backdrop should be fullscreen.
+ */
+ public static boolean useWindowFrameForBackdrop(int stackId) {
+ return stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == PINNED_STACK_ID;
+ }
}
/**
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 42ff8e8..cd5797e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -816,7 +816,9 @@
r = Rect.CREATOR.createFromParcel(data);
}
final boolean allowResizeInDockedMode = data.readInt() == 1;
- resizeStack(stackId, r, allowResizeInDockedMode);
+ final boolean preserveWindows = data.readInt() == 1;
+ final boolean animate = data.readInt() == 1;
+ resizeStack(stackId, r, allowResizeInDockedMode, preserveWindows, animate);
reply.writeNoException();
return true;
}
@@ -3815,9 +3817,8 @@
return res;
}
@Override
- public void resizeStack(int stackId, Rect r, boolean allowResizeInDockedMode)
- throws RemoteException
- {
+ public void resizeStack(int stackId, Rect r, boolean allowResizeInDockedMode,
+ boolean preserveWindows, boolean animate) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -3829,6 +3830,8 @@
data.writeInt(0);
}
data.writeInt(allowResizeInDockedMode ? 1 : 0);
+ data.writeInt(preserveWindows ? 1 : 0);
+ data.writeInt(animate ? 1 : 0);
mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 22de2ff..5b3ffe0 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -146,8 +146,8 @@
public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds) throws RemoteException;
public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) throws RemoteException;
- public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode)
- throws RemoteException;
+ public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
+ boolean preserveWindows, boolean animate) throws RemoteException;
/**
* Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 67bb58a..24ab506 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -97,7 +97,8 @@
@Override
public void run() {
try {
- ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, null, true);
+ ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, null, true, false,
+ false);
} catch (RemoteException e) {
Log.w(TAG, "Failed to resize stack: " + e);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2c55ee2..76fbebf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9411,14 +9411,24 @@
}
@Override
- public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode) {
+ public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
+ boolean preserveWindows, boolean animate) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- mStackSupervisor.resizeStackLocked(
- stackId, bounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
- !PRESERVE_WINDOWS, allowResizeInDockedMode);
+ if (animate) {
+ if (stackId == PINNED_STACK_ID) {
+ mWindowManager.animateResizePinnedStack(bounds);
+ } else {
+ throw new IllegalArgumentException("Stack: " + stackId
+ + " doesn't support animated resize.");
+ }
+ } else {
+ mStackSupervisor.resizeStackLocked(stackId, bounds, null /* tempTaskBounds */,
+ null /* tempTaskInsetBounds */, preserveWindows,
+ allowResizeInDockedMode);
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8db2f8f..11dd8a3 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -98,6 +98,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import static android.Manifest.permission.START_ANY_ACTIVITY;
@@ -2019,7 +2020,7 @@
// If this is a forced resize, let it go through even if the bounds is not changing,
// as we might need a relayout due to surface size change (to/from fullscreen).
final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
- if (task.mBounds != null && task.mBounds.equals(bounds) && !forced) {
+ if (Objects.equals(task.mBounds, bounds) && !forced) {
// Nothing to do here...
return true;
}
@@ -2257,10 +2258,7 @@
// If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
// window), we need to clear the replace window settings. Otherwise, we schedule a
// timeout to remove the old window if the replacing window is not coming in time.
- // In case of the pinned stack we don't resize the task during the move, but we will
- // resize the stack soon after so we want to retain the replacing window.
- mWindowManager.scheduleClearReplacingWindowIfNeeded(topActivity.appToken,
- !kept || stackId == PINNED_STACK_ID);
+ mWindowManager.scheduleClearReplacingWindowIfNeeded(topActivity.appToken, !kept);
}
// The task might have already been running and its visibility needs to be synchronized with
@@ -2294,7 +2292,8 @@
return false;
}
- moveActivityToStackLocked(r, PINNED_STACK_ID, "moveTopActivityToPinnedStack", bounds);
+ moveActivityToStackLocked(r, PINNED_STACK_ID, "moveTopActivityToPinnedStack", null);
+ mWindowManager.animateResizePinnedStack(bounds);
return true;
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 552af03..43a17c9 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -134,7 +134,7 @@
/** Fraction of animation at which the recents thumbnail becomes completely transparent */
private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.5f;
- private static final int DEFAULT_APP_TRANSITION_DURATION = 336;
+ static final int DEFAULT_APP_TRANSITION_DURATION = 336;
private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336;
private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 336;
private static final long APP_TRANSITION_TIMEOUT_MS = 5000;
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
new file mode 100644
index 0000000..5f97478
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -0,0 +1,142 @@
+/*
+ * 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.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.view.animation.LinearInterpolator;
+
+/**
+ * Enables animating bounds of objects.
+ *
+ * In multi-window world bounds of both stack and tasks can change. When we need these bounds to
+ * change smoothly and not require the app to relaunch (e.g. because it handles resizes and
+ * relaunching it would cause poorer experience), these class provides a way to directly animate
+ * the bounds of the resized object.
+ *
+ * The object that is resized needs to implement {@link AnimateBoundsUser} interface.
+ */
+public class BoundsAnimationController {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "BoundsAnimationController" : TAG_WM;
+
+ // Only acccessed on UI thread.
+ private ArrayMap<AnimateBoundsUser, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
+
+ private final class BoundsAnimator extends ValueAnimator
+ implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
+ private final AnimateBoundsUser mTarget;
+ private final Rect mFrom;
+ private final Rect mTo;
+ private final Rect mTmpRect;
+
+ BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to) {
+ super();
+ mTarget = target;
+ mFrom = from;
+ mTo = to;
+ mTmpRect = new Rect();
+ addUpdateListener(this);
+ addListener(this);
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float value = (Float) animation.getAnimatedValue();
+ final float remains = 1 - value;
+ mTmpRect.left = (int) (mFrom.left * remains + mTo.left * value);
+ mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value);
+ mTmpRect.right = (int) (mFrom.right * remains + mTo.right * value);
+ mTmpRect.bottom = (int) (mFrom.bottom * remains + mTo.bottom * value);
+ if (DEBUG_ANIM) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + ", mBounds="
+ + mTmpRect + ", from=" + mFrom + ", mTo=" + mTo + ", value=" + value
+ + ", remains=" + remains);
+ if (!mTarget.setSize(mTmpRect)) {
+ // Whoops, the target doesn't feel like animating anymore. Let's immediately finish
+ // any further animation.
+ animation.cancel();
+ }
+ }
+
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finishAnimation();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ finishAnimation();
+ }
+
+ private void finishAnimation() {
+ mTarget.finishBoundsAnimation();
+ removeListener(this);
+ removeUpdateListener(this);
+ mRunningAnimations.remove(mTarget);
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+ }
+
+ public interface AnimateBoundsUser {
+ /**
+ * Asks the target to directly (without any intermediate steps, like scheduling animation)
+ * resize its bounds.
+ *
+ * @return Whether the target still wants to be animated and successfully finished the
+ * operation. If it returns false, the animation will immediately be cancelled. The target
+ * should return false when something abnormal happened, e.g. it was completely removed
+ * from the hierarchy and is not valid anymore.
+ */
+ boolean setSize(Rect bounds);
+
+ /**
+ * Callback for the target to inform it that the animation is finished, so it can do some
+ * necessary cleanup.
+ */
+ void finishBoundsAnimation();
+ }
+
+ void animateBounds(AnimateBoundsUser target, Rect from, Rect to) {
+ final BoundsAnimator existing = mRunningAnimations.get(target);
+ if (existing != null) {
+ existing.cancel();
+ }
+ BoundsAnimator animator = new BoundsAnimator(target, from, to);
+ mRunningAnimations.put(target, animator);
+ animator.setFloatValues(0f, 1f);
+ animator.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+ animator.setInterpolator(new LinearInterpolator());
+ animator.start();
+ }
+}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index f02e49e..e0880ad 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -20,6 +20,7 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Debug;
+import android.os.RemoteException;
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
@@ -47,7 +48,8 @@
import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-public class TaskStack implements DimLayer.DimLayerUser {
+public class TaskStack implements DimLayer.DimLayerUser,
+ BoundsAnimationController.AnimateBoundsUser {
// If the stack should be resized to fullscreen.
private static final boolean FULLSCREEN = true;
@@ -804,4 +806,32 @@
}
return false;
}
+
+ @Override // AnimatesBounds
+ public boolean setSize(Rect bounds) {
+ synchronized (mService.mWindowMap) {
+ if (mDisplayContent == null) {
+ return false;
+ }
+ }
+ try {
+ mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false);
+ } catch (RemoteException e) {
+ }
+ return true;
+ }
+
+ @Override // AnimatesBounds
+ public void finishBoundsAnimation() {
+ synchronized (mService.mWindowMap) {
+ if (mTasks.isEmpty()) {
+ return;
+ }
+ final Task task = mTasks.get(mTasks.size() - 1);
+ if (task != null) {
+ task.setDragResizing(false);
+ mService.requestTraversal();
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 93a1015..2b88af4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -157,6 +157,7 @@
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.StatusBarManager.DISABLE_MASK;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -643,6 +644,9 @@
final WindowAnimator mAnimator;
+ private final BoundsAnimationController mBoundsAnimationController =
+ new BoundsAnimationController();
+
SparseArray<Task> mTaskIdToTask = new SparseArray<>();
/** All of the TaskStacks in the window manager, unordered. For an ordered list call
@@ -2848,11 +2852,12 @@
if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
win.prepareWindowToDisplayDuringRelayout(outConfig);
}
- if ((attrChanges& LayoutParams.FORMAT_CHANGED) != 0) {
- // If the format can be changed in place yaay!
- // If not, fall back to a surface re-build
+ if ((attrChanges & LayoutParams.FORMAT_CHANGED) != 0) {
+ // If the format can't be changed in place, preserve the old surface until the app draws
+ // on the new one. This prevents blinking when we change elevation of freeform and
+ // pinned windows.
if (!winAnimator.tryChangeFormatInPlaceLocked()) {
- winAnimator.destroySurfaceLocked();
+ winAnimator.preserveSurfaceLocked();
result |= RELAYOUT_RES_SURFACE_CHANGED
| WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
}
@@ -8085,7 +8090,8 @@
break;
case RESIZE_STACK: {
try {
- mActivityManager.resizeStack(msg.arg1, (Rect) msg.obj, msg.arg2 == 1);
+ mActivityManager.resizeStack(msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false,
+ false);
} catch (RemoteException e) {
// This will not happen since we are in the same process.
}
@@ -10273,6 +10279,31 @@
}
}
+ public void animateResizePinnedStack(final Rect bounds) {
+ synchronized (mWindowMap) {
+ final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
+ if (stack == null) {
+ Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found.");
+ return;
+ }
+ final ArrayList<Task> tasks = stack.getTasks();
+ if (tasks.isEmpty()) {
+ Slog.w(TAG, "animateResizePinnedStack: pinned stack doesn't have any tasks.");
+ return;
+ }
+ final Task task = tasks.get(tasks.size() - 1);
+ task.setDragResizing(true);
+ final Rect originalBounds = new Rect();
+ stack.getBounds(originalBounds);
+ UiThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ mBoundsAnimationController.animateBounds(stack, originalBounds, bounds);
+ }
+ });
+ }
+ }
+
public void setTaskResizeable(int taskId, boolean resizeable) {
synchronized (mWindowMap) {
Task task = mTaskIdToTask.get(taskId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c541b3f..1214948 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -57,6 +57,7 @@
import java.util.ArrayList;
import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
@@ -2051,10 +2052,21 @@
// until the window to small size, otherwise the multithread renderer will shift last
// one or more frame to wrong offset. So here we send fullscreen backdrop if either
// isDragResizing() or isDragResizeChanged() is true.
+ boolean resizing = isDragResizing() || isDragResizeChanged();
+ if (StackId.useWindowFrameForBackdrop(getStackId()) || !resizing) {
+ return frame;
+ }
DisplayInfo displayInfo = getDisplayInfo();
mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
- boolean resizing = isDragResizing() || isDragResizeChanged();
- return (inFreeformWorkspace() || !resizing) ? frame : mTmpRect;
+ return mTmpRect;
+ }
+
+ private int getStackId() {
+ final TaskStack stack = getStack();
+ if (stack == null) {
+ return INVALID_STACK_ID;
+ }
+ return stack.mStackId;
}
private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,