diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index ef50fdc5eb4f9..7da849a832e4d 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -102,13 +102,13 @@ public class Surface implements Parcelable { public @interface ScalingMode {} // From system/window.h /** @hide */ - static final int SCALING_MODE_FREEZE = 0; + public static final int SCALING_MODE_FREEZE = 0; /** @hide */ - static final int SCALING_MODE_SCALE_TO_WINDOW = 1; + public static final int SCALING_MODE_SCALE_TO_WINDOW = 1; /** @hide */ - static final int SCALING_MODE_SCALE_CROP = 2; + public static final int SCALING_MODE_SCALE_CROP = 2; /** @hide */ - static final int SCALING_MODE_NO_SCALE_CROP = 3; + public static final int SCALING_MODE_NO_SCALE_CROP = 3; /** @hide */ @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270}) diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index c30ede37a4ac8..dc9014be16461 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -85,6 +85,8 @@ public class SurfaceControl { IBinder displayToken, int mode); private static native void nativeDeferTransactionUntil(long nativeObject, IBinder handle, long frame); + private static native void nativeSetOverrideScalingMode(long nativeObject, + int scalingMode); private static native IBinder nativeGetHandle(long nativeObject); @@ -376,6 +378,11 @@ public class SurfaceControl { nativeDeferTransactionUntil(mNativeObject, handle, frame); } + public void setOverrideScalingMode(int scalingMode) { + checkNotReleased(); + nativeSetOverrideScalingMode(mNativeObject, scalingMode); + } + public IBinder getHandle() { return nativeGetHandle(mNativeObject); } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index d8233a0ea34bd..059013423f19b 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -597,6 +597,13 @@ static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeO ctrl->deferTransactionUntil(handle, frameNumber); } +static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong nativeObject, + jint scalingMode) { + auto ctrl = reinterpret_cast(nativeObject); + + ctrl->setOverrideScalingMode(scalingMode); +} + static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) { auto ctrl = reinterpret_cast(nativeObject); @@ -676,6 +683,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetDisplayPowerMode }, {"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V", (void*)nativeDeferTransactionUntil }, + {"nativeSetOverrideScalingMode", "(JI)V", + (void*)nativeSetOverrideScalingMode }, {"nativeGetHandle", "(J)Landroid/os/IBinder;", (void*)nativeGetHandle } }; diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java index b7d6062a3dc0d..eacdd811592b1 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationController.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java @@ -129,13 +129,16 @@ public class BoundsAnimationController { public void onAnimationStart(Animator animation) { if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget + " mReplacement=" + mReplacement); - if (animatingToLargerSize()) { - mTarget.setPinnedStackSize(mFrom, mTo); - } - if (!mReplacement) { mTarget.onAnimationStart(); } + + // Ensure that we have prepared the target for animation before + // we trigger any size changes, so it can swap surfaces + // in to appropriate modes, or do as it wishes otherwise. + if (animatingToLargerSize()) { + mTarget.setPinnedStackSize(mFrom, mTo); + } } @Override diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 46a8dffc02e61..4f49eed140900 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -600,7 +600,8 @@ class Task implements DimLayer.DimLayerUser { // // Anyway we don't need to synchronize position and content updates for these // windows since they aren't at the base layer and could be moved around anyway. - if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION) { + if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION && + !mStack.getBoundsAnimating()) { win.mResizedWhileNotDragResizing = true; } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 872bc6d5bc9fa..1fd2b1f2dfa3e 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -42,6 +42,7 @@ import android.util.SparseArray; import android.view.DisplayInfo; import android.view.Surface; import android.view.animation.PathInterpolator; +import android.view.SurfaceControl; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; @@ -127,10 +128,12 @@ public class TaskStack implements DimLayer.DimLayerUser, private float mAdjustImeAmount; private final int mDockedStackMinimizeThickness; - // If this is true, the task will be down or upscaled - // to perfectly fit the region it would have been cropped - // to. - private boolean mForceScaleToCrop = false; + // 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; // By default, movement animations are applied to all // window movement. If this is true, animations will not // be applied within this stack. This is useful for example @@ -1269,11 +1272,36 @@ public class TaskStack implements DimLayer.DimLayerUser, return true; } + void forceWindowsScaleable(boolean force) { + SurfaceControl.openTransaction(); + try { + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + final ArrayList activities = mTasks.get(taskNdx).mAppTokens; + for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { + final ArrayList windows = activities.get(activityNdx).allAppWindows; + for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { + final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator; + if (winAnimator == null || !winAnimator.hasSurface()) { + continue; + } + winAnimator.mSurfaceController.forceScaleableInTransaction(force); + } + } + } + } finally { + SurfaceControl.closeTransaction(); + } + } + @Override // AnimatesBounds public void onAnimationStart() { synchronized (mService.mWindowMap) { + // We force windows out of SCALING_MODE_FREEZE + // so that we can continue to animate them + // while a resize is pending. + forceWindowsScaleable(true); mFreezeMovementAnimations = true; - mForceScaleToCrop = true; + mBoundsAnimating = true; } } @@ -1281,7 +1309,8 @@ public class TaskStack implements DimLayer.DimLayerUser, public void onAnimationEnd() { synchronized (mService.mWindowMap) { mFreezeMovementAnimations = false; - mForceScaleToCrop = false; + mBoundsAnimating = false; + forceWindowsScaleable(false); mService.requestTraversal(); } if (mStackId == PINNED_STACK_ID) { @@ -1312,6 +1341,10 @@ public class TaskStack implements DimLayer.DimLayerUser, } public boolean getForceScaleToCrop() { - return mForceScaleToCrop; + return mBoundsAnimating; + } + + public boolean getBoundsAnimating() { + return mBoundsAnimating; } } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 08982f4466bca..f6ef69dc40d01 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -562,6 +562,7 @@ class WindowStateAnimator { Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState=" + drawStateToString()); } + if (mWin.mAppToken != null && mWin.mAppToken.mAnimatingWithSavedSurface) { // App has drawn something to its windows, we're no longer animating with // the saved surfaces. If the user exits now, we only want to save again diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 8799c614cf25a..6eed5e7464585 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -23,6 +23,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static android.view.Surface.SCALING_MODE_FREEZE; +import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW; import android.graphics.Point; import android.graphics.PointF; @@ -392,6 +394,13 @@ class WindowSurfaceController { mSurfaceControl.deferTransactionUntil(handle, frame); } + void forceScaleableInTransaction(boolean force) { + // -1 means we don't override the default or client specified + // scaling mode. + int scalingMode = force ? SCALING_MODE_SCALE_TO_WINDOW : -1; + mSurfaceControl.setOverrideScalingMode(scalingMode); + } + boolean clearWindowContentFrameStats() { if (mSurfaceControl == null) { return false;