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