Merge "Migrate Test Targets to New Android Ownership Model" into main
diff --git a/src/com/android/monkey/MonkeyBase.java b/src/com/android/monkey/MonkeyBase.java
index 552c3b6..25cd98c 100644
--- a/src/com/android/monkey/MonkeyBase.java
+++ b/src/com/android/monkey/MonkeyBase.java
@@ -18,13 +18,10 @@
 
 import com.android.ddmlib.CollectingOutputReceiver;
 import com.android.ddmlib.IShellOutputReceiver;
-import com.android.loganalysis.item.AnrItem;
 import com.android.loganalysis.item.BugreportItem;
 import com.android.loganalysis.item.MiscKernelLogItem;
-import com.android.loganalysis.item.MonkeyLogItem;
 import com.android.loganalysis.parser.BugreportParser;
 import com.android.loganalysis.parser.KernelLogParser;
-import com.android.loganalysis.parser.MonkeyLogParser;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.Option.Importance;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -56,7 +53,6 @@
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -259,38 +255,8 @@
             description = "Enable a continuous circular buffer to collect atrace information")
     private boolean mAtraceEnabled = false;
 
-    // options for generating ANR report via post processing script
-    @Option(name = "generate-anr-report", description = "Generate ANR report via post-processing")
-    private boolean mGenerateAnrReport = false;
-
-    @Option(
-            name = "anr-report-script",
-            description = "Path to the script for monkey ANR " + "report generation.")
-    private String mAnrReportScriptPath = null;
-
-    @Option(
-            name = "anr-report-storage-backend-base-path",
-            description = "Base path to the storage " + "backend used for saving the reports")
-    private String mAnrReportBasePath = null;
-
-    @Option(
-            name = "anr-report-storage-backend-url-prefix",
-            description =
-                    "URL prefix for the "
-                            + "storage backend that would enable web acess to the stored reports.")
-    private String mAnrReportUrlPrefix = null;
-
-    @Option(
-            name = "anr-report-storage-path",
-            description =
-                    "Sub path under the base storage "
-                            + "location for generated monkey ANR reports.")
-    private String mAnrReportPath = null;
-
     private ITestDevice mTestDevice = null;
-    private MonkeyLogItem mMonkeyLog = null;
     private BugreportItem mBugreport = null;
-    private AnrReportGenerator mAnrGen = null;
 
     /** {@inheritDoc} */
     @Override
@@ -327,7 +293,7 @@
         return LAUNCH_APP_CMD + extras;
     }
 
-    /** Run the monkey one time and return a {@link MonkeyLogItem} for the run. */
+    /** Run the monkey one time. */
     protected void runMonkey(ITestInvocationListener listener) throws DeviceNotAvailableException {
         ITestDevice device = getDevice();
         if (mRebootDevice) {
@@ -383,18 +349,6 @@
             CircularAtraceUtil.startTrace(getDevice(), null, 10);
         }
 
-        if (mGenerateAnrReport) {
-            mAnrGen =
-                    new AnrReportGenerator(
-                            mAnrReportScriptPath,
-                            mAnrReportBasePath,
-                            mAnrReportUrlPrefix,
-                            mAnrReportPath,
-                            mTestDevice.getBuildId(),
-                            mTestDevice.getBuildFlavor(),
-                            mTestDevice.getSerialNumber());
-        }
-
         try {
             onMonkeyStart();
             commandHelper.runCommand(mTestDevice, command, getMonkeyTimeoutMs());
@@ -433,25 +387,14 @@
                                 uptimeAfter,
                                 duration / 1000 / 60,
                                 duration / 1000 % 60));
-                mMonkeyLog = createMonkeyLog(listener, MONKEY_LOG_NAME, outputBuilder.toString());
+                listener.testLog(
+                        MONKEY_LOG_NAME,
+                        LogDataType.MONKEY_LOG,
+                        new ByteArrayInputStreamSource(outputBuilder.toString().getBytes()));
 
