def execute_adb_command(adb_cmd, piped_into_cmd=None, ignore_stderr=False): final_cmd = ('%s %s' % (_adb_prefix, adb_cmd)) if piped_into_cmd: final_cmd = '%s | %s' % (final_cmd, piped_into_cmd) print_verbose("Executing \"%s\"" % final_cmd) ps1 = subprocess.Popen(final_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_data, stderr_data = ps1.communicate() stdout_data = stdout_data.decode('utf-8') stderr_data = stderr_data.decode('utf-8') _check_for_more_than_one_device_error(stderr_data) _check_for_device_not_found_error(stderr_data) if not ignore_stderr and stderr_data and len(stderr_data) > 0: print_error(stderr_data) output = '' first_line = True if stdout_data: for line in stdout_data.split('\n'): line = line.strip() if not line or len(line) == 0: continue if first_line: output += line first_line = False else: output += '\n' + line print_verbose("Result is \"%s\"" % output) return output
def execute_file_related_adb_shell_command(adb_shell_cmd, file_path, piped_into_cmd=None, ignore_stderr=False, device_serial=None): file_not_found_message = 'No such file or directory' is_a_directory_message = 'Is a directory' # Error when someone tries to delete a dir with "-r" adb_cmds_prefix = [] run_as_package = get_package(file_path) if run_as_package: adb_cmds_prefix.append('shell run-as %s' % run_as_package) if root_required_to_access_file(file_path): adb_cmds_prefix.append('shell su root') # As a backup, still try with a plain-old access, if run-as is not possible and root is not available. adb_cmds_prefix.append('shell') stdout = None attempt_count = 1 for adb_cmd_prefix in adb_cmds_prefix: print_verbose('Attempt %d/%d: "%s"' % (attempt_count, len(adb_cmds_prefix), adb_cmd_prefix)) attempt_count += 1 adb_cmd = '%s %s' % (adb_cmd_prefix, adb_shell_cmd) return_code, stdout, stderr = execute_adb_command2(adb_cmd, piped_into_cmd, ignore_stderr, device_serial=device_serial) if stderr.find(file_not_found_message) >= 0: print_error('File not found: %s' % file_path) return stderr if stderr.find(is_a_directory_message) >= 0: print_error('%s is a directory' % file_path) return stderr api_version = get_device_android_api_version() if api_version >= _MIN_VERSION_ABOVE_WHICH_ADB_SHELL_RETURNS_CORRECT_EXIT_CODE and return_code == 0: return stdout return stdout
def _check_for_device_not_found_error(stderr_data): if not stderr_data: return for line in stderr_data.split('\n'): line = line.strip() if line and len(line) > 0: print_verbose(line) if line.find('error: device') > -1 and line.find('not found') > -1: print_error_and_exit(line)
def _check_for_more_than_one_device_error(stderr_data): if not stderr_data: return for line in stderr_data.split('\n'): line = line.strip() if line and len(line) > 0: print_verbose(line) if line.find('error: more than one') != -1: message = '' message += 'More than one device/emulator are connected.\n' message += 'Please select a device by providing the serial ID (-s parameter).\n' message += 'You can list all connected devices/emulators via \"devices\" subcommand.' print_error_and_exit(message)
def set_device_id(device_id): """ Make :param device_id: as main device to use Primary use-case: scripting Command line equivalent: "-s :param device_id:" """ old_adb_prefix = get_adb_prefix() if '-s' in old_adb_prefix: old_device = old_adb_prefix.split('-s ')[1] if ' ' in old_device: # Case: device ID is not the last argument old_device = old_adb_prefix.split('-s')[1].split(' ')[0] print_verbose('Switching from %s to %s' % (old_device, device_id)) old_adb_prefix.replace(old_device, device_id) print_verbose('Setting device ID to %s' % device_id) set_adb_prefix("%s -s %s" % (old_adb_prefix, device_id))
def execute_adb_command2(adb_cmd, piped_into_cmd=None, ignore_stderr=False, device_serial=None): adb_prefix = _adb_prefix if device_serial: adb_prefix = '%s -s %s' % (adb_prefix, device_serial) final_cmd = ('%s %s' % (adb_prefix, adb_cmd)) if piped_into_cmd: final_cmd = '%s | %s' % (final_cmd, piped_into_cmd) print_verbose("Executing \"%s\"" % final_cmd) ps1 = subprocess.Popen(final_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_data, stderr_data = ps1.communicate() return_code = ps1.returncode try: stdout_data = stdout_data.decode('utf-8') except UnicodeDecodeError: print_error( 'Unable to decode data as UTF-8, defaulting to printing the binary data' ) stderr_data = stderr_data.decode('utf-8') _check_for_adb_not_found_error(stderr_data) _check_for_more_than_one_device_error(stderr_data) _check_for_device_not_found_error(stderr_data) if not ignore_stderr and stderr_data: print_error(stderr_data) if not stdout_data: return return_code, None, stderr_data # stdout_data is not None if isinstance(stdout_data, bytes): print_verbose("Result is \"%s\"" % stdout_data) return return_code, stdout_data, stderr_data # str for Python 3, this used to be unicode type for python 2 elif isinstance(stdout_data, str): output = '' first_line = True for line in stdout_data.split('\n'): line = line.strip() if not line: continue if line in _IGNORED_LINES: continue if first_line: output += line first_line = False else: output += '\n' + line print_verbose("Result is \"%s\"" % output) return return_code, output, stderr_data else: print_error_and_exit('stdout_data is weird type: %s' % type(stdout_data))
def execute_adb_command(adb_cmd, piped_into_cmd=None, ignore_stderr=False, device_serial=None): adb_prefix = _adb_prefix if device_serial: adb_prefix = '%s -s %s' % (adb_prefix, device_serial) final_cmd = ('%s %s' % (adb_prefix, adb_cmd)) if piped_into_cmd: final_cmd = '%s | %s' % (final_cmd, piped_into_cmd) print_verbose("Executing \"%s\"" % final_cmd) ps1 = subprocess.Popen(final_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_data, stderr_data = ps1.communicate() try: stdout_data = stdout_data.decode('utf-8') except UnicodeDecodeError: print_error( 'Unable to decode data as UTF-8, defaulting to printing the binary data' ) stderr_data = stderr_data.decode('utf-8') _check_for_adb_not_found_error(stderr_data) _check_for_more_than_one_device_error(stderr_data) _check_for_device_not_found_error(stderr_data) if not ignore_stderr and stderr_data and len(stderr_data) > 0: print_error(stderr_data) if stdout_data: if isinstance(stdout_data, bytes): print_verbose("Result is \"%s\"" % stdout_data) return stdout_data # str for Python 3 and unicode for Python 2 # unicode is undefined for Python 3 elif isinstance(stdout_data, (str, unicode)): output = '' first_line = True for line in stdout_data.split('\n'): line = line.strip() if not line or len(line) == 0: continue if line in _IGNORED_LINES: continue if first_line: output += line first_line = False else: output += '\n' + line print_verbose("Result is \"%s\"" % output) return output return None
def execute_adb_command2(adb_cmd, piped_into_cmd=None, ignore_stderr=False, device_serial=None) -> [int, str, str]: """ :param adb_cmd: command to run inside the adb shell (so, don't prefix it with "adb") :param piped_into_cmd: command to pipe the output of this command into :param ignore_stderr: if true, errors in stderr stream will be ignored while piping commands :param device_serial: device serial to send this command to (in case of multiple devices) :return: (return_code, stdout, stderr) """ adb_prefix = _adb_prefix if device_serial: adb_prefix = '%s -s %s' % (adb_prefix, device_serial) final_cmd = ('%s %s' % (adb_prefix, adb_cmd)) if piped_into_cmd: final_cmd = '%s | %s' % (final_cmd, piped_into_cmd) print_verbose("Executing \"%s\"" % final_cmd) with subprocess.Popen(final_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as ps1: stdout_data, stderr_data = ps1.communicate() return_code = ps1.returncode try: stdout_data = stdout_data.decode('utf-8') except UnicodeDecodeError: print_error( 'Unable to decode data as UTF-8, defaulting to printing the binary data' ) stderr_data = stderr_data.decode('utf-8') _check_for_adb_not_found_error(stderr_data) _check_for_more_than_one_device_error(stderr_data) _check_for_device_not_found_error(stderr_data) if not ignore_stderr and stderr_data: print_error(stderr_data) if not stdout_data: return return_code, None, stderr_data # stdout_data is not None if isinstance(stdout_data, bytes): print_verbose("Result is \"%s\"" % stdout_data) return return_code, stdout_data, stderr_data # str for Python 3, this used to be unicode type for python 2 elif isinstance(stdout_data, str): output = '' first_line = True for line in stdout_data.split('\n'): line = line.strip() if not line: continue if line in _IGNORED_LINES: continue if first_line: output += line first_line = False else: output += '\n' + line print_verbose("Result is \"%s\"" % output) return return_code, output, stderr_data else: print_error_and_exit('stdout_data is weird type: %s' % type(stdout_data))