1*c8dee2aaSAndroid Build Coastguard Worker# Copyright 2016 Google Inc. 2*c8dee2aaSAndroid Build Coastguard Worker# 3*c8dee2aaSAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*c8dee2aaSAndroid Build Coastguard Worker# found in the LICENSE file. 5*c8dee2aaSAndroid Build Coastguard Worker 6*c8dee2aaSAndroid Build Coastguard Workerfrom __future__ import print_function 7*c8dee2aaSAndroid Build Coastguard Workerimport re 8*c8dee2aaSAndroid Build Coastguard Workerimport time 9*c8dee2aaSAndroid Build Coastguard Workerimport subprocess 10*c8dee2aaSAndroid Build Coastguard Workerimport sys 11*c8dee2aaSAndroid Build Coastguard Worker 12*c8dee2aaSAndroid Build Coastguard Workerclass Adb: 13*c8dee2aaSAndroid Build Coastguard Worker def __init__(self, device_serial=None, adb_binary=None, echo=False): 14*c8dee2aaSAndroid Build Coastguard Worker self.__invocation = [adb_binary] 15*c8dee2aaSAndroid Build Coastguard Worker if device_serial: 16*c8dee2aaSAndroid Build Coastguard Worker self.__invocation.extend(['-s', device_serial]) 17*c8dee2aaSAndroid Build Coastguard Worker self.__echo = echo 18*c8dee2aaSAndroid Build Coastguard Worker self.__is_root = None 19*c8dee2aaSAndroid Build Coastguard Worker self.__has_established_connection = False 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker def shell(self, cmd): 22*c8dee2aaSAndroid Build Coastguard Worker if self.__echo: 23*c8dee2aaSAndroid Build Coastguard Worker self.__echo_shell_cmd(cmd) 24*c8dee2aaSAndroid Build Coastguard Worker self.__invoke('shell', cmd) 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker def check(self, cmd): 27*c8dee2aaSAndroid Build Coastguard Worker if self.__echo: 28*c8dee2aaSAndroid Build Coastguard Worker self.__echo_shell_cmd(cmd) 29*c8dee2aaSAndroid Build Coastguard Worker self.__establish_connection() 30*c8dee2aaSAndroid Build Coastguard Worker result = subprocess.check_output(self.__invocation + ['shell', cmd], encoding='utf-8') 31*c8dee2aaSAndroid Build Coastguard Worker if self.__echo: 32*c8dee2aaSAndroid Build Coastguard Worker print(result, file=sys.stderr) 33*c8dee2aaSAndroid Build Coastguard Worker return result 34*c8dee2aaSAndroid Build Coastguard Worker 35*c8dee2aaSAndroid Build Coastguard Worker def root(self): 36*c8dee2aaSAndroid Build Coastguard Worker if not self.is_root(): 37*c8dee2aaSAndroid Build Coastguard Worker self.__invoke('root') 38*c8dee2aaSAndroid Build Coastguard Worker self.__has_established_connection = False 39*c8dee2aaSAndroid Build Coastguard Worker self.__is_root = None 40*c8dee2aaSAndroid Build Coastguard Worker return self.is_root() 41*c8dee2aaSAndroid Build Coastguard Worker 42*c8dee2aaSAndroid Build Coastguard Worker def is_root(self): 43*c8dee2aaSAndroid Build Coastguard Worker if self.__is_root is None: 44*c8dee2aaSAndroid Build Coastguard Worker self.__is_root = ('root' == self.check('whoami').strip()) 45*c8dee2aaSAndroid Build Coastguard Worker return self.__is_root 46*c8dee2aaSAndroid Build Coastguard Worker 47*c8dee2aaSAndroid Build Coastguard Worker def remount(self): 48*c8dee2aaSAndroid Build Coastguard Worker self.__invoke('remount') 49*c8dee2aaSAndroid Build Coastguard Worker 50*c8dee2aaSAndroid Build Coastguard Worker def reboot(self): 51*c8dee2aaSAndroid Build Coastguard Worker self.__is_root = None 52*c8dee2aaSAndroid Build Coastguard Worker self.shell('reboot') 53*c8dee2aaSAndroid Build Coastguard Worker self.__has_established_connection = False 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker def __echo_shell_cmd(self, cmd): 56*c8dee2aaSAndroid Build Coastguard Worker escaped = [re.sub(r'([^a-zA-Z0-9])', r'\\\1', x) 57*c8dee2aaSAndroid Build Coastguard Worker for x in cmd.strip().splitlines()] 58*c8dee2aaSAndroid Build Coastguard Worker self.__invoke('shell', 'echo', '$(whoami)@$(getprop ro.serialno)$', 59*c8dee2aaSAndroid Build Coastguard Worker " '\n>' ".join(escaped)) 60*c8dee2aaSAndroid Build Coastguard Worker 61*c8dee2aaSAndroid Build Coastguard Worker def __invoke(self, *args): 62*c8dee2aaSAndroid Build Coastguard Worker self.__establish_connection() 63*c8dee2aaSAndroid Build Coastguard Worker subprocess.call(self.__invocation + list(args), stdout=sys.stderr) 64*c8dee2aaSAndroid Build Coastguard Worker 65*c8dee2aaSAndroid Build Coastguard Worker def __establish_connection(self): 66*c8dee2aaSAndroid Build Coastguard Worker if self.__has_established_connection: 67*c8dee2aaSAndroid Build Coastguard Worker return 68*c8dee2aaSAndroid Build Coastguard Worker self.__has_established_connection = True 69*c8dee2aaSAndroid Build Coastguard Worker self.__invoke('wait-for-device') 70*c8dee2aaSAndroid Build Coastguard Worker while True: 71*c8dee2aaSAndroid Build Coastguard Worker time.sleep(1) 72*c8dee2aaSAndroid Build Coastguard Worker if '1' == self.check('getprop sys.boot_completed').strip(): 73*c8dee2aaSAndroid Build Coastguard Worker break 74