android-env 1.2.2__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 (142) 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 +233 -185
  14. android_env/components/adb_call_parser_test.py +165 -163
  15. android_env/components/adb_controller.py +19 -28
  16. android_env/components/adb_controller_test.py +100 -9
  17. android_env/components/adb_log_stream.py +3 -3
  18. android_env/components/adb_log_stream_test.py +1 -1
  19. android_env/components/app_screen_checker.py +15 -13
  20. android_env/components/app_screen_checker_test.py +1 -1
  21. android_env/components/config_classes.py +203 -0
  22. android_env/components/coordinator.py +53 -338
  23. android_env/components/coordinator_test.py +26 -283
  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 +2 -5
  29. android_env/components/errors_test.py +1 -1
  30. android_env/components/log_stream.py +2 -2
  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 +2 -3
  34. android_env/components/{utils.py → pixel_fns.py} +19 -20
  35. android_env/components/{utils_test.py → pixel_fns_test.py} +20 -15
  36. android_env/components/setup_step_interpreter.py +45 -37
  37. android_env/components/setup_step_interpreter_test.py +1 -1
  38. android_env/components/simulators/__init__.py +1 -1
  39. android_env/components/simulators/base_simulator.py +79 -23
  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 +62 -81
  43. android_env/components/simulators/emulator/emulator_launcher_test.py +120 -43
  44. android_env/components/simulators/emulator/emulator_simulator.py +111 -98
  45. android_env/components/simulators/emulator/emulator_simulator_test.py +174 -138
  46. android_env/components/simulators/fake/__init__.py +1 -1
  47. android_env/components/simulators/fake/fake_simulator.py +9 -17
  48. android_env/components/simulators/fake/fake_simulator_test.py +23 -8
  49. android_env/components/specs.py +1 -1
  50. android_env/components/specs_test.py +1 -1
  51. android_env/components/task_manager.py +26 -31
  52. android_env/components/task_manager_test.py +1 -18
  53. android_env/env_interface.py +1 -17
  54. android_env/environment.py +27 -17
  55. android_env/environment_test.py +51 -25
  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 +13 -1
  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 +1 -1
  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 +497 -136
  100. android_env/proto/snapshot.proto +1 -1
  101. android_env/proto/snapshot_pb2.py +30 -19
  102. android_env/proto/snapshot_pb2.pyi +117 -0
  103. android_env/proto/snapshot_pb2_grpc.py +20 -0
  104. android_env/proto/snapshot_service.proto +1 -1
  105. android_env/proto/snapshot_service_pb2.py +36 -25
  106. android_env/proto/snapshot_service_pb2.pyi +86 -0
  107. android_env/proto/snapshot_service_pb2_grpc.py +119 -28
  108. android_env/proto/state.proto +1 -1
  109. android_env/proto/state_pb2.py +46 -35
  110. android_env/proto/state_pb2.pyi +85 -0
  111. android_env/proto/state_pb2_grpc.py +20 -0
  112. android_env/proto/task.proto +4 -1
  113. android_env/proto/task_pb2.py +41 -30
  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 +1 -5
  120. android_env/wrappers/base_wrapper_test.py +1 -7
  121. android_env/wrappers/discrete_action_wrapper.py +15 -14
  122. android_env/wrappers/discrete_action_wrapper_test.py +1 -1
  123. android_env/wrappers/flat_interface_wrapper.py +5 -5
  124. android_env/wrappers/flat_interface_wrapper_test.py +1 -1
  125. android_env/wrappers/float_pixels_wrapper.py +5 -4
  126. android_env/wrappers/float_pixels_wrapper_test.py +1 -1
  127. android_env/wrappers/gym_wrapper.py +1 -1
  128. android_env/wrappers/gym_wrapper_test.py +1 -1
  129. android_env/wrappers/image_rescale_wrapper.py +13 -10
  130. android_env/wrappers/image_rescale_wrapper_test.py +1 -1
  131. android_env/wrappers/last_action_wrapper.py +5 -4
  132. android_env/wrappers/last_action_wrapper_test.py +1 -1
  133. android_env/wrappers/rate_limit_wrapper.py +1 -1
  134. android_env/wrappers/rate_limit_wrapper_test.py +1 -1
  135. android_env/wrappers/tap_action_wrapper.py +12 -12
  136. android_env/wrappers/tap_action_wrapper_test.py +49 -14
  137. {android_env-1.2.2.dist-info → android_env-1.2.3.dist-info}/METADATA +14 -16
  138. android_env-1.2.3.dist-info/RECORD +141 -0
  139. {android_env-1.2.2.dist-info → android_env-1.2.3.dist-info}/WHEEL +1 -1
  140. android_env-1.2.2.dist-info/RECORD +0 -88
  141. {android_env-1.2.2.dist-info → android_env-1.2.3.dist-info/licenses}/LICENSE +0 -0
  142. {android_env-1.2.2.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 2023 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.
@@ -21,7 +21,6 @@ from absl import logging
21
21
  from android_env import env_interface
22
22
  from android_env.proto import adb_pb2
23
23
  from android_env.proto import state_pb2
24
- from android_env.proto import task_pb2
25
24
  import dm_env
26
25
  from dm_env import specs
27
26
  import numpy as np
@@ -101,9 +100,6 @@ class BaseWrapper(env_interface.AndroidEnvInterface):
101
100
  adb_call: adb_pb2.AdbRequest) -> adb_pb2.AdbResponse:
