Merge "Dump imgdiag data for persistent processes" into main
diff --git a/test_scripts/src/main/java/com/android/art/targetprep/AllProcessesImgdiag.java b/test_scripts/src/main/java/com/android/art/targetprep/AllProcessesImgdiag.java
new file mode 100644
index 0000000..d0a9b29
--- /dev/null
+++ b/test_scripts/src/main/java/com/android/art/targetprep/AllProcessesImgdiag.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.art.targetprep;
+
+import com.android.art.tests.AppLaunchImgdiagTest;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.log.ITestLogger;
+import com.android.tradefed.result.FileInputStreamSource;
+import com.android.tradefed.result.ITestLoggerReceiver;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.targetprep.ITargetPreparer;
+
+import org.junit.Assert;
+
+import java.io.File;
+
+/** Collect imgdiag data from all zygote children at the end of the run. */
+public class AllProcessesImgdiag implements ITestLoggerReceiver, ITargetPreparer {
+ @Option(
+ name = "imgdiag-out-path",
+ description = "Path to directory containing imgdiag output files.")
+ private String mImgdiagOutPath;
+
+ private ITestLogger mTestLogger;
+
+ @Override
+ public void setTestLogger(ITestLogger testLogger) {
+ mTestLogger = testLogger;
+ }
+
+ @Override
+ public void setUp(TestInformation testInformation) {}
+
+ @Override
+ public void tearDown(TestInformation testInformation, Throwable e)
+ throws DeviceNotAvailableException {
+ Assert.assertTrue(testInformation.getDevice().doesFileExist(mImgdiagOutPath));
+
+ String zygoteChildren =
+ testInformation
+ .getDevice()
+ .executeShellCommand("ps --ppid `pidof zygote64` -o pid,args");
+
+ // Skip "PID ARGS" header.
+ for (String line : zygoteChildren.lines().skip(1).toList()) {
+ String[] vals = line.strip().split("\\s+");
+ Assert.assertEquals(2, vals.length);
+
+ String targetPid = vals[0];
+ String targetName = vals[1];
+
+ String outFileName = String.format("imgdiag_%s_%s.txt", targetName, targetPid);
+ String outFilePath = new File(mImgdiagOutPath, outFileName).getAbsolutePath();
+
+ String imgdiagCmd = AppLaunchImgdiagTest.getImgdiagRunCmd(targetPid, outFilePath);
+ testInformation.getDevice().executeShellCommand(imgdiagCmd);
+
+ File imgdiagFile = testInformation.getDevice().pullFile(outFilePath);
+ mTestLogger.testLog(
+ outFileName, LogDataType.HOST_LOG, new FileInputStreamSource(imgdiagFile));
+ }
+ }
+}
diff --git a/test_scripts/src/main/java/com/android/art/tests/AppLaunchImgdiagTest.java b/test_scripts/src/main/java/com/android/art/tests/AppLaunchImgdiagTest.java
index 853bf1e..08b9344 100644
--- a/test_scripts/src/main/java/com/android/art/tests/AppLaunchImgdiagTest.java
+++ b/test_scripts/src/main/java/com/android/art/tests/AppLaunchImgdiagTest.java
@@ -48,18 +48,13 @@
String outFileName = String.format("imgdiag_%s_%s.txt", mPackageName, targetPid);
String outFilePath = new File(mImgdiagOutPath, outFileName).getAbsolutePath();
- String imgdiagCmd =
- String.format(
- "imgdiag --zygote-diff-pid=`pidof zygote64` --image-diff-pid=%2$s"
- + " --output="
- + outFilePath
- + " --dump-dirty-objects --boot-image="
- + "/data/misc/apexdata/com.android.art/dalvik-cache/boot.art",
- mPackageName,
- targetPid);
+ String imgdiagCmd = getImgdiagRunCmd(targetPid, outFilePath);
CommandResult res = getDevice().executeShellV2Command(imgdiagCmd);
Assert.assertEquals(
- "Failed to run imgdiag. " + res.toString(), CommandStatus.SUCCESS, res.getStatus());
+ String.format(
+ "Failed to run imgdiag:\n%s\nResult:\n%s", imgdiagCmd, res.toString()),
+ CommandStatus.SUCCESS,
+ res.getStatus());
File imgdiagFile = getDevice().pullFile(outFilePath);
TestUtils testUtils = TestUtils.getInstance(getTestInformation(), mLogData);
@@ -69,4 +64,21 @@
super.tearDown();
}
+
+ /**
+ * Constructs the command line string to run the `imgdiag` tool for gathering dirty image
+ * objects.
+ *
+ * @param targetPid The process ID of the target process to analyze.
+ * @param outFilePath The absolute file path on the device where the imgdiag data will be saved.
+ * @return The complete `imgdiag` command that can be run with `adb shell`.
+ */
+ public static String getImgdiagRunCmd(String targetPid, String outFilePath) {
+ return String.format(
+ "imgdiag --zygote-diff-pid=`pidof zygote64` --image-diff-pid=%s"
+ + " --output=%s"
+ + " --dump-dirty-objects --boot-image="
+ + "/data/misc/apexdata/com.android.art/dalvik-cache/boot.art",
+ targetPid, outFilePath);
+ }
}
diff --git a/test_targets/imgdiag-app-launch/plan.xml b/test_targets/imgdiag-app-launch/plan.xml
index 9f7158b..163c79a 100644
--- a/test_targets/imgdiag-app-launch/plan.xml
+++ b/test_targets/imgdiag-app-launch/plan.xml
@@ -18,6 +18,9 @@
<option name="run-command" value="mkdir /data/local/tmp/imgdiag_out/"/>
<option name="teardown-command" value="rm -r /data/local/tmp/imgdiag_out/"/>
</target_preparer>
+ <target_preparer class="com.android.art.targetprep.AllProcessesImgdiag">
+ <option name="imgdiag-out-path" value="/data/local/tmp/imgdiag_out/"/>
+ </target_preparer>
<target_preparer class="com.android.art.targetprep.AggregateImgdiagOutput">
<option name="imgdiag-out-path" value="/data/local/tmp/imgdiag_out/"/>
</target_preparer>