def do_flash_gsi(args): """Flashes a GSI image (system.img). Also erases userdata/metadata partition and disables Android Verified Boot (AVB). Args: args: flash_gsi command arguments. """ fastboot_utils.erase() # erases userdata/cache partition # Not every device has metadata partition, so allow_error is True. fastboot_utils.erase('metadata', allow_error=True) # Flashes GSI. fastboot_utils.flash('system', args.image) # Disables AVB. with file_utils.UnopenedTemporaryFile() as vbmeta_image: # vbmeta flag 2 means disable entire AVB verification. cmd_utils.run_command(['avbtool', 'make_vbmeta_image', '--flag', '2', '--padding_size', '4096', '--output', vbmeta_image]) # Not every device uses AVB, so allow_error is True. fastboot_utils.flash('vbmeta', vbmeta_image, allow_error=True) # Reboots the device. fastboot_utils.reboot()
def test_raise_on_error(self): error_cmd = 'echo foo; exit 13' with self.assertRaises(subprocess.CalledProcessError) as context_manager: cmd_utils.run_command(error_cmd, shell=True, raise_on_error=True) proc_err = context_manager.exception self.assertEqual(13, proc_err.returncode) self.assertEqual(error_cmd, proc_err.cmd)
def erase(partition_name=None, allow_error=False): """fastboot erase a partition.""" if partition_name is None: run_command(['fastboot', '-w'], raise_on_error=not allow_error) else: run_command(['fastboot', 'erase', partition_name], raise_on_error=not allow_error)
def root(serial_num=None): command = ['adb'] if serial_num: command += ['-s', serial_num] command += ['root'] # 'read_stdout=True' to disable output run_command(command, raise_on_error=False, read_stdout=True, log_stderr=True)
def test_raise_on_error(self): error_cmd = 'echo foo; exit 13' with self.assertRaises( subprocess.CalledProcessError) as context_manager: cmd_utils.run_command(error_cmd, shell=True, raise_on_error=True) proc_err = context_manager.exception self.assertEqual(13, proc_err.returncode) self.assertEqual(error_cmd, proc_err.cmd)
def flash(partition_name, image_name=None, allow_error=False): """fastboot flash a partition with a given image.""" cmd = ['fastboot', 'flash', partition_name] # image_name can be None, for `fastboot` to flash # ${ANDROID_PRODUCT_OUT}/{partition_name}.img. if image_name is not None: cmd.append(image_name) run_command(cmd, raise_on_error=not allow_error)
def get_type(image_file, file_spec): """Gets the type of the given file_spec. Args: image_file: The image file to be query. file_spec: The full file/directory in the image_file to be query. Returns: None if file_spec does not exist. 'regular' if file_spec is a file. 'directory' if file_spec is a directory. """ debugfs_command = 'stat {}'.format(file_spec) _, output, error = run_command( [_DEBUGFS, '-R', debugfs_command, image_file], read_stdout=True, read_stderr=True, log_stderr=True) if re.search('File not found', error): logging.debug('get_type() returns None') return None # Search the "type:" field in the output, it should be 'regular' (for a file) # or 'directory' m = re.search('Type:\\s*([^\\s]+)', output) assert m is not None, '{} outputs with an unknown format.'.format(_DEBUGFS) ret = m.group(1) logging.debug('get_type() returns \'%s\'', ret) return ret
def test_read_stdout_and_stderr(self): result = cmd_utils.run_command('echo foo; echo bar>&2; exit 11', shell=True, read_stdout=True, read_stderr=True, raise_on_error=False) self.assertEqual(11, result.returncode) self.assertEqual('foo\n', result.stdoutdata) self.assertEqual('bar\n', result.stderrdata)
def test_read_stderr(self): result = cmd_utils.run_command('(echo error1; echo error2)>&2; exit 9', shell=True, read_stderr=True, raise_on_error=False) self.assertEqual(9, result.returncode) self.assertEqual(None, result.stdoutdata) self.assertEqual('error1\nerror2\n', result.stderrdata)
def dump(image_file, file_spec, out_file): """Dumps the content of the file file_spec to the output file out_file. Args: image_file: The image file to be query. file_spec: The full file/directory in the image_file to be copied. out_file: The output file name in the local directory. Returns: True if 'debugfs' command success. False otherwise. """ debugfs_command = 'dump {} {}'.format(file_spec, out_file) run_command([_DEBUGFS, '-R', debugfs_command, image_file], log_stderr=True) if not os.path.isfile(out_file): logging.debug('debugfs failed to dump the file %s', file_spec) return False return True
def test_read_stdout(self): result = cmd_utils.run_command('echo 123; echo 456; exit 7', shell=True, read_stdout=True, raise_on_error=False) self.assertEqual(7, result.returncode) self.assertEqual('123\n456\n', result.stdoutdata) self.assertEqual(None, result.stderrdata)
def test_log_stdout(self): result = cmd_utils.run_command(['echo', '456'], raise_on_error=False, log_stdout=True) self.assertEqual((0, None, None), result) self.assertEqual(('INFO', "Executed command: 'echo 456' (ret: 0)"), self._log_entries[0]) self.assertEqual(('INFO', " stdout: '456\\n'"), self._log_entries[1])
def test_change_working_directory(self): """Tests that cwd argument can be passed to subprocess.Popen().""" tmp_dir = tempfile.mkdtemp(prefix='cmd_utils_test') result = cmd_utils.run_command('pwd', shell=True, read_stdout=True, raise_on_error=False, cwd=tmp_dir) self.assertEqual('%s\n' % tmp_dir, result.stdoutdata) shutil.rmtree(tmp_dir)
def test_log_stderr(self): error_cmd = 'echo foo; echo bar; (echo 123; echo 456;)>&2; exit 3' result = cmd_utils.run_command(error_cmd, shell=True, raise_on_error=False, log_stderr=True) self.assertEqual((3, None, None), result) self.assertEqual( ('ERROR', 'Executed command: %r (ret: %d)' % (error_cmd, 3)), self._log_entries[0]) self.assertEqual(('ERROR', " stderr: '123\\n456\\n'"), self._log_entries[1])
def pull(local_filename, remote_filename, serial_num=None): command = ['adb'] if serial_num: command += ['-s', serial_num] command += ['pull', remote_filename, local_filename] # 'read_stdout=True' to disable output (returncode, _, _) = run_command( command, raise_on_error=False, read_stdout=True) return returncode == 0
def test_log_stderr(self): error_cmd = 'echo foo; echo bar; (echo 123; echo 456;)>&2; exit 3' result = cmd_utils.run_command(error_cmd, shell=True, raise_on_error=False, log_stderr=True) self.assertEqual((3, None, None), result) self.assertEqual( ('INFO', 'Executed command: %r (ret: %d)' % (error_cmd, 3)), self._log_entries[0]) self.assertEqual(('ERROR', " stderr: '123\\n456\\n'"), self._log_entries[1])
def pull(local_filename, remote_filename, serial_num=None): command = ['adb'] if serial_num: command += ['-s', serial_num] command += ['pull', remote_filename, local_filename] # 'read_stdout=True' to disable output (returncode, _, _) = run_command(command, raise_on_error=False, read_stdout=True) return returncode == 0
def checkvintf(manifest, matrix): """call checkvintf. Args: manifest: manifest file matrix: matrix file Returns: A tuple with (check_result, error_message) """ logging.debug('checkvintf %s %s...', manifest, matrix) # 'read_stdout=True' to disable output (returncode, _, stderrdata) = run_command(['checkvintf', manifest, matrix], raise_on_error=False, read_stdout=True, read_stderr=True) return (returncode == 0, stderrdata)
def checkvintf(manifest, matrix): """call checkvintf. Args: manifest: manifest file matrix: matrix file Returns: A tuple with (check_result, error_message) """ logging.debug('checkvintf %s %s...', manifest, matrix) # 'read_stdout=True' to disable output (returncode, _, stderrdata) = run_command( ['checkvintf', manifest, matrix], raise_on_error=False, read_stdout=True, read_stderr=True) return (returncode == 0, stderrdata)
def checkvintf(manifest, matrix): """Invokes host command 'checkvintf' to do VINTF check. Usage of the command: checkvintf <manifest.xml> <matrix.xml>. Args: manifest: the manifest XML file. matrix: the matrix XML file. Returns: A tuple of (result_ok, stderr). """ logging.debug('checkvintf %s %s...', manifest, matrix) # Uses 'read_stdout' and 'read_stderr' to disable output. returncode, _, stderrdata = cmd_utils.run_command( ['checkvintf', manifest, matrix], raise_on_error=False, read_stdout=True, read_stderr=True) return (returncode == 0, stderrdata)
def unsparse(output_filename, input_filename): logging.debug('Unsparsing %s...', input_filename) run_command(['simg2img', input_filename, output_filename])
def copy_file(dest, src): run_command(['cp', src, dest], sudo=True) # This is a hack to give access permission without root run_command(['chmod', '+444', dest], sudo=True)
def unmount(mount_point): logging.debug('Unmounting...') run_command(['umount', '-l', mount_point], sudo=True, raise_on_error=False)
def _make_all(): logging.info('Make %s...', _MAKE_MODULE_NAME) build_top = os.environ['ANDROID_BUILD_TOP'] run_command(['make', '-j', _MAKE_MODULE_NAME], cwd=build_top)
def secilc(options, files): """Invokes SELinux Common Intermediate Language (CIL) Compiler. Args: options: A dict of the options passed to 'secilc'. e.g., dict(mls='true', multiple-decls=None, policyvers=30) ==> '--mls true --multiple-decls --policyvers 30'. e.g., dict(M='true', m=None, c=30) ==> '-M true -m -c 30'. files: CIL files passed to 'secilc'. Returns: A tuple of (result_ok, stderr). $ secilc --help Usage: secilc [OPTION]... FILE... Options: -o, --output=<file> write binary policy to <file> (default: policy.<version>) -f, --filecontext=<file> write file contexts to <file> (default: file_contexts) -t, --target=<type> specify target architecture. may be selinux or xen. (default: selinux) -M, --mls true|false build an mls policy. Must be true or false. This will override the (mls boolean) statement if present in the policy -c, --policyvers=<version> build a binary policy with a given <version> (default: 31) -U, --handle-unknown=<action> how to handle unknown classes or permissions. may be deny, allow, or reject. (default: deny) This will override the (handleunknown action) statement if present in the policy -D, --disable-dontaudit do not add dontaudit rules to the binary policy -P, --preserve-tunables treat tunables as booleans -m, --multiple-decls allow some statements to be re-declared -N, --disable-neverallow do not check neverallow rules -G, --expand-generated Expand and remove auto-generated attributes -X, --expand-size <SIZE> Expand type attributes with fewer than <SIZE> members. -v, --verbose increment verbosity level -h, --help display usage information """ cmd = ['secilc'] for option in options: # For short options. e.g., '-m', '-c 30'. if len(option) == 1: cmd.append('-' + option) else: # For long options. e.g., '--multiple-decls', '--policyvers 30'. cmd.append('--' + option) # Some option doesn't need value. e.g., -m, -G. if options[option] is not None: cmd.append(options[option]) # Adding CIL files. cmd.extend(files) # Uses 'log_stdout' and 'log_stderr' to disable output. returncode, _, stderrdata = cmd_utils.run_command(cmd, raise_on_error=False, log_stdout=True, log_stderr=True, read_stderr=True) return (returncode == 0, stderrdata)
def test_shell_command(self): result = cmd_utils.run_command('echo uses shell', shell=True) self.assertEqual((0, None, None), result) self.assertEqual(('INFO', "Executed command: 'echo uses shell' (ret: 0)"), self._log_entries[0])
def test_command_sequence(self): result = cmd_utils.run_command(['echo', '123']) self.assertEqual((0, None, None), result) self.assertEqual(('INFO', "Executed command: 'echo 123' (ret: 0)"), self._log_entries[0])
def reboot(): """fastboot reboot a device.""" run_command(['fastboot', 'reboot'], raise_on_error=False)
def test_shell_command(self): result = cmd_utils.run_command('echo uses shell', shell=True) self.assertEqual((0, None, None), result) self.assertEqual( ('INFO', "Executed command: 'echo uses shell' (ret: 0)"), self._log_entries[0])
def mount(mount_point, image_filename): logging.debug('Mounting...') run_command( ['mount', '-t', 'ext4', '-o', 'loop', image_filename, mount_point], sudo=True)