Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc0e7012 authored by Chris Li's avatar Chris Li
Browse files

Introduce WindowStateResizeItem

To dispatch IWindow#resized through ClientTransaction instead of
directly calling the AIDL API.

This is to allow syncing with other client side configuration update.

Bug: 301870955
Test: atest FrameworksCoreTests:WindowStateResizeItemTest
Change-Id: Ie034ea04749f4cc42992ea003a9fc03a39bd02e5
parent c140750f
Loading
Loading
Loading
Loading
+193 −0
Original line number Diff line number Diff line
/*
 * 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
                + "}";
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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,
+7 −0
Original line number Diff line number Diff line
@@ -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"
}
+80 −0
Original line number Diff line number Diff line
/*
 * 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 */);
    }
}
Loading