102
101
  return self._env.execute_adb_call(adb_call)
103
102
 
104
- def update_task(self, task: task_pb2.Task) -> bool:
105
- return self._env.update_task(task)
106
-
107
103
  @property
108
104
  def raw_action(self):
109
105
  return self._env.raw_action
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -21,7 +21,6 @@ from absl import logging
21
21
  from absl.testing import absltest
22
22
  from android_env import env_interface
23
23
  from android_env.proto import state_pb2
24
- from android_env.proto import task_pb2
25
24
  from android_env.wrappers import base_wrapper
26
25
 
27
26
 
@@ -84,11 +83,6 @@ class BaseWrapperTest(absltest.TestCase):
84
83
  self.assertEqual(wrapped_env.save_state(save_request), expected_response)
85
84
  base_env.save_state.assert_called_once_with(save_request)
86
85
 
87
- task = task_pb2.Task(id='my_task')
88
- base_env.update_task.return_value = False
89
- self.assertFalse(wrapped_env.update_task(task))
90
- base_env.update_task.assert_called_once_with(task)
91
-
92
86
  wrapped_env.close()
93
87
  base_env.close.assert_called_once()
94
88
 
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -15,7 +15,7 @@
15
15
 
16
16
  """Wraps the AndroidEnv environment to provide discrete actions."""
17
17
 
18
- from typing import Optional, Sequence
18
+ from collections.abc import Sequence
19
19
 
20
20
  from android_env.components import action_type
21
21
  from android_env.wrappers import base_wrapper
@@ -24,23 +24,24 @@ from dm_env import specs
24
24
  import numpy as np
25
25
 
26
26
 
27
- NOISE_CLIP_VALUE = 0.4999
27
+ _NOISE_CLIP_VALUE = 0.4999
28
28
 
29
29
 
30
30
  class DiscreteActionWrapper(base_wrapper.BaseWrapper):
31
31
  """AndroidEnv with discrete actions."""
32
32
 
33
- def __init__(self,
34
- env: dm_env.Environment,
35
- action_grid: Optional[Sequence[int]] = (10, 10),
36
- redundant_actions: bool = True,
37
- noise: float = 0.1):
38
-
33
+ def __init__(
34
+ self,
35
+ env: dm_env.Environment,
36
+ action_grid: Sequence[int] = (10, 10),
37
+ redundant_actions: bool = True,
38
+ noise: float = 0.1,
39
+ ):
39
40
  super().__init__(env)
40
41
  self._parent_action_spec = self._env.action_spec()
41
42
  self._assert_base_env()
42
43
  self._action_grid = action_grid # [height, width]
43
- self._grid_size = np.product(self._action_grid)
44
+ self._grid_size = np.prod(self._action_grid)
44
45
  self._num_action_types = self._parent_action_spec['action_type'].num_values
45
46
  self._redundant_actions = redundant_actions
46
47
  self._noise = noise
@@ -57,9 +58,9 @@ class DiscreteActionWrapper(base_wrapper.BaseWrapper):
57
58
  """Number of discrete actions."""
58
59
 
59
60
  if self._redundant_actions:
60
- return np.product(self._action_grid) * self._num_action_types
61
+ return self._grid_size * self._num_action_types
61
62
  else:
62
- return np.product(self._action_grid) + self._num_action_types - 1
63
+ return self._grid_size + self._num_action_types - 1
63
64
 
64
65
  def step(self, action: dict[str, int]) -> dm_env.TimeStep:
65
66
  """Take a step in the base environment."""
