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

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

Issue 1381863004: Fix mojo_ tools on the first run after adb kill-server. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 2 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/android_shell_unittest.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 20 matching lines...) Expand all
31 ] 31 ]
32 32
33 # Tags used by native logging reflected in the logcat. 33 # Tags used by native logging reflected in the logcat.
34 _LOGCAT_NATIVE_TAGS = [ 34 _LOGCAT_NATIVE_TAGS = [
35 'chromium', 35 'chromium',
36 'sky', 36 'sky',
37 ] 37 ]
38 38
39 _MOJO_SHELL_PACKAGE_NAME = 'org.chromium.mojo.shell' 39 _MOJO_SHELL_PACKAGE_NAME = 'org.chromium.mojo.shell'
40 40
41 # Used to parse the output of `adb devices`.
42 _ADB_DEVICES_HEADER = 'List of devices attached'
43
41 44
42 _logger = logging.getLogger() 45 _logger = logging.getLogger()
43 46
44 47
45 def _exit_if_needed(process): 48 def _exit_if_needed(process):
46 """Exits |process| if it is still alive.""" 49 """Exits |process| if it is still alive."""
47 if process.poll() is None: 50 if process.poll() is None:
48 process.kill() 51 process.kill()
49 52
50 53
51 def _find_available_port(netstat_output, max_attempts=10000): 54 def _find_available_port(netstat_output, max_attempts=10000):
52 opened = [int(x.strip().split()[3].split(':')[1]) 55 opened = [int(x.strip().split()[3].split(':')[1])
53 for x in netstat_output if x.startswith(' tcp')] 56 for x in netstat_output if x.startswith(' tcp')]
54 for _ in xrange(max_attempts): 57 for _ in xrange(max_attempts):
55 port = random.randint(4096, 16384) 58 port = random.randint(4096, 16384)
56 if port not in opened: 59 if port not in opened:
57 return port 60 return port
58 else: 61 else:
59 raise Exception('Failed to identify an available port.') 62 raise Exception('Failed to identify an available port.')
60 63
61 64
62 def _find_available_host_port(): 65 def _find_available_host_port():
63 netstat_output = subprocess.check_output(['netstat']) 66 netstat_output = subprocess.check_output(['netstat'])
64 return _find_available_port(netstat_output) 67 return _find_available_port(netstat_output)
65 68
69 def parse_adb_devices_output(adb_devices_output):
70 """Parses the output of the `adb devices` command, returning a dictionary
71 mapping device id to the status of the device, as printed by `adb devices`.
72 """
73 # Split into lines skipping empty ones.
74 lines = [line.strip() for line in adb_devices_output.split('\n')
75 if line.strip()]
76
77 if _ADB_DEVICES_HEADER not in lines:
78 return None
79
80 # The header can be preceeded by output informing of adb server being spawned,
81 # but all non-empty lines after the header describe connected devices.
82 device_specs = lines[lines.index(_ADB_DEVICES_HEADER) + 1:]
83 return {spec.split()[0]: spec.split()[1] for spec in device_specs
84 if len(spec.split()) == 2}
qsr 2015/10/05 14:56:04 What about cutting this line in two, there is a lo
ppi 2015/10/05 15:17:42 Done.
85
66 86
67 class AndroidShell(Shell): 87 class AndroidShell(Shell):
68 """Wrapper around Mojo shell running on an Android device. 88 """Wrapper around Mojo shell running on an Android device.
69 89
70 Args: 90 Args:
71 adb_path: Path to adb, optional if adb is in PATH. 91 adb_path: Path to adb, optional if adb is in PATH.
72 target_device: Device to run on, if multiple devices are connected. 92 target_device: Device to run on, if multiple devices are connected.
73 logcat_tags: Comma-separated list of additional logcat tags to use. 93 logcat_tags: Comma-separated list of additional logcat tags to use.
74 """ 94 """
75 95
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 device is available. Otherwise, it checks that there is exactly one 226 device is available. Otherwise, it checks that there is exactly one
207 available device. 227 available device.
208 228
209 Returns: 229 Returns:
210 A tuple of (result, msg). |result| is True iff if the device is correctly 230 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 231 configured and False otherwise. |msg| is the reason for failure if
212 |result| is False and None otherwise. 232 |result| is False and None otherwise.
213 """ 233 """
214 adb_devices_output = subprocess.check_output( 234 adb_devices_output = subprocess.check_output(
215 self._adb_command(['devices'])) 235 self._adb_command(['devices']))
216 # Skip the header line, strip empty lines at the end. 236 devices = parse_adb_devices_output(adb_devices_output)
217 device_list = [line.strip() for line in adb_devices_output.split('\n')[1:] 237
218 if line.strip()] 238 if not devices:
239 return False, 'No devices connected.'
219 240
220 if self.target_device: 241 if self.target_device:
221 if any([line.startswith(self.target_device) and 242 if (self.target_device in devices and
222 line.endswith('device') for line in device_list]): 243 devices[self.target_device] == 'device'):
223 return True, None 244 return True, None
224 else: 245 else:
225 return False, 'Cannot connect to the selected device.' 246 return False, ('Cannot connect to the selected device, status: ' +
247 devices[self.target_device])
226 248
227 if len(device_list) > 1: 249 if len(devices) > 1:
228 return False, ('More than one device connected and target device not ' 250 return False, ('More than one device connected and target device not '
229 'specified.') 251 'specified.')
230 252
231 if not len(device_list): 253 if not devices.itervalues().next() == 'device':
232 return False, 'No devices connected.'
233
234 if not device_list[0].endswith('device'):
235 return False, 'Connected device is not available.' 254 return False, 'Connected device is not available.'
236 255
237 if require_root and not self._run_adb_as_root(): 256 if require_root and not self._run_adb_as_root():
238 return False, 'Cannot run on an unrooted device.' 257 return False, 'Cannot run on an unrooted device.'
239 258
240 return True, None 259 return True, None
241 260
242 def install_apk(self, shell_apk_path): 261 def install_apk(self, shell_apk_path):
243 """Installs the apk on the device. 262 """Installs the apk on the device.
244 263
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 Results.output = rf.read() 440 Results.output = rf.read()
422 441
423 run_thread = threading.Thread(target=do_run) 442 run_thread = threading.Thread(target=do_run)
424 run_thread.start() 443 run_thread.start()
425 run_thread.join(timeout) 444 run_thread.join(timeout)
426 445
427 if run_thread.is_alive(): 446 if run_thread.is_alive():
428 self.stop_shell() 447 self.stop_shell()
429 return None, Results.output, True 448 return None, Results.output, True
430 return None, Results.output, False 449 return None, Results.output, False
OLDNEW
« no previous file with comments | « no previous file | mojo/devtools/common/devtoolslib/android_shell_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698