Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: mojo/devtools/common/devtoolslib/android_shell.py

Issue 1268713005: Unify method name casing in devtools. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | mojo/devtools/common/devtoolslib/apptest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import atexit 5 import atexit
6 import hashlib 6 import hashlib
7 import json 7 import json
8 import logging 8 import logging
9 import os 9 import os
10 import os.path 10 import os.path
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 75
76 def __init__(self, adb_path="adb", target_device=None, logcat_tags=None, 76 def __init__(self, adb_path="adb", target_device=None, logcat_tags=None,
77 verbose_pipe=None): 77 verbose_pipe=None):
78 self.adb_path = adb_path 78 self.adb_path = adb_path
79 self.target_device = target_device 79 self.target_device = target_device
80 self.stop_shell_registered = False 80 self.stop_shell_registered = False
81 self.adb_running_as_root = None 81 self.adb_running_as_root = None
82 self.additional_logcat_tags = logcat_tags 82 self.additional_logcat_tags = logcat_tags
83 self.verbose_pipe = verbose_pipe if verbose_pipe else open(os.devnull, 'w') 83 self.verbose_pipe = verbose_pipe if verbose_pipe else open(os.devnull, 'w')
84 84
85 def _AdbCommand(self, args): 85 def _adb_command(self, args):
86 """Forms an adb command from the given arguments, prepending the adb path 86 """Forms an adb command from the given arguments, prepending the adb path
87 and adding a target device specifier, if needed. 87 and adding a target device specifier, if needed.
88 """ 88 """
89 adb_command = [self.adb_path] 89 adb_command = [self.adb_path]
90 if self.target_device: 90 if self.target_device:
91 adb_command.extend(['-s', self.target_device]) 91 adb_command.extend(['-s', self.target_device])
92 adb_command.extend(args) 92 adb_command.extend(args)
93 return adb_command 93 return adb_command
94 94
95 def _ReadFifo(self, fifo_path, pipe, on_fifo_closed, max_attempts=5): 95 def _read_fifo(self, fifo_path, pipe, on_fifo_closed, max_attempts=5):
96 """Reads |fifo_path| on the device and write the contents to |pipe|. 96 """Reads |fifo_path| on the device and write the contents to |pipe|.
97 97
98 Calls |on_fifo_closed| when the fifo is closed. This method will try to find 98 Calls |on_fifo_closed| when the fifo is closed. This method will try to find
99 the path up to |max_attempts|, waiting 1 second between each attempt. If it 99 the path up to |max_attempts|, waiting 1 second between each attempt. If it
100 cannot find |fifo_path|, a exception will be raised. 100 cannot find |fifo_path|, a exception will be raised.
101 """ 101 """
102 fifo_command = self._AdbCommand( 102 fifo_command = self._adb_command(
103 ['shell', 'test -e "%s"; echo $?' % fifo_path]) 103 ['shell', 'test -e "%s"; echo $?' % fifo_path])
104 104
105 def Run(): 105 def _run():
106 def _WaitForFifo(): 106 def _wait_for_fifo():
107 for _ in xrange(max_attempts): 107 for _ in xrange(max_attempts):
108 if subprocess.check_output(fifo_command)[0] == '0': 108 if subprocess.check_output(fifo_command)[0] == '0':
109 return 109 return
110 time.sleep(1) 110 time.sleep(1)
111 if on_fifo_closed: 111 if on_fifo_closed:
112 on_fifo_closed() 112 on_fifo_closed()
113 raise Exception("Unable to find fifo.") 113 raise Exception("Unable to find fifo.")
114 _WaitForFifo() 114 _wait_for_fifo()
115 stdout_cat = subprocess.Popen( 115 stdout_cat = subprocess.Popen(
116 self._AdbCommand(['shell', 'cat', fifo_path]), stdout=pipe) 116 self._adb_command(['shell', 'cat', fifo_path]), stdout=pipe)
117 atexit.register(_exit_if_needed, stdout_cat) 117 atexit.register(_exit_if_needed, stdout_cat)
118 stdout_cat.wait() 118 stdout_cat.wait()
119 if on_fifo_closed: 119 if on_fifo_closed:
120 on_fifo_closed() 120 on_fifo_closed()
121 121
122 thread = threading.Thread(target=Run, name="StdoutRedirector") 122 thread = threading.Thread(target=_run, name="StdoutRedirector")
123 thread.start() 123 thread.start()
124 124
125 def _FindAvailableDevicePort(self): 125 def _find_available_device_port(self):
126 netstat_output = subprocess.check_output( 126 netstat_output = subprocess.check_output(
127 self._AdbCommand(['shell', 'netstat'])) 127 self._adb_command(['shell', 'netstat']))
128 return _find_available_port(netstat_output) 128 return _find_available_port(netstat_output)
129 129
130 def _ForwardDevicePortToHost(self, device_port, host_port): 130 def _forward_device_port_to_host(self, device_port, host_port):
131 """Maps the device port to the host port. If |device_port| is 0, a random 131 """Maps the device port to the host port. If |device_port| is 0, a random
132 available port is chosen. 132 available port is chosen.
133 133
134 Returns: 134 Returns:
135 The device port. 135 The device port.
136 """ 136 """
137 assert host_port 137 assert host_port
138 # Root is not required for `adb forward` (hence we don't check the return 138 # Root is not required for `adb forward` (hence we don't check the return
139 # value), but if we can run adb as root, we have to do it now, because 139 # value), but if we can run adb as root, we have to do it now, because
140 # restarting adbd as root clears any port mappings. See 140 # restarting adbd as root clears any port mappings. See
141 # https://github.com/domokit/devtools/issues/20. 141 # https://github.com/domokit/devtools/issues/20.
142 self._RunAdbAsRoot() 142 self._run_adb_as_root()
143 143
144 if device_port == 0: 144 if device_port == 0:
145 # TODO(ppi): Should we have a retry loop to handle the unlikely races? 145 # TODO(ppi): Should we have a retry loop to handle the unlikely races?
146 device_port = self._FindAvailableDevicePort() 146 device_port = self._find_available_device_port()
147 subprocess.check_call(self._AdbCommand([ 147 subprocess.check_call(self._adb_command([
148 "reverse", "tcp:%d" % device_port, "tcp:%d" % host_port])) 148 "reverse", "tcp:%d" % device_port, "tcp:%d" % host_port]))
149 149
150 def _UnmapPort(): 150 def _unmap_port():
151 unmap_command = self._AdbCommand([ 151 unmap_command = self._adb_command([
152 "reverse", "--remove", "tcp:%d" % device_port]) 152 "reverse", "--remove", "tcp:%d" % device_port])
153 subprocess.Popen(unmap_command) 153 subprocess.Popen(unmap_command)
154 atexit.register(_UnmapPort) 154 atexit.register(_unmap_port)
155 return device_port 155 return device_port
156 156
157 def _ForwardHostPortToDevice(self, host_port, device_port): 157 def _forward_host_port_to_device(self, host_port, device_port):
158 """Maps the host port to the device port. If |host_port| is 0, a random 158 """Maps the host port to the device port. If |host_port| is 0, a random
159 available port is chosen. 159 available port is chosen.
160 160
161 Returns: 161 Returns:
162 The host port. 162 The host port.
163 """ 163 """
164 assert device_port 164 assert device_port
165 self._RunAdbAsRoot() 165 self._run_adb_as_root()
166 166
167 if host_port == 0: 167 if host_port == 0:
168 # TODO(ppi): Should we have a retry loop to handle the unlikely races? 168 # TODO(ppi): Should we have a retry loop to handle the unlikely races?
169 host_port = _find_available_host_port() 169 host_port = _find_available_host_port()
170 subprocess.check_call(self._AdbCommand([ 170 subprocess.check_call(self._adb_command([
171 "forward", 'tcp:%d' % host_port, 'tcp:%d' % device_port])) 171 "forward", 'tcp:%d' % host_port, 'tcp:%d' % device_port]))
172 172
173 def _UnmapPort(): 173 def _unmap_port():
174 unmap_command = self._AdbCommand([ 174 unmap_command = self._adb_command([
175 "forward", "--remove", "tcp:%d" % device_port]) 175 "forward", "--remove", "tcp:%d" % device_port])
176 subprocess.Popen(unmap_command) 176 subprocess.Popen(unmap_command)
177 atexit.register(_UnmapPort) 177 atexit.register(_unmap_port)
178 return host_port 178 return host_port
179 179
180 def _RunAdbAsRoot(self): 180 def _run_adb_as_root(self):
181 if self.adb_running_as_root is not None: 181 if self.adb_running_as_root is not None:
182 return self.adb_running_as_root 182 return self.adb_running_as_root
183 183
184 if ('cannot run as root' not in subprocess.check_output( 184 if ('cannot run as root' not in subprocess.check_output(
185 self._AdbCommand(['root']))): 185 self._adb_command(['root']))):
186 # Wait for adbd to restart. 186 # Wait for adbd to restart.
187 subprocess.check_call( 187 subprocess.check_call(
188 self._AdbCommand(['wait-for-device']), 188 self._adb_command(['wait-for-device']),
189 stdout=self.verbose_pipe) 189 stdout=self.verbose_pipe)
190 self.adb_running_as_root = True 190 self.adb_running_as_root = True
191 else: 191 else:
192 self.adb_running_as_root = False 192 self.adb_running_as_root = False
193 193
194 return self.adb_running_as_root 194 return self.adb_running_as_root
195 195
196 def _IsShellPackageInstalled(self): 196 def _is_shell_package_installed(self):
197 # Adb should print one line if the package is installed and return empty 197 # Adb should print one line if the package is installed and return empty
198 # string otherwise. 198 # string otherwise.
199 return len(subprocess.check_output(self._AdbCommand([ 199 return len(subprocess.check_output(self._adb_command([
200 'shell', 'pm', 'list', 'packages', _MOJO_SHELL_PACKAGE_NAME]))) > 0 200 'shell', 'pm', 'list', 'packages', _MOJO_SHELL_PACKAGE_NAME]))) > 0
201 201
202 def CheckDevice(self): 202 def check_device(self):
203 """Verifies if the device configuration allows adb to run. 203 """Verifies if the device configuration allows adb to run.
204 204
205 If a target device was indicated in the constructor, it checks that the 205 If a target device was indicated in the constructor, it checks that the
206 device is available. Otherwise, it checks that there is exactly one 206 device is available. Otherwise, it checks that there is exactly one
207 available device. 207 available device.
208 208
209 Returns: 209 Returns:
210 A tuple of (result, msg). |result| is True iff if the device is correctly 210 A tuple of (result, msg). |result| is True iff if the device is correctly
211 configured and False otherwise. |msg| is the reason for failure if 211 configured and False otherwise. |msg| is the reason for failure if
212 |result| is False and None otherwise. 212 |result| is False and None otherwise.
213 """ 213 """
214 adb_devices_output = subprocess.check_output( 214 adb_devices_output = subprocess.check_output(
215 self._AdbCommand(['devices'])) 215 self._adb_command(['devices']))
216 # Skip the header line, strip empty lines at the end. 216 # Skip the header line, strip empty lines at the end.
217 device_list = [line.strip() for line in adb_devices_output.split('\n')[1:] 217 device_list = [line.strip() for line in adb_devices_output.split('\n')[1:]
218 if line.strip()] 218 if line.strip()]
219 219
220 if self.target_device: 220 if self.target_device:
221 if any([line.startswith(self.target_device) and 221 if any([line.startswith(self.target_device) and
222 line.endswith('device') for line in device_list]): 222 line.endswith('device') for line in device_list]):
223 return True, None 223 return True, None
224 else: 224 else:
225 return False, 'Cannot connect to the selected device.' 225 return False, 'Cannot connect to the selected device.'
226 226
227 if len(device_list) > 1: 227 if len(device_list) > 1:
228 return False, ('More than one device connected and target device not ' 228 return False, ('More than one device connected and target device not '
229 'specified.') 229 'specified.')
230 230
231 if not len(device_list): 231 if not len(device_list):
232 return False, 'No devices connected.' 232 return False, 'No devices connected.'
233 233
234 if not device_list[0].endswith('device'): 234 if not device_list[0].endswith('device'):
235 return False, 'Connected device is not available.' 235 return False, 'Connected device is not available.'
236 236
237 return True, None 237 return True, None
238 238
239 def InstallApk(self, shell_apk_path): 239 def install_apk(self, shell_apk_path):
240 """Installs the apk on the device. 240 """Installs the apk on the device.
241 241
242 This method computes checksum of the APK and skips the installation if the 242 This method computes checksum of the APK and skips the installation if the
243 fingerprint matches the one saved on the device upon the previous 243 fingerprint matches the one saved on the device upon the previous
244 installation. 244 installation.
245 245
246 Args: 246 Args:
247 shell_apk_path: Path to the shell Android binary. 247 shell_apk_path: Path to the shell Android binary.
248 """ 248 """
249 device_sha1_path = '/sdcard/%s/%s.sha1' % (_MOJO_SHELL_PACKAGE_NAME, 249 device_sha1_path = '/sdcard/%s/%s.sha1' % (_MOJO_SHELL_PACKAGE_NAME,
250 'MojoShell') 250 'MojoShell')
251 apk_sha1 = hashlib.sha1(open(shell_apk_path, 'rb').read()).hexdigest() 251 apk_sha1 = hashlib.sha1(open(shell_apk_path, 'rb').read()).hexdigest()
252 device_apk_sha1 = subprocess.check_output(self._AdbCommand([ 252 device_apk_sha1 = subprocess.check_output(self._adb_command([
253 'shell', 'cat', device_sha1_path])) 253 'shell', 'cat', device_sha1_path]))
254 do_install = (apk_sha1 != device_apk_sha1 or 254 do_install = (apk_sha1 != device_apk_sha1 or
255 not self._IsShellPackageInstalled()) 255 not self._is_shell_package_installed())
256 256
257 if do_install: 257 if do_install:
258 subprocess.check_call( 258 subprocess.check_call(
259 self._AdbCommand(['install', '-r', shell_apk_path, '-i', 259 self._adb_command(['install', '-r', shell_apk_path, '-i',
260 _MOJO_SHELL_PACKAGE_NAME]), 260 _MOJO_SHELL_PACKAGE_NAME]),
261 stdout=self.verbose_pipe) 261 stdout=self.verbose_pipe)
262 262
263 # Update the stamp on the device. 263 # Update the stamp on the device.
264 with tempfile.NamedTemporaryFile() as fp: 264 with tempfile.NamedTemporaryFile() as fp:
265 fp.write(apk_sha1) 265 fp.write(apk_sha1)
266 fp.flush() 266 fp.flush()
267 subprocess.check_call(self._AdbCommand(['push', fp.name, 267 subprocess.check_call(self._adb_command(['push', fp.name,
268 device_sha1_path]), 268 device_sha1_path]),
269 stdout=self.verbose_pipe) 269 stdout=self.verbose_pipe)
270 else: 270 else:
271 # To ensure predictable state after running InstallApk(), we need to stop 271 # To ensure predictable state after running install_apk(), we need to stop
272 # the shell here, as this is what "adb install" implicitly does. 272 # the shell here, as this is what "adb install" implicitly does.
273 self.StopShell() 273 self.stop_shell()
274 274
275 def StartShell(self, 275 def start_shell(self,
276 arguments, 276 arguments,
277 stdout=None, 277 stdout=None,
278 on_application_stop=None): 278 on_application_stop=None):
279 """Starts the mojo shell, passing it the given arguments. 279 """Starts the mojo shell, passing it the given arguments.
280 280
281 Args: 281 Args:
282 arguments: List of arguments for the shell. It must contain the 282 arguments: List of arguments for the shell. It must contain the
283 "--origin=" arg. shell_arguments.configure_local_origin() can be used 283 "--origin=" arg. shell_arguments.configure_local_origin() can be used
284 to set up a local directory on the host machine as origin. 284 to set up a local directory on the host machine as origin.
285 stdout: Valid argument for subprocess.Popen() or None. 285 stdout: Valid argument for subprocess.Popen() or None.
286 """ 286 """
287 if not self.stop_shell_registered: 287 if not self.stop_shell_registered:
288 atexit.register(self.StopShell) 288 atexit.register(self.stop_shell)
289 self.stop_shell_registered = True 289 self.stop_shell_registered = True
290 290
291 STDOUT_PIPE = "/data/data/%s/stdout.fifo" % _MOJO_SHELL_PACKAGE_NAME 291 STDOUT_PIPE = "/data/data/%s/stdout.fifo" % _MOJO_SHELL_PACKAGE_NAME
292 292
293 cmd = self._AdbCommand(['shell', 'am', 'start', 293 cmd = self._adb_command(['shell', 'am', 'start',
294 '-S', 294 '-S',
295 '-a', 'android.intent.action.VIEW', 295 '-a', 'android.intent.action.VIEW',
296 '-n', '%s/.MojoShellActivity' % 296 '-n', '%s/.MojoShellActivity' %
297 _MOJO_SHELL_PACKAGE_NAME]) 297 _MOJO_SHELL_PACKAGE_NAME])
298 298
299 parameters = [] 299 parameters = []
300 if stdout or on_application_stop: 300 if stdout or on_application_stop:
301 # We need to run as root to access the fifo file we use for stdout 301 # We need to run as root to access the fifo file we use for stdout
302 # redirection. 302 # redirection.
303 if self._RunAdbAsRoot(): 303 if self._run_adb_as_root():
304 # Remove any leftover fifo file after the previous run. 304 # Remove any leftover fifo file after the previous run.
305 subprocess.check_call(self._AdbCommand( 305 subprocess.check_call(self._adb_command(
306 ['shell', 'rm', '-f', STDOUT_PIPE])) 306 ['shell', 'rm', '-f', STDOUT_PIPE]))
307 307
308 parameters.append('--fifo-path=%s' % STDOUT_PIPE) 308 parameters.append('--fifo-path=%s' % STDOUT_PIPE)
309 self._ReadFifo(STDOUT_PIPE, stdout, on_application_stop) 309 self._read_fifo(STDOUT_PIPE, stdout, on_application_stop)
310 else: 310 else:
311 _logger.warning("Running without root access, full stdout of the " 311 _logger.warning("Running without root access, full stdout of the "
312 "shell won't be available.") 312 "shell won't be available.")
313 # The origin has to be specified whether it's local or external. 313 # The origin has to be specified whether it's local or external.
314 assert any("--origin=" in arg for arg in arguments) 314 assert any("--origin=" in arg for arg in arguments)
315 parameters.extend(arguments) 315 parameters.extend(arguments)
316 316
317 if parameters: 317 if parameters:
318 encodedParameters = json.dumps(parameters) 318 encodedParameters = json.dumps(parameters)
319 cmd += ['--es', 'encodedParameters', encodedParameters] 319 cmd += ['--es', 'encodedParameters', encodedParameters]
320 320
321 subprocess.check_call(cmd, stdout=self.verbose_pipe) 321 subprocess.check_call(cmd, stdout=self.verbose_pipe)
322 322
323 def StopShell(self): 323 def stop_shell(self):
324 """Stops the mojo shell.""" 324 """Stops the mojo shell."""
325 subprocess.check_call(self._AdbCommand(['shell', 325 subprocess.check_call(self._adb_command(['shell',
326 'am', 326 'am',
327 'force-stop', 327 'force-stop',
328 _MOJO_SHELL_PACKAGE_NAME])) 328 _MOJO_SHELL_PACKAGE_NAME]))
329 329
330 def CleanLogs(self): 330 def clean_logs(self):
331 """Cleans the logs on the device.""" 331 """Cleans the logs on the device."""
332 subprocess.check_call(self._AdbCommand(['logcat', '-c'])) 332 subprocess.check_call(self._adb_command(['logcat', '-c']))
333 333
334 def ShowLogs(self, include_native_logs=True): 334 def show_logs(self, include_native_logs=True):
335 """Displays the log for the mojo shell. 335 """Displays the log for the mojo shell.
336 336
337 Returns: 337 Returns:
338 The process responsible for reading the logs. 338 The process responsible for reading the logs.
339 """ 339 """
340 tags = _LOGCAT_JAVA_TAGS 340 tags = _LOGCAT_JAVA_TAGS
341 if include_native_logs: 341 if include_native_logs:
342 tags.extend(_LOGCAT_NATIVE_TAGS) 342 tags.extend(_LOGCAT_NATIVE_TAGS)
343 if self.additional_logcat_tags is not None: 343 if self.additional_logcat_tags is not None:
344 tags.extend(self.additional_logcat_tags.split(",")) 344 tags.extend(self.additional_logcat_tags.split(","))
345 logcat = subprocess.Popen( 345 logcat = subprocess.Popen(
346 self._AdbCommand(['logcat', '-s', ' '.join(tags)]), 346 self._adb_command(['logcat', '-s', ' '.join(tags)]),
347 stdout=sys.stdout) 347 stdout=sys.stdout)
348 atexit.register(_exit_if_needed, logcat) 348 atexit.register(_exit_if_needed, logcat)
349 return logcat 349 return logcat
350 350
351 def ForwardObservatoryPorts(self): 351 def forward_observatory_ports(self):
352 """Forwards the ports used by the dart observatories to the host machine. 352 """Forwards the ports used by the dart observatories to the host machine.
353 """ 353 """
354 logcat = subprocess.Popen(self._AdbCommand(['logcat']), 354 logcat = subprocess.Popen(self._adb_command(['logcat']),
355 stdout=subprocess.PIPE) 355 stdout=subprocess.PIPE)
356 atexit.register(_exit_if_needed, logcat) 356 atexit.register(_exit_if_needed, logcat)
357 357
358 def _ForwardObservatoriesAsNeeded(): 358 def _forward_observatories_as_needed():
359 while True: 359 while True:
360 line = logcat.stdout.readline() 360 line = logcat.stdout.readline()
361 if not line: 361 if not line:
362 break 362 break
363 match = re.search(r'Observatory listening on http://127.0.0.1:(\d+)', 363 match = re.search(r'Observatory listening on http://127.0.0.1:(\d+)',
364 line) 364 line)
365 if match: 365 if match:
366 device_port = int(match.group(1)) 366 device_port = int(match.group(1))
367 host_port = self._ForwardHostPortToDevice(0, device_port) 367 host_port = self._forward_host_port_to_device(0, device_port)
368 print ("Dart observatory available at the host at http://127.0.0.1:%d" 368 print ("Dart observatory available at the host at http://127.0.0.1:%d"
369 % host_port) 369 % host_port)
370 370
371 logcat_watch_thread = threading.Thread(target=_ForwardObservatoriesAsNeeded) 371 logcat_watch_thread = threading.Thread(
372 target=_forward_observatories_as_needed)
372 logcat_watch_thread.start() 373 logcat_watch_thread.start()
373 374
374 @overrides(Shell) 375 @overrides(Shell)
375 def ServeLocalDirectory(self, local_dir_path, port=0): 376 def serve_local_directory(self, local_dir_path, port=0):
376 assert local_dir_path 377 assert local_dir_path
377 mappings = [('', local_dir_path)] 378 mappings = [('', local_dir_path)]
378 server_address = start_http_server(mappings, host_port=port) 379 server_address = start_http_server(mappings, host_port=port)
379 380
380 return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost( 381 return 'http://127.0.0.1:%d/' % self._forward_device_port_to_host(
381 port, server_address[1]) 382 port, server_address[1])
382 383
383 @overrides(Shell) 384 @overrides(Shell)
384 def ServeLocalDirectories(self, mappings, port=0): 385 def serve_local_directories(self, mappings, port=0):
385 assert mappings 386 assert mappings
386 server_address = start_http_server(mappings, host_port=port) 387 server_address = start_http_server(mappings, host_port=port)
387 388
388 return 'http://127.0.0.1:%d/' % self._ForwardDevicePortToHost( 389 return 'http://127.0.0.1:%d/' % self._forward_device_port_to_host(
389 port, server_address[1]) 390 port, server_address[1])
390 391
391 @overrides(Shell) 392 @overrides(Shell)
392 def ForwardHostPortToShell(self, host_port): 393 def forward_host_port_to_shell(self, host_port):
393 self._ForwardHostPortToDevice(host_port, host_port) 394 self._forward_host_port_to_device(host_port, host_port)
394 395
395 @overrides(Shell) 396 @overrides(Shell)
396 def Run(self, arguments): 397 def run(self, arguments):
397 self.CleanLogs() 398 self.clean_logs()
398 self.ForwardObservatoryPorts() 399 self.forward_observatory_ports()
399 400
400 # If we are running as root, don't carry over the native logs from logcat - 401 # If we are running as root, don't carry over the native logs from logcat -
401 # we will have these in the stdout. 402 # we will have these in the stdout.
402 p = self.ShowLogs(include_native_logs=(not self._RunAdbAsRoot())) 403 p = self.show_logs(include_native_logs=(not self._run_adb_as_root()))
403 self.StartShell(arguments, sys.stdout, p.terminate) 404 self.start_shell(arguments, sys.stdout, p.terminate)
404 p.wait() 405 p.wait()
405 return None 406 return None
406 407
407 @overrides(Shell) 408 @overrides(Shell)
408 def RunAndGetOutput(self, arguments, timeout=None): 409 def run_and_get_output(self, arguments, timeout=None):
409 class Results: 410 class Results:
410 """Workaround for Python scoping rules that prevent assigning to variables 411 """Workaround for Python scoping rules that prevent assigning to variables
411 from the outer scope. 412 from the outer scope.
412 """ 413 """
413 output = None 414 output = None
414 415
415 def do_run(): 416 def do_run():
416 (r, w) = os.pipe() 417 (r, w) = os.pipe()
417 with os.fdopen(r, "r") as rf: 418 with os.fdopen(r, "r") as rf:
418 with os.fdopen(w, "w") as wf: 419 with os.fdopen(w, "w") as wf:
419 self.StartShell(arguments, wf, wf.close) 420 self.start_shell(arguments, wf, wf.close)
420 Results.output = rf.read() 421 Results.output = rf.read()
421 422
422 run_thread = threading.Thread(target=do_run) 423 run_thread = threading.Thread(target=do_run)
423 run_thread.start() 424 run_thread.start()
424 run_thread.join(timeout) 425 run_thread.join(timeout)
425 426
426 if run_thread.is_alive(): 427 if run_thread.is_alive():
427 self.StopShell() 428 self.stop_shell()
428 return None, Results.output, True 429 return None, Results.output, True
429 return None, Results.output, False 430 return None, Results.output, False
OLDNEW
« no previous file with comments | « no previous file | mojo/devtools/common/devtoolslib/apptest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698