| #!/usr/bin/env python3 |
| # |
| # Copyright 2016 - The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| from acts.libs.proc import job |
| |
| import logging |
| from acts import error |
| |
| |
| class FastbootError(error.ActsError): |
| """Raised when there is an error in fastboot operations.""" |
| |
| def __init__(self, cmd, stdout, stderr, ret_code): |
| super().__init__() |
| self.cmd = cmd |
| self.stdout = stdout |
| self.stderr = stderr |
| self.ret_code = ret_code |
| |
| def __str__(self): |
| return ("Error executing fastboot cmd '%s'. ret: %d, stdout: %s," |
| " stderr: %s") % (self.cmd, self.ret_code, self.stdout, |
| self.stderr) |
| |
| |
| class FastbootProxy(): |
| """Proxy class for fastboot. |
| |
| For syntactic reasons, the '-' in fastboot commands need to be replaced |
| with '_'. Can directly execute fastboot commands on an object: |
| >> fb = FastbootProxy(<serial>) |
| >> fb.devices() # will return the console output of "fastboot devices". |
| """ |
| |
| def __init__(self, serial="", ssh_connection=None): |
| self.serial = serial |
| if serial: |
| self.fastboot_str = "fastboot -s {}".format(serial) |
| else: |
| self.fastboot_str = "fastboot" |
| self.ssh_connection = ssh_connection |
| |
| def _exec_fastboot_cmd(self, |
| name, |
| arg_str, |
| ignore_status=False, |
| timeout=60): |
| command = ' '.join((self.fastboot_str, name, arg_str)) |
| if self.ssh_connection: |
| result = self.connection.run(command, |
| ignore_status=True, |
| timeout=timeout) |
| else: |
| result = job.run(command, ignore_status=True, timeout=timeout) |
| ret, out, err = result.exit_status, result.stdout, result.stderr |
| # TODO: This is only a temporary workaround for b/34815412. |
| # fastboot getvar outputs to stderr instead of stdout |
| if "getvar" in command: |
| out = err |
| if ret == 0 or ignore_status: |
| return out |
| else: |
| raise FastbootError( |
| cmd=command, stdout=out, stderr=err, ret_code=ret) |
| |
| def args(self, *args, **kwargs): |
| return job.run(' '.join((self.fastboot_str, ) + args), **kwargs).stdout |
| |
| def __getattr__(self, name): |
| def fastboot_call(*args, **kwargs): |
| clean_name = name.replace('_', '-') |
| arg_str = ' '.join(str(elem) for elem in args) |
| return self._exec_fastboot_cmd(clean_name, arg_str, **kwargs) |
| |
| return fastboot_call |