summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/servertransaction/WindowStateResizeItem.java193
-rw-r--r--core/java/android/view/IWindow.aidl4
-rw-r--r--core/java/android/view/ViewRootImpl.java2
-rw-r--r--core/java/android/window/flags/windowing_sdk.aconfig7
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/WindowStateResizeItemTest.java80
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerFlags.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java53
7 files changed, 322 insertions, 19 deletions
diff --git a/core/java/android/app/servertransaction/WindowStateResizeItem.java b/core/java/android/app/servertransaction/WindowStateResizeItem.java
new file mode 100644
index 000000000000..98281338872b
--- /dev/null
+++ b/core/java/android/app/servertransaction/WindowStateResizeItem.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2023 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 android.app.servertransaction;
+
+import static android.view.Display.INVALID_DISPLAY;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ClientTransactionHandler;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.util.MergedConfiguration;
+import android.view.IWindow;
+import android.view.InsetsState;
+import android.window.ClientWindowFrames;
+
+import java.util.Objects;
+
+/**
+ * Message to deliver window resize info.
+ * @hide
+ */
+public class WindowStateResizeItem extends ClientTransactionItem {
+
+ private IWindow mWindow;
+ private ClientWindowFrames mFrames;
+ private boolean mReportDraw;
+ private MergedConfiguration mConfiguration;
+ private InsetsState mInsetsState;
+ private boolean mForceLayout;
+ private boolean mAlwaysConsumeSystemBars;
+ private int mDisplayId;
+ private int mSyncSeqId;
+ private boolean mDragResizing;
+
+ @Override
+ public void execute(@NonNull ClientTransactionHandler client,
+ @NonNull PendingTransactionActions pendingActions) {
+ try {
+ mWindow.resized(mFrames, mReportDraw, mConfiguration, mInsetsState, mForceLayout,
+ mAlwaysConsumeSystemBars, mDisplayId, mSyncSeqId, mDragResizing);
+ } catch (RemoteException e) {
+ // Should be a local call.
+ throw new RuntimeException(e);
+ }
+ }
+
+ // ObjectPoolItem implementation
+
+ private WindowStateResizeItem() {}
+
+ /** Obtains an instance initialized with provided params. */
+ public static WindowStateResizeItem obtain(@NonNull IWindow window,
+ @NonNull ClientWindowFrames frames, boolean reportDraw,
+ @NonNull MergedConfiguration configuration, @NonNull InsetsState insetsState,
+ boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, int syncSeqId,
+ boolean dragResizing) {
+ WindowStateResizeItem instance =
+ ObjectPool.obtain(WindowStateResizeItem.class);
+ if (instance == null) {
+ instance = new WindowStateResizeItem();
+ }
+ instance.mWindow = requireNonNull(window);
+ instance.mFrames = requireNonNull(frames);
+ instance.mReportDraw = reportDraw;
+ instance.mConfiguration = requireNonNull(configuration);
+ instance.mInsetsState = requireNonNull(insetsState);
+ instance.mForceLayout = forceLayout;
+ instance.mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
+ instance.mDisplayId = displayId;
+ instance.mSyncSeqId = syncSeqId;
+ instance.mDragResizing = dragResizing;
+
+ return instance;
+ }
+
+ @Override
+ public void recycle() {
+ mWindow = null;
+ mFrames = null;
+ mReportDraw = false;
+ mConfiguration = null;
+ mInsetsState = null;
+ mForceLayout = false;
+ mAlwaysConsumeSystemBars = false;
+ mDisplayId = INVALID_DISPLAY;
+ mSyncSeqId = -1;
+ mDragResizing = false;
+ ObjectPool.recycle(this);
+ }
+
+ // Parcelable implementation
+
+ /** Writes to Parcel. */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeStrongBinder(mWindow.asBinder());
+ dest.writeTypedObject(mFrames, flags);
+ dest.writeBoolean(mReportDraw);
+ dest.writeTypedObject(mConfiguration, flags);
+ dest.writeTypedObject(mInsetsState, flags);
+ dest.writeBoolean(mForceLayout);
+ dest.writeBoolean(mAlwaysConsumeSystemBars);
+ dest.writeInt(mDisplayId);
+ dest.writeInt(mSyncSeqId);
+ dest.writeBoolean(mDragResizing);
+ }
+
+ /** Reads from Parcel. */
+ private WindowStateResizeItem(@NonNull Parcel in) {
+ mWindow = IWindow.Stub.asInterface(in.readStrongBinder());
+ mFrames = in.readTypedObject(ClientWindowFrames.CREATOR);
+ mReportDraw = in.readBoolean();
+ mConfiguration = in.readTypedObject(MergedConfiguration.CREATOR);
+ mInsetsState = in.readTypedObject(InsetsState.CREATOR);
+ mForceLayout = in.readBoolean();
+ mAlwaysConsumeSystemBars = in.readBoolean();
+ mDisplayId = in.readInt();
+ mSyncSeqId = in.readInt();
+ mDragResizing = in.readBoolean();
+ }
+
+ public static final @NonNull Creator<WindowStateResizeItem> CREATOR = new Creator<>() {
+ public WindowStateResizeItem createFromParcel(@NonNull Parcel in) {
+ return new WindowStateResizeItem(in);
+ }
+
+ public WindowStateResizeItem[] newArray(int size) {
+ return new WindowStateResizeItem[size];
+ }
+ };
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final WindowStateResizeItem other = (WindowStateResizeItem) o;
+ return Objects.equals(mWindow, other.mWindow)
+ && Objects.equals(mFrames, other.mFrames)
+ && mReportDraw == other.mReportDraw
+ && Objects.equals(mConfiguration, other.mConfiguration)
+ && Objects.equals(mInsetsState, other.mInsetsState)
+ && mForceLayout == other.mForceLayout
+ && mAlwaysConsumeSystemBars == other.mAlwaysConsumeSystemBars
+ && mDisplayId == other.mDisplayId
+ && mSyncSeqId == other.mSyncSeqId
+ && mDragResizing == other.mDragResizing;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + Objects.hashCode(mWindow);
+ result = 31 * result + Objects.hashCode(mFrames);
+ result = 31 * result + (mReportDraw ? 1 : 0);
+ result = 31 * result + Objects.hashCode(mConfiguration);
+ result = 31 * result + Objects.hashCode(mInsetsState);
+ result = 31 * result + (mForceLayout ? 1 : 0);
+ result = 31 * result + (mAlwaysConsumeSystemBars ? 1 : 0);
+ result = 31 * result + mDisplayId;
+ result = 31 * result + mSyncSeqId;
+ result = 31 * result + (mDragResizing ? 1 : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "WindowStateResizeItem{window=" + mWindow
+ + ", reportDrawn=" + mReportDraw
+ + ", configuration=" + mConfiguration
+ + "}";
+ }
+}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index d554514349c3..11180aef4479 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -54,6 +54,10 @@ oneway interface IWindow {
*/
void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);
+ /**
+ * Please dispatch through WindowStateResizeItem instead of directly calling this method from
+ * the system server.
+ */
void resized(in ClientWindowFrames frames, boolean reportDraw,
in MergedConfiguration newMergedConfiguration, in InsetsState insetsState,
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index cf46bcccdf87..0fd7c0db1687 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -10521,6 +10521,8 @@ public final class ViewRootImpl implements ViewParent,
MergedConfiguration mergedConfiguration, InsetsState insetsState,
boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, int syncSeqId,
boolean dragResizing) {
+ // Although this is a AIDL method, it will only be triggered in local process through
+ // either WindowStateResizeItem or WindowlessWindowManager.
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, insetsState,
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index ec5d4ff16ee5..24dc6dbfede8 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -22,3 +22,10 @@ flag {
description: "Whether the TaskFragment system organizer feature is enabled"
bug: "284050041"
}
+
+flag {
+ namespace: "windowing_sdk"
+ name: "window_state_resize_item_flag"
+ description: "Whether to dispatch window resize through ClientTransaction is enabled"
+ bug: "301870955"
+}
diff --git a/core/tests/coretests/src/android/app/servertransaction/WindowStateResizeItemTest.java b/core/tests/coretests/src/android/app/servertransaction/WindowStateResizeItemTest.java
new file mode 100644
index 000000000000..c00eb91d752a
--- /dev/null
+++ b/core/tests/coretests/src/android/app/servertransaction/WindowStateResizeItemTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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 android.app.servertransaction;
+
+import static org.mockito.Mockito.verify;
+
+import android.app.ClientTransactionHandler;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.util.MergedConfiguration;
+import android.view.IWindow;
+import android.view.InsetsState;
+import android.window.ClientWindowFrames;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link WindowStateResizeItem}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksCoreTests:WindowStateResizeItemTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class WindowStateResizeItemTest {
+
+ @Mock
+ private ClientTransactionHandler mHandler;
+ @Mock
+ private PendingTransactionActions mPendingActions;
+ @Mock
+ private IWindow mWindow;
+ @Mock
+ private ClientWindowFrames mFrames;
+ @Mock
+ private MergedConfiguration mConfiguration;
+ @Mock
+ private InsetsState mInsetsState;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testExecute() throws RemoteException {
+ final WindowStateResizeItem item = WindowStateResizeItem.obtain(mWindow, mFrames,
+ true /* reportDraw */, mConfiguration, mInsetsState, true /* forceLayout */,
+ true /* alwaysConsumeSystemBars */, 123 /* displayId */, 321 /* syncSeqId */,
+ true /* dragResizing */);
+ item.execute(mHandler, mPendingActions);
+
+ verify(mWindow).resized(mFrames,
+ true /* reportDraw */, mConfiguration, mInsetsState, true /* forceLayout */,
+ true /* alwaysConsumeSystemBars */, 123 /* displayId */, 321 /* syncSeqId */,
+ true /* dragResizing */);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerFlags.java b/services/core/java/com/android/server/wm/WindowManagerFlags.java
index 00b9b4c490a4..5b9acb2f67c4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerFlags.java
+++ b/services/core/java/com/android/server/wm/WindowManagerFlags.java
@@ -45,5 +45,7 @@ class WindowManagerFlags {
final boolean mSyncWindowConfigUpdateFlag = Flags.syncWindowConfigUpdateFlag();
+ final boolean mWindowStateResizeItemFlag = Flags.windowStateResizeItemFlag();
+
/* End Available Flags */
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4beec2bc79e6..726d4d7c34e7 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -186,6 +186,7 @@ import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyCache;
+import android.app.servertransaction.WindowStateResizeItem;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
@@ -3732,30 +3733,44 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
markRedrawForSyncReported();
- try {
- mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
- getCompatInsetsState(), forceRelayout, alwaysConsumeSystemBars, displayId,
- syncWithBuffers ? mSyncSeqId : -1, isDragResizing);
- if (drawPending && prevRotation >= 0 && prevRotation != mLastReportedConfiguration
- .getMergedConfiguration().windowConfiguration.getRotation()) {
- mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
- ProtoLog.v(WM_DEBUG_ORIENTATION,
- "Requested redraw for orientation change: %s", this);
- }
-
- if (mWmService.mAccessibilityController.hasCallbacks()) {
- mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(displayId);
+ if (mWmService.mFlags.mWindowStateResizeItemFlag) {
+ getProcess().scheduleClientTransactionItem(
+ WindowStateResizeItem.obtain(mClient, mClientWindowFrames, reportDraw,
+ mLastReportedConfiguration, getCompatInsetsState(), forceRelayout,
+ alwaysConsumeSystemBars, displayId,
+ syncWithBuffers ? mSyncSeqId : -1, isDragResizing));
+ onResizePostDispatched(drawPending, prevRotation, displayId);
+ } else {
+ // TODO(b/301870955): cleanup after launch
+ try {
+ mClient.resized(mClientWindowFrames, reportDraw, mLastReportedConfiguration,
+ getCompatInsetsState(), forceRelayout, alwaysConsumeSystemBars, displayId,
+ syncWithBuffers ? mSyncSeqId : -1, isDragResizing);
+ onResizePostDispatched(drawPending, prevRotation, displayId);
+ } catch (RemoteException e) {
+ // Cancel orientation change of this window to avoid blocking unfreeze display.
+ setOrientationChanging(false);
+ mLastFreezeDuration = (int) (SystemClock.elapsedRealtime()
+ - mWmService.mDisplayFreezeTime);
+ Slog.w(TAG, "Failed to report 'resized' to " + this + " due to " + e);
}
- } catch (RemoteException e) {
- // Cancel orientation change of this window to avoid blocking unfreeze display.
- setOrientationChanging(false);
- mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- - mWmService.mDisplayFreezeTime);
- Slog.w(TAG, "Failed to report 'resized' to " + this + " due to " + e);
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
+ private void onResizePostDispatched(boolean drawPending, int prevRotation, int displayId) {
+ if (drawPending && prevRotation >= 0 && prevRotation != mLastReportedConfiguration
+ .getMergedConfiguration().windowConfiguration.getRotation()) {
+ mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
+ ProtoLog.v(WM_DEBUG_ORIENTATION,
+ "Requested redraw for orientation change: %s", this);
+ }
+
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
+ mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(displayId);
+ }
+ }
+
boolean inRelaunchingActivity() {
return mActivityRecord != null && mActivityRecord.isRelaunching();
}