-                boolean isAnr = mMonkeyLog.getCrash() instanceof AnrItem;
-                if (mAtraceEnabled && isAnr) {
-                    // This was identified as an ANR; post atrace data
+                if (mAtraceEnabled) {
                     listener.testLog("circular-atrace", LogDataType.TEXT, atraceStream);
                 }
-                if (mAnrGen != null) {
-                    if (isAnr) {
-                        if (!mAnrGen.genereateAnrReport(listener)) {
-                            CLog.w("Failed to post-process ANR.");
-                        } else {
-                            CLog.i("Successfully post-processed ANR.");
-                        }
-                        mAnrGen.cleanTempFiles();
-                    } else {
-                        CLog.d("ANR post-processing enabled but no ANR detected.");
-                    }
-                }
                 StreamUtil.cancel(atraceStream);
             }
         }
@@ -478,8 +421,6 @@
                 }
             }
         }
-
-        checkResults();
     }
 
     /** A hook to allow subclasses to perform actions just before the monkey starts. */
@@ -522,10 +463,6 @@
                 CLog.e("Bugreport has no main file");
                 return null;
             }
-            if (mAnrGen != null) {
-                is = new FileInputStreamSource(main);
-                mAnrGen.setBugReportInfo(is);
-            }
             return new BugreportParser().parse(new BufferedReader(new FileReader(main)));
         } catch (IOException e) {
             CLog.e("Could not process bugreport");
@@ -551,23 +488,6 @@
         }
     }
 
