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
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user