tradefed_test: Support SDK version dependent waivers.

We share the GTS setup for all Android sdk versions, but waivers
tend to be specific to only one of them. Support such kind of
filtering.

BUG=b:116284462
TEST=GtsPlacementTestCases

Change-Id: I51cfa4f746b11c6c975f5bacbfae8e619d960ca4
Reviewed-on: https://chromium-review.googlesource.com/1237701
Commit-Ready: Kazuhiro Inaba <kinaba@chromium.org>
Tested-by: Kazuhiro Inaba <kinaba@chromium.org>
Reviewed-by: Kazuhiro Inaba <kinaba@chromium.org>
diff --git a/server/cros/cts_expected_failure_parser.py b/server/cros/cts_expected_failure_parser.py
index 5800cb3..6ccdd38 100644
--- a/server/cros/cts_expected_failure_parser.py
+++ b/server/cros/cts_expected_failure_parser.py
@@ -11,18 +11,23 @@
     def __init__(self, failure_files):
         self.waivers_yaml = self._load_failures(failure_files)
 
-    def _validate_waiver_config(self, arch, board, bundle_abi, config):
+    def _validate_waiver_config(self, arch, board, bundle_abi, sdk_ver, config):
         """Validate if the test environment matches the test config.
 
         @param arch: DUT's arch type.
         @param board: DUT's board name.
         @param bundle_abi: The test's abi type.
+        @param sdk_ver: DUT's Android SDK version
         @param config: config for an expected failing test.
         @return True if test arch or board is part of the config, else False.
         """
         dut_config = ['all', arch, board]
         if bundle_abi and bundle_abi != arch:
             dut_config.append('nativebridge')
+        # Map only the versions that ARC releases care.
+        sdk_ver_map = {'25': 'N', '28': 'P'}
+        if sdk_ver in sdk_ver_map:
+           dut_config.append(sdk_ver_map[sdk_ver])
         return len(set(dut_config).intersection(config)) > 0
 
     def _load_failures(self, failure_files):
@@ -46,17 +51,19 @@
                          failure_file)
         return waivers_yaml
 
-    def find_waivers(self, arch, board, bundle_abi):
+    def find_waivers(self, arch, board, bundle_abi, sdk_ver):
         """Finds waivers for the test board.
 
         @param arch: DUT's arch type.
         @param board: DUT's board name.
         @param bundle_abi: The test's abi type.
+        @param sdk_ver: DUT's Android SDK version
         @return a set of waivers/no-test-modules applied to the test board.
         """
         applied_waiver_list = set()
         for test, config in self.waivers_yaml.iteritems():
-            if self._validate_waiver_config(arch, board, bundle_abi, config):
+            if self._validate_waiver_config(arch, board, bundle_abi, sdk_ver,
+                                            config):
                 applied_waiver_list.add(test)
         logging.info('Excluding tests/packages from rerun: %s.',
                      applied_waiver_list)
diff --git a/server/cros/tradefed_test.py b/server/cros/tradefed_test.py
index ec687b7..354b219 100644
--- a/server/cros/tradefed_test.py
+++ b/server/cros/tradefed_test.py
@@ -61,6 +61,7 @@
     _board_arch = None
     _board_name = None
     _release_channel = None
+    _android_version = None
 
     def _log_java_version(self):
         """Quick sanity and spew of java version installed on the server."""
@@ -812,13 +813,14 @@
         expected_fail_files = []
         test_board = self._get_board_name()
         test_arch = self._get_board_arch()
+        sdk_ver = self._get_android_version()
         expected_fail_dir = os.path.join(self.bindir, directory)
         if os.path.exists(expected_fail_dir):
             expected_fail_files += glob.glob(expected_fail_dir + '/*.yaml')
 
         waivers = cts_expected_failure_parser.ParseKnownCTSFailures(
             expected_fail_files)
-        return waivers.find_waivers(test_arch, test_board, bundle_abi)
+        return waivers.find_waivers(test_arch, test_board, bundle_abi, sdk_ver)
 
     def _get_abilist(self):
         """Return the abilist supported by calling adb command.
@@ -851,6 +853,15 @@
             self._board_name = self._hosts[0].get_board().split(':')[1]
         return self._board_name
 
+    def _get_android_version(self):
+        """Return target DUT Android SDK version"""
+        # TODO(kinaba): factor this out to server/hosts/cros_host.py
+        if not self._android_version:
+            self._android_version = self._hosts[0].run(
+                'grep ANDROID_SDK /etc/lsb-release',
+                ignore_status=True).stdout.rstrip().split('=')[1]
+        return self._android_version
+
     def _get_max_retry(self, max_retry):
         """Return the maximum number of retries.