-    /** Create the monkey log, parse it, and send it to a listener. */
-    protected MonkeyLogItem createMonkeyLog(
-            ITestInvocationListener listener, String monkeyLogName, String log) {
-        try (InputStreamSource source = new ByteArrayInputStreamSource(log.getBytes())) {
-            if (mAnrGen != null) {
-                mAnrGen.setMonkeyLogInfo(source);
-            }
-            listener.testLog(monkeyLogName, LogDataType.MONKEY_LOG, source);
-            return new MonkeyLogParser()
-                    .parse(new BufferedReader(new InputStreamReader(source.createInputStream())));
-        } catch (IOException e) {
-            CLog.e("Could not process monkey log.");
-            CLog.e(e);
-            return null;
-        }
-    }
-
     /**
      * A helper method to build a monkey command given the specified arguments.
      *
@@ -711,43 +631,6 @@
         return mTestDevice;
     }
 
-    /** Check the results and return if valid or throw an assertion error if not valid. */
-    private void checkResults() {
-        Assert.assertNotNull("Monkey log is null", mMonkeyLog);
-        Assert.assertNotNull("Bugreport is null", mBugreport);
-        Assert.assertNotNull("Bugreport is empty", mBugreport.getTime());
-
-        // If there are no activities, retrying the test won't matter.
-        if (mMonkeyLog.getNoActivities()) {
-            return;
-        }
-
-        Assert.assertNotNull("Start uptime is missing", mMonkeyLog.getStartUptimeDuration());
-        Assert.assertNotNull("Stop uptime is missing", mMonkeyLog.getStopUptimeDuration());
-        Assert.assertNotNull("Total duration is missing", mMonkeyLog.getTotalDuration());
-
-        long startUptime = mMonkeyLog.getStartUptimeDuration();
-        long stopUptime = mMonkeyLog.getStopUptimeDuration();
-        long totalDuration = mMonkeyLog.getTotalDuration();
-
-        Assert.assertTrue(
-                "Uptime failure", stopUptime - startUptime > totalDuration - UPTIME_BUFFER);
-
-        // False count
-        Assert.assertFalse(
-                "False count",
-                mMonkeyLog.getIsFinished()
-                        && mMonkeyLog.getTargetCount() - mMonkeyLog.getIntermediateCount() > 100);
-
-        // Monkey finished or crashed, so don't fail
-        if (mMonkeyLog.getIsFinished() || mMonkeyLog.getFinalCount() != null) {
-            return;
-        }
-
-        // Missing count
-        Assert.fail("Missing count");
-    }
-
     /** Get the monkey timeout in milliseconds */
     protected long getMonkeyTimeoutMs() {
         return (mPerEventTimeout + mThrottle) * mTargetCount;
diff --git a/src/com/android/performance/tests/BootTimeTest.java b/src/com/android/performance/tests/BootTimeTest.java
index 1ef102b..ebc0fff 100644
--- a/src/com/android/performance/tests/BootTimeTest.java
+++ b/src/com/android/performance/tests/BootTimeTest.java
@@ -109,7 +109,7 @@
     private static final String LOGCAT_FILE = "Successive_reboots_logcat";
     private static final String LOGCAT_UNLOCK_FILE = "Successive_reboots_unlock_logcat";
     private static final String BOOT_COMPLETE_ACTION = "sys.boot_completed=1";
-    private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+    private static final String RUNNER = "androidx.test.runner.AndroidJUnitRunner";
     private static final String PACKAGE_NAME = "com.android.boothelper";
     private static final String CLASS_NAME = "com.android.boothelper.BootHelperTest";
     private static final String SETUP_PIN_TEST = "setupLockScreenPin";
@@ -192,6 +192,8 @@
                     "Logging for this PID.*\\s+([0-9]+)$",
                     Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
 
+    private static final String METRIC_COUNT = "MetricCount";
+
     @Option(name = "test-run-name", description = "run name to report to result reporters")
     private String mTestRunName = BOOTTIME_TEST;
 
@@ -245,6 +247,12 @@
     private long mBootDelayTime = 2000;
 
     @Option(
+            name = "after-boot-delay",
+            isTimeVal = true,
+            description = "Time to wait immediately after the successive boots.")
+    private long mAfterBootDelayTime = 0;
+
+    @Option(
             name = "post-initial-boot-idle",
             isTimeVal = true,
             description =
@@ -334,6 +342,13 @@
             description = "Run logcat --statistics command and collect data")
     private boolean mCollectLogcat = false;
 
+    @Option(
+            name = "metric-prefix-pattern-for-count",
+            description =
+                    "A list of metric prefix pattern that will be used to count number of metrics"
+                            + " generated in the test")
+    private List<String> mMetricPrefixPatternForCount = new ArrayList<>();
+
     private IBuildInfo mBuildInfo;
     private IConfiguration mConfiguration;
     private TestInformation mTestInfo;
@@ -412,6 +427,9 @@
         mTestInfo = testInfo;
         long start = System.currentTimeMillis();
         listener.testRunStarted(mTestRunName, 1);
+        for (IMetricCollector collector : mCollectors) {
+            listener = collector.init(mInvocationContext, listener);
+        }
         try {
             try {
                 // Set the current date from the host in test device.
@@ -487,10 +505,13 @@
                         }
                         testSuccessiveBoots(true, listener);
                     } finally {
-                        try (InputStreamSource logcatData = mRebootLogcatReceiver.getLogcatData()) {
-                            listener.testLog(LOGCAT_UNLOCK_FILE, LogDataType.TEXT, logcatData);
+                        if (null != mRebootLogcatReceiver) {
+                            try (InputStreamSource logcatData =
+                                    mRebootLogcatReceiver.getLogcatData()) {
+                                listener.testLog(LOGCAT_UNLOCK_FILE, LogDataType.TEXT, logcatData);
+                            }
+                            mRebootLogcatReceiver.stop();
                         }
-                        mRebootLogcatReceiver.stop();
                         listener.testStarted(successiveBootUnlockTestId);
                         listener.testEnded(successiveBootUnlockTestId, successiveBootUnlockResult);
                     }
@@ -598,9 +619,6 @@
             throws DeviceNotAvailableException {
         CLog.v("Waiting for %d msecs before successive boots.", mBootDelayTime);
         getRunUtil().sleep(mBootDelayTime);
-        for (IMetricCollector collector : mCollectors) {
-            listener = collector.init(mInvocationContext, listener);
-        }
         for (int count = 0; count < mBootCount; count++) {
             getDevice().enableAdbRoot();
             // Property used for collecting the perfetto trace file on boot.
@@ -620,10 +638,14 @@
             double onlineTime = INVALID_TIME_DURATION;
             double bootTime = INVALID_TIME_DURATION;
             String testId = String.format("%s.%s$%d", BOOTTIME_TEST, BOOTTIME_TEST, (count + 1));
-            TestDescription successiveBootIterationTestId =
-                    new TestDescription(testId, String.format("%s", SUCCESSIVE_BOOT_TEST));
-            if (mBootTimePerIteration) {
-                listener.testStarted(successiveBootIterationTestId);
+            TestDescription successiveBootIterationTestId;
+            if (!dismissPin) {
+                successiveBootIterationTestId =
+                        new TestDescription(testId, String.format("%s", SUCCESSIVE_BOOT_TEST));
+            } else {
+                successiveBootIterationTestId =
+                        new TestDescription(
+                                testId, String.format("%s", SUCCESSIVE_BOOT_UNLOCK_TEST));
             }
             if (mGranularBootInfo || dismissPin) {
                 clearAndStartLogcat();
@@ -677,12 +699,17 @@
             if (mBootloaderInfo) analyzeBootloaderTimingInfo();
 
             if (dismissPin) {
+                getRunUtil().sleep(2000);
                 mRunner = createRemoteAndroidTestRunner(UNLOCK_PIN_TEST);
                 getDevice().runInstrumentationTests(mRunner, new CollectingTestListener());
-                // Wait for 15 secs after every unlock to make sure home screen is loaded
-                // and logs are printed
-                getRunUtil().sleep(15000);
             }
+
+            if (mBootTimePerIteration) {
+                listener.testStarted(successiveBootIterationTestId);
+            }
+
+            CLog.v("Waiting for %d msecs immediately after successive boot.", mAfterBootDelayTime);
+            getRunUtil().sleep(mAfterBootDelayTime);
             if (onlineTime != INVALID_TIME_DURATION) {
                 if (mBootInfo.containsKey(SUCCESSIVE_ONLINE)) {
                     mBootInfo.get(SUCCESSIVE_ONLINE).add(onlineTime);
@@ -739,6 +766,22 @@
                 if (!collectLogcatInfoResult.isEmpty()) {
                     iterationResult.putAll(collectLogcatInfoResult);
                 }
+                // If  metric-prefix-pattern-for-count is present, calculate the count
+                // of all metrics with the prefix pattern and add the count as a new metric to the
+                // iterationResult map.
+                if (!mMetricPrefixPatternForCount.isEmpty()) {
+                    for (String metricPrefixPattern : mMetricPrefixPatternForCount) {
+                        long metricCount =
+                                iterationResult.entrySet().stream()
+                                        .filter(
+                                                (entry) ->
+                                                        entry.getKey()
+                                                                .startsWith(metricPrefixPattern))
+                                        .count();
+                        iterationResult.put(
+                                metricPrefixPattern + METRIC_COUNT, Long.toString(metricCount));
+                    }
+                }
                 listener.testEnded(successiveBootIterationTestId, iterationResult);
             }
 
@@ -848,10 +891,13 @@
                 Matcher matcherPid = LOGCAT_STATISTICS_PID_PATTERN.matcher(outputList[i]);
                 pidFound = matcherPid.find();
                 if (!pidFound) continue;
-                CLog.d("logcat statistics pid %d output = %s", pid, outputList[i]);
+                CLog.d(
+                        "Process %s with pid %d : logcat statistics output = %s",
+                        processName, pid, outputList[i]);
                 results.put(
                         String.join(METRIC_KEY_SEPARATOR, LOGCAT_STATISTICS_SIZE, processName),
                         matcherPid.group(1).trim());
+                break;
             }
             if (!pidFound) {
                 // the process doesn't found in the logcat statistics output
@@ -860,7 +906,6 @@
                         processName, pid);
             }
         }
-
         return results;
     }