android-env 1.2.1__py3-none-any.whl → 1.2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- android_env/__init__.py +1 -1
- android_env/components/__init__.py +1 -1
- android_env/components/a11y/__init__.py +15 -0
- android_env/components/a11y/a11y_events.py +118 -0
- android_env/components/a11y/a11y_events_test.py +173 -0
- android_env/components/a11y/a11y_forests.py +128 -0
- android_env/components/a11y/a11y_forests_test.py +237 -0
- android_env/components/a11y/a11y_servicer.py +199 -0
- android_env/components/a11y/a11y_servicer_test.py +224 -0
- android_env/components/action_fns.py +132 -0
- android_env/components/action_fns_test.py +227 -0
- android_env/components/action_type.py +26 -3
- android_env/components/adb_call_parser.py +239 -196
- android_env/components/adb_call_parser_test.py +179 -209
- android_env/components/adb_controller.py +90 -52
- android_env/components/adb_controller_test.py +187 -16
- android_env/components/adb_log_stream.py +17 -5
- android_env/components/adb_log_stream_test.py +17 -3
- android_env/components/app_screen_checker.py +17 -15
- android_env/components/app_screen_checker_test.py +7 -8
- android_env/components/config_classes.py +203 -0
- android_env/components/coordinator.py +102 -338
- android_env/components/coordinator_test.py +59 -199
- android_env/components/device_settings.py +174 -0
- android_env/components/device_settings_test.py +228 -0
- android_env/components/dumpsys_thread.py +3 -4
- android_env/components/dumpsys_thread_test.py +1 -1
- android_env/components/errors.py +52 -10
- android_env/components/errors_test.py +110 -0
- android_env/components/log_stream.py +7 -5
- android_env/components/log_stream_test.py +1 -1
- android_env/components/logcat_thread.py +9 -8
- android_env/components/logcat_thread_test.py +3 -4
- android_env/components/{utils.py → pixel_fns.py} +20 -20
- android_env/components/{utils_test.py → pixel_fns_test.py} +20 -15
- android_env/components/setup_step_interpreter.py +47 -39
- android_env/components/setup_step_interpreter_test.py +4 -4
- android_env/components/simulators/__init__.py +1 -1
- android_env/components/simulators/base_simulator.py +116 -44
- android_env/components/simulators/base_simulator_test.py +131 -9
- android_env/components/simulators/emulator/__init__.py +1 -1
- android_env/components/simulators/emulator/emulator_launcher.py +67 -77
- android_env/components/simulators/emulator/emulator_launcher_test.py +153 -49
- android_env/components/simulators/emulator/emulator_simulator.py +276 -95
- android_env/components/simulators/emulator/emulator_simulator_test.py +314 -89
- android_env/components/simulators/fake/__init__.py +1 -1
- android_env/components/simulators/fake/fake_simulator.py +17 -25
- android_env/components/simulators/fake/fake_simulator_test.py +29 -12
- android_env/components/specs.py +18 -28
- android_env/components/specs_test.py +1 -44
- android_env/components/task_manager.py +48 -48
- android_env/components/task_manager_test.py +71 -60
- android_env/env_interface.py +37 -23
- android_env/environment.py +83 -51
- android_env/environment_test.py +68 -29
- android_env/loader.py +57 -43
- android_env/loader_test.py +115 -35
- android_env/proto/__init__.py +1 -1
- android_env/proto/a11y/__init__.py +15 -0
- android_env/proto/a11y/a11y.proto +75 -0
- android_env/proto/a11y/a11y_pb2.py +54 -0
- android_env/proto/a11y/a11y_pb2.pyi +49 -0
- android_env/proto/a11y/a11y_pb2_grpc.py +202 -0
- android_env/proto/a11y/android_accessibility_action.proto +32 -0
- android_env/proto/a11y/android_accessibility_action_pb2.py +37 -0
- android_env/proto/a11y/android_accessibility_action_pb2.pyi +13 -0
- android_env/proto/a11y/android_accessibility_action_pb2_grpc.py +24 -0
- android_env/proto/a11y/android_accessibility_forest.proto +29 -0
- android_env/proto/a11y/android_accessibility_forest_pb2.py +38 -0
- android_env/proto/a11y/android_accessibility_forest_pb2.pyi +13 -0
- android_env/proto/a11y/android_accessibility_forest_pb2_grpc.py +24 -0
- android_env/proto/a11y/android_accessibility_node_info.proto +122 -0
- android_env/proto/a11y/android_accessibility_node_info_clickable_span.proto +49 -0
- android_env/proto/a11y/android_accessibility_node_info_clickable_span_pb2.py +39 -0
- android_env/proto/a11y/android_accessibility_node_info_clickable_span_pb2.pyi +28 -0
- android_env/proto/a11y/android_accessibility_node_info_clickable_span_pb2_grpc.py +24 -0
- android_env/proto/a11y/android_accessibility_node_info_pb2.py +42 -0
- android_env/proto/a11y/android_accessibility_node_info_pb2.pyi +75 -0
- android_env/proto/a11y/android_accessibility_node_info_pb2_grpc.py +24 -0
- android_env/proto/a11y/android_accessibility_tree.proto +29 -0
- android_env/proto/a11y/android_accessibility_tree_pb2.py +38 -0
- android_env/proto/a11y/android_accessibility_tree_pb2.pyi +13 -0
- android_env/proto/a11y/android_accessibility_tree_pb2_grpc.py +24 -0
- android_env/proto/a11y/android_accessibility_window_info.proto +84 -0
- android_env/proto/a11y/android_accessibility_window_info_pb2.py +41 -0
- android_env/proto/a11y/android_accessibility_window_info_pb2.pyi +48 -0
- android_env/proto/a11y/android_accessibility_window_info_pb2_grpc.py +24 -0
- android_env/proto/a11y/rect.proto +30 -0
- android_env/proto/a11y/rect_pb2.py +37 -0
- android_env/proto/a11y/rect_pb2.pyi +17 -0
- android_env/proto/a11y/rect_pb2_grpc.py +24 -0
- android_env/proto/adb.proto +17 -6
- android_env/proto/adb_pb2.py +120 -107
- android_env/proto/adb_pb2.pyi +396 -0
- android_env/proto/adb_pb2_grpc.py +20 -0
- android_env/proto/emulator_controller.proto +68 -63
- android_env/proto/emulator_controller_pb2.py +142 -131
- android_env/proto/emulator_controller_pb2.pyi +672 -0
- android_env/proto/emulator_controller_pb2_grpc.py +505 -142
- android_env/proto/snapshot.proto +169 -0
- android_env/proto/snapshot_pb2.py +47 -0
- android_env/proto/snapshot_pb2.pyi +117 -0
- android_env/proto/snapshot_pb2_grpc.py +24 -0
- android_env/proto/snapshot_service.proto +289 -0
- android_env/proto/snapshot_service_pb2.py +54 -0
- android_env/proto/snapshot_service_pb2.pyi +86 -0
- android_env/proto/snapshot_service_pb2_grpc.py +487 -0
- android_env/proto/state.proto +63 -0
- android_env/proto/state_pb2.py +63 -0
- android_env/proto/state_pb2.pyi +85 -0
- android_env/proto/state_pb2_grpc.py +24 -0
- android_env/proto/task.proto +5 -1
- android_env/proto/task_pb2.py +42 -31
- android_env/proto/task_pb2.pyi +160 -0
- android_env/proto/task_pb2_grpc.py +20 -0
- android_env/wrappers/__init__.py +1 -1
- android_env/wrappers/a11y_grpc_wrapper.py +500 -0
- android_env/wrappers/a11y_grpc_wrapper_test.py +849 -0
- android_env/wrappers/base_wrapper.py +34 -13
- android_env/wrappers/base_wrapper_test.py +22 -16
- android_env/wrappers/discrete_action_wrapper.py +18 -17
- android_env/wrappers/discrete_action_wrapper_test.py +4 -4
- android_env/wrappers/flat_interface_wrapper.py +5 -5
- android_env/wrappers/flat_interface_wrapper_test.py +7 -11
- android_env/wrappers/float_pixels_wrapper.py +9 -10
- android_env/wrappers/float_pixels_wrapper_test.py +3 -3
- android_env/wrappers/gym_wrapper.py +19 -13
- android_env/wrappers/gym_wrapper_test.py +3 -5
- android_env/wrappers/image_rescale_wrapper.py +18 -21
- android_env/wrappers/image_rescale_wrapper_test.py +25 -37
- android_env/wrappers/last_action_wrapper.py +16 -13
- android_env/wrappers/last_action_wrapper_test.py +44 -51
- android_env/wrappers/rate_limit_wrapper.py +6 -3
- android_env/wrappers/rate_limit_wrapper_test.py +22 -1
- android_env/wrappers/tap_action_wrapper.py +16 -17
- android_env/wrappers/tap_action_wrapper_test.py +51 -16
- {android_env-1.2.1.dist-info → android_env-1.2.3.dist-info}/METADATA +14 -18
- android_env-1.2.3.dist-info/RECORD +141 -0
- {android_env-1.2.1.dist-info → android_env-1.2.3.dist-info}/WHEEL +1 -1
- android_env/proto/raw_observation.proto +0 -39
- android_env/proto/raw_observation_pb2.py +0 -27
- android_env/proto/raw_observation_pb2_grpc.py +0 -4
- android_env-1.2.1.dist-info/RECORD +0 -81
- {android_env-1.2.1.dist-info → android_env-1.2.3.dist-info/licenses}/LICENSE +0 -0
- {android_env-1.2.1.dist-info → android_env-1.2.3.dist-info}/top_level.txt +0 -0
android_env/environment_test.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding=utf-8
|
2
|
-
# Copyright
|
2
|
+
# Copyright 2024 DeepMind Technologies Limited.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -19,9 +19,13 @@ from unittest import mock
|
|
19
19
|
|
20
20
|
from absl.testing import absltest
|
21
21
|
from android_env import environment
|
22
|
+
from android_env.components import config_classes
|
22
23
|
from android_env.components import coordinator as coordinator_lib
|
24
|
+
from android_env.components import task_manager as task_manager_lib
|
25
|
+
from android_env.components.simulators import base_simulator
|
26
|
+
from android_env.components.simulators.fake import fake_simulator
|
23
27
|
from android_env.proto import adb_pb2
|
24
|
-
from android_env.proto import
|
28
|
+
from android_env.proto import state_pb2
|
25
29
|
import dm_env
|
26
30
|
import numpy as np
|
27
31
|
|
@@ -40,16 +44,24 @@ def _create_mock_coordinator() -> coordinator_lib.Coordinator:
|
|
40
44
|
'timedelta': dm_env.specs.Array(shape=(), dtype=np.int64),
|
41
45
|
'orientation': dm_env.specs.Array(shape=(4,), dtype=np.uint8),
|
42
46
|
}
|
43
|
-
coordinator.task_extras_spec.return_value = {
|
44
|
-
'click': dm_env.specs.Array(shape=(), dtype=np.int64),
|
45
|
-
}
|
46
47
|
return coordinator
|
47
48
|
|
48
49
|
|
50
|
+
def _create_fake_simulator() -> fake_simulator.FakeSimulator:
|
51
|
+
return fake_simulator.FakeSimulator(
|
52
|
+
config=config_classes.FakeSimulatorConfig(screen_dimensions=(123, 456))
|
53
|
+
)
|
54
|
+
|
55
|
+
|
49
56
|
class AndroidEnvTest(absltest.TestCase):
|
50
57
|
|
51
58
|
def test_specs(self):
|
52
|
-
|
59
|
+
simulator = _create_fake_simulator()
|
60
|
+
coordinator = _create_mock_coordinator()
|
61
|
+
task_manager = mock.create_autospec(task_manager_lib.TaskManager)
|
62
|
+
env = environment.AndroidEnv(
|
63
|
+
simulator=simulator, coordinator=coordinator, task_manager=task_manager
|
64
|
+
)
|
53
65
|
|
54
66
|
# Check action spec.
|
55
67
|
self.assertNotEmpty(env.action_spec())
|
@@ -78,14 +90,10 @@ class AndroidEnvTest(absltest.TestCase):
|
|
78
90
|
dm_env.specs.Array)
|
79
91
|
self.assertEqual(env.observation_spec()['orientation'].shape, (4,))
|
80
92
|
|
81
|
-
# Check extras spec.
|
82
|
-
self.assertNotEmpty(env.task_extras_spec())
|
83
|
-
self.assertIn('click', env.task_extras_spec())
|
84
|
-
self.assertEqual(env.task_extras_spec()['click'].shape, ())
|
85
|
-
self.assertEqual(env.task_extras_spec()['click'].dtype, np.int64)
|
86
|
-
|
87
93
|
def test_reset_and_step(self):
|
88
|
-
|
94
|
+
simulator = _create_fake_simulator()
|
95
|
+
coordinator = _create_mock_coordinator()
|
96
|
+
task_manager = mock.create_autospec(task_manager_lib.TaskManager)
|
89
97
|
coordinator.action_spec.return_value = {
|
90
98
|
'action_type':
|
91
99
|
dm_env.specs.DiscreteArray(num_values=3),
|
@@ -98,10 +106,9 @@ class AndroidEnvTest(absltest.TestCase):
|
|
98
106
|
'timedelta': dm_env.specs.Array(shape=(), dtype=np.int64),
|
99
107
|
'orientation': dm_env.specs.Array(shape=(4,), dtype=np.uint8),
|
100
108
|
}
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
env = environment.AndroidEnv(coordinator)
|
109
|
+
env = environment.AndroidEnv(
|
110
|
+
simulator=simulator, coordinator=coordinator, task_manager=task_manager
|
111
|
+
)
|
105
112
|
coordinator.rl_reset.return_value = dm_env.TimeStep(
|
106
113
|
step_type=dm_env.StepType.FIRST,
|
107
114
|
reward=0.0,
|
@@ -136,9 +143,8 @@ class AndroidEnvTest(absltest.TestCase):
|
|
136
143
|
self.assertIn('click', extras)
|
137
144
|
self.assertEqual(extras['click'], np.array([246], dtype=np.int64))
|
138
145
|
|
139
|
-
coordinator.stats.return_value = {
|
140
|
-
|
141
|
-
}
|
146
|
+
coordinator.stats.return_value = {'my_measurement': 135}
|
147
|
+
task_manager.stats.return_value = {'another_measurement': 79}
|
142
148
|
|
143
149
|
# Step again in the environment and check expectations again.
|
144
150
|
pixels = np.random.rand(987, 654, 3)
|
@@ -200,8 +206,12 @@ class AndroidEnvTest(absltest.TestCase):
|
|
200
206
|
np.testing.assert_equal(obs['orientation'], (1, 0, 0, 0))
|
201
207
|
|
202
208
|
def test_adb_call(self):
|
209
|
+
simulator = _create_fake_simulator()
|
203
210
|
coordinator = _create_mock_coordinator()
|
204
|
-
|
211
|
+
task_manager = mock.create_autospec(task_manager_lib.TaskManager)
|
212
|
+
env = environment.AndroidEnv(
|
213
|
+
simulator=simulator, coordinator=coordinator, task_manager=task_manager
|
214
|
+
)
|
205
215
|
call = adb_pb2.AdbRequest(
|
206
216
|
force_stop=adb_pb2.AdbRequest.ForceStop(package_name='blah'))
|
207
217
|
expected_response = adb_pb2.AdbResponse(
|
@@ -213,18 +223,47 @@ class AndroidEnvTest(absltest.TestCase):
|
|
213
223
|
self.assertEqual(response, expected_response)
|
214
224
|
coordinator.execute_adb_call.assert_called_once_with(call)
|
215
225
|
|
216
|
-
def
|
226
|
+
def test_load_state(self):
|
227
|
+
simulator = mock.create_autospec(base_simulator.BaseSimulator)
|
228
|
+
coordinator = _create_mock_coordinator()
|
229
|
+
task_manager = mock.create_autospec(task_manager_lib.TaskManager)
|
230
|
+
env = environment.AndroidEnv(
|
231
|
+
simulator=simulator, coordinator=coordinator, task_manager=task_manager
|
232
|
+
)
|
233
|
+
expected_response = state_pb2.LoadStateResponse(
|
234
|
+
status=state_pb2.LoadStateResponse.Status.OK
|
235
|
+
)
|
236
|
+
request = state_pb2.LoadStateRequest(args={'foo': 'bar'})
|
237
|
+
simulator.load_state.return_value = expected_response
|
238
|
+
response = env.load_state(request)
|
239
|
+
self.assertEqual(response, expected_response)
|
240
|
+
simulator.load_state.assert_called_once_with(request)
|
241
|
+
task_manager.stop.assert_called_once()
|
242
|
+
task_manager.start.assert_called_once()
|
243
|
+
|
244
|
+
def test_save_state(self):
|
245
|
+
simulator = mock.create_autospec(base_simulator.BaseSimulator)
|
217
246
|
coordinator = _create_mock_coordinator()
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
247
|
+
task_manager = mock.create_autospec(task_manager_lib.TaskManager)
|
248
|
+
env = environment.AndroidEnv(
|
249
|
+
simulator=simulator, coordinator=coordinator, task_manager=task_manager
|
250
|
+
)
|
251
|
+
expected_response = state_pb2.SaveStateResponse(
|
252
|
+
status=state_pb2.SaveStateResponse.Status.OK
|
253
|
+
)
|
254
|
+
request = state_pb2.SaveStateRequest(args={'foo': 'bar'})
|
255
|
+
simulator.save_state.return_value = expected_response
|
256
|
+
response = env.save_state(request)
|
257
|
+
self.assertEqual(response, expected_response)
|
258
|
+
simulator.save_state.assert_called_once_with(request)
|
224
259
|
|
225
260
|
def test_double_close(self):
|
261
|
+
simulator = _create_fake_simulator()
|
226
262
|
coordinator = _create_mock_coordinator()
|
227
|
-
|
263
|
+
task_manager = mock.create_autospec(task_manager_lib.TaskManager)
|
264
|
+
env = environment.AndroidEnv(
|
265
|
+
simulator=simulator, coordinator=coordinator, task_manager=task_manager
|
266
|
+
)
|
228
267
|
env.close()
|
229
268
|
env.close()
|
230
269
|
coordinator.close.assert_called_once()
|
android_env/loader.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding=utf-8
|
2
|
-
# Copyright
|
2
|
+
# Copyright 2024 DeepMind Technologies Limited.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -17,59 +17,73 @@
|
|
17
17
|
|
18
18
|
import os
|
19
19
|
|
20
|
+
from absl import logging
|
20
21
|
from android_env import environment
|
22
|
+
from android_env.components import config_classes
|
21
23
|
from android_env.components import coordinator as coordinator_lib
|
24
|
+
from android_env.components import device_settings as device_settings_lib
|
22
25
|
from android_env.components import task_manager as task_manager_lib
|
23
26
|
from android_env.components.simulators.emulator import emulator_simulator
|
27
|
+
from android_env.components.simulators.fake import fake_simulator
|
24
28
|
from android_env.proto import task_pb2
|
25
29
|
|
26
30
|
from google.protobuf import text_format
|
27
31
|
|
28
32
|
|
29
|
-
def
|
30
|
-
|
31
|
-
android_avd_home: str = '~/.android/avd',
|
32
|
-
android_sdk_root: str = '~/Android/Sdk',
|
33
|
-
emulator_path: str = '~/Android/Sdk/emulator/emulator',
|
34
|
-
adb_path: str = '~/Android/Sdk/platform-tools/adb',
|
35
|
-
run_headless: bool = False) -> environment.AndroidEnv:
|
36
|
-
"""Loads an AndroidEnv instance.
|
37
|
-
|
38
|
-
Args:
|
39
|
-
task_path: Path to the task textproto file.
|
40
|
-
avd_name: Name of the AVD (Android Virtual Device).
|
41
|
-
android_avd_home: Path to the AVD (Android Virtual Device).
|
42
|
-
android_sdk_root: Root directory of the SDK.
|
43
|
-
emulator_path: Path to the emulator binary.
|
44
|
-
adb_path: Path to the ADB (Android Debug Bridge).
|
45
|
-
run_headless: If True, the emulator display is turned off.
|
46
|
-
Returns:
|
47
|
-
env: An AndroidEnv instance.
|
48
|
-
"""
|
49
|
-
|
50
|
-
# Create simulator.
|
51
|
-
simulator = emulator_simulator.EmulatorSimulator(
|
52
|
-
adb_controller_args=dict(
|
53
|
-
adb_path=os.path.expanduser(adb_path),
|
54
|
-
adb_server_port=5037,
|
55
|
-
),
|
56
|
-
emulator_launcher_args=dict(
|
57
|
-
avd_name=avd_name,
|
58
|
-
android_avd_home=os.path.expanduser(android_avd_home),
|
59
|
-
android_sdk_root=os.path.expanduser(android_sdk_root),
|
60
|
-
emulator_path=os.path.expanduser(emulator_path),
|
61
|
-
run_headless=run_headless,
|
62
|
-
gpu_mode='swiftshader_indirect',
|
63
|
-
),
|
64
|
-
)
|
33
|
+
def _load_task(task_config: config_classes.TaskConfig) -> task_pb2.Task:
|
34
|
+
"""Returns the task according to `task_config`."""
|
65
35
|
|
66
|
-
# Prepare task.
|
67
36
|
task = task_pb2.Task()
|
68
|
-
|
69
|
-
|
37
|
+
match task_config:
|
38
|
+
case config_classes.FilesystemTaskConfig():
|
39
|
+
with open(task_config.path, 'r') as proto_file:
|
40
|
+
text_format.Parse(proto_file.read(), task)
|
41
|
+
case _:
|
42
|
+
logging.error('Unsupported TaskConfig: %r', task_config)
|
43
|
+
|
44
|
+
return task
|
45
|
+
|
46
|
+
|
47
|
+
def load(config: config_classes.AndroidEnvConfig) -> environment.AndroidEnv:
|
48
|
+
"""Loads an AndroidEnv instance."""
|
70
49
|
|
50
|
+
task = _load_task(config.task)
|
71
51
|
task_manager = task_manager_lib.TaskManager(task)
|
72
|
-
coordinator = coordinator_lib.Coordinator(simulator, task_manager)
|
73
52
|
|
74
|
-
|
75
|
-
|
53
|
+
match config.simulator:
|
54
|
+
case config_classes.EmulatorConfig():
|
55
|
+
_process_emulator_launcher_config(config.simulator)
|
56
|
+
simulator = emulator_simulator.EmulatorSimulator(config=config.simulator)
|
57
|
+
case config_classes.FakeSimulatorConfig():
|
58
|
+
simulator = fake_simulator.FakeSimulator(config=config.simulator)
|
59
|
+
case _:
|
60
|
+
raise ValueError('Unsupported simulator config: {config.simulator}')
|
61
|
+
|
62
|
+
device_settings = device_settings_lib.DeviceSettings(simulator)
|
63
|
+
coordinator = coordinator_lib.Coordinator(
|
64
|
+
simulator, task_manager, device_settings
|
65
|
+
)
|
66
|
+
return environment.AndroidEnv(
|
67
|
+
simulator=simulator, coordinator=coordinator, task_manager=task_manager
|
68
|
+
)
|
69
|
+
|
70
|
+
|
71
|
+
def _process_emulator_launcher_config(
|
72
|
+
emulator_config: config_classes.EmulatorConfig,
|
73
|
+
) -> None:
|
74
|
+
"""Adjusts the configuration of the emulator depending on some conditions."""
|
75
|
+
|
76
|
+
# Expand the user directory if specified.
|
77
|
+
launcher_config = emulator_config.emulator_launcher
|
78
|
+
launcher_config.android_avd_home = os.path.expanduser(
|
79
|
+
launcher_config.android_avd_home
|
80
|
+
)
|
81
|
+
launcher_config.android_sdk_root = os.path.expanduser(
|
82
|
+
launcher_config.android_sdk_root
|
83
|
+
)
|
84
|
+
launcher_config.emulator_path = os.path.expanduser(
|
85
|
+
launcher_config.emulator_path
|
86
|
+
)
|
87
|
+
emulator_config.adb_controller.adb_path = os.path.expanduser(
|
88
|
+
emulator_config.adb_controller.adb_path
|
89
|
+
)
|
android_env/loader_test.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding=utf-8
|
2
|
-
# Copyright
|
2
|
+
# Copyright 2024 DeepMind Technologies Limited.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -20,11 +20,14 @@ import os
|
|
20
20
|
from unittest import mock
|
21
21
|
|
22
22
|
from absl.testing import absltest
|
23
|
-
from android_env import
|
23
|
+
from android_env import env_interface
|
24
24
|
from android_env import loader
|
25
|
+
from android_env.components import config_classes
|
25
26
|
from android_env.components import coordinator as coordinator_lib
|
27
|
+
from android_env.components import device_settings as device_settings_lib
|
26
28
|
from android_env.components import task_manager as task_manager_lib
|
27
29
|
from android_env.components.simulators.emulator import emulator_simulator
|
30
|
+
from android_env.components.simulators.fake import fake_simulator
|
28
31
|
from android_env.proto import task_pb2
|
29
32
|
|
30
33
|
|
@@ -32,49 +35,116 @@ class LoaderTest(absltest.TestCase):
|
|
32
35
|
|
33
36
|
@mock.patch.object(task_manager_lib, 'TaskManager', autospec=True)
|
34
37
|
@mock.patch.object(emulator_simulator, 'EmulatorSimulator', autospec=True)
|
38
|
+
@mock.patch.object(device_settings_lib, 'DeviceSettings', autospec=True)
|
35
39
|
@mock.patch.object(coordinator_lib, 'Coordinator', autospec=True)
|
36
40
|
@mock.patch.object(builtins, 'open', autospec=True)
|
37
|
-
def
|
38
|
-
|
41
|
+
def test_load_emulator(
|
42
|
+
self,
|
43
|
+
mock_open,
|
44
|
+
mock_coordinator,
|
45
|
+
mock_device_settings,
|
46
|
+
mock_simulator_class,
|
47
|
+
mock_task_manager,
|
48
|
+
):
|
49
|
+
|
50
|
+
# Arrange.
|
39
51
|
mock_open.return_value.__enter__ = mock_open
|
40
52
|
mock_open.return_value.read.return_value = ''
|
53
|
+
config = config_classes.AndroidEnvConfig(
|
54
|
+
task=config_classes.FilesystemTaskConfig(path='some/path/'),
|
55
|
+
simulator=config_classes.EmulatorConfig(
|
56
|
+
emulator_launcher=config_classes.EmulatorLauncherConfig(
|
57
|
+
avd_name='my_avd',
|
58
|
+
android_avd_home='~/.android/avd',
|
59
|
+
android_sdk_root='~/Android/Sdk',
|
60
|
+
emulator_path='~/Android/Sdk/emulator/emulator',
|
61
|
+
run_headless=False,
|
62
|
+
),
|
63
|
+
adb_controller=config_classes.AdbControllerConfig(
|
64
|
+
adb_path='~/Android/Sdk/platform-tools/adb',
|
65
|
+
),
|
66
|
+
),
|
67
|
+
)
|
41
68
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
69
|
+
# Act.
|
70
|
+
env = loader.load(config)
|
71
|
+
|
72
|
+
# Assert.
|
73
|
+
self.assertIsInstance(env, env_interface.AndroidEnvInterface)
|
74
|
+
mock_simulator_class.assert_called_with(
|
75
|
+
config=config_classes.EmulatorConfig(
|
76
|
+
emulator_launcher=config_classes.EmulatorLauncherConfig(
|
77
|
+
avd_name='my_avd',
|
78
|
+
android_avd_home=os.path.expanduser('~/.android/avd'),
|
79
|
+
android_sdk_root=os.path.expanduser('~/Android/Sdk'),
|
80
|
+
emulator_path=os.path.expanduser(
|
81
|
+
'~/Android/Sdk/emulator/emulator'
|
82
|
+
),
|
83
|
+
run_headless=False,
|
84
|
+
gpu_mode='swangle_indirect',
|
85
|
+
),
|
86
|
+
adb_controller=config_classes.AdbControllerConfig(
|
87
|
+
adb_path=os.path.expanduser('~/Android/Sdk/platform-tools/adb'),
|
88
|
+
adb_server_port=5037,
|
89
|
+
),
|
90
|
+
)
|
91
|
+
)
|
92
|
+
mock_coordinator.assert_called_with(
|
93
|
+
mock_simulator_class.return_value,
|
94
|
+
mock_task_manager.return_value,
|
95
|
+
mock_device_settings.return_value,
|
50
96
|
)
|
51
97
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
98
|
+
@mock.patch.object(task_manager_lib, 'TaskManager', autospec=True)
|
99
|
+
@mock.patch.object(fake_simulator, 'FakeSimulator', autospec=True)
|
100
|
+
@mock.patch.object(device_settings_lib, 'DeviceSettings', autospec=True)
|
101
|
+
@mock.patch.object(coordinator_lib, 'Coordinator', autospec=True)
|
102
|
+
@mock.patch.object(builtins, 'open', autospec=True)
|
103
|
+
def test_load_fake_simulator(
|
104
|
+
self,
|
105
|
+
mock_open,
|
106
|
+
mock_coordinator,
|
107
|
+
mock_device_settings,
|
108
|
+
mock_simulator_class,
|
109
|
+
mock_task_manager,
|
110
|
+
):
|
111
|
+
|
112
|
+
# Arrange.
|
113
|
+
mock_open.return_value.__enter__ = mock_open
|
114
|
+
mock_open.return_value.read.return_value = ''
|
115
|
+
config = config_classes.AndroidEnvConfig(
|
116
|
+
task=config_classes.FilesystemTaskConfig(path='some/path/'),
|
117
|
+
simulator=config_classes.FakeSimulatorConfig(
|
118
|
+
screen_dimensions=(1234, 5678)
|
57
119
|
),
|
58
|
-
emulator_launcher_args=dict(
|
59
|
-
avd_name='my_avd',
|
60
|
-
android_avd_home=os.path.expanduser('~/.android/avd'),
|
61
|
-
android_sdk_root=os.path.expanduser('~/Android/Sdk'),
|
62
|
-
emulator_path=os.path.expanduser('~/Android/Sdk/emulator/emulator'),
|
63
|
-
run_headless=False,
|
64
|
-
gpu_mode='swiftshader_indirect'),
|
65
120
|
)
|
66
|
-
|
67
|
-
|
68
|
-
|
121
|
+
|
122
|
+
# Act.
|
123
|
+
env = loader.load(config)
|
124
|
+
|
125
|
+
# Assert.
|
126
|
+
self.assertIsInstance(env, env_interface.AndroidEnvInterface)
|
127
|
+
mock_simulator_class.assert_called_with(
|
128
|
+
config=config_classes.FakeSimulatorConfig(
|
129
|
+
screen_dimensions=(1234, 5678)
|
130
|
+
)
|
131
|
+
)
|
132
|
+
mock_coordinator.assert_called_with(
|
133
|
+
mock_simulator_class.return_value,
|
134
|
+
mock_task_manager.return_value,
|
135
|
+
mock_device_settings.return_value,
|
69
136
|
)
|
70
137
|
|
71
138
|
@mock.patch.object(task_manager_lib, 'TaskManager', autospec=True)
|
72
139
|
@mock.patch.object(emulator_simulator, 'EmulatorSimulator', autospec=True)
|
73
140
|
@mock.patch.object(coordinator_lib, 'Coordinator', autospec=True)
|
74
141
|
@mock.patch.object(builtins, 'open', autospec=True)
|
75
|
-
def test_task(
|
142
|
+
def test_task(
|
143
|
+
self, mock_open, mock_coordinator, mock_simulator, mock_task_manager
|
144
|
+
):
|
76
145
|
|
77
|
-
|
146
|
+
# Arrange.
|
147
|
+
del mock_coordinator, mock_simulator
|
78
148
|
mock_open.return_value.__enter__ = mock_open
|
79
149
|
mock_open.return_value.read.return_value = r'''
|
80
150
|
id: "fake_task"
|
@@ -82,20 +152,30 @@ name: "Fake Task"
|
|
82
152
|
description: "Task for testing loader."
|
83
153
|
max_episode_sec: 0
|
84
154
|
'''
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
155
|
+
config = config_classes.AndroidEnvConfig(
|
156
|
+
task=config_classes.FilesystemTaskConfig(path='some/path/'),
|
157
|
+
simulator=config_classes.EmulatorConfig(
|
158
|
+
emulator_launcher=config_classes.EmulatorLauncherConfig(
|
159
|
+
avd_name='my_avd'
|
160
|
+
),
|
161
|
+
adb_controller=config_classes.AdbControllerConfig(
|
162
|
+
adb_path='~/Android/Sdk/platform-tools/adb',
|
163
|
+
),
|
164
|
+
),
|
89
165
|
)
|
90
166
|
|
167
|
+
# Act.
|
168
|
+
env = loader.load(config)
|
169
|
+
|
170
|
+
# Assert.
|
91
171
|
expected_task = task_pb2.Task()
|
92
172
|
expected_task.id = 'fake_task'
|
93
173
|
expected_task.name = 'Fake Task'
|
94
174
|
expected_task.description = 'Task for testing loader.'
|
95
175
|
expected_task.max_episode_sec = 0
|
96
176
|
|
97
|
-
|
98
|
-
|
177
|
+
mock_task_manager.assert_called_with(expected_task)
|
178
|
+
self.assertIsInstance(env, env_interface.AndroidEnvInterface)
|
99
179
|
|
100
180
|
|
101
181
|
if __name__ == '__main__':
|
android_env/proto/__init__.py
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# coding=utf-8
|
2
|
+
# Copyright 2024 DeepMind Technologies Limited.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
// Copyright 2024 DeepMind Technologies Limited.
|
2
|
+
//
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
// you may not use this file except in compliance with the License.
|
5
|
+
// You may obtain a copy of the License at
|
6
|
+
//
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
//
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
// See the License for the specific language governing permissions and
|
13
|
+
// limitations under the License.
|
14
|
+
|
15
|
+
syntax = "proto3";
|
16
|
+
|
17
|
+
package android_env;
|
18
|
+
|
19
|
+
import "android_env/proto/a11y/android_accessibility_forest.proto";
|
20
|
+
|
21
|
+
option java_multiple_files = true;
|
22
|
+
option java_package = "com.google.androidenv.accessibilityforwarder";
|
23
|
+
|
24
|
+
// A service to send Accessibility information to a remote server.
|
25
|
+
//
|
26
|
+
// The client is assumed to be running inside an Android device (e.g. emulator
|
27
|
+
// or real device) while the server is assumed to be running outside (e.g. in a
|
28
|
+
// Python process).
|
29
|
+
service A11yService {
|
30
|
+
// Sends a forest of Accessibility trees to a server.
|
31
|
+
rpc SendForest(AndroidAccessibilityForest) returns (ForestResponse) {}
|
32
|
+
// Sends an a11y event to a server.
|
33
|
+
rpc SendEvent(EventRequest) returns (EventResponse) {}
|
34
|
+
|
35
|
+
// Long-lived bidirection communication between the client and the server.
|
36
|
+
rpc Bidi(stream ClientToServer) returns (stream ServerToClient) {}
|
37
|
+
}
|
38
|
+
|
39
|
+
// TODO(b/334952387): Remove `ForestResponse`, `EventRequest` and
|
40
|
+
// `EventResponse` once bidi communication is in-place.
|
41
|
+
message ForestResponse {
|
42
|
+
// The error if anything.
|
43
|
+
string error = 1;
|
44
|
+
}
|
45
|
+
|
46
|
+
// An Accessibility event.
|
47
|
+
message EventRequest {
|
48
|
+
// A single event as a dictionary.
|
49
|
+
map<string, string> event = 1;
|
50
|
+
}
|
51
|
+
|
52
|
+
message EventResponse {
|
53
|
+
// The error if anything.
|
54
|
+
string error = 1;
|
55
|
+
}
|
56
|
+
|
57
|
+
// The message sent from the Android device to the server running outside of the
|
58
|
+
// device.
|
59
|
+
message ClientToServer {
|
60
|
+
oneof payload {
|
61
|
+
EventRequest event = 1;
|
62
|
+
AndroidAccessibilityForest forest = 2;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
// The message sent from the server running outside of the device to the Android
|
67
|
+
// device.
|
68
|
+
message ServerToClient {
|
69
|
+
// A request to obtain the Accessibility forest.
|
70
|
+
message GetA11yForest {}
|
71
|
+
|
72
|
+
oneof payload {
|
73
|
+
GetA11yForest get_forest = 1;
|
74
|
+
}
|
75
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
4
|
+
# source: android_env/proto/a11y/a11y.proto
|
5
|
+
# Protobuf Python Version: 5.29.0
|
6
|
+
"""Generated protocol buffer code."""
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
11
|
+
from google.protobuf.internal import builder as _builder
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
14
|
+
5,
|
15
|
+
29,
|
16
|
+
0,
|
17
|
+
'',
|
18
|
+
'android_env/proto/a11y/a11y.proto'
|
19
|
+
)
|
20
|
+
# @@protoc_insertion_point(imports)
|
21
|
+
|
22
|
+
_sym_db = _symbol_database.Default()
|
23
|
+
|
24
|
+
|
25
|
+
from android_env.proto.a11y import android_accessibility_forest_pb2 as android__env_dot_proto_dot_a11y_dot_android__accessibility__forest__pb2
|
26
|
+
|
27
|
+
|
28
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!android_env/proto/a11y/a11y.proto\x12\x0b\x61ndroid_env\x1a\x39\x61ndroid_env/proto/a11y/android_accessibility_forest.proto\"\x1f\n\x0e\x46orestResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\"q\n\x0c\x45ventRequest\x12\x33\n\x05\x65vent\x18\x01 \x03(\x0b\x32$.android_env.EventRequest.EventEntry\x1a,\n\nEventEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1e\n\rEventResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\"\x82\x01\n\x0e\x43lientToServer\x12*\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x19.android_env.EventRequestH\x00\x12\x39\n\x06\x66orest\x18\x02 \x01(\x0b\x32\'.android_env.AndroidAccessibilityForestH\x00\x42\t\n\x07payload\"m\n\x0eServerToClient\x12?\n\nget_forest\x18\x01 \x01(\x0b\x32).android_env.ServerToClient.GetA11yForestH\x00\x1a\x0f\n\rGetA11yForestB\t\n\x07payload2\xf1\x01\n\x0b\x41\x31\x31yService\x12T\n\nSendForest\x12\'.android_env.AndroidAccessibilityForest\x1a\x1b.android_env.ForestResponse\"\x00\x12\x44\n\tSendEvent\x12\x19.android_env.EventRequest\x1a\x1a.android_env.EventResponse\"\x00\x12\x46\n\x04\x42idi\x12\x1b.android_env.ClientToServer\x1a\x1b.android_env.ServerToClient\"\x00(\x01\x30\x01\x42\x30\n,com.google.androidenv.accessibilityforwarderP\x01\x62\x06proto3')
|
29
|
+
|
30
|
+
_globals = globals()
|
31
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
32
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'android_env.proto.a11y.a11y_pb2', _globals)
|
33
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
34
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
35
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n,com.google.androidenv.accessibilityforwarderP\001'
|
36
|
+
_globals['_EVENTREQUEST_EVENTENTRY']._loaded_options = None
|
37
|
+
_globals['_EVENTREQUEST_EVENTENTRY']._serialized_options = b'8\001'
|
38
|
+
_globals['_FORESTRESPONSE']._serialized_start=109
|
39
|
+
_globals['_FORESTRESPONSE']._serialized_end=140
|
40
|
+
_globals['_EVENTREQUEST']._serialized_start=142
|
41
|
+
_globals['_EVENTREQUEST']._serialized_end=255
|
42
|
+
_globals['_EVENTREQUEST_EVENTENTRY']._serialized_start=211
|
43
|
+
_globals['_EVENTREQUEST_EVENTENTRY']._serialized_end=255
|
44
|
+
_globals['_EVENTRESPONSE']._serialized_start=257
|
45
|
+
_globals['_EVENTRESPONSE']._serialized_end=287
|
46
|
+
_globals['_CLIENTTOSERVER']._serialized_start=290
|
47
|
+
_globals['_CLIENTTOSERVER']._serialized_end=420
|
48
|
+
_globals['_SERVERTOCLIENT']._serialized_start=422
|
49
|
+
_globals['_SERVERTOCLIENT']._serialized_end=531
|
50
|
+
_globals['_SERVERTOCLIENT_GETA11YFOREST']._serialized_start=505
|
51
|
+
_globals['_SERVERTOCLIENT_GETA11YFOREST']._serialized_end=520
|
52
|
+
_globals['_A11YSERVICE']._serialized_start=534
|
53
|
+
_globals['_A11YSERVICE']._serialized_end=775
|
54
|
+
# @@protoc_insertion_point(module_scope)
|