diff options
| author | 2023-07-28 15:31:50 +0000 | |
|---|---|---|
| committer | 2023-07-28 15:55:50 +0000 | |
| commit | c5482b12feea61dd1ba151531cfb78a2d179dda7 (patch) | |
| tree | e3cb743b0a00ca277f3aef02a2c6d77d340409ee | |
| parent | 89563b52eaf8af7a4af18a5768e79d45c608d194 (diff) | |
Attempt to reduce race of WmTests
WmTests contains both e2e and mocked unit tests. The mocked tests
are sensitive to concurrent issue. Such as if the activity is still
destroying on main thread, then when the next test starts to establish
mocked environment, it may throw ConcurrentModificationException
when iterating invocation records because there is additional access
from other thread.
This change waits until the test activities are destroyed, that avoids
overlapping with the next test.
Bug: 293549565
Bug: 254268165
Test: TaskStackChangedListenerTest
Change-Id: I1b2eb77585ba0a1ee936ee921af95e9c2113ec63
9 files changed, 85 insertions, 0 deletions
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml index 9067593e70b9..42e3383987d6 100644 --- a/services/tests/wmtests/AndroidManifest.xml +++ b/services/tests/wmtests/AndroidManifest.xml @@ -65,6 +65,7 @@ <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityInVirtualDisplay" android:resizeableActivity="true" /> <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$LandscapeActivity" + android:configChanges="screenLayout|screenSize|smallestScreenSize|orientation" android:screenOrientation="sensorLandscape" android:showWhenLocked="true" android:turnScreenOn="true" /> diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityLeakTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityLeakTests.java index bd6ac58c2445..71d40defb775 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityLeakTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityLeakTests.java @@ -34,6 +34,8 @@ import android.os.StrictMode; import android.os.strictmode.InstanceCountViolation; import android.util.Log; +import com.android.server.wm.utils.CommonUtils; + import org.junit.After; import org.junit.Test; @@ -63,6 +65,10 @@ public class ActivityLeakTests { activity.finish(); } } + if (!mStartedActivityList.isEmpty()) { + CommonUtils.waitUntilActivityRemoved( + mStartedActivityList.get(mStartedActivityList.size() - 1)); + } mStartedActivityList.clear(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java index f6f3f0324f9c..93adddb2ac6d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java @@ -54,6 +54,8 @@ import android.window.TaskOrganizer; import androidx.test.filters.MediumTest; +import com.android.server.wm.utils.CommonUtils; + import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -172,6 +174,7 @@ public class ActivityOptionsTest { instrumentation.removeMonitor(monitor); if (mainActivity != null) { mainActivity.finish(); + CommonUtils.waitUntilActivityRemoved(mainActivity); } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java index fb957485d9eb..0fcae92fdbfc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ScreenshotTests.java @@ -56,6 +56,9 @@ import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; import androidx.test.rule.ActivityTestRule; +import com.android.server.wm.utils.CommonUtils; + +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -90,6 +93,11 @@ public class ScreenshotTests { mInstrumentation.waitForIdleSync(); } + @After + public void tearDown() { + CommonUtils.waitUntilActivityRemoved(mActivity); + } + @Test public void testScreenshotSecureLayers() throws InterruptedException { SurfaceControl secureSC = new SurfaceControl.Builder() diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java index 1a4b94b074a1..ce1a46bdd9c0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java @@ -52,6 +52,8 @@ import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; +import com.android.server.wm.utils.CommonUtils; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -87,6 +89,7 @@ public class SurfaceControlViewHostTests { @After public void tearDown() { mInstrumentation.getUiAutomation().dropShellPermissionIdentity(); + CommonUtils.waitUntilActivityRemoved(mActivity); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTests.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTests.java index abaa77632c23..77290e37a5c9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceSyncGroupTests.java @@ -47,6 +47,9 @@ import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; +import com.android.server.wm.utils.CommonUtils; + +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -79,6 +82,12 @@ public class SurfaceSyncGroupTests { mHandler = mHandlerThread.getThreadHandler(); } + @After + public void tearDown() { + mHandlerThread.quitSafely(); + CommonUtils.waitUntilActivityRemoved(mActivity); + } + @Test public void testOverlappingSyncsEnsureOrder_WhenTimeout() throws InterruptedException { WindowManager.LayoutParams params = new WindowManager.LayoutParams(); diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceViewSyncContinuousTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceViewSyncContinuousTest.java index f958e6f98fcd..c59a04ba7dcb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SurfaceViewSyncContinuousTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceViewSyncContinuousTest.java @@ -25,6 +25,9 @@ import android.view.cts.surfacevalidator.CapturedActivity; import androidx.test.rule.ActivityTestRule; +import com.android.server.wm.utils.CommonUtils; + +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -54,6 +57,11 @@ public class SurfaceViewSyncContinuousTest { } } + @After + public void tearDown() { + CommonUtils.waitUntilActivityRemoved(mCapturedActivity); + } + @Test public void testSurfaceViewSyncDuringResize() throws Throwable { mCapturedActivity.verifyTest(new SurfaceViewSyncValidatorTestCase(), mName); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java index e16208bf17f0..16c38ac9fac3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java @@ -60,6 +60,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; import java.util.Arrays; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CountDownLatch; @@ -76,6 +77,7 @@ public class TaskStackChangedListenerTest { private ITaskStackListener mTaskStackListener; private VirtualDisplay mVirtualDisplay; private ImageReader mImageReader; + private final ArrayList<Activity> mStartedActivities = new ArrayList<>(); private static final int WAIT_TIMEOUT_MS = 5000; private static final Object sLock = new Object(); @@ -94,6 +96,19 @@ public class TaskStackChangedListenerTest { mVirtualDisplay.release(); mImageReader.close(); } + // Finish from bottom to top. + final int size = mStartedActivities.size(); + for (int i = 0; i < size; i++) { + final Activity activity = mStartedActivities.get(i); + if (!activity.isFinishing()) { + activity.finish(); + } + } + // Wait for the last launched activity to be removed. + if (size > 0) { + CommonUtils.waitUntilActivityRemoved(mStartedActivities.get(size - 1)); + } + mStartedActivities.clear(); } private VirtualDisplay createVirtualDisplay() { @@ -381,6 +396,7 @@ public class TaskStackChangedListenerTest { throw new RuntimeException("Timed out waiting for Activity"); } activity.waitForResumeStateChange(true); + mStartedActivities.add(activity); return activity; } diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java b/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java index 34f9c7579abc..ed23296785c5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java +++ b/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java @@ -18,14 +18,23 @@ package com.android.server.wm.utils; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import android.app.Activity; import android.app.KeyguardManager; import android.app.UiAutomation; +import android.os.SystemClock; +import android.util.Log; import android.view.KeyEvent; import androidx.test.uiautomator.UiDevice; +import java.io.IOException; + /** Provides common utility functions. */ public class CommonUtils { + private static final String TAG = "CommonUtils"; + private static final long REMOVAL_TIMEOUT_MS = 3000; + private static final long TIMEOUT_INTERVAL_MS = 200; + public static UiAutomation getUiAutomation() { return getInstrumentation().getUiAutomation(); } @@ -50,4 +59,26 @@ public class CommonUtils { device.pressKeyCode(KeyEvent.KEYCODE_WAKEUP); device.pressKeyCode(KeyEvent.KEYCODE_MENU); } + + public static void waitUntilActivityRemoved(Activity activity) { + if (!activity.isFinishing()) { + activity.finish(); + } + final UiDevice uiDevice = UiDevice.getInstance(getInstrumentation()); + final String classPattern = activity.getComponentName().flattenToShortString(); + final long startTime = SystemClock.uptimeMillis(); + while (SystemClock.uptimeMillis() - startTime <= REMOVAL_TIMEOUT_MS) { + SystemClock.sleep(TIMEOUT_INTERVAL_MS); + final String windowTokenDump; + try { + windowTokenDump = uiDevice.executeShellCommand("dumpsys window tokens"); + } catch (IOException e) { + throw new RuntimeException(e); + } + if (!windowTokenDump.contains(classPattern)) { + return; + } + } + Log.i(TAG, "Removal timeout of " + classPattern); + } } |