diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml index 9067593e70b95..42e3383987d61 100644 --- a/services/tests/wmtests/AndroidManifest.xml +++ b/services/tests/wmtests/AndroidManifest.xml @@ -65,6 +65,7 @@ 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 bd6ac58c24458..71d40defb775b 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 f6f3f0324f9c8..93adddb2ac6d9 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 fb957485d9ebd..0fcae92fdbfc8 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 1a4b94b074a10..ce1a46bdd9c04 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 abaa77632c23c..77290e37a5c9e 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 f958e6f98fcd8..c59a04ba7dcbe 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 e16208bf17f0e..16c38ac9fac3c 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 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 34f9c7579abc1..ed23296785c53 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); + } }