diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-10-17 02:51:58 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-10-17 02:51:58 +0000 |
commit | c0c48de6138d84452870a50547ab521986cf4748 (patch) | |
tree | c6db8c6633a1c812caa9bc2fd2a2994c83db8f4c | |
parent | 32da00d9648f01cb235e7d4ec5bfc8eac10e2495 (diff) | |
parent | 639f241760f0eac593bb31c2df86caddece0c5b0 (diff) | |
download | treble-android14-qpr2-s2-release.tar.gz |
Snap for 10958510 from 639f241760f0eac593bb31c2df86caddece0c5b0 to 24Q1-releaseandroid-14.0.0_r33android-14.0.0_r32android-14.0.0_r31android-14.0.0_r30android-14.0.0_r29android14-qpr2-s3-releaseandroid14-qpr2-s2-releaseandroid14-qpr2-s1-releaseandroid14-qpr2-release
Change-Id: I6acaccc6b05a196aca098b2bcb0e1099c12266f0
-rw-r--r-- | cuttlefish/Android.bp | 34 | ||||
-rw-r--r-- | cuttlefish/build_cf_hybrid_device.py | 113 | ||||
-rw-r--r-- | cuttlefish/build_chd_utils.py | 78 |
3 files changed, 225 insertions, 0 deletions
diff --git a/cuttlefish/Android.bp b/cuttlefish/Android.bp new file mode 100644 index 0000000..1427963 --- /dev/null +++ b/cuttlefish/Android.bp @@ -0,0 +1,34 @@ +// Copyright (C) 2023 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. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +python_library_host { + name: "build_chd_lib", + srcs: [ + "build_chd_utils.py", + ], +} + +python_binary_host { + name: "build_cf_hybrid_device", + srcs: [ + "build_cf_hybrid_device.py", + ], + libs: [ + "build_chd_lib", + ], +} diff --git a/cuttlefish/build_cf_hybrid_device.py b/cuttlefish/build_cf_hybrid_device.py new file mode 100644 index 0000000..a62e919 --- /dev/null +++ b/cuttlefish/build_cf_hybrid_device.py @@ -0,0 +1,113 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2023 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. + +import argparse +import glob +import os +import subprocess +import tempfile + +from build_chd_utils import copy_files +from build_chd_utils import unzip_otatools + +"""Test command: + +WORKSPACE=out/dist && \ +python3 tools/treble/cuttlefish/build_cf_hybrid_device.py \ + --build_id 123456 \ + --otatools_zip $WORKSPACE/otatools.zip \ + --target chd-target \ + --output_dir $WORKSPACE \ + --framework_target_files_zip $WORKSPACE/device-target_files-*.zip \ + --vendor_target_files_zip $WORKSPACE/cf_arm64_only_phone-target_files-*.zip +""" + + +def _parse_args(): + """Parse the arguments for building cuttlefish hybrid devices. + + Returns: + An object of argparse.Namespace. + """ + parser = argparse.ArgumentParser() + + parser.add_argument('--build_id', required=True, + help='Build id.') + parser.add_argument('--target', required=True, + help='Target name of the cuttlefish hybrid build.') + parser.add_argument('--otatools_zip', required=True, + help='Path to the otatools.zip.') + parser.add_argument('--output_dir', required=True, + help='Path to the output directory of the hybrid build.') + parser.add_argument('--framework_target_files_zip', required=True, + help='glob pattern of framework target_files zip.') + parser.add_argument('--vendor_target_files_zip', required=True, + help='glob pattern of vendor target_files zip.') + parser.add_argument('--copy_file', action='append', default=[], + help='The file to be copied to output directory. ' + 'The format is <src glob pattern>:<dst path>.') + return parser.parse_args() + + +def run(temp_dir): + args = _parse_args() + + # unzip otatools + otatools = os.path.join(temp_dir, 'otatools') + unzip_otatools(args.otatools_zip, otatools) + + # get framework and vendor target files + matched_framework_target_files = glob.glob(args.framework_target_files_zip) + if not matched_framework_target_files: + raise ValueError('framework target files zip ' + f'{args.framework_target_files_zip} not found.') + matched_vendor_target_files = glob.glob(args.vendor_target_files_zip) + if not matched_vendor_target_files: + raise ValueError('vendor target files zip ' + f'{args.vendor_target_files_zip} not found.') + + # merge target files + framework_target_files = matched_framework_target_files[0] + vendor_target_files = matched_vendor_target_files[0] + merged_target_files = os.path.join( + args.output_dir, + f'{args.target}-target_files-{args.build_id}.zip') + command = [ + os.path.join(otatools, 'bin', 'merge_target_files'), + '--path', otatools, + '--framework-target-files', framework_target_files, + '--vendor-target-files', vendor_target_files, + '--output-target-files', merged_target_files, + '--avb-resolve-rollback-index-location-conflict' + ] + subprocess.run(command, check=True) + + # create images from the merged target files + img_zip_path = os.path.join(args.output_dir, + f'{args.target}-img-{args.build_id}.zip') + command = [ + os.path.join(otatools, 'bin', 'img_from_target_files'), + merged_target_files, + img_zip_path] + subprocess.run(command, check=True) + + # copy files + copy_files(args.copy_file, args.output_dir) + + +if __name__ == '__main__': + with tempfile.TemporaryDirectory() as temp_dir: + run(temp_dir) diff --git a/cuttlefish/build_chd_utils.py b/cuttlefish/build_chd_utils.py new file mode 100644 index 0000000..77a8eff --- /dev/null +++ b/cuttlefish/build_chd_utils.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2023 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. + +import glob +import os +import shutil +import zipfile + + +def unzip_otatools(otatools_zip_path, output_dir): + """Unzip otatools to a directory and set the permissions for execution. + + Args: + otatools_zip_path: The path to otatools zip archive. + output_dir: The root directory of the unzip output. + """ + with zipfile.ZipFile(otatools_zip_path, 'r') as zf: + zf.extractall(path=output_dir) + + for f in glob.glob(os.path.join(output_dir, 'bin', '*')): + os.chmod(f, 0o777) + + +def _parse_copy_file_pair(copy_file_pair): + """Convert a string to a source path and a destination path. + + Args: + copy_file_pair: A string in the format of <src glob pattern>:<dst path>. + + Returns: + The source path and the destination path. + + Raises: + ValueError if the input string is in a wrong format. + """ + split_pair = copy_file_pair.split(':', 1) + if len(split_pair) != 2: + raise ValueError(f'{copy_file_pair} is not a <src>:<dst> pair.') + src_list = glob.glob(split_pair[0]) + if len(src_list) != 1: + raise ValueError(f'{copy_file_pair} has more than one matched src files: ' + f'{" ".join(src_list)}.') + return src_list[0], split_pair[1] + + +def copy_files(copy_files_list, output_dir): + """Copy files to the output directory. + + Args: + copy_files_list: A list of copy file pairs, where a pair defines the src + glob pattern and the dst path. + output_dir: The root directory of the copy dst. + + Raises: + FileExistsError if the dst file already exists. + """ + for pair in copy_files_list: + src, dst = _parse_copy_file_pair(pair) + # this line does not change dst if dst is absolute. + dst = os.path.join(output_dir, dst) + os.makedirs(os.path.dirname(dst), exist_ok=True) + print(f'Copying {src} to {dst}') + if os.path.exists(dst): + raise FileExistsError(dst) + shutil.copyfile(src, dst) |