Use prebuilt aapt if built aapt not exist
Align the rule of using aapt with build system.
Bug: 205720152
Test: tapas MediaProviderTests ;\
rm $(ANDROID_HOST_OUT)/bin/aapt ;\
atest MediaProviderTests
Change-Id: Ibeec63881c4724d755f331ee8819f92399552677
diff --git a/atest/atest_utils.py b/atest/atest_utils.py
index 352f338..16eecaf 100644
--- a/atest/atest_utils.py
+++ b/atest/atest_utils.py
@@ -30,6 +30,7 @@
import logging
import os
import pickle
+import platform
import re
import shutil
import subprocess
@@ -39,6 +40,7 @@
import zipfile
from multiprocessing import Process
+from pathlib import Path
import xml.etree.ElementTree as ET
@@ -1594,3 +1596,12 @@
proc = Process(target=func, *args, **kwargs)
proc.start()
return proc
+
+def get_prebuilt_sdk_tools_dir():
+ """Get the path for the prebuilt sdk tools root dir.
+
+ Returns: The absolute path of prebuilt sdk tools directory.
+ """
+ build_top = Path(os.environ.get(constants.ANDROID_BUILD_TOP, ''))
+ return build_top.joinpath(
+ 'prebuilts/sdk/tools/', str(platform.system()).lower(), 'bin')
diff --git a/atest/test_runners/atest_tf_test_runner.py b/atest/test_runners/atest_tf_test_runner.py
index f1932c9..7bc1c73 100644
--- a/atest/test_runners/atest_tf_test_runner.py
+++ b/atest/test_runners/atest_tf_test_runner.py
@@ -27,6 +27,7 @@
import socket
from functools import partial
+from pathlib import Path
import atest_error
import atest_utils
@@ -51,7 +52,8 @@
# EVENT_RE has groups for the name and the data. "." does not match \n.
EVENT_RE = re.compile(r'\n*(?P<event_name>[A-Z_]+) (?P<json_data>{.*})(?=\n|.)*')
-EXEC_DEPENDENCIES = ('adb', 'aapt', 'fastboot')
+# Remove aapt from build dependency, use prebuilt version instead.
+EXEC_DEPENDENCIES = ('adb', 'fastboot')
TRADEFED_EXIT_MSG = 'TradeFed subprocess exited early with exit code=%s.'
@@ -59,6 +61,9 @@
_INTEGRATION_FINDERS = frozenset(['', 'INTEGRATION', 'INTEGRATION_FILE_PATH'])
+# AAPT binary name
+_AAPT = 'aapt'
+
class TradeFedExitError(Exception):
"""Raised when TradeFed exists before test run has finished."""
@@ -91,7 +96,8 @@
if not os.path.exists(self.log_path):
os.makedirs(self.log_path)
log_args = {'log_path': self.log_path,
- 'proto_path': os.path.join(self.results_dir, constants.ATEST_TEST_RECORD_PROTO)}
+ 'proto_path': os.path.join(
+ self.results_dir, constants.ATEST_TEST_RECORD_PROTO)}
self.run_cmd_dict = {'env': self._get_ld_library_path(),
'exe': self.EXECUTABLE,
'template': self._TF_TEMPLATE,
@@ -379,6 +385,16 @@
continue
filtered_paths.append(path)
env_vars['PYTHONPATH'] = ':'.join(filtered_paths)
+
+ # Use prebuilt aapt if there's no aapt under android system path which
+ # is aligned with build system.
+ # https://android.googlesource.com/platform/build/+/master/core/config.mk#529
+ if self._is_missing_exec(_AAPT):
+ prebuilt_aapt = Path.joinpath(
+ atest_utils.get_prebuilt_sdk_tools_dir(), _AAPT)
+ if os.path.exists(prebuilt_aapt):
+ env_vars['PATH'] = (str(prebuilt_aapt.parent) + ':'
+ + env_vars['PATH'])
return env_vars
# pylint: disable=unnecessary-pass
@@ -407,7 +423,7 @@
return True
# TODO: Check if there is a clever way to determine if system adb is
# good enough.
- root_dir = os.environ.get(constants.ANDROID_BUILD_TOP)
+ root_dir = os.environ.get(constants.ANDROID_BUILD_TOP, '')
return os.path.commonprefix([output, root_dir]) != root_dir
def get_test_runner_build_reqs(self):
diff --git a/atest/test_runners/atest_tf_test_runner_unittest.py b/atest/test_runners/atest_tf_test_runner_unittest.py
index 650d18a..ae20040 100755
--- a/atest/test_runners/atest_tf_test_runner_unittest.py
+++ b/atest/test_runners/atest_tf_test_runner_unittest.py
@@ -25,6 +25,7 @@
import json
from io import StringIO
+from pathlib import Path
from unittest import mock
import atest_utils
@@ -806,5 +807,33 @@
{constants.CUSTOM_ARGS: [constants.TF_MODULE_PARAMETER]})
self.assertTrue(constants.TF_ENABLE_PARAMETERIZED_MODULES in args)
+ @mock.patch('atest_utils.get_prebuilt_sdk_tools_dir')
+ @mock.patch.object(atf_tr.AtestTradefedTestRunner,
+ '_is_missing_exec', return_value=False)
+ def test_generate_env_vars_aapt_already_in_system_path(
+ self, _mock_is_missing_exec, mock_prebuilt_sdk_dir):
+ """Test generate_env_vars if aapt already in system path."""
+ prebuilt_sdk_dir = Path('/my/test/sdk/dir')
+ mock_prebuilt_sdk_dir.return_value = prebuilt_sdk_dir
+
+ env_vars = self.tr.generate_env_vars(extra_args={})
+
+ self.assertFalse(
+ str(prebuilt_sdk_dir) + ':' in env_vars.get('PATH', ''))
+
+ @mock.patch('os.path.exists', return_value=True)
+ @mock.patch('atest_utils.get_prebuilt_sdk_tools_dir')
+ @mock.patch.object(atf_tr.AtestTradefedTestRunner,
+ '_is_missing_exec', return_value=True)
+ def test_generate_env_vars_aapt_not_in_system_path(
+ self, _mock_is_missing_exec, mock_prebuilt_sdk_dir, _mock_exist):
+ """Test generate_env_vars if aapt not in system path."""
+ prebuilt_sdk_dir = Path('/my/test/sdk/dir')
+ mock_prebuilt_sdk_dir.return_value = prebuilt_sdk_dir
+
+ env_vars = self.tr.generate_env_vars(extra_args={})
+
+ self.assertTrue(str(prebuilt_sdk_dir) + ':' in env_vars.get('PATH', ''))
+
if __name__ == '__main__':
unittest.main()