def start_cmd(self, cmds, device=True): """ Start a subprocess with adb command(s) Args: cmds: command(s) to be run device: if True, the device serial number must be specified by `-s serialno` argument Raises: RuntimeError: if `device` is True and serialno is not specified Returns: a subprocess """ if device: if not self.serialno: raise RuntimeError("please set serialno first") cmd_options = self.cmd_options + ['-s', self.serialno] else: cmd_options = self.cmd_options cmds = cmd_options + split_cmd(cmds) LOGGING.debug(" ".join(cmds)) if not PY3: cmds = [c.encode(get_std_encoding(sys.stdin)) for c in cmds] proc = subprocess.Popen(cmds, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return proc
def start_shell(self, cmds): """ Handle `adb shell` command(s) Args: cmds: adb shell command(s) Returns: None """ cmds = ['shell'] + split_cmd(cmds) return self.start_cmd(cmds)
def raw_shell(self, cmds, ensure_unicode=True): """ Handle `adb shell` command(s) with unicode support Args: cmds: adb shell command(s) ensure_unicode: decode/encode unicode True or False, default is True Returns: command(s) output """ cmds = ['shell'] + split_cmd(cmds) out = self.cmd(cmds, ensure_unicode=False) if not ensure_unicode: return out # use shell encoding to decode output try: return out.decode(self.SHELL_ENCODING) except UnicodeDecodeError: warnings.warn("shell output decode {} fail. repr={}".format(self.SHELL_ENCODING, repr(out))) return text_type(repr(out))
def shell(self, cmd): """ Run the `adb shell` command on the device Args: cmd: a command to be run Raises: AdbShellError: if command return value is non-zero or if any other `AdbError` occurred Returns: command output """ if self.sdk_version < SDK_VERISON_NEW: # for sdk_version < 25, adb shell do not raise error # https://stackoverflow.com/questions/9379400/adb-error-codes cmd = split_cmd(cmd) + [";", "echo", "---$?---"] out = self.raw_shell(cmd).rstrip() m = re.match("(.*)---(\d+)---$", out, re.DOTALL) if not m: warnings.warn("return code not matched") stdout = out returncode = 0 else: stdout = m.group(1) returncode = int(m.group(2)) if returncode > 0: raise AdbShellError("", stdout) return stdout else: try: out = self.raw_shell(cmd) except AdbError as err: raise AdbShellError(err.stdout, err.stderr) else: return out