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.
- 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 +233 -185
- android_env/components/adb_call_parser_test.py +165 -163
- android_env/components/adb_controller.py +19 -28
- android_env/components/adb_controller_test.py +100 -9
- android_env/components/adb_log_stream.py +3 -3
- android_env/components/adb_log_stream_test.py +1 -1
- android_env/components/app_screen_checker.py +15 -13
- android_env/components/app_screen_checker_test.py +1 -1
- android_env/components/config_classes.py +203 -0
- android_env/components/coordinator.py +53 -338
- android_env/components/coordinator_test.py +26 -283
- 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 +2 -5
- android_env/components/errors_test.py +1 -1
- android_env/components/log_stream.py +2 -2
- android_env/components/log_stream_test.py +1 -1
- android_env/components/logcat_thread.py +9 -8
- android_env/components/logcat_thread_test.py +2 -3
- android_env/components/{utils.py → pixel_fns.py} +19 -20
- android_env/components/{utils_test.py → pixel_fns_test.py} +20 -15
- android_env/components/setup_step_interpreter.py +45 -37
- android_env/components/setup_step_interpreter_test.py +1 -1
- android_env/components/simulators/__init__.py +1 -1
- android_env/components/simulators/base_simulator.py +79 -23
- 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 +62 -81
- android_env/components/simulators/emulator/emulator_launcher_test.py +120 -43
- android_env/components/simulators/emulator/emulator_simulator.py +111 -98
- android_env/components/simulators/emulator/emulator_simulator_test.py +174 -138
- android_env/components/simulators/fake/__init__.py +1 -1
- android_env/components/simulators/fake/fake_simulator.py +9 -17
- android_env/components/simulators/fake/fake_simulator_test.py +23 -8
- android_env/components/specs.py +1 -1
- android_env/components/specs_test.py +1 -1
- android_env/components/task_manager.py +26 -31
- android_env/components/task_manager_test.py +1 -18
- android_env/env_interface.py +1 -17
- android_env/environment.py +27 -17
- android_env/environment_test.py +51 -25
- 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 +13 -1
- 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 +1 -1
- 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 +497 -136
- android_env/proto/snapshot.proto +1 -1
- android_env/proto/snapshot_pb2.py +30 -19
- android_env/proto/snapshot_pb2.pyi +117 -0
- android_env/proto/snapshot_pb2_grpc.py +20 -0
- android_env/proto/snapshot_service.proto +1 -1
- android_env/proto/snapshot_service_pb2.py +36 -25
- android_env/proto/snapshot_service_pb2.pyi +86 -0
- android_env/proto/snapshot_service_pb2_grpc.py +119 -28
- android_env/proto/state.proto +1 -1
- android_env/proto/state_pb2.py +46 -35
- android_env/proto/state_pb2.pyi +85 -0
- android_env/proto/state_pb2_grpc.py +20 -0
- android_env/proto/task.proto +4 -1
- android_env/proto/task_pb2.py +41 -30
- 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 +1 -5
- android_env/wrappers/base_wrapper_test.py +1 -7
- android_env/wrappers/discrete_action_wrapper.py +15 -14
- android_env/wrappers/discrete_action_wrapper_test.py +1 -1
- android_env/wrappers/flat_interface_wrapper.py +5 -5
- android_env/wrappers/flat_interface_wrapper_test.py +1 -1
- android_env/wrappers/float_pixels_wrapper.py +5 -4
- android_env/wrappers/float_pixels_wrapper_test.py +1 -1
- android_env/wrappers/gym_wrapper.py +1 -1
- android_env/wrappers/gym_wrapper_test.py +1 -1
- android_env/wrappers/image_rescale_wrapper.py +13 -10
- android_env/wrappers/image_rescale_wrapper_test.py +1 -1
- android_env/wrappers/last_action_wrapper.py +5 -4
- android_env/wrappers/last_action_wrapper_test.py +1 -1
- android_env/wrappers/rate_limit_wrapper.py +1 -1
- android_env/wrappers/rate_limit_wrapper_test.py +1 -1
- android_env/wrappers/tap_action_wrapper.py +12 -12
- android_env/wrappers/tap_action_wrapper_test.py +49 -14
- {android_env-1.2.2.dist-info → android_env-1.2.3.dist-info}/METADATA +14 -16
- android_env-1.2.3.dist-info/RECORD +141 -0
- {android_env-1.2.2.dist-info → android_env-1.2.3.dist-info}/WHEEL +1 -1
- android_env-1.2.2.dist-info/RECORD +0 -88
- {android_env-1.2.2.dist-info → android_env-1.2.3.dist-info/licenses}/LICENSE +0 -0
- {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
|
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
|
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
|
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
|
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
|
-
|
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__(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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.
|
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
|
61
|
+
return self._grid_size * self._num_action_types
|
61
62
|
else:
|
62
|
-
return
|
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,
|
137
|
-
noise_y = max(min(noise_y,
|
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
|
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
|
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:
|
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) ->
|
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) ->
|
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
|
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
|
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 =
|
39
|
-
|
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
|
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
|
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:
|
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
|
-
|
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
|
77
|
+
assert new_shape.ndim == 1
|
78
78
|
assert len(new_shape) == 2
|
79
|
-
resized_array = np.array(
|
80
|
-
grayscale_or_rbg_array.astype('uint8')).resize(
|
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
|
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
|
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 =
|
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
|
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
|
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(
|
55
|
-
|
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(
|
67
|
-
|
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
|
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(
|
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.
|
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
|
+
Metadata-Version: 2.4
|
2
2
|
Name: android-env
|
3
|
-
Version: 1.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
|
217
|
-
Requires-Dist:
|
215
|
+
Requires-Dist: absl-py>=0.1.0
|
216
|
+
Requires-Dist: dm_env
|
218
217
|
Requires-Dist: grpcio
|
219
|
-
Requires-Dist: numpy
|
220
|
-
Requires-Dist: portpicker
|
221
|
-
Requires-Dist: protobuf
|
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
|
227
|
+
Requires-Dist: dm-acme; extra == "acme"
|
225
228
|
Provides-Extra: gym
|
226
|
-
Requires-Dist: gym
|
227
|
-
|
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.
|