blob: 5fb61a8ccf462966054e5fbabaa03c40c6da638d [file] [log] [blame]
Chris Craikad0b04f2015-07-21 13:44:22 -07001# Copyright (c) 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import optparse
6import subprocess
7import sys
8
9
10class OptionParserIgnoreErrors(optparse.OptionParser):
11 """Wrapper for OptionParser that ignores errors and produces no output."""
12
13 def error(self, msg):
14 pass
15
16 def exit(self):
17 pass
18
19 def print_usage(self):
20 pass
21
22 def print_help(self):
23 pass
24
25 def print_version(self):
26 pass
27
28
29def add_adb_serial(adb_command, device_serial):
30 if device_serial is not None:
31 adb_command.insert(1, device_serial)
32 adb_command.insert(1, '-s')
33
34
35def construct_adb_shell_command(shell_args, device_serial):
36 adb_command = ['adb', 'shell', ' '.join(shell_args)]
37 add_adb_serial(adb_command, device_serial)
38 return adb_command
39
40
41def run_adb_shell(shell_args, device_serial):
42 """Runs "adb shell" with the given arguments.
43
44 Args:
45 shell_args: array of arguments to pass to adb shell.
46 device_serial: if not empty, will add the appropriate command-line
47 parameters so that adb targets the given device.
48 Returns:
49 A tuple containing the adb output (stdout & stderr) and the return code
50 from adb. Will exit if adb fails to start.
51 """
52 adb_command = construct_adb_shell_command(shell_args, device_serial)
53
54 adb_output = []
55 adb_return_code = 0
56 try:
57 adb_output = subprocess.check_output(adb_command, stderr=subprocess.STDOUT,
58 shell=False, universal_newlines=True)
59 except OSError as error:
60 # This usually means that the adb executable was not found in the path.
61 print >> sys.stderr, ('\nThe command "%s" failed with the following error:'
62 % ' '.join(adb_command))
63 print >> sys.stderr, ' %s\n' % str(error)
64 print >> sys.stderr, 'Is adb in your path?'
65 sys.exit(1)
66 except subprocess.CalledProcessError as error:
67 # The process exited with an error.
68 adb_return_code = error.returncode
69 adb_output = error.output
70
71 return (adb_output, adb_return_code)
72
73
74def get_device_sdk_version():
75 """Uses adb to attempt to determine the SDK version of a running device."""
76
77 getprop_args = ['getprop', 'ro.build.version.sdk']
78
79 # get_device_sdk_version() is called before we even parse our command-line
80 # args. Therefore, parse just the device serial number part of the
81 # command-line so we can send the adb command to the correct device.
82 parser = OptionParserIgnoreErrors()
83 parser.add_option('-e', '--serial', dest='device_serial', type='string')
84 options, unused_args = parser.parse_args()
85
86 success = False
87
88 adb_output, adb_return_code = run_adb_shell(getprop_args,
89 options.device_serial)
90
91 if adb_return_code == 0:
92 # ADB may print output other than the version number (e.g. it chould
93 # print a message about starting the ADB server).
94 # Break the ADB output into white-space delimited segments.
95 parsed_output = str.split(adb_output)
96 if parsed_output:
97 # Assume that the version number is the last thing printed by ADB.
98 version_string = parsed_output[-1]
99 if version_string:
100 try:
101 # Try to convert the text into an integer.
102 version = int(version_string)
103 except ValueError:
104 version = -1
105 else:
106 success = True
107
108 if not success:
109 print >> sys.stderr, (
110 '\nThe command "%s" failed with the following message:'
111 % ' '.join(getprop_args))
112 print >> sys.stderr, adb_output
113 sys.exit(1)
114
115 return version