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

Commit 539232a1 authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "Wait for config callback to reduce flakiness" into main

parents d6492fde c2b0097c
Loading
Loading
Loading
Loading
+73 −12
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -35,9 +34,14 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import static java.util.Objects.requireNonNull;

import android.app.ActivityThread;
import android.app.IApplicationThread;
import android.app.WindowConfiguration;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
@@ -50,6 +54,8 @@ import android.view.WindowManagerGlobal;
import android.window.WindowContextInfo;
import android.window.WindowTokenClient;

import androidx.annotation.NonNull;

import com.android.server.inputmethod.InputMethodDialogWindowContext;

import org.junit.After;
@@ -58,6 +64,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

// TODO(b/157888351): Move the test to inputmethod package once we find the way to test the
//  scenario there.
/**
@@ -138,44 +147,96 @@ public class InputMethodDialogWindowContextTest extends WindowTestsBase {
    @Test
    public void testGetSettingsContextOnDualDisplayContent() {
        final Context context = mWindowContext.get(mSecondaryDisplay.getDisplayId());
        final MaxBoundsVerifier maxBoundsVerifier = new MaxBoundsVerifier();
        context.registerComponentCallbacks(maxBoundsVerifier);

        final WindowTokenClient tokenClient = (WindowTokenClient) context.getWindowContextToken();
        assertNotNull(tokenClient);
        spyOn(tokenClient);
        spyOn(requireNonNull(tokenClient));

        final DisplayArea.Tokens imeContainer = mSecondaryDisplay.getImeContainer();
        spyOn(imeContainer);
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mSecondaryDisplay);

        mSecondaryDisplay.mFirstRoot.placeImeContainer(imeContainer);
        final DisplayAreaGroup firstDaGroup = mSecondaryDisplay.mFirstRoot;
        maxBoundsVerifier.setMaxBounds(firstDaGroup.getMaxBounds());

        firstDaGroup.placeImeContainer(imeContainer);

        verify(imeContainer, timeout(WAIT_TIMEOUT_MS)).onConfigurationChanged(
                eq(mSecondaryDisplay.mFirstRoot.getConfiguration()));
                eq(firstDaGroup.getConfiguration()));
        verify(tokenClient, timeout(WAIT_TIMEOUT_MS)).onConfigurationChanged(
                eq(mSecondaryDisplay.mFirstRoot.getConfiguration()),
                eq(firstDaGroup.getConfiguration()),
                eq(mSecondaryDisplay.mDisplayId));
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mSecondaryDisplay.mFirstRoot);
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(firstDaGroup);
        maxBoundsVerifier.waitAndAssertMaxMetricsMatches();
        assertImeSwitchContextMetricsValidity(context, mSecondaryDisplay);

        // Clear the previous invocation histories in case we may count the previous
        // onConfigurationChanged invocation into the next verification.
        clearInvocations(tokenClient, imeContainer);
        mSecondaryDisplay.mSecondRoot.placeImeContainer(imeContainer);
        final DisplayAreaGroup secondDaGroup = mSecondaryDisplay.mSecondRoot;
        maxBoundsVerifier.setMaxBounds(secondDaGroup.getMaxBounds());

        secondDaGroup.placeImeContainer(imeContainer);

        verify(imeContainer, timeout(WAIT_TIMEOUT_MS)).onConfigurationChanged(
                eq(mSecondaryDisplay.mSecondRoot.getConfiguration()));
                eq(secondDaGroup.getConfiguration()));
        verify(tokenClient, timeout(WAIT_TIMEOUT_MS)).onConfigurationChanged(
                eq(mSecondaryDisplay.mSecondRoot.getConfiguration()),
                eq(secondDaGroup.getConfiguration()),
                eq(mSecondaryDisplay.mDisplayId));
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mSecondaryDisplay.mSecondRoot);
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(secondDaGroup);
        maxBoundsVerifier.waitAndAssertMaxMetricsMatches();
        assertImeSwitchContextMetricsValidity(context, mSecondaryDisplay);
    }

    private void assertImeSwitchContextMetricsValidity(Context context, DisplayContent dc) {
        assertThat(context.getDisplayId()).isEqualTo(dc.getDisplayId());

        final Rect imeContainerBounds = dc.getImeContainer().getBounds();
        final Rect contextBounds = context.getSystemService(WindowManager.class)
                .getMaximumWindowMetrics().getBounds();
        final Rect imeContainerBounds = dc.getImeContainer().getBounds();
        assertThat(contextBounds).isEqualTo(imeContainerBounds);
    }

    private static final class MaxBoundsVerifier implements ComponentCallbacks {

        private CountDownLatch mLatch;

        private Rect mMaxBounds;

        /**
         * Sets max bounds to verify whether it matches the
         * {@link WindowConfiguration#getMaxBounds()} reported from
         * {@link #onConfigurationChanged(Configuration)} callback, and also resets the count down
         * latch.
         *
         * @param maxBounds max bounds to verify
         */
        private void setMaxBounds(@NonNull Rect maxBounds) {
            mMaxBounds = maxBounds;
            mLatch = new CountDownLatch(1);
        }

        /**
         * Waits for the {@link #onConfigurationChanged(Configuration)} callback whose the reported
         * {@link WindowConfiguration#getMaxBounds()} matches {@link #mMaxBounds}.
         */
        private void waitAndAssertMaxMetricsMatches() {
            try {
                assertThat(mLatch.await(WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue();
            } catch (InterruptedException e) {
                throw new RuntimeException("Test failed because of " + e);
            }
        }

        @Override
        public void onConfigurationChanged(@NonNull Configuration newConfig) {
            if (newConfig.windowConfiguration.getMaxBounds().equals(mMaxBounds)) {
                mLatch.countDown();
            }
        }

        @Override
        public void onLowMemory() {}
    }
}