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

Commit a551007e authored by Chris Li's avatar Chris Li Committed by Android (Google) Code Review
Browse files

Merge "Fix ConcurrentModificationException in WindowContext" into main

parents a0c71092 d0dc1743
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import static com.android.window.flags.Flags.bundleClientTransactionFlag;

import static java.util.Objects.requireNonNull;

import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityThread;
@@ -94,6 +96,7 @@ public class ClientTransactionListenerController {
     * The listener will be invoked with two parameters: {@link Activity#getActivityToken()} and
     * {@link ActivityWindowInfo}.
     */
    @AnyThread
    public void registerActivityWindowInfoChangedListener(
            @NonNull BiConsumer<IBinder, ActivityWindowInfo> listener) {
        if (!activityWindowInfoFlag()) {
@@ -108,6 +111,7 @@ public class ClientTransactionListenerController {
     * Unregisters the listener that was previously registered via
     * {@link #registerActivityWindowInfoChangedListener(BiConsumer)}
     */
    @AnyThread
    public void unregisterActivityWindowInfoChangedListener(
            @NonNull BiConsumer<IBinder, ActivityWindowInfo> listener) {
        if (!activityWindowInfoFlag()) {
@@ -122,6 +126,7 @@ public class ClientTransactionListenerController {
     * Called when receives a {@link ClientTransaction} that is updating an activity's
     * {@link ActivityWindowInfo}.
     */
    @MainThread
    public void onActivityWindowInfoChanged(@NonNull IBinder activityToken,
            @NonNull ActivityWindowInfo activityWindowInfo) {
        if (!activityWindowInfoFlag()) {
@@ -141,17 +146,20 @@ public class ClientTransactionListenerController {
    }

    /** Called when starts executing a remote {@link ClientTransaction}. */
    @MainThread
    public void onClientTransactionStarted() {
        mIsClientTransactionExecuting = true;
    }

    /** Called when finishes executing a remote {@link ClientTransaction}. */
    @MainThread
    public void onClientTransactionFinished() {
        notifyDisplayManagerIfNeeded();
        mIsClientTransactionExecuting = false;
    }

    /** Called before updating the Configuration of the given {@code context}. */
    @MainThread
    public void onContextConfigurationPreChanged(@NonNull Context context) {
        if (!bundleClientTransactionFlag() || ActivityThread.isSystem()) {
            // Not enable for system server.
@@ -166,6 +174,7 @@ public class ClientTransactionListenerController {
    }

    /** Called after updating the Configuration of the given {@code context}. */
    @MainThread
    public void onContextConfigurationPostChanged(@NonNull Context context) {
        if (!bundleClientTransactionFlag() || ActivityThread.isSystem()) {
            // Not enable for system server.
+23 −7
Original line number Diff line number Diff line
@@ -144,17 +144,26 @@ public class WindowTokenClient extends Binder {
        if (context == null) {
            return;
        }
        if (shouldReportConfigChange) {
            // Only report to ClientTransactionListenerController when shouldReportConfigChange,
            // which is on the MainThread.
            final ClientTransactionListenerController controller =
                ClientTransactionListenerController.getInstance();
                    getClientTransactionListenerController();
            controller.onContextConfigurationPreChanged(context);
            try {
            onConfigurationChangedInner(context, newConfig, newDisplayId, shouldReportConfigChange);
                onConfigurationChangedInner(context, newConfig, newDisplayId,
                        shouldReportConfigChange);
            } finally {
                controller.onContextConfigurationPostChanged(context);
            }
        } else {
            onConfigurationChangedInner(context, newConfig, newDisplayId, shouldReportConfigChange);
        }
    }

    private void onConfigurationChangedInner(@NonNull Context context,
    /** Handles onConfiguration changed. */
    @VisibleForTesting
    public void onConfigurationChangedInner(@NonNull Context context,
            @NonNull Configuration newConfig, int newDisplayId, boolean shouldReportConfigChange) {
        CompatibilityInfo.applyOverrideScaleIfNeeded(newConfig);
        final boolean displayChanged;
@@ -233,4 +242,11 @@ public class WindowTokenClient extends Binder {
            mContextRef.clear();
        }
    }

    /** Gets {@link ClientTransactionListenerController}. */
    @VisibleForTesting
    @NonNull
    public ClientTransactionListenerController getClientTransactionListenerController() {
        return ClientTransactionListenerController.getInstance();
    }
}
+38 −0
Original line number Diff line number Diff line
@@ -23,15 +23,19 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat
import static com.android.window.flags.Flags.FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -45,6 +49,7 @@ import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.DisplayInfo;
import android.window.ActivityWindowInfo;
import android.window.WindowTokenClient;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -55,6 +60,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@@ -180,4 +186,36 @@ public class ClientTransactionListenerControllerTest {

        verify(mActivityWindowInfoListener, never()).accept(any(), any());
    }

    @Test
    public void testWindowTokenClient_onConfigurationChanged() {
        doNothing().when(mController).onContextConfigurationPreChanged(any());
        doNothing().when(mController).onContextConfigurationPostChanged(any());

        final WindowTokenClient windowTokenClient = spy(new WindowTokenClient());
        final Context context = mock(Context.class);
        windowTokenClient.attachContext(context);

        doReturn(mController).when(windowTokenClient).getClientTransactionListenerController();
        doNothing().when(windowTokenClient).onConfigurationChangedInner(any(), any(), anyInt(),
                anyBoolean());

        // Not trigger when shouldReportConfigChange is false.
        windowTokenClient.onConfigurationChanged(mConfiguration, 123 /* newDisplayId */,
                false /* shouldReportConfigChange*/);

        verify(mController, never()).onContextConfigurationPreChanged(any());
        verify(mController, never()).onContextConfigurationPostChanged(any());

        // Trigger in order when shouldReportConfigChange is true.
        clearInvocations(windowTokenClient);
        final InOrder inOrder = inOrder(mController, windowTokenClient);
        windowTokenClient.onConfigurationChanged(mConfiguration, 123 /* newDisplayId */,
                true /* shouldReportConfigChange*/);

        inOrder.verify(mController).onContextConfigurationPreChanged(context);
        inOrder.verify(windowTokenClient).onConfigurationChangedInner(context, mConfiguration,
                123 /* newDisplayId */, true /* shouldReportConfigChange*/);
        inOrder.verify(mController).onContextConfigurationPostChanged(context);
    }
}