Merge "Merge <uses-library> dependency configs into dexpreopt.config files."
diff --git a/core/Makefile b/core/Makefile
index 79255ca..95bac40 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -4130,6 +4130,7 @@
# Additional tools to unpack and repack the apex file.
INTERNAL_OTATOOLS_MODULES += \
apexer \
+ apex_compression_tool \
deapexer \
debugfs_static \
merge_zips \
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 883f92d..3a0c0f1 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -34,3 +34,8 @@
SOONG_CONFIG_art_module += source_build
endif
SOONG_CONFIG_art_module_source_build ?= true
+
+# Apex build mode variables
+ifdef APEX_BUILD_FOR_PRE_S_DEVICES
+$(call add_soong_config_var_value,ANDROID,library_linking_strategy,prefer_static)
+endif
diff --git a/core/combo/arch/arm64/armv8-a-branchprot.mk b/core/combo/arch/arm64/armv8-a-branchprot.mk
new file mode 100644
index 0000000..77f3535
--- /dev/null
+++ b/core/combo/arch/arm64/armv8-a-branchprot.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2021 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.
+#
+
+# .mk file required to support build for the new armv8-a-branchprot Arm64 arch
+# variant. The file just needs to be present but does not require to contain
+# anything
diff --git a/envsetup.sh b/envsetup.sh
index 8fa608b..c03e2cb 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -33,7 +33,9 @@
- allmod: List all modules.
- gomod: Go to the directory containing a module.
- pathmod: Get the directory containing a module.
-- refreshmod: Refresh list of modules for allmod/gomod/pathmod.
+- outmod: Gets the location of a module's installed outputs with a certain extension.
+- installmod: Adb installs a module's built APK.
+- refreshmod: Refresh list of modules for allmod/gomod/pathmod/outmod/installmod.
- syswrite: Remount partitions (e.g. system.img) as writable, rebooting if necessary.
Environment options:
@@ -411,7 +413,10 @@
fi
complete -F _lunch lunch
+ complete -F _complete_android_module_names pathmod
complete -F _complete_android_module_names gomod
+ complete -F _complete_android_module_names outmod
+ complete -F _complete_android_module_names installmod
complete -F _complete_android_module_names m
}
@@ -1378,9 +1383,8 @@
> $ANDROID_PRODUCT_OUT/module-info.json.build.log 2>&1
}
-# List all modules for the current device, as cached in module-info.json. If any build change is
-# made and it should be reflected in the output, you should run 'refreshmod' first.
-function allmod() {
+# Verifies that module-info.txt exists, creating it if it doesn't.
+function verifymodinfo() {
if [ ! "$ANDROID_PRODUCT_OUT" ]; then
echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
return 1
@@ -1390,6 +1394,12 @@
echo "Could not find module-info.json. It will only be built once, and it can be updated with 'refreshmod'" >&2
refreshmod || return 1
fi
+}
+
+# List all modules for the current device, as cached in module-info.json. If any build change is
+# made and it should be reflected in the output, you should run 'refreshmod' first.
+function allmod() {
+ verifymodinfo || return 1
python -c "import json; print('\n'.join(sorted(json.load(open('$ANDROID_PRODUCT_OUT/module-info.json')).keys())))"
}
@@ -1397,20 +1407,12 @@
# Get the path of a specific module in the android tree, as cached in module-info.json. If any build change
# is made, and it should be reflected in the output, you should run 'refreshmod' first.
function pathmod() {
- if [ ! "$ANDROID_PRODUCT_OUT" ]; then
- echo "No ANDROID_PRODUCT_OUT. Try running 'lunch' first." >&2
- return 1
- fi
-
if [[ $# -ne 1 ]]; then
echo "usage: pathmod <module>" >&2
return 1
fi
- if [ ! -f "$ANDROID_PRODUCT_OUT/module-info.json" ]; then
- echo "Could not find module-info.json. It will only be built once, and it can be updated with 'refreshmod'" >&2
- refreshmod || return 1
- fi
+ verifymodinfo || return 1
local relpath=$(python -c "import json, os
module = '$1'
@@ -1442,6 +1444,59 @@
cd $path
}
+# Gets the list of a module's installed outputs, as cached in module-info.json.
+# If any build change is made, and it should be reflected in the output, you should run 'refreshmod' first.
+function outmod() {
+ if [[ $# -ne 1 ]]; then
+ echo "usage: outmod <module>" >&2
+ return 1
+ fi
+
+ verifymodinfo || return 1
+
+ local relpath
+ relpath=$(python -c "import json, os
+module = '$1'
+module_info = json.load(open('$ANDROID_PRODUCT_OUT/module-info.json'))
+if module not in module_info:
+ exit(1)
+for output in module_info[module]['installed']:
+ print(os.path.join('$ANDROID_BUILD_TOP', output))" 2>/dev/null)
+
+ if [ $? -ne 0 ]; then
+ echo "Could not find module '$1' (try 'refreshmod' if there have been build changes?)" >&2
+ return 1
+ elif [ ! -z "$relpath" ]; then
+ echo "$relpath"
+ fi
+}
+
+# adb install a module's apk, as cached in module-info.json. If any build change
+# is made, and it should be reflected in the output, you should run 'refreshmod' first.
+# Usage: installmod [adb install arguments] <module>
+# For example: installmod -r Dialer -> adb install -r /path/to/Dialer.apk
+function installmod() {
+ if [[ $# -eq 0 ]]; then
+ echo "usage: installmod [adb install arguments] <module>" >&2
+ return 1
+ fi
+
+ local _path
+ _path=$(outmod ${@:$#:1})
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+
+ _path=$(echo "$_path" | grep -E \\.apk$ | head -n 1)
+ if [ -z "$_path" ]; then
+ echo "Module '$1' does not produce a file ending with .apk (try 'refreshmod' if there have been build changes?)" >&2
+ return 1
+ fi
+ local length=$(( $# - 1 ))
+ echo adb install ${@:1:$length} $_path
+ adb install ${@:1:$length} $_path
+}
+
function _complete_android_module_names() {
local word=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(allmod | grep -E "^$word") )
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index e34dc23..a2150ad 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -49,6 +49,10 @@
BOARD_GSI_DYNAMIC_PARTITIONS_SIZE := 3221225472
endif
+# TODO(b/123695868, b/146149698):
+# This flag is set by mainline but isn't desired for GSI
+BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR :=
+
# Enable chain partition for boot, mainly for GKI images.
BOARD_AVB_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_BOOT_ALGORITHM := SHA256_RSA2048
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index c27badc..7d9d90e 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -72,7 +72,12 @@
endif
-PRODUCT_MAKEFILES += $(LOCAL_DIR)/mainline_sdk.mk
+PRODUCT_MAKEFILES += \
+ $(LOCAL_DIR)/mainline_sdk.mk \
+ $(LOCAL_DIR)/module_arm.mk \
+ $(LOCAL_DIR)/module_arm64.mk \
+ $(LOCAL_DIR)/module_x86.mk \
+ $(LOCAL_DIR)/module_x86_64.mk \
COMMON_LUNCH_CHOICES := \
aosp_arm64-eng \
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index a4cf1d2..2ca6687 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -19,8 +19,12 @@
LLNDK: libvndksupport.so
LLNDK: libvulkan.so
VNDK-SP: android.hardware.common-V2-ndk_platform.so
+VNDK-SP: android.hardware.common-unstable-ndk_platform.so
VNDK-SP: android.hardware.common.fmq-V1-ndk_platform.so
+VNDK-SP: android.hardware.common.fmq-ndk_platform.so
+VNDK-SP: android.hardware.common.fmq-unstable-ndk_platform.so
VNDK-SP: android.hardware.graphics.common-V2-ndk_platform.so
+VNDK-SP: android.hardware.graphics.common-unstable-ndk_platform.so
VNDK-SP: android.hardware.graphics.common@1.0.so
VNDK-SP: android.hardware.graphics.common@1.1.so
VNDK-SP: android.hardware.graphics.common@1.2.so
@@ -58,7 +62,10 @@
VNDK-SP: libz.so
VNDK-core: android.hardware.audio.common@2.0.so
VNDK-core: android.hardware.authsecret-V1-ndk_platform.so
+VNDK-core: android.hardware.authsecret-ndk_platform.so
+VNDK-core: android.hardware.authsecret-unstable-ndk_platform.so
VNDK-core: android.hardware.automotive.occupant_awareness-V1-ndk_platform.so
+VNDK-core: android.hardware.automotive.occupant_awareness-ndk_platform.so
VNDK-core: android.hardware.configstore-utils.so
VNDK-core: android.hardware.configstore@1.0.so
VNDK-core: android.hardware.configstore@1.1.so
@@ -69,27 +76,49 @@
VNDK-core: android.hardware.graphics.bufferqueue@1.0.so
VNDK-core: android.hardware.graphics.bufferqueue@2.0.so
VNDK-core: android.hardware.health.storage-V1-ndk_platform.so
+VNDK-core: android.hardware.health.storage-ndk_platform.so
+VNDK-core: android.hardware.health.storage-unstable-ndk_platform.so
VNDK-core: android.hardware.identity-V2-ndk_platform.so
+VNDK-core: android.hardware.identity-ndk_platform.so
VNDK-core: android.hardware.keymaster-V2-ndk_platform.so
+VNDK-core: android.hardware.keymaster-ndk_platform.so
VNDK-core: android.hardware.light-V1-ndk_platform.so
+VNDK-core: android.hardware.light-ndk_platform.so
VNDK-core: android.hardware.media.bufferpool@2.0.so
VNDK-core: android.hardware.media.omx@1.0.so
VNDK-core: android.hardware.media@1.0.so
VNDK-core: android.hardware.memtrack-V1-ndk_platform.so
+VNDK-core: android.hardware.memtrack-ndk_platform.so
+VNDK-core: android.hardware.memtrack-unstable-ndk_platform.so
VNDK-core: android.hardware.memtrack@1.0.so
VNDK-core: android.hardware.oemlock-V1-ndk_platform.so
+VNDK-core: android.hardware.oemlock-ndk_platform.so
+VNDK-core: android.hardware.oemlock-unstable-ndk_platform.so
VNDK-core: android.hardware.power-V1-ndk_platform.so
+VNDK-core: android.hardware.power-ndk_platform.so
VNDK-core: android.hardware.rebootescrow-V1-ndk_platform.so
+VNDK-core: android.hardware.rebootescrow-ndk_platform.so
VNDK-core: android.hardware.security.keymint-V1-ndk_platform.so
+VNDK-core: android.hardware.security.keymint-ndk_platform.so
+VNDK-core: android.hardware.security.keymint-unstable-ndk_platform.so
VNDK-core: android.hardware.security.secureclock-V1-ndk_platform.so
+VNDK-core: android.hardware.security.secureclock-ndk_platform.so
+VNDK-core: android.hardware.security.secureclock-unstable-ndk_platform.so
VNDK-core: android.hardware.security.sharedsecret-V1-ndk_platform.so
+VNDK-core: android.hardware.security.sharedsecret-ndk_platform.so
+VNDK-core: android.hardware.security.sharedsecret-unstable-ndk_platform.so
VNDK-core: android.hardware.soundtrigger@2.0-core.so
VNDK-core: android.hardware.soundtrigger@2.0.so
VNDK-core: android.hardware.vibrator-V1-ndk_platform.so
+VNDK-core: android.hardware.vibrator-ndk_platform.so
VNDK-core: android.hardware.weaver-V1-ndk_platform.so
+VNDK-core: android.hardware.weaver-ndk_platform.so
+VNDK-core: android.hardware.weaver-unstable-ndk_platform.so
VNDK-core: android.hidl.token@1.0-utils.so
VNDK-core: android.hidl.token@1.0.so
VNDK-core: android.system.keystore2-V1-ndk_platform.so
+VNDK-core: android.system.keystore2-ndk_platform.so
+VNDK-core: android.system.keystore2-unstable-ndk_platform.so
VNDK-core: android.system.suspend@1.0.so
VNDK-core: libaudioroute.so
VNDK-core: libaudioutils.so
diff --git a/target/product/module_arm.mk b/target/product/module_arm.mk
new file mode 100644
index 0000000..09ccf5f
--- /dev/null
+++ b/target/product/module_arm.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2021 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.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/board/module_arm/device.mk)
+
+PRODUCT_NAME := module_arm
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := module_arm
diff --git a/target/product/module_arm64.mk b/target/product/module_arm64.mk
new file mode 100644
index 0000000..468c9db
--- /dev/null
+++ b/target/product/module_arm64.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2021 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.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/board/module_arm64/device.mk)
+
+PRODUCT_NAME := module_arm64
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := module_arm64
diff --git a/target/product/module_x86.mk b/target/product/module_x86.mk
new file mode 100644
index 0000000..dec4aed
--- /dev/null
+++ b/target/product/module_x86.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2021 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.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/board/module_x86/device.mk)
+
+PRODUCT_NAME := module_x86
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := module_x86
diff --git a/target/product/module_x86_64.mk b/target/product/module_x86_64.mk
new file mode 100644
index 0000000..5fabade
--- /dev/null
+++ b/target/product/module_x86_64.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2021 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.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/board/module_x86_64/device.mk)
+
+PRODUCT_NAME := module_x86_64
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := module_x86_64
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index bca70a9..473d854 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -28,6 +28,8 @@
"add_img_to_target_files.py",
],
libs: [
+ "ota_metadata_proto",
+ "releasetools_apex_utils",
"releasetools_build_image",
"releasetools_build_super_image",
"releasetools_common",
@@ -122,13 +124,15 @@
"releasetools_check_target_files_vintf",
"releasetools_common",
"releasetools_verity_utils",
+ "apex_manifest",
],
required: [
"brillo_update_payload",
"checkvintf",
"lz4",
"toybox",
- "unpack_bootimg"
+ "unpack_bootimg",
+ "deapexer",
],
target: {
darwin: {
@@ -169,6 +173,8 @@
"apex_utils.py",
],
libs: [
+ "apex_manifest",
+ "ota_metadata_proto",
"releasetools_common",
],
}
@@ -544,6 +550,8 @@
],
data: [
"testdata/**/*",
+ ":com.android.apex.compressed.v1",
+ ":com.android.apex.compressed.v1_original",
],
target: {
darwin: {
@@ -551,6 +559,9 @@
enabled: false,
},
},
+ required: [
+ "deapexer",
+ ],
}
python_test_host {
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 5f35d78..7839b47 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -62,6 +62,9 @@
import rangelib
import sparse_img
import verity_utils
+import ota_metadata_pb2
+
+from apex_utils import GetApexInfoFromTargetFiles
if sys.hexversion < 0x02070000:
print("Python 2.7 or newer is required.", file=sys.stderr)
@@ -94,13 +97,13 @@
name: The name of the output file, regardless of the final destination.
"""
- def __init__(self, output_zip, input_dir, prefix, name):
+ def __init__(self, output_zip, input_dir, *args):
# We write the intermediate output file under the given input_dir, even if
# the final destination is a zip archive.
- self.name = os.path.join(input_dir, prefix, name)
+ self.name = os.path.join(input_dir, *args)
self._output_zip = output_zip
if self._output_zip:
- self._zip_name = os.path.join(prefix, name)
+ self._zip_name = os.path.join(*args)
def Write(self):
if self._output_zip:
@@ -179,7 +182,6 @@
block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.map")
CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system", img,
block_list=block_list)
-
return img.name
@@ -754,6 +756,22 @@
os.path.join(OPTIONS.input_tmp, "IMAGES",
"{}.img".format(partition_name))))
+def AddApexInfo(output_zip):
+ apex_infos = GetApexInfoFromTargetFiles(OPTIONS.input_tmp)
+ apex_metadata_proto = ota_metadata_pb2.ApexMetadata()
+ apex_metadata_proto.apex_info.extend(apex_infos)
+ apex_info_bytes = apex_metadata_proto.SerializeToString()
+
+ output_file = os.path.join(OPTIONS.input_tmp, "META", "apex_info.pb")
+ with open(output_file, "wb") as ofile:
+ ofile.write(apex_info_bytes)
+ if output_zip:
+ arc_name = "META/apex_info.pb"
+ if arc_name in output_zip.namelist():
+ OPTIONS.replace_updated_files_list.append(arc_name)
+ else:
+ common.ZipWrite(output_zip, output_file, arc_name)
+
def AddImagesToTargetFiles(filename):
"""Creates and adds images (boot/recovery/system/...) to a target_files.zip.
@@ -914,6 +932,8 @@
banner("system_other")
AddSystemOther(output_zip)
+ AddApexInfo(output_zip)
+
if not OPTIONS.is_signing:
banner("userdata")
AddUserdata(output_zip)
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index c8a0dcc..3177fa0 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -21,7 +21,12 @@
import shutil
import zipfile
+import apex_manifest
import common
+from common import UnzipTemp, RunAndCheckOutput, MakeTempFile, OPTIONS
+
+import ota_metadata_pb2
+
logger = logging.getLogger(__name__)
@@ -29,6 +34,8 @@
APEX_PAYLOAD_IMAGE = 'apex_payload.img'
+APEX_PUBKEY = 'apex_pubkey'
+
class ApexInfoError(Exception):
"""An Exception raised during Apex Information command."""
@@ -69,7 +76,7 @@
if not os.path.exists(self.debugfs_path):
raise ApexSigningError(
"Couldn't find location of debugfs_static: " +
- "Path {} does not exist. ".format(debugfs_path) +
+ "Path {} does not exist. ".format(self.debugfs_path) +
"Make sure bin/debugfs_static can be found in -p <path>")
list_cmd = ['deapexer', '--debugfs_path',
self.debugfs_path, 'list', self.apex_path]
@@ -105,7 +112,7 @@
if not os.path.exists(self.debugfs_path):
raise ApexSigningError(
"Couldn't find location of debugfs_static: " +
- "Path {} does not exist. ".format(debugfs_path) +
+ "Path {} does not exist. ".format(self.debugfs_path) +
"Make sure bin/debugfs_static can be found in -p <path>")
payload_dir = common.MakeTempDir()
extract_cmd = ['deapexer', '--debugfs_path',
@@ -127,8 +134,9 @@
# signed apk file.
unsigned_apk = common.MakeTempFile()
os.rename(apk_path, unsigned_apk)
- common.SignFile(unsigned_apk, apk_path, key_name, self.key_passwords.get(key_name),
- codename_to_api_level_map=self.codename_to_api_level_map)
+ common.SignFile(
+ unsigned_apk, apk_path, key_name, self.key_passwords.get(key_name),
+ codename_to_api_level_map=self.codename_to_api_level_map)
has_signed_apk = True
return payload_dir, has_signed_apk
@@ -300,13 +308,13 @@
return payload_info
-def SignUncompressedApex(avbtool, apex_data, payload_key, container_key,
+def SignUncompressedApex(avbtool, apex_file, payload_key, container_key,
container_pw, apk_keys, codename_to_api_level_map,
no_hashtree, signing_args=None):
"""Signs the current uncompressed APEX with the given payload/container keys.
Args:
- apex_data: Raw uncompressed APEX data.
+ apex_file: Uncompressed APEX file.
payload_key: The path to payload signing key (w/ extension).
container_key: The path to container signing key (w/o extension).
container_pw: The matching password of the container_key, or None.
@@ -318,12 +326,6 @@
Returns:
The path to the signed APEX file.
"""
- apex_file = common.MakeTempFile(prefix='apex-', suffix='.apex')
- with open(apex_file, 'wb') as apex_fp:
- apex_fp.write(apex_data)
-
- APEX_PUBKEY = 'apex_pubkey'
-
# 1. Extract the apex payload image and sign the containing apk files. Repack
# the apex file after signing.
apk_signer = ApexApkSigner(apex_file, container_pw,
@@ -382,6 +384,80 @@
return signed_apex
+def SignCompressedApex(avbtool, apex_file, payload_key, container_key,
+ container_pw, apk_keys, codename_to_api_level_map,
+ no_hashtree, signing_args=None):
+ """Signs the current compressed APEX with the given payload/container keys.
+
+ Args:
+ apex_file: Raw uncompressed APEX data.
+ payload_key: The path to payload signing key (w/ extension).
+ container_key: The path to container signing key (w/o extension).
+ container_pw: The matching password of the container_key, or None.
+ apk_keys: A dict that holds the signing keys for apk files.
+ codename_to_api_level_map: A dict that maps from codename to API level.
+ no_hashtree: Don't include hashtree in the signed APEX.
+ signing_args: Additional args to be passed to the payload signer.
+
+ Returns:
+ The path to the signed APEX file.
+ """
+ debugfs_path = os.path.join(OPTIONS.search_path, 'bin', 'debugfs_static')
+
+ # 1. Decompress original_apex inside compressed apex.
+ original_apex_file = common.MakeTempFile(prefix='original-apex-',
+ suffix='.apex')
+ # Decompression target path should not exist
+ os.remove(original_apex_file)
+ common.RunAndCheckOutput(['deapexer', '--debugfs_path', debugfs_path,
+ 'decompress', '--input', apex_file,
+ '--output', original_apex_file])
+
+ # 2. Sign original_apex
+ signed_original_apex_file = SignUncompressedApex(
+ avbtool,
+ original_apex_file,
+ payload_key,
+ container_key,
+ container_pw,
+ apk_keys,
+ codename_to_api_level_map,
+ no_hashtree,
+ signing_args)
+
+ # 3. Compress signed original apex.
+ compressed_apex_file = common.MakeTempFile(prefix='apex-container-',
+ suffix='.capex')
+ common.RunAndCheckOutput(['apex_compression_tool',
+ 'compress',
+ '--apex_compression_tool_path', os.getenv('PATH'),
+ '--input', signed_original_apex_file,
+ '--output', compressed_apex_file])
+
+ # 4. Align apex
+ aligned_apex = common.MakeTempFile(prefix='apex-container-', suffix='.capex')
+ common.RunAndCheckOutput(['zipalign', '-f', '4096', compressed_apex_file,
+ aligned_apex])
+
+ # 5. Sign the APEX container with container_key.
+ signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.capex')
+
+ # Specify the 4K alignment when calling SignApk.
+ extra_signapk_args = OPTIONS.extra_signapk_args[:]
+ extra_signapk_args.extend(['-a', '4096'])
+
+ password = container_pw.get(container_key) if container_pw else None
+ common.SignFile(
+ aligned_apex,
+ signed_apex,
+ container_key,
+ password,
+ codename_to_api_level_map=codename_to_api_level_map,
+ extra_signapk_args=extra_signapk_args)
+
+ return signed_apex
+
+
def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
apk_keys, codename_to_api_level_map,
no_hashtree, signing_args=None):
@@ -404,7 +480,7 @@
with open(apex_file, 'wb') as output_fp:
output_fp.write(apex_data)
- debugfs_path = os.path.join(OPTIONS.search_path, "bin", "debugfs_static")
+ debugfs_path = os.path.join(OPTIONS.search_path, 'bin', 'debugfs_static')
cmd = ['deapexer', '--debugfs_path', debugfs_path,
'info', '--print-type', apex_file]
@@ -413,7 +489,18 @@
if apex_type == 'UNCOMPRESSED':
return SignUncompressedApex(
avbtool,
- apex_data,
+ apex_file,
+ payload_key=payload_key,
+ container_key=container_key,
+ container_pw=None,
+ codename_to_api_level_map=codename_to_api_level_map,
+ no_hashtree=no_hashtree,
+ apk_keys=apk_keys,
+ signing_args=signing_args)
+ elif apex_type == 'COMPRESSED':
+ return SignCompressedApex(
+ avbtool,
+ apex_file,
payload_key=payload_key,
container_key=container_key,
container_pw=None,
@@ -427,4 +514,72 @@
except common.ExternalError as e:
raise ApexInfoError(
- 'Failed to get type for {}:\n{}'.format(apex_file))
+ 'Failed to get type for {}:\n{}'.format(apex_file, e))
+
+def GetApexInfoFromTargetFiles(input_file):
+ """
+ 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")
+
+ if os.path.isdir(input_file):
+ tmp_dir = input_file
+ else:
+ tmp_dir = UnzipTemp(input_file, ["SYSTEM/apex/*"])
+ target_dir = os.path.join(tmp_dir, "SYSTEM/apex/")
+
+ 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, "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)
+
+ apex_infos.append(apex_info)
+
+ return apex_infos
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 6b82d32..41644d8 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -229,11 +229,11 @@
import common
import ota_utils
+from ota_utils import (UNZIP_PATTERN, FinalizeMetadata, GetPackageMetadata,
+ PropertyFiles)
import target_files_diff
from check_target_files_vintf import CheckVintfIfTrebleEnabled
from non_ab_ota import GenerateNonAbOtaPackage
-from ota_utils import (UNZIP_PATTERN, FinalizeMetadata, GetPackageMetadata,
- PropertyFiles)
if sys.hexversion < 0x02070000:
print("Python 2.7 or newer is required.", file=sys.stderr)
@@ -961,7 +961,8 @@
for part in partition_state]
return ["--partition_timestamps", ",".join(partition_timestamps)]
-def GeneratePartitionTimestampFlagsDowngrade(pre_partition_state, post_partition_state):
+def GeneratePartitionTimestampFlagsDowngrade(
+ pre_partition_state, post_partition_state):
assert pre_partition_state is not None
partition_timestamps = {}
for part in pre_partition_state:
@@ -970,9 +971,9 @@
partition_timestamps[part.partition_name] = \
max(part.version, partition_timestamps[part.partition_name])
return [
- "--partition_timestamps",
- ",".join([key + ":" + val for (key, val) in partition_timestamps.items()])
- ]
+ "--partition_timestamps",
+ ",".join([key + ":" + val for (key, val) in partition_timestamps.items()])
+ ]
def IsSparseImage(filepath):
with open(filepath, 'rb') as fp:
@@ -1026,7 +1027,8 @@
else:
staging_file = output_file
output_zip = zipfile.ZipFile(staging_file, "w",
- compression=zipfile.ZIP_DEFLATED, allowZip64=True)
+ compression=zipfile.ZIP_DEFLATED,
+ allowZip64=True)
if source_file is not None:
assert "ab_partitions" in OPTIONS.source_info_dict, \
@@ -1080,9 +1082,9 @@
if OPTIONS.downgrade:
max_timestamp = source_info.GetBuildProp("ro.build.date.utc")
partition_timestamps_flags = GeneratePartitionTimestampFlagsDowngrade(
- metadata.precondition.partition_state,
- metadata.postcondition.partition_state
- )
+ metadata.precondition.partition_state,
+ metadata.postcondition.partition_state
+ )
else:
max_timestamp = str(metadata.postcondition.timestamp)
partition_timestamps_flags = GeneratePartitionTimestampFlags(
@@ -1091,14 +1093,14 @@
additional_args += ["--max_timestamp", max_timestamp]
if SupportsMainlineGkiUpdates(source_file):
- logger.warn("Detected build with mainline GKI, include full boot image.")
+ logger.warning("Detected build with mainline GKI, include full boot image.")
additional_args.extend(["--full_boot", "true"])
payload.Generate(
target_file,
source_file,
additional_args + partition_timestamps_flags
- )
+ )
# Sign the payload.
payload_signer = PayloadSigner()
@@ -1117,7 +1119,7 @@
secondary_payload = Payload(secondary=True)
secondary_payload.Generate(secondary_target_file,
additional_args=["--max_timestamp",
- max_timestamp])
+ max_timestamp])
secondary_payload.Sign(payload_signer)
secondary_payload.WriteToZip(output_zip)
@@ -1125,7 +1127,7 @@
# into A/B OTA package.
target_zip = zipfile.ZipFile(target_file, "r", allowZip64=True)
if (target_info.get("verity") == "true" or
- target_info.get("avb_enable") == "true"):
+ target_info.get("avb_enable") == "true"):
care_map_list = [x for x in ["care_map.pb", "care_map.txt"] if
"META/" + x in target_zip.namelist()]
@@ -1140,6 +1142,15 @@
else:
logger.warning("Cannot find care map file in target_file package")
+ # Copy apex_info.pb over to generated OTA package.
+ try:
+ apex_info_entry = target_zip.getinfo("META/apex_info.pb")
+ with target_zip.open(apex_info_entry, "r") as zfp:
+ common.ZipWriteStr(output_zip, "apex_info.pb", zfp.read(),
+ compress_type=zipfile.ZIP_STORED)
+ except KeyError:
+ logger.warning("target_file doesn't contain apex_info.pb %s", target_file)
+
common.ZipClose(target_zip)
CheckVintfIfTrebleEnabled(target_file, target_info)
@@ -1334,13 +1345,14 @@
if OPTIONS.partial:
OPTIONS.info_dict['ab_partitions'] = \
list(
- set(OPTIONS.info_dict['ab_partitions']) & set(OPTIONS.partial)
- )
+ set(OPTIONS.info_dict['ab_partitions']) & set(OPTIONS.partial)
+ )
if OPTIONS.source_info_dict:
OPTIONS.source_info_dict['ab_partitions'] = \
list(
- set(OPTIONS.source_info_dict['ab_partitions']) & set(OPTIONS.partial)
- )
+ set(OPTIONS.source_info_dict['ab_partitions']) &
+ set(OPTIONS.partial)
+ )
# Load OEM dicts if provided.
OPTIONS.oem_dicts = _LoadOemDicts(OPTIONS.oem_source)
@@ -1349,7 +1361,7 @@
# use_dynamic_partitions but target build does.
if (OPTIONS.source_info_dict and
OPTIONS.source_info_dict.get("use_dynamic_partitions") != "true" and
- OPTIONS.target_info_dict.get("use_dynamic_partitions") == "true"):
+ OPTIONS.target_info_dict.get("use_dynamic_partitions") == "true"):
if OPTIONS.target_info_dict.get("dynamic_partition_retrofit") != "true":
raise common.ExternalError(
"Expect to generate incremental OTA for retrofitting dynamic "
@@ -1365,7 +1377,8 @@
ab_update = OPTIONS.info_dict.get("ab_update") == "true"
allow_non_ab = OPTIONS.info_dict.get("allow_non_ab") == "true"
if OPTIONS.force_non_ab:
- assert allow_non_ab, "--force_non_ab only allowed on devices that supports non-A/B"
+ assert allow_non_ab,\
+ "--force_non_ab only allowed on devices that supports non-A/B"
assert ab_update, "--force_non_ab only allowed on A/B devices"
generate_ab = not OPTIONS.force_non_ab and ab_update
diff --git a/tools/releasetools/ota_metadata.proto b/tools/releasetools/ota_metadata.proto
index 20d3091..5da8b84 100644
--- a/tools/releasetools/ota_metadata.proto
+++ b/tools/releasetools/ota_metadata.proto
@@ -16,8 +16,8 @@
// If you change this file,
// Please update ota_metadata_pb2.py by executing
-// protoc ota_metadata.proto --python_out $ANDROID_BUILD_TOP/build/tools/releasetools
-
+// protoc ota_metadata.proto --python_out
+// $ANDROID_BUILD_TOP/build/tools/releasetools
syntax = "proto3";
@@ -65,6 +65,19 @@
repeated PartitionState partition_state = 7;
}
+message ApexInfo {
+ string package_name = 1;
+ int64 version = 2;
+ bool is_compressed = 3;
+ int64 decompressed_size = 4;
+}
+
+// Just a container to hold repeated apex_info, so that we can easily serialize
+// a list of apex_info to string.
+message ApexMetadata {
+ repeated ApexInfo apex_info = 1;
+}
+
// The metadata of an OTA package. It contains the information of the package
// and prerequisite to install the update correctly.
message OtaMetadata {
diff --git a/tools/releasetools/ota_metadata_pb2.py b/tools/releasetools/ota_metadata_pb2.py
index ff2b2c5..27cc930 100644
--- a/tools/releasetools/ota_metadata_pb2.py
+++ b/tools/releasetools/ota_metadata_pb2.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: ota_metadata.proto
-
+"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
@@ -18,7 +18,8 @@
package='build.tools.releasetools',
syntax='proto3',
serialized_options=b'H\003',
- serialized_pb=b'\n\x12ota_metadata.proto\x12\x18\x62uild.tools.releasetools\"X\n\x0ePartitionState\x12\x16\n\x0epartition_name\x18\x01 \x01(\t\x12\x0e\n\x06\x64\x65vice\x18\x02 \x03(\t\x12\r\n\x05\x62uild\x18\x03 \x03(\t\x12\x0f\n\x07version\x18\x04 \x01(\t\"\xce\x01\n\x0b\x44\x65viceState\x12\x0e\n\x06\x64\x65vice\x18\x01 \x03(\t\x12\r\n\x05\x62uild\x18\x02 \x03(\t\x12\x19\n\x11\x62uild_incremental\x18\x03 \x01(\t\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x11\n\tsdk_level\x18\x05 \x01(\t\x12\x1c\n\x14security_patch_level\x18\x06 \x01(\t\x12\x41\n\x0fpartition_state\x18\x07 \x03(\x0b\x32(.build.tools.releasetools.PartitionState\"\xe1\x03\n\x0bOtaMetadata\x12;\n\x04type\x18\x01 \x01(\x0e\x32-.build.tools.releasetools.OtaMetadata.OtaType\x12\x0c\n\x04wipe\x18\x02 \x01(\x08\x12\x11\n\tdowngrade\x18\x03 \x01(\x08\x12P\n\x0eproperty_files\x18\x04 \x03(\x0b\x32\x38.build.tools.releasetools.OtaMetadata.PropertyFilesEntry\x12;\n\x0cprecondition\x18\x05 \x01(\x0b\x32%.build.tools.releasetools.DeviceState\x12<\n\rpostcondition\x18\x06 \x01(\x0b\x32%.build.tools.releasetools.DeviceState\x12#\n\x1bretrofit_dynamic_partitions\x18\x07 \x01(\x08\x12\x16\n\x0erequired_cache\x18\x08 \x01(\x03\x1a\x34\n\x12PropertyFilesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"4\n\x07OtaType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x06\n\x02\x41\x42\x10\x01\x12\t\n\x05\x42LOCK\x10\x02\x12\t\n\x05\x42RICK\x10\x03\x42\x02H\x03\x62\x06proto3'
+ create_key=_descriptor._internal_create_key,
+ serialized_pb=b'\n\x12ota_metadata.proto\x12\x18\x62uild.tools.releasetools\"X\n\x0ePartitionState\x12\x16\n\x0epartition_name\x18\x01 \x01(\t\x12\x0e\n\x06\x64\x65vice\x18\x02 \x03(\t\x12\r\n\x05\x62uild\x18\x03 \x03(\t\x12\x0f\n\x07version\x18\x04 \x01(\t\"\xce\x01\n\x0b\x44\x65viceState\x12\x0e\n\x06\x64\x65vice\x18\x01 \x03(\t\x12\r\n\x05\x62uild\x18\x02 \x03(\t\x12\x19\n\x11\x62uild_incremental\x18\x03 \x01(\t\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x11\n\tsdk_level\x18\x05 \x01(\t\x12\x1c\n\x14security_patch_level\x18\x06 \x01(\t\x12\x41\n\x0fpartition_state\x18\x07 \x03(\x0b\x32(.build.tools.releasetools.PartitionState\"c\n\x08\x41pexInfo\x12\x14\n\x0cpackage_name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\x03\x12\x15\n\ris_compressed\x18\x03 \x01(\x08\x12\x19\n\x11\x64\x65\x63ompressed_size\x18\x04 \x01(\x03\"E\n\x0c\x41pexMetadata\x12\x35\n\tapex_info\x18\x01 \x03(\x0b\x32\".build.tools.releasetools.ApexInfo\"\x98\x04\n\x0bOtaMetadata\x12;\n\x04type\x18\x01 \x01(\x0e\x32-.build.tools.releasetools.OtaMetadata.OtaType\x12\x0c\n\x04wipe\x18\x02 \x01(\x08\x12\x11\n\tdowngrade\x18\x03 \x01(\x08\x12P\n\x0eproperty_files\x18\x04 \x03(\x0b\x32\x38.build.tools.releasetools.OtaMetadata.PropertyFilesEntry\x12;\n\x0cprecondition\x18\x05 \x01(\x0b\x32%.build.tools.releasetools.DeviceState\x12<\n\rpostcondition\x18\x06 \x01(\x0b\x32%.build.tools.releasetools.DeviceState\x12#\n\x1bretrofit_dynamic_partitions\x18\x07 \x01(\x08\x12\x16\n\x0erequired_cache\x18\x08 \x01(\x03\x12\x35\n\tapex_info\x18\t \x03(\x0b\x32\".build.tools.releasetools.ApexInfo\x1a\x34\n\x12PropertyFilesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"4\n\x07OtaType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x06\n\x02\x41\x42\x10\x01\x12\t\n\x05\x42LOCK\x10\x02\x12\t\n\x05\x42RICK\x10\x03\x42\x02H\x03\x62\x06proto3'
)
@@ -28,28 +29,33 @@
full_name='build.tools.releasetools.OtaMetadata.OtaType',
filename=None,
file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
values=[
_descriptor.EnumValueDescriptor(
name='UNKNOWN', index=0, number=0,
serialized_options=None,
- type=None),
+ type=None,
+ create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='AB', index=1, number=1,
serialized_options=None,
- type=None),
+ type=None,
+ create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='BLOCK', index=2, number=2,
serialized_options=None,
- type=None),
+ type=None,
+ create_key=_descriptor._internal_create_key),
_descriptor.EnumValueDescriptor(
name='BRICK', index=3, number=3,
serialized_options=None,
- type=None),
+ type=None,
+ create_key=_descriptor._internal_create_key),
],
containing_type=None,
serialized_options=None,
- serialized_start=777,
- serialized_end=829,
+ serialized_start=1004,
+ serialized_end=1056,
)
_sym_db.RegisterEnumDescriptor(_OTAMETADATA_OTATYPE)
@@ -60,6 +66,7 @@
filename=None,
file=DESCRIPTOR,
containing_type=None,
+ create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='partition_name', full_name='build.tools.releasetools.PartitionState.partition_name', index=0,
@@ -67,28 +74,28 @@
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='device', full_name='build.tools.releasetools.PartitionState.device', index=1,
number=2, type=9, cpp_type=9, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='build', full_name='build.tools.releasetools.PartitionState.build', index=2,
number=3, type=9, cpp_type=9, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='version', full_name='build.tools.releasetools.PartitionState.version', index=3,
number=4, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
@@ -112,6 +119,7 @@
filename=None,
file=DESCRIPTOR,
containing_type=None,
+ create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='device', full_name='build.tools.releasetools.DeviceState.device', index=0,
@@ -119,49 +127,49 @@
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='build', full_name='build.tools.releasetools.DeviceState.build', index=1,
number=2, type=9, cpp_type=9, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='build_incremental', full_name='build.tools.releasetools.DeviceState.build_incremental', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='timestamp', full_name='build.tools.releasetools.DeviceState.timestamp', index=3,
number=4, type=3, cpp_type=2, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='sdk_level', full_name='build.tools.releasetools.DeviceState.sdk_level', index=4,
number=5, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='security_patch_level', full_name='build.tools.releasetools.DeviceState.security_patch_level', index=5,
number=6, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='partition_state', full_name='build.tools.releasetools.DeviceState.partition_state', index=6,
number=7, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
@@ -179,12 +187,98 @@
)
+_APEXINFO = _descriptor.Descriptor(
+ name='ApexInfo',
+ full_name='build.tools.releasetools.ApexInfo',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='package_name', full_name='build.tools.releasetools.ApexInfo.package_name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=b"".decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
+ _descriptor.FieldDescriptor(
+ name='version', full_name='build.tools.releasetools.ApexInfo.version', index=1,
+ number=2, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
+ _descriptor.FieldDescriptor(
+ name='is_compressed', full_name='build.tools.releasetools.ApexInfo.is_compressed', index=2,
+ number=3, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
+ _descriptor.FieldDescriptor(
+ name='decompressed_size', full_name='build.tools.releasetools.ApexInfo.decompressed_size', index=3,
+ number=4, type=3, cpp_type=2, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=347,
+ serialized_end=446,
+)
+
+
+_APEXMETADATA = _descriptor.Descriptor(
+ name='ApexMetadata',
+ full_name='build.tools.releasetools.ApexMetadata',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='apex_info', full_name='build.tools.releasetools.ApexMetadata.apex_info', index=0,
+ number=1, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=448,
+ serialized_end=517,
+)
+
+
_OTAMETADATA_PROPERTYFILESENTRY = _descriptor.Descriptor(
name='PropertyFilesEntry',
full_name='build.tools.releasetools.OtaMetadata.PropertyFilesEntry',
filename=None,
file=DESCRIPTOR,
containing_type=None,
+ create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='key', full_name='build.tools.releasetools.OtaMetadata.PropertyFilesEntry.key', index=0,
@@ -192,14 +286,14 @@
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='value', full_name='build.tools.releasetools.OtaMetadata.PropertyFilesEntry.value', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=b"".decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
@@ -212,8 +306,8 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=723,
- serialized_end=775,
+ serialized_start=950,
+ serialized_end=1002,
)
_OTAMETADATA = _descriptor.Descriptor(
@@ -222,6 +316,7 @@
filename=None,
file=DESCRIPTOR,
containing_type=None,
+ create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='type', full_name='build.tools.releasetools.OtaMetadata.type', index=0,
@@ -229,56 +324,63 @@
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='wipe', full_name='build.tools.releasetools.OtaMetadata.wipe', index=1,
number=2, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='downgrade', full_name='build.tools.releasetools.OtaMetadata.downgrade', index=2,
number=3, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='property_files', full_name='build.tools.releasetools.OtaMetadata.property_files', index=3,
number=4, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='precondition', full_name='build.tools.releasetools.OtaMetadata.precondition', index=4,
number=5, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='postcondition', full_name='build.tools.releasetools.OtaMetadata.postcondition', index=5,
number=6, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='retrofit_dynamic_partitions', full_name='build.tools.releasetools.OtaMetadata.retrofit_dynamic_partitions', index=6,
number=7, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='required_cache', full_name='build.tools.releasetools.OtaMetadata.required_cache', index=7,
number=8, type=3, cpp_type=2, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
+ _descriptor.FieldDescriptor(
+ name='apex_info', full_name='build.tools.releasetools.OtaMetadata.apex_info', index=8,
+ number=9, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
@@ -292,19 +394,23 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=348,
- serialized_end=829,
+ serialized_start=520,
+ serialized_end=1056,
)
_DEVICESTATE.fields_by_name['partition_state'].message_type = _PARTITIONSTATE
+_APEXMETADATA.fields_by_name['apex_info'].message_type = _APEXINFO
_OTAMETADATA_PROPERTYFILESENTRY.containing_type = _OTAMETADATA
_OTAMETADATA.fields_by_name['type'].enum_type = _OTAMETADATA_OTATYPE
_OTAMETADATA.fields_by_name['property_files'].message_type = _OTAMETADATA_PROPERTYFILESENTRY
_OTAMETADATA.fields_by_name['precondition'].message_type = _DEVICESTATE
_OTAMETADATA.fields_by_name['postcondition'].message_type = _DEVICESTATE
+_OTAMETADATA.fields_by_name['apex_info'].message_type = _APEXINFO
_OTAMETADATA_OTATYPE.containing_type = _OTAMETADATA
DESCRIPTOR.message_types_by_name['PartitionState'] = _PARTITIONSTATE
DESCRIPTOR.message_types_by_name['DeviceState'] = _DEVICESTATE
+DESCRIPTOR.message_types_by_name['ApexInfo'] = _APEXINFO
+DESCRIPTOR.message_types_by_name['ApexMetadata'] = _APEXMETADATA
DESCRIPTOR.message_types_by_name['OtaMetadata'] = _OTAMETADATA
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
@@ -322,6 +428,20 @@
})
_sym_db.RegisterMessage(DeviceState)
+ApexInfo = _reflection.GeneratedProtocolMessageType('ApexInfo', (_message.Message,), {
+ 'DESCRIPTOR' : _APEXINFO,
+ '__module__' : 'ota_metadata_pb2'
+ # @@protoc_insertion_point(class_scope:build.tools.releasetools.ApexInfo)
+ })
+_sym_db.RegisterMessage(ApexInfo)
+
+ApexMetadata = _reflection.GeneratedProtocolMessageType('ApexMetadata', (_message.Message,), {
+ 'DESCRIPTOR' : _APEXMETADATA,
+ '__module__' : 'ota_metadata_pb2'
+ # @@protoc_insertion_point(class_scope:build.tools.releasetools.ApexMetadata)
+ })
+_sym_db.RegisterMessage(ApexMetadata)
+
OtaMetadata = _reflection.GeneratedProtocolMessageType('OtaMetadata', (_message.Message,), {
'PropertyFilesEntry' : _reflection.GeneratedProtocolMessageType('PropertyFilesEntry', (_message.Message,), {
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index e8674b6..176e258 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -626,6 +626,10 @@
elif filename in ["META/care_map.pb", "META/care_map.txt"]:
pass
+ # Skip apex_info.pb because we sign/modify apexes
+ elif filename == "META/apex_info.pb":
+ pass
+
# Updates system_other.avbpubkey in /product/etc/.
elif filename in (
"PRODUCT/etc/security/avb/system_other.avbpubkey",
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index 8bf7778..b556b3a 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -33,10 +33,11 @@
GetTargetFilesZipWithoutPostinstallConfig,
Payload, PayloadSigner, POSTINSTALL_CONFIG,
StreamingPropertyFiles, AB_PARTITIONS)
+from apex_utils import GetApexInfoFromTargetFiles
from test_utils import PropertyFilesTestCase
-def construct_target_files(secondary=False):
+def construct_target_files(secondary=False, compressedApex=False):
"""Returns a target-files.zip file for generating OTA packages."""
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
@@ -78,6 +79,11 @@
target_files_zip.writestr('IMAGES/system_other.img',
os.urandom(len("system_other")))
+ if compressedApex:
+ apex_file_name = 'com.android.apex.compressed.v1.capex'
+ apex_file = os.path.join(test_utils.get_current_dir(), apex_file_name)
+ target_files_zip.write(apex_file, 'SYSTEM/apex/' + apex_file_name)
+
return target_files
@@ -274,6 +280,21 @@
},
metadata)
+ @test_utils.SkipIfExternalToolsUnavailable()
+ def test_GetApexInfoFromTargetFiles(self):
+ target_files = construct_target_files(compressedApex=True)
+ apex_infos = GetApexInfoFromTargetFiles(target_files)
+ self.assertEqual(len(apex_infos), 1)
+ self.assertEqual(apex_infos[0].package_name, "com.android.apex.compressed")
+ self.assertEqual(apex_infos[0].version, 1)
+ self.assertEqual(apex_infos[0].is_compressed, True)
+ # Compare the decompressed APEX size with the original uncompressed APEX
+ original_apex_name = 'com.android.apex.compressed.v1_original.apex'
+ original_apex_filepath = os.path.join(test_utils.get_current_dir(), original_apex_name)
+ uncompressed_apex_size = os.path.getsize(original_apex_filepath)
+ self.assertEqual(apex_infos[0].decompressed_size, uncompressed_apex_size)
+
+
def test_GetPackageMetadata_retrofitDynamicPartitions(self):
target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
common.OPTIONS.retrofit_dynamic_partitions = True
diff --git a/tools/releasetools/test_sign_apex.py b/tools/releasetools/test_sign_apex.py
index 82f5938..646b04d 100644
--- a/tools/releasetools/test_sign_apex.py
+++ b/tools/releasetools/test_sign_apex.py
@@ -57,3 +57,17 @@
False,
apk_keys)
self.assertTrue(os.path.exists(signed_test_apex))
+
+ @test_utils.SkipIfExternalToolsUnavailable()
+ def test_SignCompressedApexFile(self):
+ apex = os.path.join(test_utils.get_current_dir(), 'com.android.apex.compressed.v1.capex')
+ payload_key = os.path.join(self.testdata_dir, 'testkey_RSA4096.key')
+ container_key = os.path.join(self.testdata_dir, 'testkey')
+ signed_apex = sign_apex.SignApexFile(
+ 'avbtool',
+ apex,
+ payload_key,
+ container_key,
+ False,
+ codename_to_api_level_map={'S': 31})
+ self.assertTrue(os.path.exists(signed_apex))
diff --git a/tools/releasetools/test_utils.py b/tools/releasetools/test_utils.py
index ccd97a9..808b392 100755
--- a/tools/releasetools/test_utils.py
+++ b/tools/releasetools/test_utils.py
@@ -55,6 +55,11 @@
current_dir = os.path.dirname(os.path.realpath(__file__))
return os.path.join(current_dir, 'testdata')
+def get_current_dir():
+ """Returns the current dir, relative to the script dir."""
+ # The script dir is the one we want, which could be different from pwd.
+ current_dir = os.path.dirname(os.path.realpath(__file__))
+ return current_dir
def get_search_path():
"""Returns the search path that has 'framework/signapk.jar' under."""