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.
|
@@ -17,11 +17,12 @@
|
|
17
17
|
|
18
18
|
import os
|
19
19
|
import time
|
20
|
-
from typing import Any
|
20
|
+
from typing import Any
|
21
21
|
|
22
22
|
from absl import logging
|
23
23
|
from android_env.components import adb_controller
|
24
24
|
from android_env.components import adb_log_stream
|
25
|
+
from android_env.components import config_classes
|
25
26
|
from android_env.components import errors
|
26
27
|
from android_env.components import log_stream
|
27
28
|
from android_env.components.simulators import base_simulator
|
@@ -38,15 +39,19 @@ from android_env.proto import snapshot_service_pb2_grpc
|
|
38
39
|
from google.protobuf import empty_pb2
|
39
40
|
|
40
41
|
|
41
|
-
_DEFAULT_SNAPSHOT_NAME = 'default_snapshot'
|
42
|
+
_DEFAULT_SNAPSHOT_NAME: str = 'default_snapshot'
|
42
43
|
|
43
44
|
|
44
|
-
def
|
45
|
+
def _is_existing_emulator_provided(
|
46
|
+
launcher_config: config_classes.EmulatorLauncherConfig,
|
47
|
+
) -> bool:
|
45
48
|
"""Returns true if all necessary args were provided."""
|
49
|
+
|
46
50
|
return bool(
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
launcher_config.adb_port
|
52
|
+
and launcher_config.emulator_console_port
|
53
|
+
and launcher_config.grpc_port
|
54
|
+
)
|
50
55
|
|
51
56
|
|
52
57
|
def _pick_adb_port() -> int:
|
@@ -58,6 +63,7 @@ def _pick_adb_port() -> int:
|
|
58
63
|
Returns:
|
59
64
|
port: an available port for adb.
|
60
65
|
"""
|
66
|
+
|
61
67
|
for p in range(5555, 5587, 2):
|
62
68
|
if portpicker.is_port_free(p):
|
63
69
|
return p
|
@@ -73,29 +79,13 @@ def _pick_emulator_grpc_port() -> int:
|
|
73
79
|
Returns:
|
74
80
|
port: an available port for emulator grpc.
|
75
81
|
"""
|
82
|
+
|
76
83
|
if portpicker.is_port_free(8554):
|
77
84
|
return 8554
|
78
85
|
else:
|
79
86
|
return portpicker.pick_unused_port()
|
80
87
|
|
81
88
|
|
82
|
-
def _reconnect_on_grpc_error(func):
|
83
|
-
"""Decorator function for reconnecting to emulator upon grpc errors."""
|
84
|
-
|
85
|
-
def wrapper(*args, **kwargs):
|
86
|
-
try:
|
87
|
-
return func(*args, **kwargs) # pytype: disable=missing-parameter # always-use-return-annotations
|
88
|
-
except grpc.RpcError:
|
89
|
-
logging.exception('RpcError caught. Reconnecting to emulator...')
|
90
|
-
emu = args[0] # The first arg of the function is "self"
|
91
|
-
emu._emulator_stub, emu._snapshot_stub = emu._connect_to_emulator( # pylint: disable=protected-access
|
92
|
-
emu._grpc_port # pylint: disable=protected-access
|
93
|
-
)
|
94
|
-
return func(*args, **kwargs) # pytype: disable=missing-parameter # always-use-return-annotations
|
95
|
-
|
96
|
-
return wrapper
|
97
|
-
|
98
|
-
|
99
89
|
class EmulatorBootError(errors.SimulatorError):
|
100
90
|
"""Raised when an emulator failed to boot."""
|
101
91
|
|
@@ -107,90 +97,86 @@ class EmulatorCrashError(errors.SimulatorError):
|
|
107
97
|
class EmulatorSimulator(base_simulator.BaseSimulator):
|
108
98
|
"""Controls an Android Emulator."""
|
109
99
|
|
110
|
-
def __init__(
|
111
|
-
|
112
|
-
emulator_launcher_args: dict[str, Any],
|
113
|
-
adb_controller_args: dict[str, Any],
|
114
|
-
tmp_dir: str = '/tmp/android_env/simulator',
|
115
|
-
logfile_path: Optional[str] = None,
|
116
|
-
launch_n_times_without_reboot: int = 1,
|
117
|
-
launch_n_times_without_reinstall: int = 2,
|
118
|
-
**kwargs,
|
119
|
-
):
|
120
|
-
"""Instantiates an EmulatorSimulator.
|
100
|
+
def __init__(self, config: config_classes.EmulatorConfig):
|
101
|
+
"""Instantiates an EmulatorSimulator."""
|
121
102
|
|
122
|
-
|
123
|
-
|
124
|
-
adb_controller_args: Arguments for AdbController.
|
125
|
-
tmp_dir: Temporary directory to hold simulator files.
|
126
|
-
logfile_path: Path to file which holds emulator logs. If not provided, it
|
127
|
-
will be determined by the EmulatorLauncher.
|
128
|
-
launch_n_times_without_reboot: The number of times to try launching the
|
129
|
-
emulator before rebooting (reboot on the n+1-st try).
|
130
|
-
launch_n_times_without_reinstall: The number of times to try launching the
|
131
|
-
emulator before reinstalling (reinstall on the n+1-st try).
|
132
|
-
**kwargs: keyword arguments for base class.
|
133
|
-
"""
|
103
|
+
super().__init__(config)
|
104
|
+
self._config = config
|
134
105
|
|
135
106
|
# If adb_port, console_port and grpc_port are all already provided,
|
136
107
|
# we assume the emulator already exists and there's no need to launch.
|
137
|
-
if
|
108
|
+
if _is_existing_emulator_provided(self._config.emulator_launcher):
|
138
109
|
self._existing_emulator_provided = True
|
139
|
-
self._adb_port = emulator_launcher_args['adb_port']
|
140
|
-
self._console_port = emulator_launcher_args['emulator_console_port']
|
141
|
-
self._grpc_port = emulator_launcher_args['grpc_port']
|
142
110
|
logging.info('Connecting to existing emulator "%r"',
|
143
111
|
self.adb_device_name())
|
144
112
|
else:
|
145
113
|
self._existing_emulator_provided = False
|
146
|
-
self.
|
147
|
-
self.
|
148
|
-
|
114
|
+
self._config.emulator_launcher.adb_port = _pick_adb_port()
|
115
|
+
self._config.emulator_launcher.emulator_console_port = (
|
116
|
+
portpicker.pick_unused_port()
|
117
|
+
)
|
118
|
+
self._config.emulator_launcher.grpc_port = _pick_emulator_grpc_port()
|
149
119
|
|
150
120
|
self._channel = None
|
151
|
-
self._emulator_stub =
|
121
|
+
self._emulator_stub: emulator_controller_pb2_grpc.EmulatorControllerStub | None = (
|
122
|
+
None
|
123
|
+
)
|
152
124
|
self._snapshot_stub = None
|
153
125
|
# Set the image format to RGBA. The width and height of the returned
|
154
126
|
# screenshots will use the device's width and height.
|
155
127
|
self._image_format = emulator_controller_pb2.ImageFormat(
|
156
128
|
format=emulator_controller_pb2.ImageFormat.ImgFormat.RGBA8888)
|
157
129
|
|
158
|
-
if
|
130
|
+
if (
|
131
|
+
self._config.launch_n_times_without_reboot
|
132
|
+
> self._config.launch_n_times_without_reinstall
|
133
|
+
):
|
159
134
|
raise ValueError(
|
160
|
-
|
161
|
-
f'({launch_n_times_without_reboot}) should not be
|
162
|
-
|
163
|
-
f'({launch_n_times_without_reinstall})'
|
164
|
-
|
165
|
-
self._launch_n_times_without_reinstall = launch_n_times_without_reinstall
|
166
|
-
|
167
|
-
super().__init__(**kwargs)
|
135
|
+
'Number of launch attempts before reboot'
|
136
|
+
f' ({self._config.launch_n_times_without_reboot}) should not be'
|
137
|
+
' greater than number of launch attempts before reinstall'
|
138
|
+
f' ({self._config.launch_n_times_without_reinstall})'
|
139
|
+
)
|
168
140
|
|
169
141
|
# Initialize own ADB controller.
|
170
|
-
self.
|
142
|
+
self._config.adb_controller.device_name = self.adb_device_name()
|
171
143
|
self._adb_controller = self.create_adb_controller()
|
172
144
|
self._adb_controller.init_server()
|
173
|
-
logging.info(
|
174
|
-
|
145
|
+
logging.info(
|
146
|
+
'Initialized simulator with ADB server port %r.',
|
147
|
+
self._config.adb_controller.adb_server_port,
|
148
|
+
)
|
175
149
|
|
176
150
|
# If necessary, create EmulatorLauncher.
|
177
151
|
if self._existing_emulator_provided:
|
178
|
-
self._logfile_path = logfile_path or None
|
152
|
+
self._logfile_path = self._config.logfile_path or None
|
179
153
|
self._launcher = None
|
180
154
|
else:
|
181
|
-
|
182
|
-
'
|
183
|
-
|
184
|
-
'adb_server_port': self._adb_controller_args['adb_server_port'],
|
185
|
-
'emulator_console_port': self._console_port,
|
186
|
-
'grpc_port': self._grpc_port,
|
187
|
-
'tmp_dir': tmp_dir,
|
188
|
-
})
|
189
|
-
self._emulator_launcher_args = emulator_launcher_args
|
190
|
-
logging.info('emulator_launcher_args: %r', self._emulator_launcher_args)
|
155
|
+
logging.info(
|
156
|
+
'emulator_launcher config: %r', self._config.emulator_launcher
|
157
|
+
)
|
191
158
|
self._launcher = emulator_launcher.EmulatorLauncher(
|
192
|
-
|
193
|
-
|
159
|
+
config=self._config.emulator_launcher,
|
160
|
+
adb_controller_config=self._config.adb_controller,
|
161
|
+
)
|
162
|
+
self._logfile_path = (
|
163
|
+
self._config.logfile_path or self._launcher.logfile_path()
|
164
|
+
)
|
165
|
+
|
166
|
+
def _reconnect_on_grpc_error(func):
|
167
|
+
"""Decorator function for reconnecting to emulator upon grpc errors."""
|
168
|
+
|
169
|
+
def wrapper(self, *args, **kwargs):
|
170
|
+
try:
|
171
|
+
return func(self, *args, **kwargs)
|
172
|
+
except grpc.RpcError:
|
173
|
+
logging.exception('RpcError caught. Reconnecting to emulator...')
|
174
|
+
self._emulator_stub, self._snapshot_stub = self._connect_to_emulator(
|
175
|
+
self._config.emulator_launcher.grpc_port
|
176
|
+
)
|
177
|
+
return func(self, *args, **kwargs)
|
178
|
+
|
179
|
+
return wrapper
|
194
180
|
|
195
181
|
def get_logs(self) -> str:
|
196
182
|
"""Returns logs recorded by the emulator."""
|
@@ -201,28 +187,29 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
201
187
|
return f'Logfile does not exist: {self._logfile_path}.'
|
202
188
|
|
203
189
|
def adb_device_name(self) -> str:
|
204
|
-
return 'emulator-%s' % (self.
|
190
|
+
return 'emulator-%s' % (self._config.emulator_launcher.adb_port - 1)
|
205
191
|
|
206
192
|
def create_adb_controller(self):
|
207
193
|
"""Returns an ADB controller which can communicate with this simulator."""
|
208
|
-
return adb_controller.AdbController(
|
209
|
-
device_name=self.adb_device_name(), **self._adb_controller_args)
|
194
|
+
return adb_controller.AdbController(self._config.adb_controller)
|
210
195
|
|
211
196
|
def create_log_stream(self) -> log_stream.LogStream:
|
212
197
|
return adb_log_stream.AdbLogStream(
|
213
198
|
adb_command_prefix=self._adb_controller.command_prefix(),
|
214
|
-
verbose=self.
|
199
|
+
verbose=self._config.verbose_logs,
|
200
|
+
)
|
215
201
|
|
216
202
|
def _launch_impl(self) -> None:
|
217
203
|
"""Prepares an Android Emulator for RL interaction.
|
218
204
|
|
219
205
|
The behavior depends on `self._num_launch_attempts`'s value:
|
220
|
-
* <= self.
|
221
|
-
* > self.
|
222
|
-
self.
|
223
|
-
killed and started again).
|
224
|
-
* > self.
|
225
|
-
killed, emulator files are deleted and the process started
|
206
|
+
* <= self._config.launch_n_times_without_reboot -> Normal boot behavior.
|
207
|
+
* > self._config.launch_n_times_without_reboot but <=
|
208
|
+
self._config.launch_n_times_without_reinstall -> reboot (i.e. process
|
209
|
+
is killed and started again).
|
210
|
+
* > self._config.launch_n_times_without_reinstall -> reinstall (i.e.
|
211
|
+
process is killed, emulator files are deleted and the process started
|
212
|
+
again).
|
226
213
|
"""
|
227
214
|
|
228
215
|
logging.info('Attempt %r at launching the Android Emulator (%r)',
|
@@ -230,19 +217,27 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
230
217
|
|
231
218
|
if self._launcher is not None:
|
232
219
|
# If not the first time, then shutdown the emulator first.
|
233
|
-
if (
|
234
|
-
self.
|
220
|
+
if (
|
221
|
+
self._emulator_stub is not None
|
222
|
+
and self._num_launch_attempts
|
223
|
+
> self._config.launch_n_times_without_reboot
|
224
|
+
):
|
235
225
|
self._shutdown_emulator()
|
236
226
|
# Subsequent attempts cause the emulator files to be reinstalled.
|
237
|
-
if
|
227
|
+
if (
|
228
|
+
self._num_launch_attempts
|
229
|
+
> self._config.launch_n_times_without_reinstall
|
230
|
+
):
|
238
231
|
logging.info('Closing emulator (%r)', self.adb_device_name())
|
239
232
|
self._launcher.close()
|
240
233
|
self._launcher = emulator_launcher.EmulatorLauncher(
|
241
|
-
|
234
|
+
config=self._config.emulator_launcher,
|
235
|
+
adb_controller_config=self._config.adb_controller,
|
236
|
+
)
|
242
237
|
self._launcher.launch_emulator_process()
|
243
238
|
# Establish grpc connection to emulator process.
|
244
239
|
self._emulator_stub, self._snapshot_stub = self._connect_to_emulator(
|
245
|
-
self.
|
240
|
+
self._config.emulator_launcher.grpc_port
|
246
241
|
)
|
247
242
|
|
248
243
|
# Confirm booted status.
|
@@ -272,6 +267,7 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
272
267
|
* If an error occurred during the snapshot loading process, the status
|
273
268
|
will be `ERROR` and the `error_message` field will be filled.
|
274
269
|
"""
|
270
|
+
assert self._snapshot_stub is not None
|
275
271
|
snapshot_name = request.args.get('snapshot_name', _DEFAULT_SNAPSHOT_NAME)
|
276
272
|
snapshot_list = self._snapshot_stub.ListSnapshots(
|
277
273
|
snapshot_service_pb2.SnapshotFilter(
|
@@ -317,6 +313,7 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
317
313
|
* If an error occurred during the snapshot saving process, the status
|
318
314
|
will be `ERROR` and the `error_message` field will be filled.
|
319
315
|
"""
|
316
|
+
assert self._snapshot_stub is not None
|
320
317
|
snapshot_name = request.args.get('snapshot_name', _DEFAULT_SNAPSHOT_NAME)
|
321
318
|
snapshot_result = self._snapshot_stub.SaveSnapshot(
|
322
319
|
snapshot_service_pb2.SnapshotPackage(snapshot_id=snapshot_name)
|
@@ -366,6 +363,9 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
366
363
|
def _confirm_booted(self, startup_wait_time_sec: int = 300):
|
367
364
|
"""Waits until the emulator is fully booted."""
|
368
365
|
|
366
|
+
assert (
|
367
|
+
self._emulator_stub is not None
|
368
|
+
), 'Emulator stub has not been initialized yet.'
|
369
369
|
start_time = time.time()
|
370
370
|
deadline = start_time + startup_wait_time_sec
|
371
371
|
success = False
|
@@ -403,7 +403,9 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
403
403
|
3 identifier: Identifies a particular finger in a multitouch event.
|
404
404
|
"""
|
405
405
|
|
406
|
-
assert
|
406
|
+
assert (
|
407
|
+
self._emulator_stub is not None
|
408
|
+
), 'Emulator stub has not been initialized yet.'
|
407
409
|
touch_events = [
|
408
410
|
emulator_controller_pb2.Touch(
|
409
411
|
x=t[0], y=t[1], pressure=int(t[2]), identifier=t[3])
|
@@ -421,11 +423,15 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
421
423
|
See the emulator_controller_pb2 for details.
|
422
424
|
event_type: Type of key event to be sent.
|
423
425
|
"""
|
426
|
+
|
424
427
|
event_types = emulator_controller_pb2.KeyboardEvent.KeyEventType.keys()
|
425
428
|
if event_type not in event_types:
|
426
429
|
raise ValueError(
|
427
430
|
f'Event type must be one of {event_types} but is {event_type}.')
|
428
431
|
|
432
|
+
assert (
|
433
|
+
self._emulator_stub is not None
|
434
|
+
), 'Emulator stub has not been initialized yet.'
|
429
435
|
self._emulator_stub.sendKey(
|
430
436
|
emulator_controller_pb2.KeyboardEvent(
|
431
437
|
codeType=emulator_controller_pb2.KeyboardEvent.KeyCodeType.XKB,
|
@@ -437,9 +443,12 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
437
443
|
)
|
438
444
|
|
439
445
|
@_reconnect_on_grpc_error
|
440
|
-
def
|
446
|
+
def _get_screenshot_impl(self) -> np.ndarray:
|
441
447
|
"""Fetches the latest screenshot from the emulator."""
|
442
|
-
|
448
|
+
|
449
|
+
assert (
|
450
|
+
self._emulator_stub is not None
|
451
|
+
), 'Emulator stub has not been initialized yet.'
|
443
452
|
assert self._image_format, 'ImageFormat has not been initialized yet.'
|
444
453
|
image_proto = self._emulator_stub.getScreenshot(self._image_format)
|
445
454
|
h, w = image_proto.format.height, image_proto.format.width
|
@@ -455,6 +464,8 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
455
464
|
logging.info('Emulator (%r) is not up.', self.adb_device_name())
|
456
465
|
return
|
457
466
|
|
467
|
+
assert self._launcher is not None, 'Launcher is already down.'
|
468
|
+
|
458
469
|
logging.info('Shutting down the emulator (%r)...', self.adb_device_name())
|
459
470
|
self._emulator_stub.setVmState(
|
460
471
|
emulator_controller_pb2.VmRunState(
|
@@ -462,6 +473,8 @@ class EmulatorSimulator(base_simulator.BaseSimulator):
|
|
462
473
|
self._launcher.confirm_shutdown()
|
463
474
|
|
464
475
|
def close(self):
|
476
|
+
super().close()
|
477
|
+
|
465
478
|
if self._launcher is not None:
|
466
479
|
self._shutdown_emulator()
|
467
480
|
logging.info('Closing emulator (%r)', self.adb_device_name())
|