diff --git a/MacrobenchmarkSample/gradle/libs.versions.toml b/MacrobenchmarkSample/gradle/libs.versions.toml index 9de3abb2..426ced12 100644 --- a/MacrobenchmarkSample/gradle/libs.versions.toml +++ b/MacrobenchmarkSample/gradle/libs.versions.toml @@ -19,7 +19,7 @@ profileInstaller = "1.4.1" runtimeTracing = "1.7.8" tracing = "1.3.0-beta01" tracingPerfetto = "1.0.0" -uiAutomator = "2.3.0" +uiAutomator = "2.4.0-SNAPSHOT" [libraries] compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/Common.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/Common.kt index 9738eafc..6c665d92 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/Common.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/Common.kt @@ -16,18 +16,14 @@ package com.example.macrobenchmark.baselineprofile -import androidx.benchmark.macro.MacrobenchmarkScope -import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.UiAutomatorTestScope const val TARGET_PACKAGE = "com.example.macrobenchmark.target" /** - * Clears the application data for the package specified in the [MacrobenchmarkScope]. - * @param scope The [MacrobenchmarkScope] providing information about the benchmark, - * including the package name of the app under test. + * Clears the application data for the launcher package. */ -fun UiDevice.clearData(scope: MacrobenchmarkScope) { - val command = "pm clear ${scope.packageName}" - val output = executeShellCommand(command) -// Assert.assertEquals("Success", output) +fun UiAutomatorTestScope.clearData() { + val command = "pm clear $TARGET_PACKAGE" + uiDevice.executeShellCommand(command) } \ No newline at end of file diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/ComposeActivityBaselineProfileGenerator.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/ComposeActivityBaselineProfileGenerator.kt index 7264400b..43d5fb51 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/ComposeActivityBaselineProfileGenerator.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/ComposeActivityBaselineProfileGenerator.kt @@ -19,16 +19,12 @@ package com.example.macrobenchmark.baselineprofile import android.content.Intent import androidx.benchmark.macro.junit4.BaselineProfileRule import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner -import androidx.test.uiautomator.By import androidx.test.uiautomator.Direction -import com.example.macrobenchmark.benchmark.util.findOrFail -import com.example.macrobenchmark.benchmark.util.waitAndFind -import org.junit.Ignore +import androidx.test.uiautomator.uiAutomator import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -@Ignore // TODO causing stale object excpetion on CI .. why? @RunWith(AndroidJUnit4ClassRunner::class) class ComposeActivityBaselineProfileGenerator { @@ -42,16 +38,16 @@ class ComposeActivityBaselineProfileGenerator { maxIterations = 15, stableIterations = 3 ) { - // Start into the Compose Activity - startActivityAndWait(Intent("$TARGET_PACKAGE.COMPOSE_ACTIVITY")) + uiAutomator { + // Start into the Compose Activity + startIntent(Intent("$TARGET_PACKAGE.COMPOSE_ACTIVITY")) - // Scrolling through the Compose journey - device.waitAndFind(By.res("myLazyColumn")).also { - it.setGestureMargin(device.displayWidth / 10) - it.fling(Direction.DOWN) + // Scrolling through the Compose journey + with(onView { viewIdResourceName == "myLazyColumn" }) { + setGestureMargin(device.displayWidth / 10) + listOf(Direction.DOWN, Direction.UP).forEach { fling(it) } + } } - - device.findOrFail(By.res("myLazyColumn")).fling(Direction.UP) } } } diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/LoginBaselineProfileGenerator.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/LoginBaselineProfileGenerator.kt index 9792a33d..d9fdd2da 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/LoginBaselineProfileGenerator.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/LoginBaselineProfileGenerator.kt @@ -19,7 +19,7 @@ package com.example.macrobenchmark.baselineprofile import android.content.Intent import androidx.benchmark.macro.junit4.BaselineProfileRule import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner -import androidx.test.uiautomator.By +import androidx.test.uiautomator.uiAutomator import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -37,12 +37,13 @@ class LoginBaselineProfileGenerator { maxIterations = 15, stableIterations = 3 ) { - device.clearData(this) - startActivityAndWait(Intent("$packageName.LOGIN_ACTIVITY")) - device.findObject(By.res("userName")).text = "user" - device.findObject(By.res("password")).text = "password" - device.findObject(By.res("login")).click() - device.waitForIdle() + uiAutomator { + clearData() + startIntent(Intent("$packageName.LOGIN_ACTIVITY")) + onView { viewIdResourceName == "userName" }.text = "user" + onView { viewIdResourceName == "password" }.text = "password" + onView { viewIdResourceName == "login" }.click() + } } } } diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/RecyclerViewActivityBaselineProfileGenerator.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/RecyclerViewActivityBaselineProfileGenerator.kt index a5ab1b8a..db9fcc81 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/RecyclerViewActivityBaselineProfileGenerator.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/RecyclerViewActivityBaselineProfileGenerator.kt @@ -19,14 +19,12 @@ package com.example.macrobenchmark.baselineprofile import android.content.Intent import androidx.benchmark.macro.junit4.BaselineProfileRule import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner -import androidx.test.uiautomator.By import androidx.test.uiautomator.Direction -import org.junit.Ignore +import androidx.test.uiautomator.uiAutomator import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -@Ignore // TODO flinging not working, ignore for now to test the pipeline @RunWith(AndroidJUnit4ClassRunner::class) class RecyclerViewActivityBaselineProfileGenerator { @@ -40,14 +38,14 @@ class RecyclerViewActivityBaselineProfileGenerator { maxIterations = 15, stableIterations = 3 ) { - // Start into the RecyclerViewActivity - startActivityAndWait(Intent("$TARGET_PACKAGE.RECYCLER_VIEW_ACTIVITY")) + uiAutomator { + // Start into the RecyclerViewActivity + startIntent(Intent("$TARGET_PACKAGE.RECYCLER_VIEW_ACTIVITY")) - // Scrolling RecyclerView journey - device.findObject(By.res(packageName, "recycler")).also { - it.setGestureMargin(device.displayWidth / 10) - it.fling(Direction.DOWN) - it.fling(Direction.UP) + with(onView { viewIdResourceName == "recycler" }) { + setGestureMargin(device.displayWidth / 10) + listOf(Direction.DOWN, Direction.UP).forEach { fling(it) } + } } } } diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/StartupProfileGenerator.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/StartupProfileGenerator.kt index ba884bbc..7d015e63 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/StartupProfileGenerator.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/baselineprofile/StartupProfileGenerator.kt @@ -18,6 +18,7 @@ package com.example.macrobenchmark.baselineprofile import androidx.benchmark.macro.junit4.BaselineProfileRule import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.uiautomator.uiAutomator import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -41,7 +42,9 @@ class StartupProfileGenerator { stableIterations = 3, includeInStartupProfile = true ) { - startActivityAndWait() + uiAutomator { + startApp() + } } } } \ No newline at end of file diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/LoginBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/LoginBenchmark.kt index e94c0af7..1486e1a1 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/LoginBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/LoginBenchmark.kt @@ -25,10 +25,11 @@ import androidx.benchmark.macro.StartupMode import androidx.benchmark.macro.StartupTimingMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.uiautomator.By +import androidx.test.uiautomator.UiAutomatorTestScope +import androidx.test.uiautomator.uiAutomator +import com.example.macrobenchmark.benchmark.permissions.allowNotifications import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE -import com.example.macrobenchmark.benchmark.permissions.allowNotifications import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -51,15 +52,17 @@ class LoginBenchmark { @Test fun loginInSetupBlock() { benchmarkLoginActivity(setupBlock = { - startActivityAndWait(Intent("$packageName.LOGIN_ACTIVITY")) - login() + uiAutomator { + startIntent(Intent("$packageName.LOGIN_ACTIVITY")) + login() + } }) } @Test fun loginWithUiAutomator() { benchmarkLoginActivity { - login() + uiAutomator { login() } } } @@ -67,17 +70,17 @@ class LoginBenchmark { fun loginInAfterPermissionsGranted() { benchmarkLoginActivity(setupBlock = { allowNotifications() - - startActivityAndWait(Intent("$packageName.LOGIN_ACTIVITY")) - login() + uiAutomator { + startIntent(Intent("$packageName.LOGIN_ACTIVITY")) + login() + } }) } - private fun MacrobenchmarkScope.login() { - device.findObject(By.res("userName")).text = "user" - device.findObject(By.res("password")).text = "password" - device.findObject(By.res("login")).click() - device.waitForIdle() + private fun UiAutomatorTestScope.login() { + onView { viewIdResourceName == "userName" }.text = "user" + onView { viewIdResourceName == "password" }.text = "password" + onView { viewIdResourceName == "login" }.click() } private fun benchmarkLoginActivity( @@ -93,12 +96,10 @@ class LoginBenchmark { iterations = DEFAULT_ITERATIONS, setupBlock = setupBlock, ) { - startActivityAndWait( - Intent() - .putExtras(extras) - .setAction("$packageName.LOGIN_ACTIVITY") - ) - measureBlock() + uiAutomator { + startIntent(Intent().putExtras(extras).setAction("$packageName.LOGIN_ACTIVITY")) + measureBlock() + } } } } \ No newline at end of file diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/clickslatency/ClickLatencyBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/clickslatency/ClickLatencyBenchmark.kt index 30b55ec6..37e94a53 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/clickslatency/ClickLatencyBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/clickslatency/ClickLatencyBenchmark.kt @@ -19,16 +19,14 @@ package com.example.macrobenchmark.benchmark.clickslatency; import android.content.Intent import androidx.benchmark.macro.CompilationMode import androidx.benchmark.macro.ExperimentalMetricApi -import androidx.benchmark.macro.MacrobenchmarkScope import androidx.benchmark.macro.TraceSectionMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.uiautomator.By -import androidx.test.uiautomator.Until +import androidx.test.uiautomator.UiAutomatorTestScope +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE -import junit.framework.TestCase.fail import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -47,147 +45,93 @@ class ClickLatencyBenchmark { @Test fun simpleViewClick() { - var firstStart = true benchmarkRule.measureRepeated( - packageName = TARGET_PACKAGE, - metrics = listOf(TraceSectionMetric("ClickTrace")), - compilationMode = CompilationMode.Full(), - startupMode = null, - iterations = DEFAULT_ITERATIONS, - setupBlock = { - if (firstStart) { - startActivityAndWait() - firstStart = false - } - } + packageName = TARGET_PACKAGE, + metrics = listOf(TraceSectionMetric("ClickTrace")), + compilationMode = CompilationMode.Full(), + startupMode = null, + iterations = DEFAULT_ITERATIONS, ) { - clickOnId("launchRecyclerActivity") - waitForTextShown("RecyclerView Sample") - device.pressBack() - waitForTextGone("RecyclerView Sample") + uiAutomator { + startApp() + val title = "RecyclerView Sample" + onView { viewIdResourceName == "launchRecyclerActivity" }.click() + onView { text == title && isVisibleToUser } + pressBack() + onView { text == title && !isVisibleToUser } + } } } @Test fun recyclerViewClick() { - var firstStart = true benchmarkRule.measureRepeated( - packageName = TARGET_PACKAGE, - metrics = listOf(TraceSectionMetric("ClickTrace")), - compilationMode = CompilationMode.Full(), - startupMode = null, - iterations = DEFAULT_ITERATIONS, - setupBlock = { - if (firstStart) { - val intent = Intent("$packageName.RECYCLER_VIEW_ACTIVITY") - startActivityAndWait(intent) - firstStart = false - } - } + packageName = TARGET_PACKAGE, + metrics = listOf(TraceSectionMetric("ClickTrace")), + compilationMode = CompilationMode.Full(), + startupMode = null, + iterations = DEFAULT_ITERATIONS, ) { - clickOnFirstItem() + uiAutomator { + startIntent(Intent("$packageName.RECYCLER_VIEW_ACTIVITY")) + clickOnFirstItem() + } } } @Test fun composeLazyColumnClick() { - var firstStart = true benchmarkRule.measureRepeated( - packageName = TARGET_PACKAGE, - metrics = listOf(TraceSectionMetric("ClickTrace")), - compilationMode = CompilationMode.Full(), - startupMode = null, - iterations = DEFAULT_ITERATIONS, - setupBlock = { - if (firstStart) { - val intent = Intent("$packageName.COMPOSE_ACTIVITY") - startActivityAndWait(intent) - firstStart = false - } - } + packageName = TARGET_PACKAGE, + metrics = listOf(TraceSectionMetric("ClickTrace")), + compilationMode = CompilationMode.Full(), + startupMode = null, + iterations = DEFAULT_ITERATIONS, ) { - clickOnFirstItem() + uiAutomator { + startIntent(Intent("$packageName.COMPOSE_ACTIVITY")) + clickOnFirstItem() + } } } @Test fun listViewClick() { - var firstStart = true benchmarkRule.measureRepeated( - packageName = TARGET_PACKAGE, - metrics = listOf(TraceSectionMetric("ClickTrace")), - compilationMode = CompilationMode.Full(), - startupMode = null, - iterations = DEFAULT_ITERATIONS, - setupBlock = { - if (firstStart) { - val intent = Intent("$packageName.LIST_VIEW_ACTIVITY") - startActivityAndWait(intent) - firstStart = false - } - } + packageName = TARGET_PACKAGE, + metrics = listOf(TraceSectionMetric("ClickTrace")), + compilationMode = CompilationMode.Full(), + startupMode = null, + iterations = DEFAULT_ITERATIONS, ) { - clickOnFirstItem() + uiAutomator { + startIntent(Intent("$packageName.LIST_VIEW_ACTIVITY")) + clickOnFirstItem() + } } } @Test fun scrollViewClick() { - var firstStart = true benchmarkRule.measureRepeated( - packageName = TARGET_PACKAGE, - metrics = listOf(TraceSectionMetric("ClickTrace")), - compilationMode = CompilationMode.Full(), - startupMode = null, - iterations = DEFAULT_ITERATIONS, - setupBlock = { - if (firstStart) { - val intent = Intent("$packageName.SCROLL_VIEW_ACTIVITY") - startActivityAndWait(intent) - firstStart = false - } - } + packageName = TARGET_PACKAGE, + metrics = listOf(TraceSectionMetric("ClickTrace")), + compilationMode = CompilationMode.Full(), + startupMode = null, + iterations = DEFAULT_ITERATIONS, ) { - clickOnFirstItem() + uiAutomator { + startIntent(Intent("$packageName.SCROLL_VIEW_ACTIVITY")) + clickOnFirstItem() + } } } - private fun MacrobenchmarkScope.clickOnFirstItem() { - clickOnText("Item 0") - waitForTextShown("Item clicked") - // Dismiss dialog - device.pressBack() - waitForTextGone("Item clicked") - } - - private fun MacrobenchmarkScope.waitForTextShown(text: String) { - check(device.wait(Until.hasObject(By.text(text)), 500)) { - "View showing '$text' not found after waiting 500 ms." - } - } - - private fun MacrobenchmarkScope.waitForTextGone(text: String) { - check(device.wait(Until.gone(By.text(text)), 500)) { - "View showing '$text' not found after waiting 500 ms." - } - } - - private fun MacrobenchmarkScope.clickOnText(text: String) { - device - .findObject(By.text(text)) - .click() - } - - private fun MacrobenchmarkScope.clickOnId(resourceId: String) { - val selector = By.res(resourceId) - if (!device.wait(Until.hasObject(selector), 2_500)) { - fail("Did not find object with id $resourceId") - } - - device - .findObject(selector) - .click() - // Chill to ensure we capture the end of the click span in the trace. - Thread.sleep(100) + private fun UiAutomatorTestScope.clickOnFirstItem() { + onView { text == "Item 0" }.click() + onView { text == "Item clicked" && isVisibleToUser } + pressBack() + onView { text == "Item clicked" && !isVisibleToUser } } } + diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/FrameTimingBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/FrameTimingBenchmark.kt index 74abacf9..a421a591 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/FrameTimingBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/FrameTimingBenchmark.kt @@ -26,8 +26,8 @@ import androidx.benchmark.macro.TraceSectionMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.uiautomator.By import androidx.test.uiautomator.Direction +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE import org.junit.Rule @@ -55,17 +55,21 @@ class FrameTimingBenchmark { // [END_EXCLUDE] setupBlock = { // Before starting to measure, navigate to the UI to be measured - val intent = Intent("$packageName.RECYCLER_VIEW_ACTIVITY") - startActivityAndWait(intent) + uiAutomator { + startIntent(Intent("$packageName.RECYCLER_VIEW_ACTIVITY")) + } } ) { - val recycler = device.findObject(By.res(packageName, "recycler")) - // Set gesture margin to avoid triggering gesture navigation - // with input events from automation. - recycler.setGestureMargin(device.displayWidth / 5) + uiAutomator { + val recycler = onView { viewIdResourceName == "recycler" } - // Scroll down several times - repeat(3) { recycler.fling(Direction.DOWN) } + // Set gesture margin to avoid triggering gesture navigation + // with input events from automation. + recycler.setGestureMargin(device.displayWidth / 5) + + // Scroll down several times + repeat(3) { recycler.fling(Direction.DOWN) } + } } } // [END macrobenchmark_control_your_app] @@ -97,8 +101,9 @@ class FrameTimingBenchmark { // [END_EXCLUDE] setupBlock = { // Before starting to measure, navigate to the UI to be measured - val intent = Intent("$packageName.COMPOSE_ACTIVITY") - startActivityAndWait(intent) + uiAutomator { + startIntent(Intent("$packageName.COMPOSE_ACTIVITY")) + } } ) { /** @@ -109,14 +114,18 @@ class FrameTimingBenchmark { * * Once done that, we can access the composable using By.res("someIdentifier") */ - val column = device.findObject(By.res("myLazyColumn")) + uiAutomator { + with(onView { viewIdResourceName == "myLazyColumn" }) { + // Set gesture margin to avoid triggering gesture navigation + // with input events from automation. + setGestureMargin(device.displayWidth / 5) - // Set gesture margin to avoid triggering gesture navigation - // with input events from automation. - column.setGestureMargin(device.displayWidth / 5) - - // Scroll down several times - repeat(1) { column.drag(Point(column.visibleCenter.x, column.visibleBounds.top)) } + // Scroll down several times + repeat(1) { + drag(Point(visibleCenter.x, visibleBounds.top)) + } + } + } } } } diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/NestedRecyclerFrameTimingBenchmarks.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/NestedRecyclerFrameTimingBenchmarks.kt index e8cb0ea0..b8414aba 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/NestedRecyclerFrameTimingBenchmarks.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/NestedRecyclerFrameTimingBenchmarks.kt @@ -16,20 +16,20 @@ package com.example.macrobenchmark.benchmark.frames -import androidx.benchmark.macro.* +import androidx.benchmark.macro.ExperimentalMetricApi +import androidx.benchmark.macro.FrameTimingMetric +import androidx.benchmark.macro.MacrobenchmarkScope +import androidx.benchmark.macro.StartupMode import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.uiautomator.By import androidx.test.uiautomator.Direction -import androidx.test.uiautomator.Until +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE -import com.example.macrobenchmark.benchmark.util.waitAndFind import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import java.util.concurrent.TimeUnit @ExperimentalMetricApi @LargeTest @@ -61,45 +61,41 @@ class NestedRecyclerFrameTimingBenchmarks { } private fun MacrobenchmarkScope.navigateToNestedRvScreen(useRecyclerViewPool: Boolean) { - startActivityAndWait() - // navigate to the activity - val selector = - By.res(if (useRecyclerViewPool) "nestedRecyclerWithPoolsActivity" else "nestedRecyclerActivity") + uiAutomator { + startApp() - val button = device.waitAndFind(selector) - button.click() + onView { + val resourceName = + if (useRecyclerViewPool) "nestedRecyclerWithPoolsActivity" else "nestedRecyclerActivity" + viewIdResourceName == resourceName + }.click() - // wait until the activity is shown - device.wait( - Until.hasObject(By.clazz("$packageName.NestedRecyclerActivity")), - TimeUnit.SECONDS.toMillis(10) - ) + // wait until the activity is shown + onView { className == "$packageName.NestedRecyclerActivity" } + } } - private fun MacrobenchmarkScope.measureScrollingNestedRecycler() { - val recycler = device.findObject(By.res(packageName, "recycler")) - // Set gesture margin to avoid triggering gesture navigation with input events from automation. - recycler.setGestureMargin(device.displayWidth / 5) - - repeat(3) { index -> - val visibleNestedRecyclers = - recycler.findObjects(By.res(packageName, "row_recycler")) - - // scroll the second recycler, because the first one may be shown just a pixel - val nestedRecyclerToScroll = visibleNestedRecyclers[1] - + private fun MacrobenchmarkScope.measureScrollingNestedRecycler() = + uiAutomator { + val recycler = onView { viewIdResourceName == "recycler" } // Set gesture margin to avoid triggering gesture navigation with input events from automation. - nestedRecyclerToScroll.setGestureMargin(device.displayWidth / 3) - - // swipe horizontally - nestedRecyclerToScroll.fling(Direction.RIGHT) - // scroll down twice and once up - recycler.swipe(if (index < 2) Direction.UP else Direction.DOWN, 0.5f) - // wait until the swipe is done - device.waitForIdle() + recycler.setGestureMargin(device.displayWidth / 5) + + repeat(3) { index -> + // scroll the second recycler, because the first one may be shown just a pixel + val nestedRecyclerToScroll = onViews { viewIdResourceName == "row_recycler" }[1] + + with(nestedRecyclerToScroll) { + // Set gesture margin to avoid triggering gesture navigation with input events from automation. + setGestureMargin(device.displayWidth / 3) + + // swipe horizontally + fling(Direction.RIGHT) + // scroll down twice and once up + swipe(if (index < 2) Direction.UP else Direction.DOWN, 0.5f) + // wait until the swipe is done + } + } } - } - } - diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/NonExportedActivityBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/NonExportedActivityBenchmark.kt index ccb1855a..786ac132 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/NonExportedActivityBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/NonExportedActivityBenchmark.kt @@ -23,16 +23,13 @@ import androidx.benchmark.macro.StartupMode import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.uiautomator.By import androidx.test.uiautomator.Direction -import androidx.test.uiautomator.Until +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE -import junit.framework.TestCase.fail import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import java.util.concurrent.TimeUnit @LargeTest @@ -59,38 +56,35 @@ class NonExportedActivityBenchmark { // [END_EXCLUDE] setupBlock = setupBenchmark() ) { - // [START_EXCLUDE] - val recycler = device.findObject(By.res(packageName, "recycler")) + uiAutomator { + // [START_EXCLUDE] + with(onView { viewIdResourceName == "recycler" }) { - // Set gesture margin to avoid triggering gesture navigation - // with input events from automation. - recycler.setGestureMargin(device.displayWidth / 5) + // Set gesture margin to avoid triggering gesture navigation + // with input events from automation. + setGestureMargin(uiDevice.displayWidth / 5) - // Fling the recycler several times - repeat(3) { recycler.fling(Direction.DOWN) } - // [END_EXCLUDE] + // Fling the recycler several times + repeat(3) { fling(Direction.DOWN) } + } + // [END_EXCLUDE] + } } } private fun setupBenchmark(): MacrobenchmarkScope.() -> Unit = { // Before starting to measure, navigate to the UI to be measured - startActivityAndWait() + uiAutomator { + startApp() - // click a button to launch the target activity. - // While we use button text here to find the button, you could also use - // accessibility info or resourceId. - val selector = By.text("RecyclerView") - if (!device.wait(Until.hasObject(selector), 5_500)) { - fail("Could not find resource in time") - } - val launchRecyclerActivity = device.findObject(selector) - launchRecyclerActivity.click() + // click a button to launch the target activity. + // While we use button text here to find the button, you could also use + // accessibility info or resourceId. + onView { text == "RecyclerView" }.click() - // wait until the activity is shown - device.wait( - Until.hasObject(By.clazz("$packageName.NonExportedRecyclerActivity")), - TimeUnit.SECONDS.toMillis(10) - ) + // wait until the activity is shown + onView { className == "$packageName.NonExportedRecyclerActivity" } + } } // [END macrobenchmark_navigate_within_app] diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/TextInputFrameTimingBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/TextInputFrameTimingBenchmark.kt index b4d3b467..020346f7 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/TextInputFrameTimingBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/frames/TextInputFrameTimingBenchmark.kt @@ -23,7 +23,7 @@ import androidx.benchmark.macro.StartupMode import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.uiautomator.By +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE import org.junit.Rule @@ -48,14 +48,18 @@ class TextInputFrameTimingBenchmark { iterations = DEFAULT_ITERATIONS, setupBlock = { // Before starting to measure, navigate to the UI to be measured - val intent = Intent("$packageName.COMPOSE_ACTIVITY") - startActivityAndWait(intent) + uiAutomator { + startIntent(Intent("$packageName.COMPOSE_ACTIVITY")) + } } ) { - val input = device.findObject(By.res("input")) - repeat(3) { - input.text = "" - input.text = "Benchmark input $it" + uiAutomator { + with(onView { viewIdResourceName == "input" }) { + repeat(3) { + text = "" + text = "Benchmark input $it" + } + } } } } diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/scroll/ScrollBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/scroll/ScrollBenchmark.kt index cd7d690b..6238fae1 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/scroll/ScrollBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/scroll/ScrollBenchmark.kt @@ -25,12 +25,10 @@ import androidx.benchmark.macro.TraceSectionMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SdkSuppress -import androidx.test.uiautomator.By import androidx.test.uiautomator.Direction -import androidx.test.uiautomator.Until +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE -import junit.framework.TestCase import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -53,7 +51,6 @@ class ScrollBenchmark { fun full() = scroll(CompilationMode.Full()) private fun scroll(compilationMode: CompilationMode) { - var firstStart = true benchmarkRule.measureRepeated( packageName = TARGET_PACKAGE, metrics = listOf( @@ -64,27 +61,20 @@ class ScrollBenchmark { compilationMode = compilationMode, startupMode = null, iterations = DEFAULT_ITERATIONS, - setupBlock = { - if (firstStart) { - val intent = Intent("$packageName.SCROLL_VIEW_ACTIVITY") - startActivityAndWait(intent) - firstStart = false - } - } ) { - device.wait(Until.hasObject(By.scrollable(true)), 5_000) + uiAutomator { + startIntent(Intent("$packageName.SCROLL_VIEW_ACTIVITY")) + val scrollableObject = onView { isScrollable } - val scrollableObject = device.findObject(By.scrollable(true)) - if (scrollableObject == null) { - TestCase.fail("No scrollable view found in hierarchy") - } - scrollableObject.setGestureMargin(device.displayWidth / 10) - scrollableObject?.apply { - repeat(2) { - fling(Direction.DOWN) - } - repeat(2) { - fling(Direction.UP) + scrollableObject.setGestureMargin(device.displayWidth / 10) + + scrollableObject.apply { + repeat(2) { + fling(Direction.DOWN) + } + repeat(2) { + fling(Direction.UP) + } } } } diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/FullyDrawnStartupBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/FullyDrawnStartupBenchmark.kt index 576f577a..3e9c9774 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/FullyDrawnStartupBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/FullyDrawnStartupBenchmark.kt @@ -22,8 +22,7 @@ import androidx.benchmark.macro.StartupTimingMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.uiautomator.By -import androidx.test.uiautomator.Until +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE import org.junit.Rule @@ -43,12 +42,15 @@ class FullyDrawnStartupBenchmark { startupMode = StartupMode.COLD, iterations = DEFAULT_ITERATIONS, ) { - val intent = Intent("$TARGET_PACKAGE.FULLY_DRAWN_STARTUP_ACTIVITY") - // Waits for first rendered frame - startActivityAndWait(intent) + uiAutomator { + val intent = Intent("$TARGET_PACKAGE.FULLY_DRAWN_STARTUP_ACTIVITY") - // Waits for an element that corresponds to fully drawn state - device.wait(Until.hasObject(By.text("Fully Drawn")), 10_000) + // Waits for first rendered frame + startIntent(intent) + + // Waits for an element that corresponds to fully drawn state + onView { text == "Fully Drawn" }.click() + } } } diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/SampleStartupBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/SampleStartupBenchmark.kt index 2f299059..ae679420 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/SampleStartupBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/SampleStartupBenchmark.kt @@ -20,6 +20,7 @@ import androidx.benchmark.macro.StartupTimingMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE import org.junit.Rule @@ -44,7 +45,9 @@ class SampleStartupBenchmark { } ) { // starts default launch activity - startActivityAndWait() + uiAutomator { + startApp() + } } } // [END macrobenchmark_startup] diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/SmallListStartupBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/SmallListStartupBenchmark.kt index 47cf897a..3b3f89de 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/SmallListStartupBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/SmallListStartupBenchmark.kt @@ -21,6 +21,7 @@ import androidx.benchmark.macro.StartupMode import androidx.benchmark.macro.StartupTimingMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.filters.LargeTest +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE import org.junit.Rule @@ -49,10 +50,11 @@ class SmallListStartupBenchmark( pressHome() } ) { - val intent = Intent("$packageName.RECYCLER_VIEW_ACTIVITY") - intent.putExtra("ITEM_COUNT", LIST_ITEMS) - - startActivityAndWait(intent) + uiAutomator { + val intent = Intent("$packageName.RECYCLER_VIEW_ACTIVITY") + intent.putExtra("ITEM_COUNT", LIST_ITEMS) + startIntent(intent) + } } @Test @@ -66,10 +68,11 @@ class SmallListStartupBenchmark( pressHome() } ) { - val intent = Intent("$packageName.COMPOSE_ACTIVITY") - intent.putExtra("ITEM_COUNT", LIST_ITEMS) - - startActivityAndWait(intent) + uiAutomator { + val intent = Intent("$packageName.COMPOSE_ACTIVITY") + intent.putExtra("ITEM_COUNT", LIST_ITEMS) + startIntent(intent) + } } companion object { diff --git a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/StartupBenchmark.kt b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/StartupBenchmark.kt index 0da8cfb8..1dc55e9c 100644 --- a/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/StartupBenchmark.kt +++ b/MacrobenchmarkSample/macrobenchmark/src/main/kotlin/com/example/macrobenchmark/benchmark/startup/StartupBenchmark.kt @@ -21,8 +21,8 @@ import androidx.benchmark.macro.CompilationMode import androidx.benchmark.macro.StartupMode import androidx.benchmark.macro.StartupTimingMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule -import androidx.test.filters.SdkSuppress import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.uiautomator.uiAutomator import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE import org.junit.Rule @@ -60,11 +60,9 @@ abstract class AbstractStartupBenchmark(private val startupMode: StartupMode) { val benchmarkRule = MacrobenchmarkRule() @Test - @SdkSuppress(minSdkVersion = 24) fun startupNoCompilation() = startup(CompilationMode.None()) @Test - @SdkSuppress(minSdkVersion = 24) fun startupPartialCompilation() = startup( CompilationMode.Partial( baselineProfileMode = BaselineProfileMode.Disable, @@ -73,7 +71,6 @@ abstract class AbstractStartupBenchmark(private val startupMode: StartupMode) { ) @Test - @SdkSuppress(minSdkVersion = 24) fun startupPartialWithBaselineProfiles() = startup(CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require)) @@ -90,6 +87,8 @@ abstract class AbstractStartupBenchmark(private val startupMode: StartupMode) { pressHome() } ) { - startActivityAndWait() + uiAutomator { + startApp() + } } } \ No newline at end of file diff --git a/MacrobenchmarkSample/settings.gradle.kts b/MacrobenchmarkSample/settings.gradle.kts index f5541302..fb332303 100644 --- a/MacrobenchmarkSample/settings.gradle.kts +++ b/MacrobenchmarkSample/settings.gradle.kts @@ -24,6 +24,10 @@ pluginManagement { google() mavenCentral() gradlePluginPortal() + maven { + url = uri("https://androidx.dev/snapshots/builds/13274276/artifacts/repository") + } + } } dependencyResolutionManagement { @@ -31,5 +35,9 @@ dependencyResolutionManagement { google() mavenCentral() gradlePluginPortal() + maven { + url = uri("https://androidx.dev/snapshots/builds/13274276/artifacts/repository") + } + } }