def GetBootImageTimestamp(boot_img): """ Get timestamp from ramdisk within the boot image Args: boot_img: the boot image file. Ramdisk must be compressed with lz4 format. Return: An integer that corresponds to the timestamp of the boot image, or None if file has unknown format. Raise exception if an unexpected error has occurred. """ tmp_dir = MakeTempDir('boot_', suffix='.img') try: RunAndCheckOutput( ['unpack_bootimg', '--boot_img', boot_img, '--out', tmp_dir]) ramdisk = os.path.join(tmp_dir, 'ramdisk') if not os.path.isfile(ramdisk): logger.warning( 'Unable to get boot image timestamp: no ramdisk in boot') return None uncompressed_ramdisk = os.path.join(tmp_dir, 'uncompressed_ramdisk') RunAndCheckOutput(['lz4', '-d', ramdisk, uncompressed_ramdisk]) abs_uncompressed_ramdisk = os.path.abspath(uncompressed_ramdisk) extracted_ramdisk = MakeTempDir('extracted_ramdisk') # Use "toybox cpio" instead of "cpio" because the latter invokes cpio from # the host environment. RunAndCheckOutput( ['toybox', 'cpio', '-F', abs_uncompressed_ramdisk, '-i'], cwd=extracted_ramdisk) prop_file = None for search_path in RAMDISK_BUILD_PROP_REL_PATHS: prop_file = os.path.join(extracted_ramdisk, search_path) if os.path.isfile(prop_file): break logger.warning( 'Unable to get boot image timestamp: no %s in ramdisk', search_path) if not prop_file: return None props = PartitionBuildProps.FromBuildPropFile('boot', prop_file) timestamp = props.GetProp('ro.bootimage.build.date.utc') if timestamp: return int(timestamp) logger.warning( 'Unable to get boot image timestamp: ro.bootimage.build.date.utc is undefined' ) return None except ExternalError as e: logger.warning('Unable to get boot image timestamp: %s', e) return None
def GetApexInfoFromTargetFiles(input_file, partition, compressed_only=True): """ Get information about system APEX stored in the input_file zip Args: input_file: The filename of the target build target-files zip or directory. Return: A list of ota_metadata_pb2.ApexInfo() populated using the APEX stored in /system partition of the input_file """ # Extract the apex files so that we can run checks on them if not isinstance(input_file, str): raise RuntimeError("must pass filepath to target-files zip or directory") apex_subdir = os.path.join(partition.upper(), 'apex') if os.path.isdir(input_file): tmp_dir = input_file else: tmp_dir = UnzipTemp(input_file, [os.path.join(apex_subdir, '*')]) target_dir = os.path.join(tmp_dir, apex_subdir) # Partial target-files packages for vendor-only builds may not contain # a system apex directory. if not os.path.exists(target_dir): logger.info('No APEX directory at path: %s', target_dir) return [] apex_infos = [] debugfs_path = "debugfs" if OPTIONS.search_path: debugfs_path = os.path.join(OPTIONS.search_path, "bin", "debugfs_static") deapexer = 'deapexer' if OPTIONS.search_path: deapexer_path = os.path.join(OPTIONS.search_path, "bin", "deapexer") if os.path.isfile(deapexer_path): deapexer = deapexer_path for apex_filename in os.listdir(target_dir): apex_filepath = os.path.join(target_dir, apex_filename) if not os.path.isfile(apex_filepath) or \ not zipfile.is_zipfile(apex_filepath): logger.info("Skipping %s because it's not a zipfile", apex_filepath) continue apex_info = ota_metadata_pb2.ApexInfo() # Open the apex file to retrieve information manifest = apex_manifest.fromApex(apex_filepath) apex_info.package_name = manifest.name apex_info.version = manifest.version # Check if the file is compressed or not apex_type = RunAndCheckOutput([ deapexer, "--debugfs_path", debugfs_path, 'info', '--print-type', apex_filepath]).rstrip() if apex_type == 'COMPRESSED': apex_info.is_compressed = True elif apex_type == 'UNCOMPRESSED': apex_info.is_compressed = False else: raise RuntimeError('Not an APEX file: ' + apex_type) # Decompress compressed APEX to determine its size if apex_info.is_compressed: decompressed_file_path = MakeTempFile(prefix="decompressed-", suffix=".apex") # Decompression target path should not exist os.remove(decompressed_file_path) RunAndCheckOutput([deapexer, 'decompress', '--input', apex_filepath, '--output', decompressed_file_path]) apex_info.decompressed_size = os.path.getsize(decompressed_file_path) if not compressed_only or apex_info.is_compressed: apex_infos.append(apex_info) return apex_infos