@@ -133,8 +134,8 @@ class DiscreteActionWrapper(base_wrapper.BaseWrapper):
133
134
  noise_y = np.random.normal(loc=0.0, scale=self._noise)
134
135
 
135
136
  # Noise is clipped so that the action will strictly stay in the cell.
136
- noise_x = max(min(noise_x, NOISE_CLIP_VALUE), -NOISE_CLIP_VALUE)
137
- noise_y = max(min(noise_y, NOISE_CLIP_VALUE), -NOISE_CLIP_VALUE)
137
+ noise_x = max(min(noise_x, _NOISE_CLIP_VALUE), -_NOISE_CLIP_VALUE)
138
+ noise_y = max(min(noise_y, _NOISE_CLIP_VALUE), -_NOISE_CLIP_VALUE)
138
139
 
139
140
  x_pos = (x_pos_grid + 0.5 + noise_x) / self._action_grid[1] # WIDTH
140
141
  y_pos = (y_pos_grid + 0.5 + noise_y) / self._action_grid[0] # HEIGHT
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -15,7 +15,7 @@
15
15
 
16
16
  """Wraps the AndroidEnv environment to make its interface flat."""
17
17
 
18
- from typing import Any, Union
18
+ from typing import Any
19
19
 
20
20
  from android_env.wrappers import base_wrapper
21
21
  import dm_env
@@ -74,7 +74,7 @@ class FlatInterfaceWrapper(base_wrapper.BaseWrapper):
74
74
  assert isinstance(base_action_spec, dict)
75
75
  assert isinstance(base_action_spec[self._action_name], specs.BoundedArray)
76
76
 
77
- def _process_action(self, action: Union[int, np.ndarray, dict[str, Any]]):
77
+ def _process_action(self, action: int | np.ndarray | dict[str, Any]):
78
78
  if self._flat_actions:
79
79
  return {self._action_name: action}
80
80
  else:
@@ -103,7 +103,7 @@ class FlatInterfaceWrapper(base_wrapper.BaseWrapper):
103
103
  timestep = self._env.step(self._process_action(action))
104
104
  return self._process_timestep(timestep)
105
105
 
106
- def observation_spec(self) -> Union[specs.Array, dict[str, specs.Array]]: # pytype: disable=signature-mismatch # overriding-return-type-checks
106
+ def observation_spec(self) -> specs.Array | dict[str, specs.Array]: # pytype: disable=signature-mismatch # overriding-return-type-checks
107
107
  if self._flat_observations:
108
108
  pixels_spec = self._env.observation_spec()['pixels']
109
109
  if not self._keep_action_layer:
@@ -112,7 +112,7 @@ class FlatInterfaceWrapper(base_wrapper.BaseWrapper):
112
112
  else:
113
113
  return self._env.observation_spec()
114
114
 
115
- def action_spec(self) -> Union[specs.BoundedArray, dict[str, specs.Array]]: # pytype: disable=signature-mismatch # overriding-return-type-checks
115
+ def action_spec(self) -> specs.BoundedArray | dict[str, specs.Array]: # pytype: disable=signature-mismatch # overriding-return-type-checks
116
116
  if self._flat_actions:
117
117
  return self._env.action_spec()[self._action_name]
118
118
  else:
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -15,7 +15,7 @@
15
15
 
16
16
  """Converts pixel observation to from int to float32 between 0.0 and 1.0."""
17
17
 
18
- from android_env.components import utils
18
+ from android_env.components import pixel_fns
19
19
  from android_env.wrappers import base_wrapper
20
20
  import dm_env
21
21
  from dm_env import specs
@@ -35,8 +35,9 @@ class FloatPixelsWrapper(base_wrapper.BaseWrapper):
35
35
  self, observation: dict[str, np.ndarray]
36
36
  ) -> dict[str, np.ndarray]:
37
37
  if self._should_convert_int_to_float:
38
- float_pixels = utils.convert_int_to_float(observation['pixels'],
39
- self._input_spec, np.float32)
38
+ float_pixels = pixel_fns.convert_int_to_float(
39
+ observation['pixels'], self._input_spec
40
+ )
40
41
  observation['pixels'] = float_pixels
41
42
  return observation
42
43
 
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -15,7 +15,7 @@
15
15
 
16
16
  """Wraps the AndroidEnv environment to rescale the observations."""
17
17
 
18
- from typing import Optional, Sequence
18
+ from collections.abc import Sequence
19
19
 
20
20
  from android_env.wrappers import base_wrapper
