summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jooyung Han <jooyung@google.com> 2022-09-20 17:00:27 +0900
committer Jooyung Han <jooyung@google.com> 2022-09-21 13:27:49 +0900
commit7113b19be803d54abca058b9d9384bee0625b206 (patch)
tree63d2b8654479083db9b6317f78330c90494335f9
parentb2dce1ae5ede592d2cdaf02987de7d6a7e35ebeb (diff)
Add a host tool to create an APEX bundle
Even though the soong build system generates a bundle module for an apex, the bundle module itself should be further processed to be an AppBundle (.aab) file which can be uploaded to Play. This script fills the gap by invoking bundletool to create an AppBundle (.aab) file out of soong-built bundle module for an apex. (Note: uploading APEX bundle (.aab) to Play is not supported yet.) You can create an .aab file by: - TARGET_BUILD_APPS={apex name} m dist - m build-apex-bundle - build-apex-bundle --output out.aab out/dist/{apex name}-base.zip For now it creates a single-ABI APEX bundle. In the future it can be extended to support multiple-ABI APEX bundles. Bug: 236673372 Test: m build-apex-bundle Test: TARGET_BUILD_APPS=com.google.cf.bt m dist Test: build-apex-bundle --output bt.aab out/dist/com.google.cf.bt-base.zip Change-Id: Id321efcd42c0fe60294a8348047c9ebbf7acf391
-rw-r--r--scripts/Android.bp11
-rw-r--r--scripts/build-apex-bundle.py114
2 files changed, 125 insertions, 0 deletions
diff --git a/scripts/Android.bp b/scripts/Android.bp
index b5b588b8d..5dd45cd50 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -199,6 +199,17 @@ python_binary_host {
],
}
+python_binary_host {
+ name: "build-apex-bundle",
+ main: "build-apex-bundle.py",
+ srcs: [
+ "build-apex-bundle.py",
+ ],
+ required: [
+ "bundletool",
+ ],
+}
+
sh_binary_host {
name: "list_image",
src: "list_image.sh",
diff --git a/scripts/build-apex-bundle.py b/scripts/build-apex-bundle.py
new file mode 100644
index 000000000..dcdd9ef7d
--- /dev/null
+++ b/scripts/build-apex-bundle.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""A tool to create an APEX bundle out of Soong-built base.zip"""
+
+from __future__ import print_function
+
+import argparse
+import sys
+import tempfile
+import zipfile
+import os
+import json
+import subprocess
+
+
+def parse_args():
+ """Parse commandline arguments."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--overwrite',
+ action='store_true',
+ help='If set, any previous existing output will be overwritten')
+ parser.add_argument('--output', help='specify the output .aab file')
+ parser.add_argument(
+ 'input', help='specify the input <apex name>-base.zip file')
+ return parser.parse_args()
+
+
+def build_bundle(input, output, overwrite):
+ base_zip = zipfile.ZipFile(input)
+
+ tmpdir = tempfile.mkdtemp()
+ tmp_base_zip = os.path.join(tmpdir, 'base.zip')
+ tmp_bundle_config = os.path.join(tmpdir, 'bundle_config.json')
+
+ bundle_config = None
+ abi = []
+
+ # This block performs three tasks
+ # - extract/load bundle_config.json from input => bundle_config
+ # - get ABI from input => abi
+ # - discard bundle_config.json from input => tmp/base.zip
+ with zipfile.ZipFile(tmp_base_zip, 'a') as out:
+ for info in base_zip.infolist():
+
+ # discard bundle_config.json
+ if info.filename == 'bundle_config.json':
+ bundle_config = json.load(base_zip.open(info.filename))
+ continue
+
+ # get ABI from apex/{abi}.img
+ dir, basename = os.path.split(info.filename)
+ name, ext = os.path.splitext(basename)
+ if dir == 'apex' and ext == '.img':
+ abi.append(name)
+
+ # copy entries to tmp/base.zip
+ out.writestr(info, base_zip.open(info.filename).read())
+
+ base_zip.close()
+
+ if not bundle_config:
+ raise ValueError(f'bundle_config.json not found in {input}')
+ if len(abi) != 1:
+ raise ValueError(f'{input} should have only a single apex/*.img file')
+
+ # add ABI to tmp/bundle_config.json
+ apex_config = bundle_config['apex_config']
+ if 'supported_abi_set' not in apex_config:
+ apex_config['supported_abi_set'] = []
+ supported_abi_set = apex_config['supported_abi_set']
+ supported_abi_set.append({'abi': abi})
+
+ with open(tmp_bundle_config, 'w') as out:
+ json.dump(bundle_config, out)
+
+ # invoke bundletool
+ cmd = [
+ 'bundletool', 'build-bundle', '--config', tmp_bundle_config, '--modules',
+ tmp_base_zip, '--output', output
+ ]
+ if overwrite:
+ cmd.append('--overwrite')
+ subprocess.check_call(cmd)
+
+
+def main():
+ """Program entry point."""
+ try:
+ args = parse_args()
+ build_bundle(args.input, args.output, args.overwrite)
+
+ # pylint: disable=broad-except
+ except Exception as err:
+ print('error: ' + str(err), file=sys.stderr)
+ sys.exit(-1)
+
+
+if __name__ == '__main__':
+ main()