Merge "Allow to specify what to run coverage against"
diff --git a/atest/TEST_MAPPING b/atest/TEST_MAPPING
index cebe409..32e6a6d 100644
--- a/atest/TEST_MAPPING
+++ b/atest/TEST_MAPPING
@@ -1,6 +1,32 @@
 // Below lists the TEST_MAPPING tests to do ASuite unittests to make sure
 // the expectation of ASuite are still good.
 {
+  "mainline-presubmit": [
+    {
+      "name": "HelloWorldTests"
+    },
+    {
+      "name": "hello_world_test",
+      "host": true
+    },
+    {
+      "name": "CtsApacheHttpLegacy27ApiSignatureTestCases"
+    },
+    {
+      "name": "ziparchive-tests"
+    },
+    {
+      "name": "CtsDpiTestCases",
+      "options": [
+        {
+          "include-filter": "android.dpi.cts.ConfigurationScreenLayoutTest"
+        }
+      ]
+    },
+    {
+      "name": "CtsSampleHostTestCases"
+    }
+  ],
   "presubmit": [
     {
       // Host side ATest unittests.
diff --git a/device_build_interfaces/com/android/tradefed/device/INativeDevice.java b/device_build_interfaces/com/android/tradefed/device/INativeDevice.java
index 808c5fd..9ec2270 100644
--- a/device_build_interfaces/com/android/tradefed/device/INativeDevice.java
+++ b/device_build_interfaces/com/android/tradefed/device/INativeDevice.java
@@ -125,16 +125,6 @@
     public boolean setProperty(String propKey, String propValue) throws DeviceNotAvailableException;
 
     /**
-     * Retrieve the given fastboot variable value from the device.
-     *
-     * @param variableName the variable name
-     * @return the property value or <code>null</code> if it does not exist
-     * @throws DeviceNotAvailableException, UnsupportedOperationException
-     */
-    public String getFastbootVariable(String variableName)
-            throws DeviceNotAvailableException, UnsupportedOperationException;
-
-    /**
      * Convenience method to get the bootloader version of this device.
      * <p/>
      * Will attempt to retrieve bootloader version from the device's current state. (ie if device
@@ -935,16 +925,6 @@
     public void reboot(@Nullable String reason) throws DeviceNotAvailableException;
 
     /**
-     * Reboots the device into fastbootd mode.
-     *
-     * <p>Blocks until device is in fastbootd mode.
-     *
-     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
-     *     recovered.
-     */
-    public void rebootIntoFastbootd() throws DeviceNotAvailableException;
-
-    /**
      * Reboots only userspace part of device.
      *
      * <p>Blocks until device becomes available.
diff --git a/src/com/android/tradefed/config/RetryConfigurationFactory.java b/src/com/android/tradefed/config/RetryConfigurationFactory.java
index bbc8c0d..3a49cb8 100644
--- a/src/com/android/tradefed/config/RetryConfigurationFactory.java
+++ b/src/com/android/tradefed/config/RetryConfigurationFactory.java
@@ -49,7 +49,7 @@
         RetryRescheduler retryRunner = (RetryRescheduler) rerunner;
         retryRunner.setConfiguration(retryConfig);
         try {
-            retryRunner.run(null);
+            retryRunner.run(null, null);
             return retryRunner.getRetryConfiguration();
         } catch (Exception e) {
             throw new ConfigurationException(e.getMessage(), e);
diff --git a/src/com/android/tradefed/device/NativeDevice.java b/src/com/android/tradefed/device/NativeDevice.java
index 8e2d9f4..ee6c71d 100644
--- a/src/com/android/tradefed/device/NativeDevice.java
+++ b/src/com/android/tradefed/device/NativeDevice.java
@@ -632,9 +632,7 @@
         return prop;
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public String getFastbootVariable(String variableName)
+    private String getFastbootVariable(String variableName)
             throws DeviceNotAvailableException, UnsupportedOperationException {
         CommandResult result = executeFastbootCommand("getvar", variableName);
         if (result.getStatus() == CommandStatus.SUCCESS) {
@@ -2897,43 +2895,21 @@
     @Override
     public void rebootIntoBootloader()
             throws DeviceNotAvailableException, UnsupportedOperationException {
-        rebootIntoFastbootInternal(true);
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public void rebootIntoFastbootd()
-            throws DeviceNotAvailableException, UnsupportedOperationException {
-        rebootIntoFastbootInternal(false);
-    }
-
-    /**
-     * Reboots the device into bootloader or fastbootd mode.
-     *
-     * @param isBootloader: true to boot the device into bootloader mode, false to boot the device
-     *     into fastbootd mode.
-     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
-     *     recovered.
-     */
-    private void rebootIntoFastbootInternal(boolean isBootloader)
-            throws DeviceNotAvailableException {
-        final RebootMode mode =
-                isBootloader ? RebootMode.REBOOT_INTO_BOOTLOADER : RebootMode.REBOOT_INTO_FASTBOOT;
         if (!mFastbootEnabled) {
             throw new UnsupportedOperationException(
-                    String.format("Fastboot is not available and cannot reboot into %s", mode));
+                    "Fastboot is not available and cannot reboot into bootloader");
         }
         // If we go to bootloader, it's probably for flashing so ensure we re-check the provider
         mShouldSkipContentProviderSetup = false;
         CLog.i(
-                "Rebooting device %s in state %s into %s",
-                getSerialNumber(), getDeviceState(), mode);
+                "Rebooting device %s in state %s into bootloader",
+                getSerialNumber(), getDeviceState());
         if (TestDeviceState.FASTBOOT.equals(getDeviceState())) {
             CLog.i("device %s already in fastboot. Rebooting anyway", getSerialNumber());
-            executeFastbootCommand(String.format("reboot-%s", mode));
+            executeFastbootCommand("reboot-bootloader");
         } else {
-            CLog.i("Booting device %s into %s", getSerialNumber(), mode);
-            doAdbReboot(mode, null);
+            CLog.i("Booting device %s into bootloader", getSerialNumber());
+            doAdbRebootBootloader();
         }
         if (!mStateMonitor.waitForDeviceBootloader(mOptions.getFastbootTimeout())) {
             recoverDeviceFromBootloader();
diff --git a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
index d2dab70..cd3296e 100644
--- a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
+++ b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
@@ -102,12 +102,11 @@
     private List<String> mModuleArgs = new ArrayList<>();
 
     @Option(
-        name = TEST_ARG_OPTION,
-        description =
-                "the arguments to pass to a test. The expected format is"
-                        + "\"<test-class>:<arg-name>:[<arg-key>:=]<arg-value>\"",
-        importance = Importance.ALWAYS
-    )
+            name = TEST_ARG_OPTION,
+            description =
+                    "The arguments to pass to a test or its preparers. The expected format is"
+                            + "\"<test-class>:<arg-name>:[<arg-key>:=]<arg-value>\"",
+            importance = Importance.ALWAYS)
     private List<String> mTestArgs = new ArrayList<>();
 
     @Option(
diff --git a/src/com/android/tradefed/testtype/suite/ModuleListener.java b/src/com/android/tradefed/testtype/suite/ModuleListener.java
index 3dad444..f78d76f 100644
--- a/src/com/android/tradefed/testtype/suite/ModuleListener.java
+++ b/src/com/android/tradefed/testtype/suite/ModuleListener.java
@@ -111,15 +111,20 @@
     }
 
     /** Helper to log the test passed if it didn't fail. */
-    private void logTestPassed(String testName) {
+    private void logTestPassed(TestDescription testName) {
         if (!mTestFailed && !mCollectTestsOnly) {
+            String runName = "";
+            // Only print the run name in addition to test case fully qualified if different.
+            if (!testName.getClassName().startsWith(getCurrentRunResults().getName())) {
+                runName = getCurrentRunResults().getName() + " ";
+            }
+            String runAndTestCase = String.format("%s%s", runName, testName.toString());
             CLog.logAndDisplay(
                     LogLevel.INFO,
-                    "[%d/%d] %s %s pass",
+                    "[%d/%d] %s pass",
                     mTestsRan,
                     getExpectedTests(),
-                    getCurrentRunResults().getName(),
-                    testName);
+                    runAndTestCase);
         }
         mTestsRan++;
     }
@@ -133,7 +138,7 @@
     /** {@inheritDoc} */
     @Override
     public void testEnded(TestDescription test, long endTime, HashMap<String, Metric> testMetrics) {
-        logTestPassed(test.toString());
+        logTestPassed(test);
         super.testEnded(test, endTime, testMetrics);
     }
 
diff --git a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
index 0f40af6..c4cd8cc 100644
--- a/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
+++ b/src/com/android/tradefed/testtype/suite/SuiteModuleLoader.java
@@ -64,7 +64,7 @@
 public class SuiteModuleLoader {
 
     public static final String CONFIG_EXT = ".config";
-    private Map<String, List<OptionDef>> mTestOptions = new HashMap<>();
+    private Map<String, List<OptionDef>> mTestOrPreparerOptions = new HashMap<>();
     private Map<String, List<OptionDef>> mModuleOptions = new HashMap<>();
     private boolean mIncludeAll;
     private Map<String, List<SuiteTestFilter>> mIncludeFilters = new HashMap<>();
@@ -93,7 +93,7 @@
         mIncludeFilters = includeFilters;
         mExcludeFilters = excludeFilters;
 
-        parseArgs(testArgs, mTestOptions);
+        parseArgs(testArgs, mTestOrPreparerOptions);
         parseArgs(moduleArgs, mModuleOptions);
     }
 
@@ -620,6 +620,10 @@
         // Set target preparers
         List<ITargetPreparer> preparers = config.getTargetPreparers();
         for (ITargetPreparer preparer : preparers) {
+            String className = preparer.getClass().getName();
+            if (mTestOrPreparerOptions.containsKey(className)) {
+                config.injectOptionValues(mTestOrPreparerOptions.get(className));
+            }
             if (preparer instanceof IAbiReceiver) {
                 ((IAbiReceiver) preparer).setAbi(abi);
             }
@@ -629,8 +633,8 @@
         List<IRemoteTest> tests = config.getTests();
         for (IRemoteTest test : tests) {
             String className = test.getClass().getName();
-            if (mTestOptions.containsKey(className)) {
-                config.injectOptionValues(mTestOptions.get(className));
+            if (mTestOrPreparerOptions.containsKey(className)) {
+                config.injectOptionValues(mTestOrPreparerOptions.get(className));
             }
             addFiltersToTest(test, abi, fullId, mIncludeFilters, mExcludeFilters);
             if (test instanceof IAbiReceiver) {
diff --git a/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java b/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
index ad77eee..0709915 100644
--- a/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
+++ b/src/com/android/tradefed/testtype/suite/params/ModuleParameters.java
@@ -29,10 +29,9 @@
 
     public static final String INSTANT_APP_FAMILY = "instant_app_family";
     public static final String MULTI_ABI_FAMILY = "multi_abi_family";
+    public static final String SECONDARY_USER_FAMILY = "secondary_user_family";
     public static final String[] FAMILY_LIST =
-            new String[] {
-                INSTANT_APP_FAMILY, MULTI_ABI_FAMILY,
-            };
+            new String[] {INSTANT_APP_FAMILY, MULTI_ABI_FAMILY, SECONDARY_USER_FAMILY};
 
     private final String mName;
     /** Defines whether several module parameters are associated and mutually exclusive. */
diff --git a/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java b/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
index 96538ec..c1a10d7 100644
--- a/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
+++ b/src/com/android/tradefed/testtype/suite/retry/ResultsPlayer.java
@@ -22,6 +22,7 @@
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.StubDevice;
 import com.android.tradefed.invoker.IInvocationContext;
+import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.ILogSaverListener;
 import com.android.tradefed.result.ITestInvocationListener;
@@ -29,7 +30,6 @@
 import com.android.tradefed.result.TestDescription;
 import com.android.tradefed.result.TestResult;
 import com.android.tradefed.result.TestRunResult;
-import com.android.tradefed.testtype.IInvocationContextReceiver;
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.util.TimeUtil;
 
@@ -41,15 +41,13 @@
 import java.util.Map.Entry;
 
 /** Special runner that replays the results given to it. */
-public final class ResultsPlayer
-        implements IRemoteTest, IInvocationContextReceiver, IConfigurationReceiver {
+public final class ResultsPlayer implements IRemoteTest, IConfigurationReceiver {
 
     private class ReplayModuleHolder {
         public IInvocationContext mModuleContext;
         public List<Entry<TestDescription, TestResult>> mResults = new ArrayList<>();
     }
 
-    private IInvocationContext mContext;
     private Map<TestRunResult, ReplayModuleHolder> mModuleResult;
     private IConfiguration mConfiguration;
 
@@ -59,11 +57,12 @@
     }
 
     @Override
-    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+    public void run(TestInformation testInfo, ITestInvocationListener listener)
+            throws DeviceNotAvailableException {
         // Very first thing of the retry is to check whether all devices are available, this avoids
         // use wasting time replaying result for an invocation that will fail right after during
         // the re-run.
-        for (ITestDevice device : mContext.getDevices()) {
+        for (ITestDevice device : testInfo.getContext().getDevices()) {
             if (device.getIDevice() instanceof StubDevice) {
                 continue;
             }
@@ -83,9 +82,11 @@
 
             IInvocationContext moduleContext = holder.mModuleContext;
             if (moduleContext != null) {
-                for (String deviceName : mContext.getDeviceConfigNames()) {
-                    moduleContext.addAllocatedDevice(deviceName, mContext.getDevice(deviceName));
-                    moduleContext.addDeviceBuildInfo(deviceName, mContext.getBuildInfo(deviceName));
+                for (String deviceName : testInfo.getContext().getDeviceConfigNames()) {
+                    moduleContext.addAllocatedDevice(
+                            deviceName, testInfo.getContext().getDevice(deviceName));
+                    moduleContext.addDeviceBuildInfo(
+                            deviceName, testInfo.getContext().getBuildInfo(deviceName));
                 }
                 listener.testModuleStarted(moduleContext);
             }
@@ -141,12 +142,6 @@
 
     /** {@inheritDoc} */
     @Override
-    public void setInvocationContext(IInvocationContext invocationContext) {
-        mContext = invocationContext;
-    }
-
-    /** {@inheritDoc} */
-    @Override
     public void setConfiguration(IConfiguration configuration) {
         mConfiguration = configuration;
     }
diff --git a/src/com/android/tradefed/testtype/suite/retry/RetryRescheduler.java b/src/com/android/tradefed/testtype/suite/retry/RetryRescheduler.java
index e75267b..f7d917e 100644
--- a/src/com/android/tradefed/testtype/suite/retry/RetryRescheduler.java
+++ b/src/com/android/tradefed/testtype/suite/retry/RetryRescheduler.java
@@ -25,6 +25,7 @@
 import com.android.tradefed.config.Option.Importance;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.invoker.IRescheduler;
+import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.FileLogger;
 import com.android.tradefed.log.ILeveledLogOutput;
 import com.android.tradefed.log.LogUtil.CLog;
@@ -109,7 +110,10 @@
     private IConfiguration mRescheduledConfiguration;
 
     @Override
-    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+    public void run(
+            TestInformation testInfo /* do not use - should be null */,
+            ITestInvocationListener listener /* do not use - should be null */)
+            throws DeviceNotAvailableException {
         // Get the re-loader for previous results
         Object loader = mConfiguration.getConfigurationObject(PREVIOUS_LOADER_NAME);
         if (loader == null) {
diff --git a/test_framework/com/android/tradefed/targetprep/FastbootCommandPreparer.java b/test_framework/com/android/tradefed/targetprep/FastbootCommandPreparer.java
index 51baa0f..62df086 100644
--- a/test_framework/com/android/tradefed/targetprep/FastbootCommandPreparer.java
+++ b/test_framework/com/android/tradefed/targetprep/FastbootCommandPreparer.java
@@ -30,33 +30,13 @@
  */
 @OptionClass(alias = "fastboot-command-preparer")
 public class FastbootCommandPreparer extends BaseTargetPreparer {
-
-    private enum FastbootMode {
-        BOOTLOADER,
-        FASTBOOTD,
-    }
-
-    @Option(
-            name = "fastboot-mode",
-            description = "True to boot the device into bootloader mode, false for fastbootd mode.")
-    private FastbootMode mFastbootMode = FastbootMode.BOOTLOADER;
-
-    @Option(
-            name = "stay-fastboot",
-            description = "True to keep the device in bootloader or fastbootd mode.")
-    private boolean mStayFastboot = false;
-
     @Option(name = "command", description = "Fastboot commands to run.")
     private List<String> mFastbootCommands = new ArrayList<String>();
 
     @Override
     public void setUp(TestInformation testInformation)
             throws TargetSetupError, BuildError, DeviceNotAvailableException {
-        if (mFastbootMode == FastbootMode.BOOTLOADER) {
-            testInformation.getDevice().rebootIntoBootloader();
-        } else {
-            testInformation.getDevice().rebootIntoFastbootd();
-        }
+        testInformation.getDevice().rebootIntoBootloader();
 
         for (String cmd : mFastbootCommands) {
             // Ignore reboots since we'll reboot in the end.
@@ -67,9 +47,7 @@
             testInformation.getDevice().executeFastbootCommand(cmd.split("\\s+"));
         }
 
-        if (!mStayFastboot) {
-            testInformation.getDevice().reboot();
-        }
+        testInformation.getDevice().reboot();
     }
 
     /** {@inheritDoc} */
diff --git a/tests/src/com/android/tradefed/device/NativeDeviceTest.java b/tests/src/com/android/tradefed/device/NativeDeviceTest.java
index 40d56c0..c45e163 100644
--- a/tests/src/com/android/tradefed/device/NativeDeviceTest.java
+++ b/tests/src/com/android/tradefed/device/NativeDeviceTest.java
@@ -1666,46 +1666,6 @@
         EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
     }
 
-    /** Unit test for {@link NativeDevice#rebootIntoBootloader()}}. */
-    @Test
-    public void testRebootIntoBootloader() throws Exception {
-        NativeDevice testDevice =
-                new NativeDevice(mMockIDevice, mMockStateMonitor, mMockDvcMonitor) {
-                    @Override
-                    public TestDeviceState getDeviceState() {
-                        return TestDeviceState.ONLINE;
-                    }
-                };
-        String into = "bootloader";
-        mMockIDevice.reboot(into);
-        EasyMock.expectLastCall();
-        EasyMock.expect(mMockStateMonitor.waitForDeviceBootloader(EasyMock.anyLong()))
-                .andReturn(true);
-        EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
-        testDevice.rebootIntoBootloader();
-        EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
-    }
-
-    /** Unit test for {@link NativeDevice#rebootIntoFastbootd()}}. */
-    @Test
-    public void testRebootIntoFastbootd() throws Exception {
-        NativeDevice testDevice =
-                new NativeDevice(mMockIDevice, mMockStateMonitor, mMockDvcMonitor) {
-                    @Override
-                    public TestDeviceState getDeviceState() {
-                        return TestDeviceState.ONLINE;
-                    }
-                };
-        String into = "fastboot";
-        mMockIDevice.reboot(into);
-        EasyMock.expectLastCall();
-        EasyMock.expect(mMockStateMonitor.waitForDeviceBootloader(EasyMock.anyLong()))
-                .andReturn(true);
-        EasyMock.replay(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
-        testDevice.rebootIntoFastbootd();
-        EasyMock.verify(mMockIDevice, mMockStateMonitor, mMockDvcMonitor);
-    }
-
     /** Unit test for {@link NativeDevice#unlockDevice()} already decrypted. */
     @Test
     public void testUnlockDevice_skipping() throws Exception {
diff --git a/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java b/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java
index 6a75933..6f4fe50 100644
--- a/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/SuiteModuleLoaderTest.java
@@ -26,6 +26,7 @@
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.targetprep.BaseTargetPreparer;
 import com.android.tradefed.testtype.Abi;
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IRemoteTest;
@@ -54,6 +55,7 @@
 
     private static final String TEST_CONFIG =
             "<configuration description=\"Runs a stub tests part of some suite\">\n"
+                    + "    <target_preparer class=\"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$PreparerInject\" />\n"
                     + "    <test class=\"com.android.tradefed.testtype.suite.SuiteModuleLoaderTest"
                     + "$TestInject\" />\n"
                     + "</configuration>";
@@ -96,6 +98,12 @@
         FileUtil.writeToFile(TEST_INSTANT_CONFIG, module);
     }
 
+    @OptionClass(alias = "preparer-inject")
+    public static class PreparerInject extends BaseTargetPreparer {
+        @Option(name = "preparer-string")
+        public String preparer = null;
+    }
+
     @OptionClass(alias = "test-inject")
     public static class TestInject implements IRemoteTest {
         @Option(name = "simple-string")
@@ -168,6 +176,11 @@
     @Test
     public void testInjectConfigOptions_testArgs() throws Exception {
         List<String> testArgs = new ArrayList<>();
+        // Value for ITargetPreparer
+        testArgs.add(
+                "com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$PreparerInject:"
+                        + "preparer-string:preparer");
+        // Values for IRemoteTest
         testArgs.add(
                 "com.android.tradefed.testtype.suite.SuiteModuleLoaderTest$TestInject:"
                         + "simple-string:value1");
@@ -210,6 +223,9 @@
         assertNotNull(res.get("armeabi-v7a module1"));
         IConfiguration config = res.get("armeabi-v7a module1");
 
+        PreparerInject preparer = (PreparerInject) config.getTargetPreparers().get(0);
+        assertEquals("preparer", preparer.preparer);
+
         TestInject checker = (TestInject) config.getTests().get(0);
         assertEquals("value1", checker.test);
         assertEquals("", checker.testEmpty);
diff --git a/tests/src/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java b/tests/src/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
index 06c8b32..eda01e0 100644
--- a/tests/src/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/retry/ResultsPlayerTest.java
@@ -24,6 +24,7 @@
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.invoker.IInvocationContext;
 import com.android.tradefed.invoker.InvocationContext;
+import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.ILeveledLogOutput;
 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
 import com.android.tradefed.result.ITestInvocationListener;
@@ -47,6 +48,7 @@
     private ResultsPlayer mPlayer;
     private ITestInvocationListener mMockListener;
     private IInvocationContext mContext;
+    private TestInformation mTestInfo;
     private ITestDevice mMockDevice;
     private IDevice mMockIDevice;
     private IConfiguration mMockConfig;
@@ -64,9 +66,9 @@
         EasyMock.expect(mMockLogOutput.getLogLevel()).andReturn(LogLevel.VERBOSE);
         mMockLogOutput.setLogLevel(LogLevel.WARN);
         mMockLogOutput.setLogLevel(LogLevel.VERBOSE);
+        mTestInfo = TestInformation.newBuilder().setInvocationContext(mContext).build();
 
         mPlayer = new ResultsPlayer();
-        mPlayer.setInvocationContext(mContext);
         mPlayer.setConfiguration(mMockConfig);
         mContext.addAllocatedDevice(ConfigurationDef.DEFAULT_DEVICE_NAME, mMockDevice);
 
@@ -96,7 +98,7 @@
         mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
 
         EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
-        mPlayer.run(mMockListener);
+        mPlayer.run(mTestInfo, mMockListener);
         EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
     }
 
@@ -142,7 +144,7 @@
         mMockListener.testModuleEnded();
 
         EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
-        mPlayer.run(mMockListener);
+        mPlayer.run(mTestInfo, mMockListener);
         EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
     }
 
@@ -169,7 +171,7 @@
         mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
 
         EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
-        mPlayer.run(mMockListener);
+        mPlayer.run(mTestInfo, mMockListener);
         EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
     }
 
@@ -212,7 +214,7 @@
         mMockListener.testRunEnded(500L, new HashMap<String, Metric>());
 
         EasyMock.replay(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
-        mPlayer.run(mMockListener);
+        mPlayer.run(mTestInfo, mMockListener);
         EasyMock.verify(mMockListener, mMockDevice, mMockConfig, mMockLogOutput);
     }
 
diff --git a/tests/src/com/android/tradefed/testtype/suite/retry/RetryReschedulerTest.java b/tests/src/com/android/tradefed/testtype/suite/retry/RetryReschedulerTest.java
index a7709aa..245b2ed 100644
--- a/tests/src/com/android/tradefed/testtype/suite/retry/RetryReschedulerTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/retry/RetryReschedulerTest.java
@@ -124,7 +124,7 @@
                 mRescheduledConfiguration,
                 mMockCommandOptions,
                 mMockRequirements);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -169,7 +169,7 @@
                 mRescheduledConfiguration,
                 mMockCommandOptions,
                 mMockRequirements);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -206,7 +206,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -245,7 +245,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -284,7 +284,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -329,7 +329,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -368,7 +368,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -411,7 +411,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -452,7 +452,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -490,7 +490,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
@@ -539,7 +539,7 @@
                 mMockFactory,
                 mRescheduledConfiguration,
                 mMockCommandOptions);
-        mTest.run(null);
+        mTest.run(null, null);
         EasyMock.verify(
                 mMockRescheduler,
                 mMockLoader,
diff --git a/tests/src/com/android/tradefed/util/AaptParserTest.java b/tests/src/com/android/tradefed/util/AaptParserTest.java
index b754df1..5355aeb 100644
--- a/tests/src/com/android/tradefed/util/AaptParserTest.java
+++ b/tests/src/com/android/tradefed/util/AaptParserTest.java
@@ -139,4 +139,85 @@
         assertEquals("arm64-v8a", p.getNativeCode().get(0));
         assertEquals("armeabi-v7a", p.getNativeCode().get(1));
     }
+
+    public void testParseXmlTree_withRequestLegacyFlagTrue() {
+        AaptParser p = new AaptParser();
+        p.parseXmlTree(
+                "N: android=http://schemas.android.com/apk/res/android\n"
+                        + "  E: manifest (line=2)\n"
+                        + "    A: android:versionCode(0x0101021b)=(type 0x10)0x1d\n"
+                        + "    A: android:versionName(0x0101021c)=\"R\" (Raw: \"R\")\n"
+                        + "    A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1d\n"
+                        + "    A: android:compileSdkVersionCodename(0x01010573)=\"R\" (Raw: "
+                        + "\"R\")\n"
+                        + "    A: package=\"com.android.foo\" (Raw: \"com.android.foo\")\n"
+                        + "    A: platformBuildVersionCode=(type 0x10)0x1d\n"
+                        + "    A: platformBuildVersionName=\"R\" (Raw: \"R\")\n"
+                        + "    E: uses-sdk (line=5)\n"
+                        + "      A: android:minSdkVersion(0x0101020c)=(type 0x10)0x1c\n"
+                        + "      A: android:targetSdkVersion(0x01010270)=\"R\" (Raw: \"R\")\n"
+                        + "    E: application (line=12)\n"
+                        + "      A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1e\n"
+                        + "      A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff\n"
+                        + "      A: android:extractNativeLibs(0x010104ea)=(type 0x12)0xffffffff\n"
+                        + "      A: android:appComponentFactory(0x0101057a)=\"androidx.core.app"
+                        + ".CoreComponentFactory\" (Raw: \"androidx.core.app"
+                        + ".CoreComponentFactory\")\n"
+                        + "      A: android:requestLegacyExternalStorage(0x01010603)=(type 0x12)"
+                        + "0xffffffff\n");
+        assertTrue(p.isRequestingLegacyStorage());
+    }
+
+    public void testParseXmlTree_withRequestLegacyFlagFalse() {
+        AaptParser p = new AaptParser();
+        p.parseXmlTree(
+                "N: android=http://schemas.android.com/apk/res/android\n"
+                        + "  E: manifest (line=2)\n"
+                        + "    A: android:versionCode(0x0101021b)=(type 0x10)0x1d\n"
+                        + "    A: android:versionName(0x0101021c)=\"R\" (Raw: \"R\")\n"
+                        + "    A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1d\n"
+                        + "    A: android:compileSdkVersionCodename(0x01010573)=\"R\" (Raw: "
+                        + "\"R\")\n"
+                        + "    A: package=\"com.android.foo\" (Raw: \"com.android.foo\")\n"
+                        + "    A: platformBuildVersionCode=(type 0x10)0x1d\n"
+                        + "    A: platformBuildVersionName=\"R\" (Raw: \"R\")\n"
+                        + "    E: uses-sdk (line=5)\n"
+                        + "      A: android:minSdkVersion(0x0101020c)=(type 0x10)0x1c\n"
+                        + "      A: android:targetSdkVersion(0x01010270)=\"R\" (Raw: \"R\")\n"
+                        + "    E: application (line=12)\n"
+                        + "      A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1e\n"
+                        + "      A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff\n"
+                        + "      A: android:extractNativeLibs(0x010104ea)=(type 0x12)0xffffffff\n"
+                        + "      A: android:appComponentFactory(0x0101057a)=\"androidx.core.app"
+                        + ".CoreComponentFactory\" (Raw: \"androidx.core.app"
+                        + ".CoreComponentFactory\")\n"
+                        + "      A: android:requestLegacyExternalStorage(0x01010603)=(type 0x12)"
+                        + "0x0\n");
+        assertFalse(p.isRequestingLegacyStorage());
+    }
+
+    public void testParseXmlTree_withoutRequestLegacyFlag() {
+        AaptParser p = new AaptParser();
+        p.parseXmlTree(
+                "N: android=http://schemas.android.com/apk/res/android\n"
+                        + "  E: manifest (line=2)\n"
+                        + "    A: android:versionCode(0x0101021b)=(type 0x10)0x1d\n"
+                        + "    A: android:versionName(0x0101021c)=\"R\" (Raw: \"R\")\n"
+                        + "    A: android:compileSdkVersion(0x01010572)=(type 0x10)0x1d\n"
+                        + "    A: android:compileSdkVersionCodename(0x01010573)=\"R\" (Raw: "
+                        + "\"R\")\n"
+                        + "    A: package=\"com.android.foo\" (Raw: \"com.android.foo\")\n"
+                        + "    A: platformBuildVersionCode=(type 0x10)0x1d\n"
+                        + "    A: platformBuildVersionName=\"R\" (Raw: \"R\")\n"
+                        + "    E: uses-sdk (line=5)\n"
+                        + "      A: android:minSdkVersion(0x0101020c)=(type 0x10)0x1c\n"
+                        + "      A: android:targetSdkVersion(0x01010270)=\"R\" (Raw: \"R\")\n"
+                        + "    E: application (line=12)\n"
+                        + "      A: android:targetSdkVersion(0x01010270)=(type 0x10)0x1e\n"
+                        + "      A: android:supportsRtl(0x010103af)=(type 0x12)0xffffffff\n"
+                        + "      A: android:extractNativeLibs(0x010104ea)=(type 0x12)0xffffffff\n"
+                        + "      A: android:appComponentFactory(0x0101057a)=\"androidx.core.app"
+                        + ".CoreComponentFactory\" (Raw: \"androidx.core.app");
+        assertFalse(p.isRequestingLegacyStorage());
+    }
 }