21
21
  import dm_env
@@ -37,8 +37,9 @@ class ImageRescaleWrapper(base_wrapper.BaseWrapper):
37
37
  def __init__(
38
38
  self,
39
39
  env: dm_env.Environment,
40
- zoom_factors: Optional[Sequence[float]] = (0.5, 0.5),
41
- grayscale: bool = False):
40
+ zoom_factors: Sequence[float] | None = (0.5, 0.5),
41
+ grayscale: bool = False,
42
+ ):
42
43
  super().__init__(env)
43
44
  assert 'pixels' in self._env.observation_spec()
44
45
  assert self._env.observation_spec()['pixels'].shape[-1] in [1, 3], (
@@ -70,14 +71,16 @@ class ImageRescaleWrapper(base_wrapper.BaseWrapper):
70
71
  return self._resize_image_array(image, new_shape)
71
72
 
72
73
  def _resize_image_array(
73
- self,
74
- grayscale_or_rbg_array: np.ndarray,
75
- new_shape: Sequence[int]) -> np.ndarray:
74
+ self, grayscale_or_rbg_array: np.ndarray, new_shape: np.ndarray
75
+ ) -> np.ndarray:
76
76
  """Resize color or grayscale/action_layer array to new_shape."""
77
- assert np.array(new_shape).ndim == 1
77
+ assert new_shape.ndim == 1
78
78
  assert len(new_shape) == 2
79
- resized_array = np.array(Image.fromarray(
80
- grayscale_or_rbg_array.astype('uint8')).resize(new_shape))
79
+ resized_array = np.array(
80
+ Image.fromarray(grayscale_or_rbg_array.astype('uint8')).resize(
81
+ tuple(new_shape)
82
+ )
83
+ )
81
84
  if resized_array.ndim == 2:
82
85
  return np.expand_dims(resized_array, axis=-1)
83
86
  return resized_array
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -16,7 +16,7 @@
16
16
  """Extends Android observation with the latest action taken."""
17
17
 
18
18
  from android_env.components import action_type
19
- from android_env.components import utils
19
+ from android_env.components import pixel_fns
20
20
  from android_env.wrappers import base_wrapper
21
21
  import dm_env
22
22
  from dm_env import specs
@@ -76,8 +76,9 @@ class LastActionWrapper(base_wrapper.BaseWrapper):
76
76
  if ('action_type' in last_action and
77
77
  last_action['action_type'] == action_type.ActionType.TOUCH):
78
78
  touch_position = last_action['touch_position']
79
- x, y = utils.touch_position_to_pixel_position(
80
- touch_position, width_height=self._screen_dimensions[::-1])
79
+ x, y = pixel_fns.touch_position_to_pixel_position(
80
+ touch_position, width_height=self._screen_dimensions[::-1]
81
+ )
81
82
  last_action_layer[y, x] = 255
82
83
 
83
84
  return last_action_layer
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -15,7 +15,7 @@
15
15
 
16
16
  """Wraps the AndroidEnv environment to provide tap actions of a given duration."""
17
17
 
18
- from typing import Sequence
18
+ from collections.abc import Sequence
19
19
 
20
20
  from android_env.components import action_type
21
21
  from android_env.wrappers import base_wrapper
@@ -23,9 +23,6 @@ import dm_env
23
23
  import numpy as np
24
24
 
25
25
 
26
- ActionType = action_type.ActionType
27
-
28
-
29
26
  class TapActionWrapper(base_wrapper.BaseWrapper):
30
27
  """AndroidEnv with tap actions."""
31
28
 
@@ -51,20 +48,23 @@ class TapActionWrapper(base_wrapper.BaseWrapper):
51
48
  if self._touch_only:
52
49
  assert action['action_type'] == 0
53
50
  touch_action = action.copy()
54
- touch_action['action_type'] = np.array(ActionType.TOUCH).astype(
55
- self.action_spec()['action_type'].dtype)
51
+ touch_action['action_type'] = np.array(
52
+ action_type.ActionType.TOUCH
53
+ ).astype(self.action_spec()['action_type'].dtype)
56
54
  actions = [touch_action] * self._num_frames
57
55
  lift_action = action.copy()
58
- lift_action['action_type'] = np.array(ActionType.LIFT).astype(
59
- self.action_spec()['action_type'].dtype)
56
+ lift_action['action_type'] = np.array(action_type.ActionType.LIFT).astype(
57
+ self.action_spec()['action_type'].dtype
58
+ )
60
59
  actions.append(lift_action)
