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.
Files changed (145) hide show
  1. android_env/__init__.py +1 -1
  2. android_env/components/__init__.py +1 -1
  3. android_env/components/a11y/__init__.py +15 -0
  4. android_env/components/a11y/a11y_events.py +118 -0
  5. android_env/components/a11y/a11y_events_test.py +173 -0
  6. android_env/components/a11y/a11y_forests.py +128 -0
  7. android_env/components/a11y/a11y_forests_test.py +237 -0
  8. android_env/components/a11y/a11y_servicer.py +199 -0
  9. android_env/components/a11y/a11y_servicer_test.py +224 -0
  10. android_env/components/action_fns.py +132 -0
  11. android_env/components/action_fns_test.py +227 -0
  12. android_env/components/action_type.py +26 -3
  13. android_env/components/adb_call_parser.py +239 -196
  14. android_env/components/adb_call_parser_test.py +179 -209
  15. android_env/components/adb_controller.py +90 -52
  16. android_env/components/adb_controller_test.py +187 -16
  17. android_env/components/adb_log_stream.py +17 -5
  18. android_env/components/adb_log_stream_test.py +17 -3
  19. android_env/components/app_screen_checker.py +17 -15
  20. android_env/components/app_screen_checker_test.py +7 -8
  21. android_env/components/config_classes.py +203 -0
  22. android_env/components/coordinator.py +102 -338
  23. android_env/components/coordinator_test.py +59 -199
  24. android_env/components/device_settings.py +174 -0
  25. android_env/components/device_settings_test.py +228 -0
  26. android_env/components/dumpsys_thread.py +3 -4
  27. android_env/components/dumpsys_thread_test.py +1 -1
  28. android_env/components/errors.py +52 -10
  29. android_env/components/errors_test.py +110 -0
  30. android_env/components/log_stream.py +7 -5
  31. android_env/components/log_stream_test.py +1 -1
  32. android_env/components/logcat_thread.py +9 -8
  33. android_env/components/logcat_thread_test.py +3 -4
  34. android_env/components/{utils.py → pixel_fns.py} +20 -20
  35. android_env/components/{utils_test.py → pixel_fns_test.py} +20 -15
  36. android_env/components/setup_step_interpreter.py +47 -39
  37. android_env/components/setup_step_interpreter_test.py +4 -4
  38. android_env/components/simulators/__init__.py +1 -1
  39. android_env/components/simulators/base_simulator.py +116 -44
  40. android_env/components/simulators/base_simulator_test.py +131 -9
  41. android_env/components/simulators/emulator/__init__.py +1 -1
  42. android_env/components/simulators/emulator/emulator_launcher.py +67 -77
  43. android_env/components/simulators/emulator/emulator_launcher_test.py +153 -49
  44. android_env/components/simulators/emulator/emulator_simulator.py +276 -95
  45. android_env/components/simulators/emulator/emulator_simulator_test.py +314 -89
  46. android_env/components/simulators/fake/__init__.py +1 -1
  47. android_env/components/simulators/fake/fake_simulator.py +17 -25
  48. android_env/components/simulators/fake/fake_simulator_test.py +29 -12
  49. android_env/components/specs.py +18 -28
  50. android_env/components/specs_test.py +1 -44
  51. android_env/components/task_manager.py +48 -48
  52. android_env/components/task_manager_test.py +71 -60
  53. android_env/env_interface.py +37 -23
  54. android_env/environment.py +83 -51
  55. android_env/environment_test.py +68 -29
  56. android_env/loader.py +57 -43
  57. android_env/loader_test.py +115 -35
  58. android_env/proto/__init__.py +1 -1
  59. android_env/proto/a11y/__init__.py +15 -0
  60. android_env/proto/a11y/a11y.proto +75 -0
  61. android_env/proto/a11y/a11y_pb2.py +54 -0
  62. android_env/proto/a11y/a11y_pb2.pyi +49 -0
  63. android_env/proto/a11y/a11y_pb2_grpc.py +202 -0
  64. android_env/proto/a11y/android_accessibility_action.proto +32 -0
  65. android_env/proto/a11y/android_accessibility_action_pb2.py +37 -0
  66. android_env/proto/a11y/android_accessibility_action_pb2.pyi +13 -0
  67. android_env/proto/a11y/android_accessibility_action_pb2_grpc.py +24 -0
  68. android_env/proto/a11y/android_accessibility_forest.proto +29 -0
  69. android_env/proto/a11y/android_accessibility_forest_pb2.py +38 -0
  70. android_env/proto/a11y/android_accessibility_forest_pb2.pyi +13 -0
  71. android_env/proto/a11y/android_accessibility_forest_pb2_grpc.py +24 -0
  72. android_env/proto/a11y/android_accessibility_node_info.proto +122 -0
  73. android_env/proto/a11y/android_accessibility_node_info_clickable_span.proto +49 -0
  74. android_env/proto/a11y/android_accessibility_node_info_clickable_span_pb2.py +39 -0
  75. android_env/proto/a11y/android_accessibility_node_info_clickable_span_pb2.pyi +28 -0
  76. android_env/proto/a11y/android_accessibility_node_info_clickable_span_pb2_grpc.py +24 -0
  77. android_env/proto/a11y/android_accessibility_node_info_pb2.py +42 -0
  78. android_env/proto/a11y/android_accessibility_node_info_pb2.pyi +75 -0
  79. android_env/proto/a11y/android_accessibility_node_info_pb2_grpc.py +24 -0
  80. android_env/proto/a11y/android_accessibility_tree.proto +29 -0
  81. android_env/proto/a11y/android_accessibility_tree_pb2.py +38 -0
  82. android_env/proto/a11y/android_accessibility_tree_pb2.pyi +13 -0
  83. android_env/proto/a11y/android_accessibility_tree_pb2_grpc.py +24 -0
  84. android_env/proto/a11y/android_accessibility_window_info.proto +84 -0
  85. android_env/proto/a11y/android_accessibility_window_info_pb2.py +41 -0
  86. android_env/proto/a11y/android_accessibility_window_info_pb2.pyi +48 -0
  87. android_env/proto/a11y/android_accessibility_window_info_pb2_grpc.py +24 -0
  88. android_env/proto/a11y/rect.proto +30 -0
  89. android_env/proto/a11y/rect_pb2.py +37 -0
  90. android_env/proto/a11y/rect_pb2.pyi +17 -0
  91. android_env/proto/a11y/rect_pb2_grpc.py +24 -0
  92. android_env/proto/adb.proto +17 -6
  93. android_env/proto/adb_pb2.py +120 -107
  94. android_env/proto/adb_pb2.pyi +396 -0
  95. android_env/proto/adb_pb2_grpc.py +20 -0
  96. android_env/proto/emulator_controller.proto +68 -63
  97. android_env/proto/emulator_controller_pb2.py +142 -131
  98. android_env/proto/emulator_controller_pb2.pyi +672 -0
  99. android_env/proto/emulator_controller_pb2_grpc.py +505 -142
  100. android_env/proto/snapshot.proto +169 -0
  101. android_env/proto/snapshot_pb2.py +47 -0
  102. android_env/proto/snapshot_pb2.pyi +117 -0
  103. android_env/proto/snapshot_pb2_grpc.py +24 -0
  104. android_env/proto/snapshot_service.proto +289 -0
  105. android_env/proto/snapshot_service_pb2.py +54 -0
  106. android_env/proto/snapshot_service_pb2.pyi +86 -0
  107. android_env/proto/snapshot_service_pb2_grpc.py +487 -0
  108. android_env/proto/state.proto +63 -0
  109. android_env/proto/state_pb2.py +63 -0
  110. android_env/proto/state_pb2.pyi +85 -0
  111. android_env/proto/state_pb2_grpc.py +24 -0
  112. android_env/proto/task.proto +5 -1
  113. android_env/proto/task_pb2.py +42 -31
  114. android_env/proto/task_pb2.pyi +160 -0
  115. android_env/proto/task_pb2_grpc.py +20 -0
  116. android_env/wrappers/__init__.py +1 -1
  117. android_env/wrappers/a11y_grpc_wrapper.py +500 -0
  118. android_env/wrappers/a11y_grpc_wrapper_test.py +849 -0
  119. android_env/wrappers/base_wrapper.py +34 -13
  120. android_env/wrappers/base_wrapper_test.py +22 -16
  121. android_env/wrappers/discrete_action_wrapper.py +18 -17
  122. android_env/wrappers/discrete_action_wrapper_test.py +4 -4
  123. android_env/wrappers/flat_interface_wrapper.py +5 -5
  124. android_env/wrappers/flat_interface_wrapper_test.py +7 -11
  125. android_env/wrappers/float_pixels_wrapper.py +9 -10
  126. android_env/wrappers/float_pixels_wrapper_test.py +3 -3
  127. android_env/wrappers/gym_wrapper.py +19 -13
  128. android_env/wrappers/gym_wrapper_test.py +3 -5
  129. android_env/wrappers/image_rescale_wrapper.py +18 -21
  130. android_env/wrappers/image_rescale_wrapper_test.py +25 -37
  131. android_env/wrappers/last_action_wrapper.py +16 -13
  132. android_env/wrappers/last_action_wrapper_test.py +44 -51
  133. android_env/wrappers/rate_limit_wrapper.py +6 -3
  134. android_env/wrappers/rate_limit_wrapper_test.py +22 -1
  135. android_env/wrappers/tap_action_wrapper.py +16 -17
  136. android_env/wrappers/tap_action_wrapper_test.py +51 -16
  137. {android_env-1.2.1.dist-info → android_env-1.2.3.dist-info}/METADATA +14 -18
  138. android_env-1.2.3.dist-info/RECORD +141 -0
  139. {android_env-1.2.1.dist-info → android_env-1.2.3.dist-info}/WHEEL +1 -1
  140. android_env/proto/raw_observation.proto +0 -39
  141. android_env/proto/raw_observation_pb2.py +0 -27
  142. android_env/proto/raw_observation_pb2_grpc.py +0 -4
  143. android_env-1.2.1.dist-info/RECORD +0 -81
  144. {android_env-1.2.1.dist-info → android_env-1.2.3.dist-info/licenses}/LICENSE +0 -0
  145. {android_env-1.2.1.dist-info → android_env-1.2.3.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2022 DeepMind Technologies Limited.
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 task_pb2
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
- env = environment.AndroidEnv(_create_mock_coordinator())
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
- coordinator = mock.create_autospec(coordinator_lib.Coordinator)
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
- coordinator.task_extras_spec.return_value = {
102
- 'click': dm_env.specs.Array(shape=(1,), dtype=np.int64),
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
- 'my_measurement': 135,
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
- env = environment.AndroidEnv(coordinator)
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 test_update_task(self):
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
- env = environment.AndroidEnv(coordinator)
219
- task = task_pb2.Task()
220
- coordinator.update_task.return_value = True
221
- response = env.update_task(task)
222
- self.assertEqual(response, True)
223
- coordinator.update_task.assert_called_once_with(task)
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
- env = environment.AndroidEnv(coordinator)
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 2022 DeepMind Technologies Limited.
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 load(task_path: str,
30
- avd_name: str,
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
- with open(task_path, 'r') as proto_file:
69
- text_format.Parse(proto_file.read(), task)
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
- # Load environment.
75
- return environment.AndroidEnv(coordinator=coordinator)
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
+ )
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2022 DeepMind Technologies Limited.
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 environment
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 test_load(self, mock_open, coordinator, simulator, task_manager):
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
- env = loader.load(
43
- task_path='some/path/',
44
- avd_name='my_avd',
45
- android_avd_home='~/.android/avd',
46
- android_sdk_root='~/Android/Sdk',
47
- emulator_path='~/Android/Sdk/emulator/emulator',
48
- adb_path='~/Android/Sdk/platform-tools/adb',
49
- run_headless=False,
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
- self.assertIsInstance(env, environment.AndroidEnv)
53
- simulator.assert_called_with(
54
- adb_controller_args=dict(
55
- adb_path=os.path.expanduser('~/Android/Sdk/platform-tools/adb'),
56
- adb_server_port=5037,
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
- coordinator.assert_called_with(
67
- simulator.return_value,
68
- task_manager.return_value,
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(self, mock_open, coordinator, simulator, task_manager):
142
+ def test_task(
143
+ self, mock_open, mock_coordinator, mock_simulator, mock_task_manager
144
+ ):
76
145
 
77
- del coordinator, simulator
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
- env = loader.load(
87
- task_path='some/path/',
88
- avd_name='my_avd',
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
- task_manager.assert_called_with(expected_task)
98
- assert isinstance(env, environment.AndroidEnv)
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__':
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2022 DeepMind Technologies Limited.
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.
@@ -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)