diff --git a/android_env/components/adb_controller.py b/android_env/components/adb_controller.py index 8273757..314aca5 100644 --- a/android_env/components/adb_controller.py +++ b/android_env/components/adb_controller.py @@ -61,7 +61,7 @@ def command_prefix(self, include_device_name: bool = True) -> list[str]: # port explicitly. adb_port_args = ['-P', str(self._config.adb_server_port)] command_prefix = [ - self._config.adb_path, + os.fspath(self._config.adb_path), *adb_port_args, ] if include_device_name: diff --git a/android_env/components/config_classes.py b/android_env/components/config_classes.py index a1792dc..c217740 100644 --- a/android_env/components/config_classes.py +++ b/android_env/components/config_classes.py @@ -17,6 +17,7 @@ import dataclasses import enum +import pathlib @dataclasses.dataclass @@ -113,7 +114,7 @@ class EmulatorLauncherConfig: # Path to the KVM device. kvm_device: str = '/dev/kvm' # Path to directory which will hold temporary files. - tmp_dir: str = '/tmp/android_env/simulator/' + tmp_dir: pathlib.Path | str = '/tmp/android_env/simulator/' # GPU mode override. # Please see # https://developer.android.com/studio/run/emulator-acceleration#accel-graphics. @@ -155,7 +156,7 @@ class EmulatorConfig(SimulatorConfig): ) # Path to file which holds emulator logs. If not provided, it will be # determined by the EmulatorLauncher. - logfile_path: str = '' + logfile_path: pathlib.Path | str = '' # The number of times to try launching the emulator before rebooting (reboot # on the n+1-st try). launch_n_times_without_reboot: int = 1 @@ -195,7 +196,7 @@ class TaskConfig: """Base config class for loading tasks.""" # The directory for temporary task-related resources. - tmp_dir: str = '' + tmp_dir: pathlib.Path | str = '' @dataclasses.dataclass @@ -203,7 +204,7 @@ class FilesystemTaskConfig(TaskConfig): """Config for protobuf files stored in the local filesystem.""" # Filesystem path to `.binarypb` or `.textproto` protobuf Task. - path: str = '' + path: pathlib.Path | str = '' @dataclasses.dataclass diff --git a/android_env/components/simulators/emulator/emulator_launcher.py b/android_env/components/simulators/emulator/emulator_launcher.py index 8958c58..9de512c 100644 --- a/android_env/components/simulators/emulator/emulator_launcher.py +++ b/android_env/components/simulators/emulator/emulator_launcher.py @@ -15,8 +15,8 @@ """Prepares and launches an emulator process.""" -import glob import os +import pathlib import subprocess import tempfile @@ -43,15 +43,16 @@ def __init__( # Create directory for tmp files. # Note: this will be deleted once EmulatorLauncher instance is cleaned up. - os.makedirs(config.tmp_dir, exist_ok=True) + tmp_dir = pathlib.Path(config.tmp_dir) + tmp_dir.mkdir(parents=True, exist_ok=True) self._local_tmp_dir_handle = tempfile.TemporaryDirectory( - dir=config.tmp_dir, prefix='simulator_instance_' + dir=tmp_dir, prefix='simulator_instance_' ) - self._local_tmp_dir = self._local_tmp_dir_handle.name - self._logfile_path = os.path.join(self._local_tmp_dir, 'emulator_output') + self._local_tmp_dir = pathlib.Path(self._local_tmp_dir_handle.name) + self._logfile_path = self._local_tmp_dir / 'emulator_output' logging.info('Simulator local_tmp_dir: %s', self._local_tmp_dir) - def logfile_path(self) -> str: + def logfile_path(self) -> pathlib.Path: return self._logfile_path def launch_emulator_process(self) -> None: @@ -60,23 +61,25 @@ def launch_emulator_process(self) -> None: logging.info('Booting new emulator: %s', self._config.emulator_path) # Set necessary environment variables. - base_lib_dir = self._config.emulator_path[:-8] + 'lib64/' + emulator_path = pathlib.Path(self._config.emulator_path) + emulator_dir = emulator_path.parent + base_lib_dir = emulator_dir / 'lib64' ld_library_path = ':'.join([ - base_lib_dir + 'x11/', base_lib_dir + 'qt/lib/', - base_lib_dir + 'gles_swiftshader/', base_lib_dir + os.fspath(base_lib_dir / 'x11'), + os.fspath(base_lib_dir / 'qt/lib'), + os.fspath(base_lib_dir / 'gles_swiftshader'), + os.fspath(base_lib_dir), ]) extra_env_vars = { 'ANDROID_HOME': '', - 'ANDROID_SDK_ROOT': self._config.android_sdk_root, - 'ANDROID_AVD_HOME': self._config.android_avd_home, - 'ANDROID_EMULATOR_KVM_DEVICE': self._config.kvm_device, + 'ANDROID_SDK_ROOT': os.fspath(self._config.android_sdk_root), + 'ANDROID_AVD_HOME': os.fspath(self._config.android_avd_home), + 'ANDROID_EMULATOR_KVM_DEVICE': os.fspath(self._config.kvm_device), 'ANDROID_ADB_SERVER_PORT': str( self._adb_controller_config.adb_server_port ), 'LD_LIBRARY_PATH': ld_library_path, - 'QT_XKB_CONFIG_ROOT': str( - self._config.emulator_path[:-8] + 'qt_config/' - ), + 'QT_XKB_CONFIG_ROOT': os.fspath(emulator_dir / 'qt_config'), 'ANDROID_EMU_ENABLE_CRASH_REPORTING': '1', 'SHOW_PERF_STATS': str(1 if self._config.show_perf_stats else 0), } @@ -114,9 +117,9 @@ def launch_emulator_process(self) -> None: ) command = ( [ - self._config.emulator_path, + os.fspath(self._config.emulator_path), '-adb-path', - self._adb_controller_config.adb_path, + os.fspath(self._adb_controller_config.adb_path), '-gpu', self._config.gpu_mode, '-no-audio', diff --git a/android_env/components/simulators/emulator/emulator_launcher_test.py b/android_env/components/simulators/emulator/emulator_launcher_test.py index 0678ec9..0b649b0 100644 --- a/android_env/components/simulators/emulator/emulator_launcher_test.py +++ b/android_env/components/simulators/emulator/emulator_launcher_test.py @@ -17,6 +17,7 @@ import builtins import os +import pathlib import subprocess import tempfile from unittest import mock @@ -55,10 +56,14 @@ def setUp(self): self._ports = ['-ports', f'{self._emulator_console_port},{self._adb_port}'] self._snapshot = ['-no-snapshot'] - base_lib_dir = self._emulator_path[:-8] + 'lib64/' + emulator_path = pathlib.Path(self._emulator_path) + emulator_dir = emulator_path.parent + base_lib_dir = emulator_dir / 'lib64' ld_library_path = ':'.join([ - base_lib_dir + 'x11/', base_lib_dir + 'qt/lib/', - base_lib_dir + 'gles_swiftshader/', base_lib_dir + os.fspath(base_lib_dir / 'x11'), + os.fspath(base_lib_dir / 'qt/lib'), + os.fspath(base_lib_dir / 'gles_swiftshader'), + os.fspath(base_lib_dir), ]) # Instantiate the config to extract default values. @@ -70,7 +75,7 @@ def setUp(self): 'ANDROID_EMULATOR_KVM_DEVICE': '/dev/kvm', 'ANDROID_ADB_SERVER_PORT': '1234', 'LD_LIBRARY_PATH': ld_library_path, - 'QT_XKB_CONFIG_ROOT': str(self._emulator_path[:-8] + 'qt_config/'), + 'QT_XKB_CONFIG_ROOT': os.fspath(emulator_dir / 'qt_config'), 'ANDROID_EMU_ENABLE_CRASH_REPORTING': '1', } diff --git a/android_env/components/simulators/emulator/emulator_simulator.py b/android_env/components/simulators/emulator/emulator_simulator.py index 8ef551a..0852be6 100644 --- a/android_env/components/simulators/emulator/emulator_simulator.py +++ b/android_env/components/simulators/emulator/emulator_simulator.py @@ -19,7 +19,7 @@ from collections.abc import Callable, Mapping import functools -import os +import pathlib import platform import time from typing import Any, Final, final @@ -183,9 +183,11 @@ def __init__( def get_logs(self) -> str: """Returns logs recorded by the emulator.""" - if self._logfile_path and os.path.exists(self._logfile_path): - with open(self._logfile_path, 'rb') as f: - return f.read().decode('utf-8') + logfile_path = ( + pathlib.Path(self._logfile_path) if self._logfile_path else None + ) + if logfile_path and logfile_path.exists(): + return logfile_path.read_text(encoding='utf-8') else: return f'Logfile does not exist: {self._logfile_path}.' diff --git a/android_env/components/simulators/emulator/emulator_simulator_test.py b/android_env/components/simulators/emulator/emulator_simulator_test.py index 257bcd8..a9a602f 100644 --- a/android_env/components/simulators/emulator/emulator_simulator_test.py +++ b/android_env/components/simulators/emulator/emulator_simulator_test.py @@ -17,6 +17,7 @@ import builtins import os +import pathlib import time from unittest import mock @@ -137,12 +138,12 @@ def test_logfile_path(self): simulator = emulator_simulator.EmulatorSimulator(config) with mock.patch.object( - os.path, 'exists', autospec=True, return_value=True - ), mock.patch.object(builtins, 'open', autospec=True) as mock_open: - mock_file = mock_open.return_value.__enter__.return_value - mock_file.read.return_value = b'fake_logs' + pathlib.Path, 'exists', autospec=True, return_value=True + ), mock.patch.object( + pathlib.Path, 'read_text', autospec=True, return_value='fake_logs' + ) as mock_read_text: logs = simulator.get_logs() - mock_open.assert_called_once_with('fake/logfile/path', 'rb') + mock_read_text.assert_called_once_with(mock.ANY, encoding='utf-8') self.assertEqual(logs, 'fake_logs') def test_launch_operation_order(self): diff --git a/android_env/loader.py b/android_env/loader.py index aac854d..bc58343 100644 --- a/android_env/loader.py +++ b/android_env/loader.py @@ -15,7 +15,7 @@ """Function for loading AndroidEnv.""" -import os +import pathlib from absl import logging from android_env import environment @@ -79,15 +79,19 @@ def _process_emulator_launcher_config( # Expand the user directory if specified. launcher_config = emulator_config.emulator_launcher - launcher_config.android_avd_home = os.path.expanduser( - launcher_config.android_avd_home - ) - launcher_config.android_sdk_root = os.path.expanduser( - launcher_config.android_sdk_root - ) - launcher_config.emulator_path = os.path.expanduser( - launcher_config.emulator_path - ) - emulator_config.adb_controller.adb_path = os.path.expanduser( - emulator_config.adb_controller.adb_path - ) + if launcher_config.android_avd_home: + launcher_config.android_avd_home = pathlib.Path( + launcher_config.android_avd_home + ).expanduser() + if launcher_config.android_sdk_root: + launcher_config.android_sdk_root = pathlib.Path( + launcher_config.android_sdk_root + ).expanduser() + if launcher_config.emulator_path: + launcher_config.emulator_path = pathlib.Path( + launcher_config.emulator_path + ).expanduser() + if emulator_config.adb_controller.adb_path: + emulator_config.adb_controller.adb_path = pathlib.Path( + emulator_config.adb_controller.adb_path + ).expanduser() diff --git a/android_env/loader_test.py b/android_env/loader_test.py index 6a56c9f..8c7949e 100644 --- a/android_env/loader_test.py +++ b/android_env/loader_test.py @@ -14,7 +14,7 @@ # limitations under the License. import builtins -import os +import pathlib from typing import cast from unittest import mock @@ -79,16 +79,18 @@ def test_load_emulator( config=config_classes.EmulatorConfig( emulator_launcher=config_classes.EmulatorLauncherConfig( avd_name='my_avd', - android_avd_home=os.path.expanduser('~/.android/avd'), - android_sdk_root=os.path.expanduser('~/Android/Sdk'), - emulator_path=os.path.expanduser( + android_avd_home=pathlib.Path('~/.android/avd').expanduser(), + android_sdk_root=pathlib.Path('~/Android/Sdk').expanduser(), + emulator_path=pathlib.Path( '~/Android/Sdk/emulator/emulator' - ), + ).expanduser(), run_headless=False, gpu_mode='swangle_indirect', ), adb_controller=config_classes.AdbControllerConfig( - adb_path=os.path.expanduser('~/Android/Sdk/platform-tools/adb'), + adb_path=pathlib.Path( + '~/Android/Sdk/platform-tools/adb' + ).expanduser(), adb_server_port=5037, ), )