diff options
Diffstat (limited to 'apct-tests')
4 files changed, 118 insertions, 8 deletions
diff --git a/apct-tests/perftests/core/AndroidTest.xml b/apct-tests/perftests/core/AndroidTest.xml index 1b289130124f..478cfc1fe811 100644 --- a/apct-tests/perftests/core/AndroidTest.xml +++ b/apct-tests/perftests/core/AndroidTest.xml @@ -25,4 +25,9 @@ <option name="package" value="com.android.perftests.core" /> <option name="hidden-api-checks" value="false"/> </test> + + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="directory-keys" value="/data/local/CorePerfTests" /> + <option name="collect-on-run-ended-only" value="true" /> + </metrics_collector> </configuration> diff --git a/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java index 27790e649a26..a22a638fd32e 100644 --- a/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java +++ b/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java @@ -44,7 +44,11 @@ import org.junit.Rule; import org.junit.Test; @LargeTest -public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase { +public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase + implements ManualBenchmarkState.CustomizedIterationListener { + + private static final int PROFILED_ITERATIONS = 2; + @Rule public final PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter(); @@ -59,10 +63,24 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase { sUiAutomation.dropShellPermissionIdentity(); } + /** The last {@link #PROFILED_ITERATIONS} will provide the information of method profiling. */ + @Override + public void onStart(int iteration) { + startProfiling(WindowAddRemovePerfTest.class.getSimpleName() + + "_MethodTracing_" + iteration + ".trace"); + } + + @Override + public void onFinished(int iteration) { + stopProfiling(); + } + @Test @ManualBenchmarkTest(warmupDurationNs = TIME_1_S_IN_NS, targetTestDurationNs = TIME_5_S_IN_NS) public void testAddRemoveWindow() throws Throwable { - new TestWindow().runBenchmark(mPerfStatusReporter.getBenchmarkState()); + final ManualBenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + state.setCustomizedIterations(PROFILED_ITERATIONS, this); + new TestWindow().runBenchmark(state); } private static class TestWindow extends BaseIWindow { @@ -102,6 +120,7 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase { state.addExtraResult("remove", elapsedTimeNsOfRemove); elapsedTimeNs = elapsedTimeNsOfAdd + elapsedTimeNsOfRemove; + inputChannel.dispose(); } } } diff --git a/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java b/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java index 4d278c3c2d9a..62e9ba84530c 100644 --- a/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java +++ b/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java @@ -21,6 +21,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import android.app.Activity; import android.app.UiAutomation; import android.content.Intent; +import android.os.ParcelFileDescriptor; import android.perftests.utils.PerfTestActivity; import androidx.test.rule.ActivityTestRule; @@ -32,6 +33,10 @@ import org.junit.BeforeClass; import org.junit.runner.Description; import org.junit.runners.model.Statement; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.concurrent.TimeUnit; public class WindowManagerPerfTestBase { @@ -40,16 +45,54 @@ public class WindowManagerPerfTestBase { static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S; static final long TIME_5_S_IN_NS = 5 * NANOS_PER_S; + /** + * The out directory matching the directory-keys of collector in AndroidTest.xml. The directory + * is in /data because while enabling method profling of system server, it cannot write the + * trace to external storage. + */ + static final File BASE_OUT_PATH = new File("/data/local/CorePerfTests"); + @BeforeClass public static void setUpOnce() { + if (!BASE_OUT_PATH.exists()) { + executeShellCommand("mkdir -p " + BASE_OUT_PATH); + } // In order to be closer to the real use case. - sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP"); - sUiAutomation.executeShellCommand("wm dismiss-keyguard"); + executeShellCommand("input keyevent KEYCODE_WAKEUP"); + executeShellCommand("wm dismiss-keyguard"); getInstrumentation().getContext().startActivity(new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } /** + * Executes shell command with reading the output. It may also used to block until the current + * command is completed. + */ + static ByteArrayOutputStream executeShellCommand(String command) { + final ParcelFileDescriptor pfd = sUiAutomation.executeShellCommand(command); + final byte[] buf = new byte[512]; + final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + int bytesRead; + try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { + while ((bytesRead = fis.read(buf)) != -1) { + bytes.write(buf, 0, bytesRead); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return bytes; + } + + /** Starts method tracing on system server. */ + void startProfiling(String subPath) { + executeShellCommand("am profile start system " + new File(BASE_OUT_PATH, subPath)); + } + + void stopProfiling() { + executeShellCommand("am profile stop system"); + } + + /** * Provides an activity that keeps screen on and is able to wait for a stable lifecycle stage. */ static class PerfTestActivityRule extends ActivityTestRule<PerfTestActivity> { diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java index a83254b463f4..b07523976bfe 100644 --- a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java +++ b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java @@ -88,6 +88,15 @@ public final class ManualBenchmarkState { int[] percentiles() default {}; } + /** The interface to receive the events of customized iteration. */ + public interface CustomizedIterationListener { + /** The customized iteration starts. */ + void onStart(int iteration); + + /** The customized iteration finished. */ + void onFinished(int iteration); + } + /** It means the entire {@link StatsReport} is not given. */ private static final int DEFAULT_STATS_REPORT = -2; @@ -105,7 +114,8 @@ public final class ManualBenchmarkState { private static final int NOT_STARTED = 0; // The benchmark has not started yet. private static final int WARMUP = 1; // The benchmark is warming up. private static final int RUNNING = 2; // The benchmark is running. - private static final int FINISHED = 3; // The benchmark has stopped. + private static final int RUNNING_CUSTOMIZED = 3; // Running for customized measurement. + private static final int FINISHED = 4; // The benchmark has stopped. private int mState = NOT_STARTED; // Current benchmark state. @@ -116,6 +126,14 @@ public final class ManualBenchmarkState { private int mMaxIterations = 0; + /** + * Additinal iteration that used to apply customized measurement. The result during these + * iterations won't be counted into {@link #mStats}. + */ + private int mMaxCustomizedIterations; + private int mCustomizedIterations; + private CustomizedIterationListener mCustomizedIterationListener; + // Individual duration in nano seconds. private ArrayList<Long> mResults = new ArrayList<>(); @@ -189,10 +207,25 @@ public final class ManualBenchmarkState { final boolean keepRunning = mResults.size() < mMaxIterations; if (!keepRunning) { mStats = new Stats(mResults); + if (mMaxCustomizedIterations > 0 && mCustomizedIterationListener != null) { + mState = RUNNING_CUSTOMIZED; + mCustomizedIterationListener.onStart(mCustomizedIterations); + return true; + } mState = FINISHED; } return keepRunning; } + case RUNNING_CUSTOMIZED: { + mCustomizedIterationListener.onFinished(mCustomizedIterations); + mCustomizedIterations++; + if (mCustomizedIterations >= mMaxCustomizedIterations) { + mState = FINISHED; + return false; + } + mCustomizedIterationListener.onStart(mCustomizedIterations); + return true; + } case FINISHED: throw new IllegalStateException("The benchmark has finished."); default: @@ -210,11 +243,21 @@ public final class ManualBenchmarkState { } /** - * Adds additional result while this benchmark isn't warming up. It is used when a sequence of - * operations is executed consecutively, the duration of each operation can also be recorded. + * This is used to run the benchmark with more information by enabling some debug mechanism but + * we don't want to account the special runs (slower) in the stats report. + */ + public void setCustomizedIterations(int iterations, CustomizedIterationListener listener) { + mMaxCustomizedIterations = iterations; + mCustomizedIterationListener = listener; + } + + /** + * Adds additional result while this benchmark isn't warming up or running in customized state. + * It is used when a sequence of operations is executed consecutively, the duration of each + * operation can also be recorded. */ public void addExtraResult(String key, long duration) { - if (isWarmingUp()) { + if (isWarmingUp() || mState == RUNNING_CUSTOMIZED) { return; } if (mExtraResults == null) { |