1#!/usr/bin/env python3.4 2# 3# Copyright 2016 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17from acts.libs.proc import job 18 19import logging 20 21 22class FastbootError(Exception): 23 """Raised when there is an error in fastboot operations.""" 24 25 def __init__(self, cmd, stdout, stderr, ret_code): 26 self.cmd = cmd 27 self.stdout = stdout 28 self.stderr = stderr 29 self.ret_code = ret_code 30 31 def __str__(self): 32 return ("Error executing fastboot cmd '%s'. ret: %d, stdout: %s," 33 " stderr: %s") % (self.cmd, self.ret_code, self.stdout, 34 self.stderr) 35 36 37class FastbootProxy(): 38 """Proxy class for fastboot. 39 40 For syntactic reasons, the '-' in fastboot commands need to be replaced 41 with '_'. Can directly execute fastboot commands on an object: 42 >> fb = FastbootProxy(<serial>) 43 >> fb.devices() # will return the console output of "fastboot devices". 44 """ 45 46 def __init__(self, serial="", ssh_connection=None): 47 self.serial = serial 48 if serial: 49 self.fastboot_str = "fastboot -s {}".format(serial) 50 else: 51 self.fastboot_str = "fastboot" 52 self.ssh_connection = ssh_connection 53 54 def _exec_fastboot_cmd(self, 55 name, 56 arg_str, 57 ignore_status=False, 58 timeout=60): 59 command = ' '.join((self.fastboot_str, name, arg_str)) 60 if self.ssh_connection: 61 result = self.connection.run(command, 62 ignore_status=True, 63 timeout=timeout) 64 else: 65 result = job.run(command, ignore_status=True, timeout=timeout) 66 ret, out, err = result.exit_status, result.stdout, result.stderr 67 # TODO: This is only a temporary workaround for b/34815412. 68 # fastboot getvar outputs to stderr instead of stdout 69 if "getvar" in command: 70 out = err 71 if ret == 0 or ignore_status: 72 return out 73 else: 74 raise FastbootError( 75 cmd=command, stdout=out, stderr=err, ret_code=ret) 76 77 def args(self, *args, **kwargs): 78 return job.run(' '.join((self.fastboot_str, ) + args), **kwargs).stdout 79 80 def __getattr__(self, name): 81 def fastboot_call(*args, **kwargs): 82 clean_name = name.replace('_', '-') 83 arg_str = ' '.join(str(elem) for elem in args) 84 return self._exec_fastboot_cmd(clean_name, arg_str, **kwargs) 85 86 return fastboot_call 87