Merge "Track removal of CtsLibcoreJavaUtilCollectionTestCases."
diff --git a/harnesses/tradefed/src/com/android/tradefed/util/VtsPythonRunnerHelper.java b/harnesses/tradefed/src/com/android/tradefed/util/VtsPythonRunnerHelper.java
index 44da74f..4f05a7a 100644
--- a/harnesses/tradefed/src/com/android/tradefed/util/VtsPythonRunnerHelper.java
+++ b/harnesses/tradefed/src/com/android/tradefed/util/VtsPythonRunnerHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.tradefed.util;
 
+import com.android.compatibility.common.tradefed.build.VtsCompatibilityInvocationHelper;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer;
@@ -27,6 +28,7 @@
 import com.android.tradefed.util.RunInterruptedException;
 import com.android.tradefed.util.RunUtil;
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 
 /**
@@ -50,6 +52,13 @@
         mVirtualenvPath = virtualEnvPath;
         mRunUtil = new RunUtil();
         activateVirtualenv(mRunUtil, getPythonVirtualEnv());
+        VtsCompatibilityInvocationHelper invocationHelper = new VtsCompatibilityInvocationHelper();
+        try {
+            mRunUtil.setWorkingDir(invocationHelper.getTestsDir());
+        } catch (FileNotFoundException e) {
+            CLog.e("VtsCompatibilityInvocationHelper cannot find test case directory. "
+                    + "Command working directory not set.");
+        }
     }
 
     /**
diff --git a/runners/host/base_test.py b/runners/host/base_test.py
index 4c11d34..dd9a66c 100644
--- a/runners/host/base_test.py
+++ b/runners/host/base_test.py
@@ -98,6 +98,8 @@
         web: WebFeature, object storing web feature util for test run
         coverage: CoverageFeature, object storing coverage feature util for test run
         sancov: SancovFeature, object storing sancov feature util for test run
+        start_vts_agents: whether to start vts agents when registering new
+                          android devices.
         profiling: ProfilingFeature, object storing profiling feature util for test run
         _bug_report_on_failure: bool, whether to catch bug report at the end
                                 of failed test cases. Default is False
@@ -105,6 +107,7 @@
                                 of failed test cases. Default is True
         test_filter: Filter object to filter test names.
     """
+    start_vts_agents = True
 
     def __init__(self, configs):
         self.tests = []
@@ -191,7 +194,8 @@
         """Returns a list of AndroidDevice objects"""
         if not hasattr(self, _ANDROID_DEVICES):
             setattr(self, _ANDROID_DEVICES,
-                    self.registerController(android_device))
+                    self.registerController(android_device,
+                                            start_services=self.start_vts_agents))
         return getattr(self, _ANDROID_DEVICES)
 
     @android_devices.setter
diff --git a/testcases/host/shell/SampleShellTest.py b/testcases/host/shell/SampleShellTest.py
index cc1424c..32bfca2 100644
--- a/testcases/host/shell/SampleShellTest.py
+++ b/testcases/host/shell/SampleShellTest.py
@@ -30,12 +30,12 @@
     REPEAT_COUNT = 10
 
     def setUpClass(self):
-        self.dut = self.registerController(android_device)[0]
+        self.dut = self.android_devices[0]
 
     def testOneCommand(self):
         """A simple testcase which just emulates a normal usage pattern."""
         self.dut.shell.InvokeTerminal("my_shell1")
-        results = self.dut.shell.my_shell1.Execute("which ls")
+        results = self.dut.shell.Execute("which ls")
         logging.info(str(results[const.STDOUT]))
         asserts.assertEqual(len(results[const.STDOUT]), 1)
         asserts.assertEqual(results[const.STDOUT][0].strip(), "/system/bin/ls")
diff --git a/testcases/host/shell_binary_crash_test/ShellBinaryCrashTest.py b/testcases/host/shell_binary_crash_test/ShellBinaryCrashTest.py
index 6fc315f..8244d71 100644
--- a/testcases/host/shell_binary_crash_test/ShellBinaryCrashTest.py
+++ b/testcases/host/shell_binary_crash_test/ShellBinaryCrashTest.py
@@ -31,7 +31,7 @@
     EXIT_CODE_SEGFAULT = 139
 
     def setUpClass(self):
-        self.dut = self.registerController(android_device)[0]
+        self.dut = self.android_devices[0]
 
     def testCrashBinary(self):
         """Tests whether the agent survives when a called binary crashes."""
diff --git a/testcases/template/cts_test/cts_test.py b/testcases/template/cts_test/cts_test.py
index 18a7dbf..ef44bac 100644
--- a/testcases/template/cts_test/cts_test.py
+++ b/testcases/template/cts_test/cts_test.py
@@ -39,9 +39,8 @@
     ]
 
     def setUpClass(self):
-        self.dut = self.registerController(android_device)[0]
-        self.dut.shell.InvokeTerminal("one")
-        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
+        self.dut = self.android_devices[0]
+        self.dut.shell.Execute("setenforce 0")  # SELinux permissive mode
         self.testcases = []
         self.CreateTestCases()
 
diff --git a/testcases/template/hal_hidl_host_test/hal_hidl_host_test.py b/testcases/template/hal_hidl_host_test/hal_hidl_host_test.py
index 8922785..ff91d2b 100644
--- a/testcases/template/hal_hidl_host_test/hal_hidl_host_test.py
+++ b/testcases/template/hal_hidl_host_test/hal_hidl_host_test.py
@@ -36,7 +36,7 @@
     # @Override
     def initParams(self):
         """Get the service combination according to the registered test HAL."""
-        self.dut = self.registerController(android_device)[0]
+        self.dut = self.android_devices[0]
         self.shell = self.dut.shell
         service_instance_combinations = self._GetServiceInstanceCombinations()
         self.params = service_instance_combinations
diff --git a/testcases/template/llvmfuzzer_test/llvmfuzzer_test.py b/testcases/template/llvmfuzzer_test/llvmfuzzer_test.py
index 2440a4c..eeb5331 100644
--- a/testcases/template/llvmfuzzer_test/llvmfuzzer_test.py
+++ b/testcases/template/llvmfuzzer_test/llvmfuzzer_test.py
@@ -36,7 +36,10 @@
     Attributes:
         _dut: AndroidDevice, the device under test as config
         _testcases: string list, list of testcases to run
+        start_vts_agents: whether to start vts agents when registering new
+                          android devices.
     """
+    start_vts_agents = False
 
     def setUpClass(self):
         """Creates a remote shell instance, and copies data files."""
@@ -54,7 +57,7 @@
         logging.info("%s: %s", config.ConfigKeys.FUZZER_CONFIGS,
                      self.fuzzer_configs)
 
-        self._dut = self.registerController(android_device, False)[0]
+        self._dut = self.android_devices[0]
         self._dut.adb.shell("mkdir %s -p" % config.FUZZER_TEST_DIR)
 
     def tearDownClass(self):
diff --git a/utils/python/android/api.py b/utils/python/android/api.py
index b51ae65..f97a8cd 100644
--- a/utils/python/android/api.py
+++ b/utils/python/android/api.py
@@ -13,4 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+PLATFORM_API_LEVEL_O = 26
 PLATFORM_API_LEVEL_O_MR1 = 27
+PLATFORM_API_LEVEL_P = 28
diff --git a/utils/python/controllers/android_device.py b/utils/python/controllers/android_device.py
index c4a34ae..ff0e167 100644
--- a/utils/python/controllers/android_device.py
+++ b/utils/python/controllers/android_device.py
@@ -24,6 +24,7 @@
 import time
 import traceback
 
+from vts.runners.host import asserts
 from vts.runners.host import errors
 from vts.runners.host import keys
 from vts.runners.host import logger as vts_logger
@@ -478,6 +479,48 @@
         return self.getProp("ro.product.first_api_level")
 
     @property
+    def sdk_version(self):
+        """Gets the SDK version that the device is running with."""
+        return self.getProp("ro.build.version.sdk")
+
+    def getLaunchApiLevel(self, strict=True):
+        """Gets the API level that the device was initially launched with.
+
+        This method reads ro.product.first_api_level from the device. If the
+        value is 0, it then reads ro.build.version.sdk.
+
+        Args:
+            strict: A boolean, whether to fail the test if the property is
+                    not an integer or not defined.
+
+        Returns:
+            An integer, the API level.
+            0 if the property is not an integer or not defined.
+        """
+        level_str = self.first_api_level
+        try:
+            level = int(level_str)
+        except ValueError:
+            error_msg = "Cannot parse first_api_level: %s" % level_str
+            if strict:
+                asserts.fail(error_msg)
+            logging.error(error_msg)
+            return 0
+
+        if level != 0:
+            return level
+
+        level_str = self.sdk_version
+        try:
+            return int(level_str)
+        except ValueError:
+            error_msg = "Cannot parse version.sdk: %s" % level_str
+            if strict:
+                asserts.fail(error_msg)
+            logging.error(error_msg)
+            return 0
+
+    @property
     def vndk_version(self):
         """Gets the VNDK version that the vendor partition is using."""
         return self.getProp("ro.vndk.version")
diff --git a/utils/python/cpu/cpu_frequency_scaling.py b/utils/python/cpu/cpu_frequency_scaling.py
index d7db434..5ce6b0e 100644
--- a/utils/python/cpu/cpu_frequency_scaling.py
+++ b/utils/python/cpu/cpu_frequency_scaling.py
@@ -54,8 +54,7 @@
         """Creates a shell mirror object and reads the configuration values."""
         if self._init:
             return
-        self._dut.shell.InvokeTerminal("cpu_frequency_scaling")
-        self._shell = self._dut.shell.cpu_frequency_scaling
+        self._shell = self._dut.shell
         self._min_cpu_number, self._max_cpu_number = self._LoadMinAndMaxCpuNo()
         self._theoretical_max_frequency = {}
         self._perf_override = False
diff --git a/utils/python/vndk/vndk_utils.py b/utils/python/vndk/vndk_utils.py
index 6bee7f2..d52686d 100644
--- a/utils/python/vndk/vndk_utils.py
+++ b/utils/python/vndk/vndk_utils.py
@@ -14,6 +14,8 @@
 # limitations under the License.
 #
 
+import logging
+
 from vts.utils.python.android import api
 
 
@@ -30,8 +32,12 @@
     Returns:
         A boolean, whether VNDK runtime should be enabled.
     """
-    return bool(int(dut.first_api_level) > api.PLATFORM_API_LEVEL_O_MR1 or
-                dut.vndk_version)
+    api_level = dut.getLaunchApiLevel(strict=False)
+    if not api_level:
+        logging.error("Cannot get first API level. "
+                      "Assume VNDK runtime to be enforced.")
+        return True
+    return bool(api_level > api.PLATFORM_API_LEVEL_O_MR1 or dut.vndk_version)
 
 
 def FormatVndkPath(pattern, bitness, version=""):