diff options
| author | 2024-08-30 16:18:08 -0700 | |
|---|---|---|
| committer | 2024-09-05 15:35:38 +0000 | |
| commit | b02e968c32df215a5150b8fd9a6f5359b8b3035f (patch) | |
| tree | 7b3f29811a432870dab45592f88a7a3527030fbb | |
| parent | ebb6e2e6f311bde51c9943317e2f972b39712431 (diff) | |
[res] Fix OverlayManagerPerfTest
The test was implemented in a really flaky way:
- It didn't wait for the overlay disablement propagation
correctly, making the setEnabled() tests measure the
phase of the Moon. Now the test is more reliable, but
unfortunately it also depends on the broadcast delivery
timings and activity restarts and redraws, so I doubt there's
a way to make it that much more precise.
- It installed some APKs that Play Protect doesn't see often
and brings up a popup asking to upload them for scanning,
and the popup default timeout is 1hr *per APK*.
Now the timeout is 10s and the installation happens in
parallel, making the whole wait to be about 10-20s
Test: atest OverlayManagerPerfTest
Flag: EXEMPT tests-only change
Change-Id: Iac9f85866cc0dbdc1b567ac599a92b2fd8998932
| -rw-r--r-- | apct-tests/perftests/core/AndroidTest.xml | 11 | ||||
| -rw-r--r-- | apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java | 129 |
2 files changed, 87 insertions, 53 deletions
diff --git a/apct-tests/perftests/core/AndroidTest.xml b/apct-tests/perftests/core/AndroidTest.xml index 86f41e1f496c..c2d54707d9f2 100644 --- a/apct-tests/perftests/core/AndroidTest.xml +++ b/apct-tests/perftests/core/AndroidTest.xml @@ -17,6 +17,17 @@ <option name="test-suite-tag" value="apct" /> <option name="test-suite-tag" value="apct-metric-instrumentation" /> + // Deal with Play Protect blocking apk installations. + // The first setting disables the verification, the second one lowers the timeout from + // 1hr to 10s, the third one resets the value after the test is complete, and the final + // setting skips the device reboot after modifying the settings. + <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> + <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" /> + <option name="set-global-setting" key="verifier_engprod" value="1" /> + <option name="restore-settings" value="true" /> + <option name="force-skip-system-props" value="true" /> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> <option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" /> diff --git a/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java b/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java index fcb13a8d51f1..a12121fd13f7 100644 --- a/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java +++ b/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java @@ -37,9 +37,13 @@ import org.junit.Rule; import org.junit.Test; import java.util.ArrayList; -import java.util.concurrent.Executor; -import java.util.concurrent.FutureTask; +import java.util.Arrays; +import java.util.Comparator; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; /** * Benchmarks for {@link android.content.om.OverlayManager}. @@ -49,7 +53,6 @@ public class OverlayManagerPerfTest { private static final int OVERLAY_PKG_COUNT = 10; private static Context sContext; private static OverlayManager sOverlayManager; - private static Executor sExecutor; private static ArrayList<TestPackageInstaller.InstalledPackage> sSmallOverlays = new ArrayList<>(); private static ArrayList<TestPackageInstaller.InstalledPackage> sLargeOverlays = @@ -58,18 +61,45 @@ public class OverlayManagerPerfTest { @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + // Uncheck the checked exceptions in a callable for convenient stream usage. + // Any exception will fail the test anyway. + private static <T> T uncheck(Callable<T> c) { + try { + return c.call(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @BeforeClass public static void classSetUp() throws Exception { sContext = InstrumentationRegistry.getTargetContext(); sOverlayManager = new OverlayManager(sContext); - sExecutor = (command) -> new Thread(command).start(); - // Install all of the test overlays. - TestPackageInstaller installer = new TestPackageInstaller(sContext); + // Install all of the test overlays. Play Protect likes to block these for 10 sec each + // so let's install them in parallel to speed up the wait. + final var installer = new TestPackageInstaller(sContext); + final var es = Executors.newFixedThreadPool(2 * OVERLAY_PKG_COUNT); + final var smallFutures = new ArrayList<Future<TestPackageInstaller.InstalledPackage>>( + OVERLAY_PKG_COUNT); + final var largeFutures = new ArrayList<Future<TestPackageInstaller.InstalledPackage>>( + OVERLAY_PKG_COUNT); for (int i = 0; i < OVERLAY_PKG_COUNT; i++) { - sSmallOverlays.add(installer.installPackage("Overlay" + i +".apk")); - sLargeOverlays.add(installer.installPackage("LargeOverlay" + i +".apk")); + final var index = i; + smallFutures.add(es.submit(() -> installer.installPackage("Overlay" + index + ".apk"))); + largeFutures.add( + es.submit(() -> installer.installPackage("LargeOverlay" + index + ".apk"))); } + es.shutdown(); + assertTrue(es.awaitTermination(15 * 2 * OVERLAY_PKG_COUNT, TimeUnit.SECONDS)); + sSmallOverlays.addAll(smallFutures.stream().map(f -> uncheck(f::get)).sorted( + Comparator.comparing( + TestPackageInstaller.InstalledPackage::getPackageName)).toList()); + sLargeOverlays.addAll(largeFutures.stream().map(f -> uncheck(f::get)).sorted( + Comparator.comparing( + TestPackageInstaller.InstalledPackage::getPackageName)).toList()); } @AfterClass @@ -77,7 +107,6 @@ public class OverlayManagerPerfTest { for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) { overlay.uninstall(); } - for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) { overlay.uninstall(); } @@ -86,37 +115,39 @@ public class OverlayManagerPerfTest { @After public void tearDown() throws Exception { // Disable all test overlays after each test. - for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) { - assertSetEnabled(sContext, overlay.getPackageName(), false); - } - - for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) { - assertSetEnabled(sContext, overlay.getPackageName(), false); - } + assertSetEnabled(false, sContext, + Stream.concat(sSmallOverlays.stream(), sLargeOverlays.stream()).map( + p -> p.getPackageName())); } /** - * Enables the overlay and waits for the APK path change sto be propagated to the context + * Enables the overlay and waits for the APK path changes to be propagated to the context * AssetManager. */ - private void assertSetEnabled(Context context, String overlayPackage, boolean eanabled) - throws Exception { - sOverlayManager.setEnabled(overlayPackage, true, UserHandle.SYSTEM); + private void assertSetEnabled(boolean enabled, Context context, Stream<String> packagesStream) { + final var overlayPackages = packagesStream.toList(); + overlayPackages.forEach( + name -> sOverlayManager.setEnabled(name, enabled, UserHandle.SYSTEM)); // Wait for the overlay changes to propagate - FutureTask<Boolean> task = new FutureTask<>(() -> { - while (true) { - for (String path : context.getAssets().getApkPaths()) { - if (eanabled == path.contains(overlayPackage)) { - return true; - } - } + final var endTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(20); + final var expectedPackagesFound = enabled ? overlayPackages.size() : 0; + boolean assetsUpdated = false; + do { + final var packagesFound = Arrays.stream(context.getAssets().getApkPaths()).filter( + assetPath -> overlayPackages.stream().anyMatch(assetPath::contains)).count(); + if (packagesFound == expectedPackagesFound) { + assetsUpdated = true; + break; } - }); + Thread.yield(); + } while (System.nanoTime() < endTime); + assertTrue("Failed to set state to " + enabled + " for overlays " + overlayPackages, + assetsUpdated); + } - sExecutor.execute(task); - assertTrue("Failed to load overlay " + overlayPackage, - task.get(20, TimeUnit.SECONDS)); + private void assertSetEnabled(boolean enabled, Context context, String overlayPackage) { + assertSetEnabled(enabled, context, Stream.of(overlayPackage)); } @Test @@ -124,11 +155,11 @@ public class OverlayManagerPerfTest { String packageName = sSmallOverlays.get(0).getPackageName(); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { - assertSetEnabled(sContext, packageName, true); + assertSetEnabled(true, sContext, packageName); // Disable the overlay for the next iteration of the test state.pauseTiming(); - assertSetEnabled(sContext, packageName, false); + assertSetEnabled(false, sContext, packageName); state.resumeTiming(); } } @@ -138,11 +169,11 @@ public class OverlayManagerPerfTest { String packageName = sSmallOverlays.get(0).getPackageName(); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { - assertSetEnabled(sContext, packageName, true); + assertSetEnabled(true, sContext, packageName); // Disable the overlay and remove the idmap for the next iteration of the test state.pauseTiming(); - assertSetEnabled(sContext, packageName, false); + assertSetEnabled(false, sContext, packageName); sOverlayManager.invalidateCachesForOverlay(packageName, UserHandle.SYSTEM); state.resumeTiming(); } @@ -153,11 +184,11 @@ public class OverlayManagerPerfTest { String packageName = sLargeOverlays.get(0).getPackageName(); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { - assertSetEnabled(sContext, packageName, true); + assertSetEnabled(true, sContext, packageName); // Disable the overlay and remove the idmap for the next iteration of the test state.pauseTiming(); - assertSetEnabled(sContext, packageName, false); + assertSetEnabled(false, sContext, packageName); sOverlayManager.invalidateCachesForOverlay(packageName, UserHandle.SYSTEM); state.resumeTiming(); } @@ -169,30 +200,28 @@ public class OverlayManagerPerfTest { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { state.pauseTiming(); - assertSetEnabled(sContext, packageName, true); + assertSetEnabled(true, sContext, packageName); state.resumeTiming(); - assertSetEnabled(sContext, packageName, false); + assertSetEnabled(false, sContext, packageName); } } @Test public void getStringOneSmallOverlay() throws Exception { String packageName = sSmallOverlays.get(0).getPackageName(); - assertSetEnabled(sContext, packageName, true); + assertSetEnabled(true, sContext, packageName); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { sContext.getString(R.string.short_text); } - - assertSetEnabled(sContext, packageName, false); } @Test public void getStringOneLargeOverlay() throws Exception { String packageName = sLargeOverlays.get(0).getPackageName(); - assertSetEnabled(sContext, packageName, true); + assertSetEnabled(true, sContext, packageName); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { @@ -200,16 +229,12 @@ public class OverlayManagerPerfTest { sContext.getString(resId); } } - - assertSetEnabled(sContext, packageName, false); } @Test public void getStringTenOverlays() throws Exception { - // Enable all test overlays - for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) { - assertSetEnabled(sContext, overlay.getPackageName(), true); - } + // Enable all small test overlays + assertSetEnabled(true, sContext, sSmallOverlays.stream().map(p -> p.getPackageName())); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { @@ -219,10 +244,8 @@ public class OverlayManagerPerfTest { @Test public void getStringLargeTenOverlays() throws Exception { - // Enable all test overlays - for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) { - assertSetEnabled(sContext, overlay.getPackageName(), true); - } + // Enable all large test overlays + assertSetEnabled(true, sContext, sLargeOverlays.stream().map(p -> p.getPackageName())); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { |