1c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui#!/usr/bin/env python
2c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui#
3c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# Copyright (C) 2016 The Android Open Source Project
4c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui#
5c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# Licensed under the Apache License, Version 2.0 (the "License");
6c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# you may not use this file except in compliance with the License.
7c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# You may obtain a copy of the License at
8c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui#
9c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui#      http://www.apache.org/licenses/LICENSE-2.0
10c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui#
11c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# Unless required by applicable law or agreed to in writing, software
12c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# distributed under the License is distributed on an "AS IS" BASIS,
13c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# See the License for the specific language governing permissions and
15c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui# limitations under the License.
16c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui#
17c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
18c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui"""utils.py: export utility functions.
19c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui"""
20c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
21c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuifrom __future__ import print_function
22c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuiimport logging
23b8439265477bac5e32131a757e90abf510a77bf9Yabin Cuiimport os
24c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuiimport os.path
25c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuiimport subprocess
26c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuiimport sys
27c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
28c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuidef get_script_dir():
29c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    return os.path.dirname(os.path.realpath(__file__))
30c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
31c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
32c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuidef is_windows():
33c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    return sys.platform == 'win32' or sys.platform == 'cygwin'
34c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
35b8439265477bac5e32131a757e90abf510a77bf9Yabin Cuidef is_darwin():
36b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    return sys.platform == 'darwin'
37b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui
3898058a897528620916427e96485c58b8a534c6b3Yabin Cuidef is_python3():
3998058a897528620916427e96485c58b8a534c6b3Yabin Cui    return sys.version_info >= (3, 0)
4098058a897528620916427e96485c58b8a534c6b3Yabin Cui
41c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
42c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuidef log_debug(msg):
43c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    logging.debug(msg)
44c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
45c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
46c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuidef log_info(msg):
47c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    logging.info(msg)
48c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
49c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
50c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuidef log_warning(msg):
51c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    logging.warning(msg)
52c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
53c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
54c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuidef log_fatal(msg):
55c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    raise Exception(msg)
56c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
57b8439265477bac5e32131a757e90abf510a77bf9Yabin Cuidef log_exit(msg):
58b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    sys.exit(msg)
59b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui
6098058a897528620916427e96485c58b8a534c6b3Yabin Cuidef str_to_bytes(str):
6198058a897528620916427e96485c58b8a534c6b3Yabin Cui    if not is_python3():
6298058a897528620916427e96485c58b8a534c6b3Yabin Cui        return str
6398058a897528620916427e96485c58b8a534c6b3Yabin Cui    # In python 3, str are wide strings whereas the C api expects 8 bit strings, hence we have to convert
6498058a897528620916427e96485c58b8a534c6b3Yabin Cui    # For now using utf-8 as the encoding.
6598058a897528620916427e96485c58b8a534c6b3Yabin Cui    return str.encode('utf-8')
6698058a897528620916427e96485c58b8a534c6b3Yabin Cui
6798058a897528620916427e96485c58b8a534c6b3Yabin Cuidef bytes_to_str(bytes):
6898058a897528620916427e96485c58b8a534c6b3Yabin Cui    if not is_python3():
6998058a897528620916427e96485c58b8a534c6b3Yabin Cui        return bytes
7098058a897528620916427e96485c58b8a534c6b3Yabin Cui    return bytes.decode('utf-8')
71c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
72c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuidef get_target_binary_path(arch, binary_name):
7343c6963ba019dfc131c8cdb92cd4fcac8e23bba0Yabin Cui    if arch == 'aarch64':
7443c6963ba019dfc131c8cdb92cd4fcac8e23bba0Yabin Cui        arch = 'arm64'
758d367acde0d5fd09a3427703dc11583d44eb8199Yabin Cui    arch_dir = os.path.join(get_script_dir(), "bin", "android", arch)
76c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    if not os.path.isdir(arch_dir):
77c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        log_fatal("can't find arch directory: %s" % arch_dir)
78c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    binary_path = os.path.join(arch_dir, binary_name)
79c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    if not os.path.isfile(binary_path):
80c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        log_fatal("can't find binary: %s" % binary_path)
81c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    return binary_path
82c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
83c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
84c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuidef get_host_binary_path(binary_name):
858d367acde0d5fd09a3427703dc11583d44eb8199Yabin Cui    dir = os.path.join(get_script_dir(), 'bin')
86c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    if is_windows():
878d367acde0d5fd09a3427703dc11583d44eb8199Yabin Cui        if binary_name.endswith('.so'):
888d367acde0d5fd09a3427703dc11583d44eb8199Yabin Cui            binary_name = binary_name[0:-3] + '.dll'
89cbddd3829b6cf125340d1795f04931a5c8ff83efYabin Cui        elif binary_name.find('.') == -1:
90cbddd3829b6cf125340d1795f04931a5c8ff83efYabin Cui            binary_name += '.exe'
91c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        dir = os.path.join(dir, 'windows')
92c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    elif sys.platform == 'darwin': # OSX
938d367acde0d5fd09a3427703dc11583d44eb8199Yabin Cui        if binary_name.endswith('.so'):
948d367acde0d5fd09a3427703dc11583d44eb8199Yabin Cui            binary_name = binary_name[0:-3] + '.dylib'
95c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        dir = os.path.join(dir, 'darwin')
96c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    else:
97c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        dir = os.path.join(dir, 'linux')
988d367acde0d5fd09a3427703dc11583d44eb8199Yabin Cui    dir = os.path.join(dir, 'x86_64' if sys.maxsize > 2 ** 32 else 'x86')
99c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    binary_path = os.path.join(dir, binary_name)
100c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    if not os.path.isfile(binary_path):
101c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        log_fatal("can't find binary: %s" % binary_path)
102c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    return binary_path
103c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
104c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
105b8439265477bac5e32131a757e90abf510a77bf9Yabin Cuidef is_executable_available(executable, option='--help'):
106b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    """ Run an executable to see if it exists. """
107b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    try:
108b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        subproc = subprocess.Popen([executable, option], stdout=subprocess.PIPE,
109b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                                   stderr=subprocess.PIPE)
110b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        subproc.communicate()
111b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        return subproc.returncode == 0
112b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    except:
113b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        return False
114b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui
115b8439265477bac5e32131a757e90abf510a77bf9Yabin Cuiexpected_tool_paths = {
116b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    'adb': {
117b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'test_option': 'version',
118b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'darwin': [(True, 'Library/Android/sdk/platform-tools/adb'),
119b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                   (False, '../../platform-tools/adb')],
120b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'linux': [(True, 'Android/Sdk/platform-tools/adb'),
121b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                  (False, '../../platform-tools/adb')],
122b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'windows': [(True, 'AppData/Local/Android/sdk/platform-tools/adb'),
123b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                    (False, '../../platform-tools/adb')],
124b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    },
125b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    'readelf': {
126b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'test_option': '--help',
127b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'darwin': [(True, 'Library/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-readelf'),
128b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                   (False, '../toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-readelf')],
129b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'linux': [(True, 'Android/Sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-readelf'),
130b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                  (False, '../toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-readelf')],
131b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'windows': [(True, 'AppData/Local/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64/bin/aarch64-linux-android-readelf'),
132b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                    (False, '../toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64/bin/aarch64-linux-android-readelf')],
133b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    },
134b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    'addr2line': {
135b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'test_option': '--help',
136b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'darwin': [(True, 'Library/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line'),
137b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                   (False, '../toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line')],
138b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'linux': [(True, 'Android/Sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-addr2line'),
139b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                  (False, '../toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-addr2line')],
140b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        'windows': [(True, 'AppData/Local/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64/bin/aarch64-linux-android-addr2line'),
141b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui                    (False, '../toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64/bin/aarch64-linux-android-addr2line')],
142b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    },
143b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui}
144b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui
145b8439265477bac5e32131a757e90abf510a77bf9Yabin Cuidef find_tool_path(toolname):
146b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    if toolname not in expected_tool_paths:
147b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        return None
148b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    test_option = expected_tool_paths[toolname]['test_option']
149b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    if is_executable_available(toolname, test_option):
150b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        return toolname
151b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    platform = 'linux'
152b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    if is_windows():
153b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        platform = 'windows'
154b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    elif is_darwin():
155b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        platform = 'darwin'
156b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    paths = expected_tool_paths[toolname][platform]
157b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    home = os.environ.get('HOMEPATH') if is_windows() else os.environ.get('HOME')
158b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    for (relative_to_home, path) in paths:
159b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        path = path.replace('/', os.sep)
160b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        if relative_to_home:
161b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui            path = os.path.join(home, path)
162b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        else:
163b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui            path = os.path.join(get_script_dir(), path)
164b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        if is_executable_available(path, test_option):
165b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui            return path
166b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    return None
167b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui
168b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui
169c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cuiclass AdbHelper(object):
170b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    def __init__(self):
171b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        adb_path = find_tool_path('adb')
172b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        if not adb_path:
173b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui            log_exit("Can't find adb in PATH environment.")
174c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        self.adb_path = adb_path
175c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
1767c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
177c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    def run(self, adb_args):
178c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        return self.run_and_return_output(adb_args)[0]
179c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
1807c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
18121db24b10e5fd3f1833569ae5f957e114172e1d2Yabin Cui    def run_and_return_output(self, adb_args, stdout_file=None):
182c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        adb_args = [self.adb_path] + adb_args
183c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        log_debug('run adb cmd: %s' % adb_args)
18421db24b10e5fd3f1833569ae5f957e114172e1d2Yabin Cui        if stdout_file:
185cb38f9409733232cad495fba96590aba15fb073bYabin Cui            with open(stdout_file, 'wb') as stdout_fh:
18621db24b10e5fd3f1833569ae5f957e114172e1d2Yabin Cui                returncode = subprocess.call(adb_args, stdout=stdout_fh)
187cb38f9409733232cad495fba96590aba15fb073bYabin Cui            stdoutdata = ''
188cb38f9409733232cad495fba96590aba15fb073bYabin Cui        else:
189cb38f9409733232cad495fba96590aba15fb073bYabin Cui            subproc = subprocess.Popen(adb_args, stdout=subprocess.PIPE)
190cb38f9409733232cad495fba96590aba15fb073bYabin Cui            (stdoutdata, _) = subproc.communicate()
191cb38f9409733232cad495fba96590aba15fb073bYabin Cui            returncode = subproc.returncode
192cb38f9409733232cad495fba96590aba15fb073bYabin Cui        result = (returncode == 0)
193b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        if stdoutdata and adb_args[1] != 'push' and adb_args[1] != 'pull':
19498058a897528620916427e96485c58b8a534c6b3Yabin Cui            stdoutdata = bytes_to_str(stdoutdata)
195c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui            log_debug(stdoutdata)
196c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        log_debug('run adb cmd: %s  [result %s]' % (adb_args, result))
197c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        return (result, stdoutdata)
198c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
1997c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui    def check_run(self, adb_args):
2007c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        self.check_run_and_return_output(adb_args)
2017c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
2027c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
20321db24b10e5fd3f1833569ae5f957e114172e1d2Yabin Cui    def check_run_and_return_output(self, adb_args, stdout_file=None):
20421db24b10e5fd3f1833569ae5f957e114172e1d2Yabin Cui        result, stdoutdata = self.run_and_return_output(adb_args, stdout_file)
2057c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        if not result:
206b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui            log_exit('run "adb %s" failed' % adb_args)
2077c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        return stdoutdata
2087c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
2097c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
210c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui    def switch_to_root(self):
211c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        result, stdoutdata = self.run_and_return_output(['shell', 'whoami'])
212c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        if not result:
213c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui            return False
214c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        if stdoutdata.find('root') != -1:
215c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui            return True
2167c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        build_type = self.get_property('ro.build.type')
2177c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        if build_type == 'user':
218c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui            return False
219c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        self.run(['root'])
220c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        result, stdoutdata = self.run_and_return_output(['shell', 'whoami'])
221c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        if result and stdoutdata.find('root') != -1:
222c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui            return True
223c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui        return False
224c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
2257c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui    def get_property(self, name):
2267c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        result, stdoutdata = self.run_and_return_output(['shell', 'getprop', name])
2277c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        if not result:
2287c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui            return None
2297c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        return stdoutdata
2307c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
2317c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
2327c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui    def set_property(self, name, value):
2337c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui        return self.run(['shell', 'setprop', name, value])
2347c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
2357c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
2367c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cuidef load_config(config_file):
2377c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui    if not os.path.exists(config_file):
238b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        log_exit("can't find config_file: %s" % config_file)
2397c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui    config = {}
24098058a897528620916427e96485c58b8a534c6b3Yabin Cui    if is_python3():
24198058a897528620916427e96485c58b8a534c6b3Yabin Cui        with open(config_file, 'r') as fh:
24298058a897528620916427e96485c58b8a534c6b3Yabin Cui            source = fh.read()
24398058a897528620916427e96485c58b8a534c6b3Yabin Cui            exec(source, config)
24498058a897528620916427e96485c58b8a534c6b3Yabin Cui    else:
24598058a897528620916427e96485c58b8a534c6b3Yabin Cui        execfile(config_file, config)
2467c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui    return config
2477c83a6129e024993e5611eb2e1dc21cd574b6ab2Yabin Cui
248c5f4f7e30bf4d1becffbefe99cc8b7a0f76cdb8aYabin Cui
249b8439265477bac5e32131a757e90abf510a77bf9Yabin Cuidef flatten_arg_list(arg_list):
250b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    res = []
251b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    if arg_list:
252b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui        for items in arg_list:
253b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui            res += items
254b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui    return res
255b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui
256b8439265477bac5e32131a757e90abf510a77bf9Yabin Cui
25743c6963ba019dfc131c8cdb92cd4fcac8e23bba0Yabin Cuilogging.getLogger().setLevel(logging.DEBUG)
258