Loading apct-tests/perftests/core/AndroidTest.xml +5 −0 Original line number Diff line number Diff line Loading @@ -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> apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java +21 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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 { Loading Loading @@ -102,6 +120,7 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase { state.addExtraResult("remove", elapsedTimeNsOfRemove); elapsedTimeNs = elapsedTimeNsOfAdd + elapsedTimeNsOfRemove; inputChannel.dispose(); } } } Loading apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java +45 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -40,15 +45,53 @@ 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. */ Loading apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java +47 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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<>(); Loading Loading @@ -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: Loading @@ -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) { Loading Loading
apct-tests/perftests/core/AndroidTest.xml +5 −0 Original line number Diff line number Diff line Loading @@ -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>
apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java +21 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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 { Loading Loading @@ -102,6 +120,7 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase { state.addExtraResult("remove", elapsedTimeNsOfRemove); elapsedTimeNs = elapsedTimeNsOfAdd + elapsedTimeNsOfRemove; inputChannel.dispose(); } } } Loading
apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java +45 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -40,15 +45,53 @@ 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. */ Loading
apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java +47 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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<>(); Loading Loading @@ -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: Loading @@ -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) { Loading