diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java index cf34b0bad78d9..f406be9ebac78 100644 --- a/core/java/android/view/WindowContainerTransaction.java +++ b/core/java/android/view/WindowContainerTransaction.java @@ -26,6 +26,7 @@ import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.util.ArrayMap; +import android.view.SurfaceControl; import java.util.ArrayList; import java.util.List; @@ -77,8 +78,28 @@ public class WindowContainerTransaction implements Parcelable { public WindowContainerTransaction scheduleFinishEnterPip(IWindowContainer container, Rect bounds) { Change chg = getOrCreateChange(container.asBinder()); - chg.mSchedulePipCallback = true; chg.mPinnedBounds = new Rect(bounds); + chg.mChangeMask |= Change.CHANGE_PIP_CALLBACK; + + return this; + } + + /** + * Send a SurfaceControl transaction to the server, which the server will apply in sync with + * the next bounds change. As this uses deferred transaction and not BLAST it is only + * able to sync with a single window, and the first visible window in this hierarchy of type + * BASE_APPLICATION to resize will be used. If there are bound changes included in this + * WindowContainer transaction (from setBounds or scheduleFinishEnterPip), the SurfaceControl + * transaction will be synced with those bounds. If there are no changes, then + * the SurfaceControl transaction will be synced with the next bounds change. This means + * that you can call this, apply the WindowContainer transaction, and then later call + * dismissPip() to achieve synchronization. + */ + public WindowContainerTransaction setBoundsChangeTransaction(IWindowContainer container, + SurfaceControl.Transaction t) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mBoundsChangeTransaction = t; + chg.mChangeMask |= Change.CHANGE_BOUNDS_TRANSACTION; return this; } @@ -174,6 +195,8 @@ public class WindowContainerTransaction implements Parcelable { */ public static class Change implements Parcelable { public static final int CHANGE_FOCUSABLE = 1; + public static final int CHANGE_BOUNDS_TRANSACTION = 1 << 1; + public static final int CHANGE_PIP_CALLBACK = 1 << 2; private final Configuration mConfiguration = new Configuration(); private boolean mFocusable = true; @@ -181,8 +204,8 @@ public class WindowContainerTransaction implements Parcelable { private @ActivityInfo.Config int mConfigSetMask = 0; private @WindowConfiguration.WindowConfig int mWindowSetMask = 0; - private boolean mSchedulePipCallback = false; private Rect mPinnedBounds = null; + private SurfaceControl.Transaction mBoundsChangeTransaction = null; public Change() {} @@ -192,11 +215,14 @@ public class WindowContainerTransaction implements Parcelable { mChangeMask = in.readInt(); mConfigSetMask = in.readInt(); mWindowSetMask = in.readInt(); - mSchedulePipCallback = (in.readInt() != 0); - if (mSchedulePipCallback ) { + if ((mChangeMask & Change.CHANGE_PIP_CALLBACK) != 0) { mPinnedBounds = new Rect(); mPinnedBounds.readFromParcel(in); } + if ((mChangeMask & Change.CHANGE_BOUNDS_TRANSACTION) != 0) { + mBoundsChangeTransaction = + SurfaceControl.Transaction.CREATOR.createFromParcel(in); + } } public Configuration getConfiguration() { @@ -233,6 +259,10 @@ public class WindowContainerTransaction implements Parcelable { return mPinnedBounds; } + public SurfaceControl.Transaction getBoundsChangeTransaction() { + return mBoundsChangeTransaction; + } + @Override public String toString() { final boolean changesBounds = @@ -264,10 +294,12 @@ public class WindowContainerTransaction implements Parcelable { dest.writeInt(mConfigSetMask); dest.writeInt(mWindowSetMask); - dest.writeInt(mSchedulePipCallback ? 1 : 0); - if (mSchedulePipCallback ) { + if (mPinnedBounds != null) { mPinnedBounds.writeToParcel(dest, flags); } + if (mBoundsChangeTransaction != null) { + mBoundsChangeTransaction.writeToParcel(dest, flags); + } } @Override diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 34b5c117d1188..0733b3404fa00 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -422,6 +422,8 @@ class Task extends WindowContainer { /** When set, will force the task to report as invisible. */ boolean mForceHidden = false; + SurfaceControl.Transaction mMainWindowSizeChangeTransaction; + private final FindRootHelper mFindRootHelper = new FindRootHelper(); private class FindRootHelper { private ActivityRecord mRoot; @@ -3981,4 +3983,17 @@ class Task extends WindowContainer { mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged( this, true /* force */); } + + /** + * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this + * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy + * to resize, and it will defer the transaction until that resize frame completes. + */ + void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t) { + mMainWindowSizeChangeTransaction = t; + } + + SurfaceControl.Transaction getMainWindowSizeChangeTransaction() { + return mMainWindowSizeChangeTransaction; + } } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 4b13a0c1f75dd..0a6a694d84a98 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -553,6 +553,12 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub WindowContainerTransaction.Change c) { int effects = sanitizeAndApplyChange(wc, c); + final SurfaceControl.Transaction t = c.getBoundsChangeTransaction(); + if (t != null) { + Task tr = (Task) wc; + tr.setMainWindowSizeChangeTransaction(t); + } + Rect enterPipBounds = c.getEnterPipBounds(); if (enterPipBounds != null) { Task tr = (Task) wc; diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 9552df7b58993..a1a9af680e92c 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -873,6 +873,14 @@ class WindowStateAnimator { clipRect = mTmpClipRect; } + if (mSurfaceResized && (mAttrType == TYPE_BASE_APPLICATION) && + (task != null) && (task.getMainWindowSizeChangeTransaction() != null)) { + mSurfaceController.deferTransactionUntil(mWin.getDeferTransactionBarrier(), + mWin.getFrameNumber()); + SurfaceControl.mergeToGlobalTransaction(task.getMainWindowSizeChangeTransaction()); + task.setMainWindowSizeChangeTransaction(null); + } + float surfaceWidth = mSurfaceController.getWidth(); float surfaceHeight = mSurfaceController.getHeight();