61
60
 
62
61
  else:
63
- if action['action_type'] == ActionType.TOUCH:
62
+ if action['action_type'] == action_type.ActionType.TOUCH:
64
63
  actions = [action] * self._num_frames
65
64
  lift_action = action.copy()
66
- lift_action['action_type'] = np.array(ActionType.LIFT).astype(
67
- self.action_spec()['action_type'].dtype)
65
+ lift_action['action_type'] = np.array(
66
+ action_type.ActionType.LIFT
67
+ ).astype(self.action_spec()['action_type'].dtype)
68
68
  actions.append(lift_action)
69
69
  else:
70
70
  actions = [action] * (self._num_frames + 1)
@@ -1,5 +1,5 @@
1
1
  # coding=utf-8
2
- # Copyright 2023 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.
@@ -26,9 +26,6 @@ from dm_env import specs
26
26
  import numpy as np
27
27
 
28
28
 
29
- ActionType = action_type.ActionType
30
-
31
-
32
29
  def _make_array_spec(shape, dtype, name):
33
30
  return specs.BoundedArray(
34
31
  name=name,
@@ -56,8 +53,8 @@ class TapActionWrapperTest(absltest.TestCase):
56
53
  wrapped_env = tap_action_wrapper.TapActionWrapper(
57
54
  self.base_env, num_frames=3)
58
55
  action = {
59
- 'action_type': np.array(ActionType.REPEAT, dtype=np.int32),
60
- 'touch_position': np.array([0.5, 0.5], dtype=np.float32)
56
+ 'action_type': np.array(action_type.ActionType.REPEAT, dtype=np.int32),
57
+ 'touch_position': np.array([0.5, 0.5], dtype=np.float32),
61
58
  }
62
59
  actions = wrapped_env._process_action(action)
63
60
  self.assertLen(actions, wrapped_env._num_frames + 1)
@@ -67,8 +64,8 @@ class TapActionWrapperTest(absltest.TestCase):
67
64
  wrapped_env = tap_action_wrapper.TapActionWrapper(
68
65
  self.base_env, num_frames=3)
69
66
  action = {
70
- 'action_type': np.array(ActionType.LIFT, dtype=np.int32),
71
- 'touch_position': np.array([0.5, 0.5], dtype=np.float32)
67
+ 'action_type': np.array(action_type.ActionType.LIFT, dtype=np.int32),
68
+ 'touch_position': np.array([0.5, 0.5], dtype=np.float32),
72
69
  }
73
70
  actions = wrapped_env._process_action(action)
74
71
  self.assertLen(actions, wrapped_env._num_frames + 1)
@@ -78,12 +75,14 @@ class TapActionWrapperTest(absltest.TestCase):
78
75
  wrapped_env = tap_action_wrapper.TapActionWrapper(
79
76
  self.base_env, num_frames=3)
80
77
  action = {
81
- 'action_type': np.array(ActionType.TOUCH, dtype=np.int32),
82
- 'touch_position': np.array([0.5, 0.5], dtype=np.float32)
78
+ 'action_type': np.array(action_type.ActionType.TOUCH, dtype=np.int32),
79
+ 'touch_position': np.array([0.5, 0.5], dtype=np.float32),
83
80
  }
84
81
  actions = wrapped_env._process_action(action)
85
82
  self.assertLen(actions, wrapped_env._num_frames + 1)
86
- self.assertEqual(actions[-1]['action_type'], np.array(ActionType.LIFT))
83
+ self.assertEqual(
84
+ actions[-1]['action_type'], np.array(action_type.ActionType.LIFT)
85
+ )
87
86
 
88
87
  def test_reset(self):
89
88
  wrapped_env = tap_action_wrapper.TapActionWrapper(
@@ -95,6 +94,7 @@ class TapActionWrapperTest(absltest.TestCase):
95
94
  self.assertEqual(fake_timestep, ts)
96
95
 
97
96
  def test_step(self):
97
+ # Arrange.
98
98
  wrapped_env = tap_action_wrapper.TapActionWrapper(
99
99
  self.base_env, num_frames=5)
100
100
  fake_timestep = dm_env.TimeStep(
@@ -103,13 +103,21 @@ class TapActionWrapperTest(absltest.TestCase):
103
103
  discount=1.0,
104
104
  observation='fake_obs')
105
105
  self.base_env.step.return_value = fake_timestep
106
+ self.base_env.stats.return_value = {}
107
+
108
+ # Act.
106
109
  ts = wrapped_env.step({
107
- 'action_type': np.array(ActionType.REPEAT, dtype=np.int32),
108
- 'touch_position': np.array([0.5, 0.5], dtype=np.float32)
110
+ 'action_type': np.array(action_type.ActionType.REPEAT, dtype=np.int32),
111
+ 'touch_position': np.array([0.5, 0.5], dtype=np.float32),
109
112
  })
113
+ stats = wrapped_env.stats()
114
+
115
+ # Assert.
110
116
  self.assertEqual(wrapped_env._num_frames+1, self.base_env.step.call_count)
111
117
  self.assertIsInstance(ts, dm_env.TimeStep)
112
- self.assertEqual(wrapped_env._env_steps, 6)
118
+ self.assertIsInstance(stats, dict)
119
+ self.assertIn('env_steps', stats)
120
+ self.assertEqual(stats['env_steps'], 6)
113
121
 
114
122
  def test_observation_spec(self):
115
123
  wrapped_env = tap_action_wrapper.TapActionWrapper(
@@ -129,5 +137,32 @@ class TapActionWrapperTest(absltest.TestCase):
129
137
  self.assertEqual(self.base_env.action_spec(),
130
138
  action_spec)
131
139
 
140
+ def test_stats(self):
141
+ """Checks that returned stats have expected properties."""
142
+
143
+ # Arrange.
144
+ self.base_env.stats.return_value = {
145
+ 'some_key': 12345,
146
+ 'another_key': 5.4321,
147
+ }
148
+ wrapped_env = tap_action_wrapper.TapActionWrapper(
149
+ self.base_env, num_frames=5
150
+ )
151
+
152
+ # Act.
153
+ stats = wrapped_env.stats()
154
+
155
+ # Assert.
156
+ self.assertIsInstance(stats, dict)
157
+ # Original entries should still be present.
158
+ self.assertIn('some_key', stats)
159
+ self.assertEqual(stats['some_key'], 12345)
160
+ self.assertIn('another_key', stats)
161
+ self.assertEqual(stats['another_key'], 5.4321)
162
+ # TapActionWrapper inserts its own `env_steps`.
163
+ self.assertIn('env_steps', stats)
164
+ self.assertEqual(stats['env_steps'], 0)
165
+
166
+
132
167
  if __name__ == '__main__':
133
168
  absltest.main()
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: android-env
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: AndroidEnv environment and library for training agents.
5
- Home-page: https://github.com/deepmind/android_env
6
5
  Author: DeepMind
7
6
  License:
8
7
  Apache License
@@ -213,22 +212,21 @@ Keywords: Android,OS,reinforcement-learning
213
212
  Requires-Python: >=3.10
214
213
  Description-Content-Type: text/plain
215
214
  License-File: LICENSE
216
- Requires-Dist: absl-py (>=0.1.0)
217
- Requires-Dist: dm-env
215
+ Requires-Dist: absl-py>=0.1.0
216
+ Requires-Dist: dm_env
218
217
  Requires-Dist: grpcio
219
- Requires-Dist: numpy (>=1.21)
220
- Requires-Dist: portpicker (>=1.2.0)
221
- Requires-Dist: protobuf (>=2.6)
218
+ Requires-Dist: numpy>=1.21
219
+ Requires-Dist: portpicker>=1.2.0
220
+ Requires-Dist: protobuf>=2.6
222
221
  Requires-Dist: pygame
222
+ Provides-Extra: testing
223
+ Requires-Dist: gym; extra == "testing"
224
+ Requires-Dist: pillow; extra == "testing"
225
+ Requires-Dist: pytype; extra == "testing"
223
226
  Provides-Extra: acme
224
- Requires-Dist: dm-acme ; extra == 'acme'
227
+ Requires-Dist: dm-acme; extra == "acme"
225
228
  Provides-Extra: gym
226
- Requires-Dist: gym ; extra == 'gym'
227
- Provides-Extra: testing
228
- Requires-Dist: attrs (==20.3.0) ; extra == 'testing'
229
- Requires-Dist: gym ; extra == 'testing'
230
- Requires-Dist: pillow ; extra == 'testing'
231
- Requires-Dist: pytype ; extra == 'testing'
232
- Requires-Dist: pytest-xdist ; extra == 'testing'
229
+ Requires-Dist: gym; extra == "gym"
230
+ Dynamic: license-file
233
231
 
234
232
  Read the README at https://github.com/deepmind/android_env for more information.