Merge "Revert "Revert "Removing N from PLATFORM_VERSION_ALL_CODENAMES""" into nyc-mr1-dev
diff --git a/core/Makefile b/core/Makefile
index 32c1755..1e81c14 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -793,6 +793,7 @@
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_squashfs_compressor=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "system_squashfs_block_size=$(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
+$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "system_squashfs_disable_4k_align=$(BOARD_SYSTEMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH),$(hide) echo "system_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH)" >> $(1))
$(if $(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "userdata_fs_type=$(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
$(if $(BOARD_USERDATAIMAGE_PARTITION_SIZE),$(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)" >> $(1))
@@ -804,6 +805,7 @@
$(if $(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "vendor_squashfs_compressor=$(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
$(if $(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "vendor_squashfs_compressor_opt=$(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
$(if $(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "vendor_squashfs_block_size=$(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
+$(if $(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "vendor_squashfs_disable_4k_align=$(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH),$(hide) echo "vendor_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH)" >> $(1))
$(if $(BOARD_OEMIMAGE_PARTITION_SIZE),$(hide) echo "oem_size=$(BOARD_OEMIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_OEMIMAGE_JOURNAL_SIZE),$(hide) echo "oem_journal_size=$(BOARD_OEMIMAGE_JOURNAL_SIZE)" >> $(1))
@@ -883,10 +885,10 @@
else
recovery_fstab := $(strip $(wildcard $(TARGET_DEVICE_DIR)/recovery.fstab))
endif
-ifdef TARGET_RECOVERY_BRICK
-recovery_brick := $(TARGET_RECOVERY_BRICK)
+ifdef TARGET_RECOVERY_WIPE
+recovery_wipe := $(TARGET_RECOVERY_WIPE)
else
-recovery_brick :=
+recovery_wipe :=
endif
# Prior to A/B update, we used to have:
@@ -973,8 +975,8 @@
cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/$(newline))
$(hide) $(foreach item,$(recovery_fstab), \
cp -f $(item) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.fstab)
- $(if $(strip $(recovery_brick)), \
- $(hide) cp -f $(recovery_brick) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.brick)
+ $(if $(strip $(recovery_wipe)), \
+ $(hide) cp -f $(recovery_wipe) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.wipe)
$(hide) cp $(RECOVERY_INSTALL_OTA_KEYS) $(TARGET_RECOVERY_ROOT_OUT)/res/keys
$(hide) cat $(INSTALLED_DEFAULT_PROP_TARGET) $(recovery_build_prop) \
> $(TARGET_RECOVERY_ROOT_OUT)/default.prop
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 6e96880..f84a66f 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -24,6 +24,23 @@
my_sanitize := $(my_global_sanitize)
endif
+# Add a filter point for 32-bit vs 64-bit sanitization (to lighten the burden).
+SANITIZE_ARCH ?= 32 64
+ifeq ($(filter $(SANITIZE_ARCH),$(my_32_64_bit_suffix)),)
+ my_sanitize :=
+endif
+
+# Add a filter point based on module owner (to lighten the burden). The format is a space- or
+# colon-separated list of owner names.
+ifneq (,$(SANITIZE_NEVER_BY_OWNER))
+ ifneq (,$(LOCAL_MODULE_OWNER))
+ ifneq (,$(filter $(LOCAL_MODULE_OWNER),$(subst :, ,$(SANITIZE_NEVER_BY_OWNER))))
+ $(warning Not sanitizing $(LOCAL_MODULE) based on module owner.)
+ my_sanitize :=
+ endif
+ endif
+endif
+
# Don't apply sanitizers to NDK code.
ifdef LOCAL_SDK_VERSION
my_sanitize :=
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 2a7ffb7..9410c3c 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -11,6 +11,10 @@
DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
endif
+# Pass special classpath to skip uses library check.
+# Should modify build system to pass used libraries properly later.
+DEX2OAT_CLASSPATH := "&"
+
DEX2OAT_DEPENDENCY += $(DEX2OAT)
# Use the first preloaded-classes file in PRODUCT_COPY_FILES.
@@ -94,6 +98,7 @@
$(hide) mkdir -p $(dir $(2))
$(hide) ANDROID_LOG_TAGS="*:e" $(DEX2OAT) \
--runtime-arg -Xms$(DEX2OAT_XMS) --runtime-arg -Xmx$(DEX2OAT_XMX) \
+ --runtime-arg -classpath --runtime-arg $(DEX2OAT_CLASSPATH) \
--boot-image=$(PRIVATE_DEX_PREOPT_IMAGE_LOCATION) \
--dex-file=$(1) \
--dex-location=$(PRIVATE_DEX_LOCATION) \
diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk
index 910c8b7..e3761ae 100644
--- a/core/tasks/vendor_module_check.mk
+++ b/core/tasks/vendor_module_check.mk
@@ -43,6 +43,7 @@
synaptics \
ti \
trusted_logic \
+ verizon \
widevine
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 5acd4dd..141c27b 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -113,7 +113,7 @@
# Must be of the form "YYYY-MM-DD" on production devices.
#
# If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
- PLATFORM_SECURITY_PATCH := 2016-07-05
+ PLATFORM_SECURITY_PATCH := 2016-08-05
endif
ifeq "" "$(PLATFORM_BASE_OS)"
diff --git a/target/product/core.mk b/target/product/core.mk
index 75cf649..0a4e0fd 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -53,6 +53,7 @@
QuickSearchBox \
Settings \
SharedStorageBackup \
+ StorageManager \
Telecom \
TeleService \
VpnDialogs \
diff --git a/target/product/product_launched_with_l.mk b/target/product/product_launched_with_l.mk
new file mode 100644
index 0000000..b86f424
--- /dev/null
+++ b/target/product/product_launched_with_l.mk
@@ -0,0 +1,2 @@
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+PRODUCT_SHIPPING_API_LEVEL := 21
diff --git a/target/product/product_launched_with_l_mr1.mk b/target/product/product_launched_with_l_mr1.mk
new file mode 100644
index 0000000..7a5bd0f
--- /dev/null
+++ b/target/product/product_launched_with_l_mr1.mk
@@ -0,0 +1,2 @@
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+PRODUCT_SHIPPING_API_LEVEL := 22
diff --git a/target/product/product_launched_with_m.mk b/target/product/product_launched_with_m.mk
new file mode 100644
index 0000000..afd8647
--- /dev/null
+++ b/target/product/product_launched_with_m.mk
@@ -0,0 +1,2 @@
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+PRODUCT_SHIPPING_API_LEVEL := 23
diff --git a/target/product/product_launched_with_n.mk b/target/product/product_launched_with_n.mk
new file mode 100644
index 0000000..f7c5d79
--- /dev/null
+++ b/target/product/product_launched_with_n.mk
@@ -0,0 +1,2 @@
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+PRODUCT_SHIPPING_API_LEVEL := 24
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 82d5397..66d5907 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -261,7 +261,8 @@
# original image.
class BlockImageDiff(object):
- def __init__(self, tgt, src=None, threads=None, version=4):
+ def __init__(self, tgt, src=None, threads=None, version=4,
+ disable_imgdiff=False):
if threads is None:
threads = multiprocessing.cpu_count() // 2
if threads == 0:
@@ -274,6 +275,7 @@
self._max_stashed_size = 0
self.touched_src_ranges = RangeSet()
self.touched_src_sha1 = None
+ self.disable_imgdiff = disable_imgdiff
assert version in (1, 2, 3, 4)
@@ -340,6 +342,21 @@
return ctx.hexdigest()
def WriteTransfers(self, prefix):
+ def WriteTransfersZero(out, to_zero):
+ """Limit the number of blocks in command zero to 1024 blocks.
+
+ This prevents the target size of one command from being too large; and
+ might help to avoid fsync errors on some devices."""
+
+ zero_blocks_limit = 1024
+ total = 0
+ while to_zero:
+ zero_blocks = to_zero.first(zero_blocks_limit)
+ out.append("zero %s\n" % (zero_blocks.to_string_raw(),))
+ total += zero_blocks.size()
+ to_zero = to_zero.subtract(zero_blocks)
+ return total
+
out = []
total = 0
@@ -521,9 +538,8 @@
elif xf.style == "zero":
assert xf.tgt_ranges
to_zero = xf.tgt_ranges.subtract(xf.src_ranges)
- if to_zero:
- out.append("%s %s\n" % (xf.style, to_zero.to_string_raw()))
- total += to_zero.size()
+ assert WriteTransfersZero(out, to_zero) == to_zero.size()
+ total += to_zero.size()
else:
raise ValueError("unknown transfer style '%s'\n" % xf.style)
@@ -552,7 +568,8 @@
# Zero out extended blocks as a workaround for bug 20881595.
if self.tgt.extended:
- out.append("zero %s\n" % (self.tgt.extended.to_string_raw(),))
+ assert (WriteTransfersZero(out, self.tgt.extended) ==
+ self.tgt.extended.size())
total += self.tgt.extended.size()
# We erase all the blocks on the partition that a) don't contain useful
@@ -714,6 +731,7 @@
# produces significantly smaller patches than bsdiff).
# This is permissible if:
#
+ # - imgdiff is not disabled, and
# - the source and target files are monotonic (ie, the
# data is stored with blocks in increasing order), and
# - we haven't removed any blocks from the source set.
@@ -723,7 +741,7 @@
# zip file (plus possibly extra zeros in the last block),
# which is what imgdiff needs to operate. (imgdiff is
# fine with extra zeros at the end of the file.)
- imgdiff = (xf.intact and
+ imgdiff = (not self.disable_imgdiff and xf.intact and
xf.tgt_name.split(".")[-1].lower()
in ("apk", "jar", "zip"))
xf.style = "imgdiff" if imgdiff else "bsdiff"
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index b622376..3d41e83 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -400,12 +400,16 @@
build_command.extend(["-C", fs_config])
if "selinux_fc" in prop_dict:
build_command.extend(["-c", prop_dict["selinux_fc"]])
+ if "block_list" in prop_dict:
+ build_command.extend(["-B", prop_dict["block_list"]])
if "squashfs_compressor" in prop_dict:
build_command.extend(["-z", prop_dict["squashfs_compressor"]])
if "squashfs_compressor_opt" in prop_dict:
build_command.extend(["-zo", prop_dict["squashfs_compressor_opt"]])
if "squashfs_block_size" in prop_dict:
build_command.extend(["-b", prop_dict["squashfs_block_size"]])
+ if "squashfs_disable_4k_align" in prop_dict and prop_dict.get("squashfs_disable_4k_align") == "true":
+ build_command.extend(["-a"])
elif fs_type.startswith("f2fs"):
build_command = ["mkf2fsuserimg.sh"]
build_command.extend([out_file, prop_dict["partition_size"]])
@@ -550,6 +554,7 @@
copy_prop("system_squashfs_compressor", "squashfs_compressor")
copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
copy_prop("system_squashfs_block_size", "squashfs_block_size")
+ copy_prop("system_squashfs_disable_4k_align", "squashfs_disable_4k_align")
copy_prop("system_base_fs_file", "base_fs_file")
elif mount_point == "data":
# Copy the generic fs type first, override with specific one if available.
@@ -568,6 +573,7 @@
copy_prop("vendor_squashfs_compressor", "squashfs_compressor")
copy_prop("vendor_squashfs_compressor_opt", "squashfs_compressor_opt")
copy_prop("vendor_squashfs_block_size", "squashfs_block_size")
+ copy_prop("vendor_squashfs_disable_4k_align", "squashfs_disable_4k_align")
copy_prop("vendor_base_fs_file", "base_fs_file")
elif mount_point == "oem":
copy_prop("fs_type", "fs_type")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index b5c0114..422ba43 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1341,11 +1341,12 @@
class BlockDifference(object):
def __init__(self, partition, tgt, src=None, check_first_block=False,
- version=None):
+ version=None, disable_imgdiff=False):
self.tgt = tgt
self.src = src
self.partition = partition
self.check_first_block = check_first_block
+ self.disable_imgdiff = disable_imgdiff
if version is None:
version = 1
@@ -1356,7 +1357,8 @@
self.version = version
b = blockimgdiff.BlockImageDiff(tgt, src, threads=OPTIONS.worker_threads,
- version=self.version)
+ version=self.version,
+ disable_imgdiff=self.disable_imgdiff)
tmpdir = tempfile.mkdtemp()
OPTIONS.tempfiles.append(tmpdir)
self.path = os.path.join(tmpdir, partition)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 861c485..915a29e 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -113,6 +113,17 @@
Generate a log file that shows the differences in the source and target
builds for an incremental package. This option is only meaningful when
-i is specified.
+
+ --payload_signer <signer>
+ Specify the signer when signing the payload and metadata for A/B OTAs.
+ By default (i.e. without this flag), it calls 'openssl pkeyutl' to sign
+ with the package private key. If the private key cannot be accessed
+ directly, a payload signer that knows how to do that should be specified.
+ The signer will be supplied with "-inkey <path_to_key>",
+ "-in <input_file>" and "-out <output_file>" parameters.
+
+ --payload_signer_args <args>
+ Specify the arguments needed for payload signer.
"""
import sys
@@ -124,6 +135,7 @@
import multiprocessing
import os
import subprocess
+import shlex
import tempfile
import zipfile
@@ -160,6 +172,8 @@
OPTIONS.stash_threshold = 0.8
OPTIONS.gen_verify = False
OPTIONS.log_diff = None
+OPTIONS.payload_signer = None
+OPTIONS.payload_signer_args = []
def MostPopularKey(d, default):
"""Given a dict, return the key corresponding to the largest
@@ -834,6 +848,10 @@
OPTIONS.target_info_dict)
metadata["pre-build"] = source_fp
metadata["post-build"] = target_fp
+ metadata["pre-build-incremental"] = GetBuildProp(
+ "ro.build.version.incremental", OPTIONS.source_info_dict)
+ metadata["post-build-incremental"] = GetBuildProp(
+ "ro.build.version.incremental", OPTIONS.target_info_dict)
source_boot = common.GetBootableImage(
"/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT",
@@ -859,9 +877,15 @@
# disk type is ext4
system_partition = OPTIONS.source_info_dict["fstab"]["/system"]
check_first_block = system_partition.fs_type == "ext4"
+ # Disable using imgdiff for squashfs. 'imgdiff -z' expects input files to be
+ # in zip formats. However with squashfs, a) all files are compressed in LZ4;
+ # b) the blocks listed in block map may not contain all the bytes for a given
+ # file (because they're rounded to be 4K-aligned).
+ disable_imgdiff = system_partition.fs_type == "squashfs"
system_diff = common.BlockDifference("system", system_tgt, system_src,
check_first_block,
- version=blockimgdiff_version)
+ version=blockimgdiff_version,
+ disable_imgdiff=disable_imgdiff)
if HasVendorPartition(target_zip):
if not HasVendorPartition(source_zip):
@@ -875,9 +899,11 @@
# disk type is ext4
vendor_partition = OPTIONS.source_info_dict["fstab"]["/vendor"]
check_first_block = vendor_partition.fs_type == "ext4"
+ disable_imgdiff = vendor_partition.fs_type == "squashfs"
vendor_diff = common.BlockDifference("vendor", vendor_tgt, vendor_src,
check_first_block,
- version=blockimgdiff_version)
+ version=blockimgdiff_version,
+ disable_imgdiff=disable_imgdiff)
else:
vendor_diff = None
@@ -1151,17 +1177,19 @@
"default_system_dev_certificate",
"build/target/product/security/testkey")
- # A/B updater expects key in RSA format.
- cmd = ["openssl", "pkcs8",
- "-in", OPTIONS.package_key + OPTIONS.private_key_suffix,
- "-inform", "DER", "-nocrypt"]
- rsa_key = common.MakeTempFile(prefix="key-", suffix=".key")
- cmd.extend(["-out", rsa_key])
- p1 = common.Run(cmd, stdout=subprocess.PIPE)
- p1.wait()
- assert p1.returncode == 0, "openssl pkcs8 failed"
+ # A/B updater expects a signing key in RSA format. Gets the key ready for
+ # later use in step 3, unless a payload_signer has been specified.
+ if OPTIONS.payload_signer is None:
+ cmd = ["openssl", "pkcs8",
+ "-in", OPTIONS.package_key + OPTIONS.private_key_suffix,
+ "-inform", "DER", "-nocrypt"]
+ rsa_key = common.MakeTempFile(prefix="key-", suffix=".key")
+ cmd.extend(["-out", rsa_key])
+ p1 = common.Run(cmd, stdout=subprocess.PIPE)
+ p1.wait()
+ assert p1.returncode == 0, "openssl pkcs8 failed"
- # Stage the output zip package for signing.
+ # Stage the output zip package for package signing.
temp_zip_file = tempfile.NamedTemporaryFile()
output_zip = zipfile.ZipFile(temp_zip_file, "w",
compression=zipfile.ZIP_DEFLATED)
@@ -1178,6 +1206,8 @@
metadata = {
"post-build": CalculateFingerprint(oem_props, oem_dict,
OPTIONS.info_dict),
+ "post-build-incremental" : GetBuildProp("ro.build.version.incremental",
+ OPTIONS.info_dict),
"pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
OPTIONS.info_dict),
"post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict),
@@ -1188,6 +1218,8 @@
if source_file is not None:
metadata["pre-build"] = CalculateFingerprint(oem_props, oem_dict,
OPTIONS.source_info_dict)
+ metadata["pre-build-incremental"] = GetBuildProp(
+ "ro.build.version.incremental", OPTIONS.source_info_dict)
# 1. Generate payload.
payload_file = common.MakeTempFile(prefix="payload-", suffix=".bin")
@@ -1218,21 +1250,30 @@
signed_metadata_sig_file = common.MakeTempFile(prefix="signed-sig-",
suffix=".bin")
# 3a. Sign the payload hash.
- cmd = ["openssl", "pkeyutl", "-sign",
- "-inkey", rsa_key,
- "-pkeyopt", "digest:sha256",
- "-in", payload_sig_file,
- "-out", signed_payload_sig_file]
+ if OPTIONS.payload_signer is not None:
+ cmd = [OPTIONS.payload_signer]
+ cmd.extend(OPTIONS.payload_signer_args)
+ else:
+ cmd = ["openssl", "pkeyutl", "-sign",
+ "-inkey", rsa_key,
+ "-pkeyopt", "digest:sha256"]
+ cmd.extend(["-in", payload_sig_file,
+ "-out", signed_payload_sig_file])
+
p1 = common.Run(cmd, stdout=subprocess.PIPE)
p1.wait()
assert p1.returncode == 0, "openssl sign payload failed"
# 3b. Sign the metadata hash.
- cmd = ["openssl", "pkeyutl", "-sign",
- "-inkey", rsa_key,
- "-pkeyopt", "digest:sha256",
- "-in", metadata_sig_file,
- "-out", signed_metadata_sig_file]
+ if OPTIONS.payload_signer is not None:
+ cmd = [OPTIONS.payload_signer]
+ cmd.extend(OPTIONS.payload_signer_args)
+ else:
+ cmd = ["openssl", "pkeyutl", "-sign",
+ "-inkey", rsa_key,
+ "-pkeyopt", "digest:sha256"]
+ cmd.extend(["-in", metadata_sig_file,
+ "-out", signed_metadata_sig_file])
p1 = common.Run(cmd, stdout=subprocess.PIPE)
p1.wait()
assert p1.returncode == 0, "openssl sign metadata failed"
@@ -1260,6 +1301,11 @@
p1.wait()
assert p1.returncode == 0, "brillo_update_payload properties failed"
+ if OPTIONS.wipe_user_data:
+ with open(properties_file, "a") as f:
+ f.write("POWERWASH=1\n")
+ metadata["ota-wipe"] = "yes"
+
# Add the signed payload file and properties into the zip.
common.ZipWrite(output_zip, properties_file, arcname="payload_properties.txt")
common.ZipWrite(output_zip, signed_payload_file, arcname="payload.bin",
@@ -1493,6 +1539,10 @@
metadata["pre-build"] = source_fp
metadata["post-build"] = target_fp
+ metadata["pre-build-incremental"] = GetBuildProp(
+ "ro.build.version.incremental", OPTIONS.source_info_dict)
+ metadata["post-build-incremental"] = GetBuildProp(
+ "ro.build.version.incremental", OPTIONS.target_info_dict)
source_boot = common.GetBootableImage(
"/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT",
@@ -1880,6 +1930,10 @@
OPTIONS.gen_verify = True
elif o == "--log_diff":
OPTIONS.log_diff = a
+ elif o == "--payload_signer":
+ OPTIONS.payload_signer = a
+ elif o == "--payload_signer_args":
+ OPTIONS.payload_signer_args = shlex.split(a)
else:
return False
return True
@@ -1909,6 +1963,8 @@
"stash_threshold=",
"gen_verify",
"log_diff=",
+ "payload_signer=",
+ "payload_signer_args=",
], extra_option_handler=option_handler)
if len(args) != 2:
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index f758ae0..1a3f074 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -51,10 +51,12 @@
in which they appear on the command line.
-o (--replace_ota_keys)
- Replace the certificate (public key) used by OTA package
- verification with the one specified in the input target_files
- zip (in the META/otakeys.txt file). Key remapping (-k and -d)
- is performed on this key.
+ Replace the certificate (public key) used by OTA package verification
+ with the ones specified in the input target_files zip (in the
+ META/otakeys.txt file). Key remapping (-k and -d) is performed on the
+ keys. For A/B devices, the payload verification key will be replaced
+ as well. If there're multiple OTA keys, only the first one will be used
+ for payload verification.
-t (--tag_changes) <+tag>,<-tag>,...
Comma-separated list of changes to make to the set of tags (in
@@ -63,6 +65,9 @@
removed. Changes are processed in the order they appear.
Default value is "-test-keys,-dev-keys,+release-keys".
+ --replace_verity_keyid <path_to_X509_PEM_cert_file>
+ Replace the veritykeyid in BOOT/cmdline of input_target_file_zip
+ with keyid of the cert pointed by <path_to_X509_PEM_cert_file>
"""
import sys
@@ -92,6 +97,7 @@
OPTIONS.replace_ota_keys = False
OPTIONS.replace_verity_public_key = False
OPTIONS.replace_verity_private_key = False
+OPTIONS.replace_verity_keyid = False
OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys")
def GetApkCerts(tf_zip):
@@ -171,7 +177,9 @@
for i in input_tf_zip.infolist()
if i.filename.endswith('.apk')])
rebuild_recovery = False
+ system_root_image = misc_info.get("system_root_image") == "true"
+ # tmpdir will only be used to regenerate the recovery-from-boot patch.
tmpdir = tempfile.mkdtemp()
def write_to_temp(fn, attr, data):
fn = os.path.join(tmpdir, fn)
@@ -207,14 +215,15 @@
new_data = ReplaceVerityPublicKey(output_tf_zip, info.filename,
OPTIONS.replace_verity_public_key[1])
write_to_temp(info.filename, info.external_attr, new_data)
- # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch.
- elif (info.filename.startswith("BOOT/") or
- info.filename.startswith("RECOVERY/") or
- info.filename.startswith("META/") or
- info.filename.startswith("ROOT/") or
- info.filename == "SYSTEM/etc/recovery-resource.dat"):
- write_to_temp(info.filename, info.external_attr, data)
-
+ elif (info.filename == "BOOT/cmdline" and
+ OPTIONS.replace_verity_keyid):
+ new_cmdline = ReplaceVerityKeyId(input_tf_zip, output_tf_zip,
+ OPTIONS.replace_verity_keyid[1])
+ # Writing the new cmdline to tmpdir is redundant as the bootimage
+ # gets build in the add_image_to_target_files and rebuild_recovery
+ # is not exercised while building the boot image for the A/B
+ # path
+ write_to_temp(info.filename, info.external_attr, new_cmdline)
# Sign APKs.
if info.filename.endswith(".apk"):
name = os.path.basename(info.filename)
@@ -228,6 +237,8 @@
# an APK we're not supposed to sign.
print "NOT signing: %s" % (name,)
common.ZipWriteStr(output_tf_zip, out_info, data)
+
+ # System properties.
elif info.filename in ("SYSTEM/build.prop",
"VENDOR/build.prop",
"BOOT/RAMDISK/default.prop",
@@ -238,19 +249,30 @@
if info.filename in ("BOOT/RAMDISK/default.prop",
"RECOVERY/RAMDISK/default.prop"):
write_to_temp(info.filename, info.external_attr, new_data)
+
elif info.filename.endswith("mac_permissions.xml"):
print "rewriting %s with new keys." % (info.filename,)
new_data = ReplaceCerts(data)
common.ZipWriteStr(output_tf_zip, out_info, new_data)
+
+ # Trigger a rebuild of the recovery patch if needed.
elif info.filename in ("SYSTEM/recovery-from-boot.p",
"SYSTEM/etc/recovery.img",
"SYSTEM/bin/install-recovery.sh"):
rebuild_recovery = True
+
+ # Don't copy OTA keys if we're replacing them.
elif (OPTIONS.replace_ota_keys and
- info.filename in ("RECOVERY/RAMDISK/res/keys",
- "SYSTEM/etc/security/otacerts.zip")):
- # don't copy these files if we're regenerating them below
+ info.filename in (
+ "BOOT/RAMDISK/res/keys",
+ "RECOVERY/RAMDISK/res/keys",
+ "SYSTEM/etc/security/otacerts.zip",
+ "SYSTEM/etc/update_engine/update-payload-key.pub.pem")):
pass
+
+ # Skip verity keys since they have been processed above.
+ # TODO: verity_key is at a wrong location (BOOT/verity_key). Will fix and
+ # clean up verity related lines in a separate CL.
elif (OPTIONS.replace_verity_private_key and
info.filename == "META/misc_info.txt"):
pass
@@ -258,14 +280,36 @@
info.filename in ("BOOT/RAMDISK/verity_key",
"BOOT/verity_key")):
pass
+
+ elif (info.filename == "BOOT/cmdline" and
+ OPTIONS.replace_verity_keyid):
+ pass
+
+ # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch. This case
+ # must come AFTER other matching rules.
+ elif (info.filename.startswith("BOOT/") or
+ info.filename.startswith("RECOVERY/") or
+ info.filename.startswith("META/") or
+ info.filename.startswith("ROOT/") or
+ info.filename == "SYSTEM/etc/recovery-resource.dat"):
+ write_to_temp(info.filename, info.external_attr, data)
+ common.ZipWriteStr(output_tf_zip, out_info, data)
+
+ # A non-APK file; copy it verbatim.
else:
- # a non-APK file; copy it verbatim
common.ZipWriteStr(output_tf_zip, out_info, data)
if OPTIONS.replace_ota_keys:
new_recovery_keys = ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info)
if new_recovery_keys:
- write_to_temp("RECOVERY/RAMDISK/res/keys", 0o755 << 16, new_recovery_keys)
+ if system_root_image:
+ recovery_keys_location = "BOOT/RAMDISK/res/keys"
+ else:
+ recovery_keys_location = "RECOVERY/RAMDISK/res/keys"
+ # The "new_recovery_keys" has been already written into the output_tf_zip
+ # while calling ReplaceOtaKeys(). We're just putting the same copy to
+ # tmpdir in case we need to regenerate the recovery-from-boot patch.
+ write_to_temp(recovery_keys_location, 0o755 << 16, new_recovery_keys)
if rebuild_recovery:
recovery_img = common.GetBootableImage(
@@ -398,7 +442,8 @@
"build/target/product/security/testkey")
mapped_keys.append(
OPTIONS.key_map.get(devkey, devkey) + ".x509.pem")
- print "META/otakeys.txt has no keys; using", mapped_keys[0]
+ print("META/otakeys.txt has no keys; using %s for OTA package"
+ " verification." % (mapped_keys[0],))
# recovery uses a version of the key that has been slightly
# predigested (by DumpPublicKey.java) and put in res/keys.
@@ -411,8 +456,13 @@
new_recovery_keys, _ = p.communicate()
if p.returncode != 0:
raise common.ExternalError("failed to run dumpkeys")
- common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys",
- new_recovery_keys)
+
+ # system_root_image puts the recovery keys at BOOT/RAMDISK.
+ if misc_info.get("system_root_image") == "true":
+ recovery_keys_location = "BOOT/RAMDISK/res/keys"
+ else:
+ recovery_keys_location = "RECOVERY/RAMDISK/res/keys"
+ common.ZipWriteStr(output_tf_zip, recovery_keys_location, new_recovery_keys)
# SystemUpdateActivity uses the x509.pem version of the keys, but
# put into a zipfile system/etc/security/otacerts.zip.
@@ -426,6 +476,20 @@
common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip",
temp_file.getvalue())
+ # For A/B devices, update the payload verification key.
+ if misc_info.get("ab_update") == "true":
+ # Unlike otacerts.zip that may contain multiple keys, we can only specify
+ # ONE payload verification key.
+ if len(mapped_keys) > 1:
+ print("\n WARNING: Found more than one OTA keys; Using the first one"
+ " as payload verification key.\n\n")
+
+ print "Using %s for payload verification." % (mapped_keys[0],)
+ common.ZipWrite(
+ output_tf_zip,
+ mapped_keys[0],
+ arcname="SYSTEM/etc/update_engine/update-payload-key.pub.pem")
+
return new_recovery_keys
def ReplaceVerityPublicKey(targetfile_zip, filename, key_path):
@@ -444,6 +508,30 @@
common.ZipWriteStr(targetfile_output_zip, "META/misc_info.txt", new_misc_info)
misc_info["verity_key"] = key_path
+def ReplaceVerityKeyId(targetfile_input_zip, targetfile_output_zip, keypath):
+ in_cmdline = targetfile_input_zip.read("BOOT/cmdline")
+ # copy in_cmdline to output_zip if veritykeyid is not present in in_cmdline
+ if "veritykeyid" not in in_cmdline:
+ common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", in_cmdline)
+ return in_cmdline
+ out_cmdline = []
+ for param in in_cmdline.split():
+ if "veritykeyid" in param:
+ # extract keyid using openssl command
+ p = common.Run(["openssl", "x509", "-in", keypath, "-text"], stdout=subprocess.PIPE)
+ keyid, stderr = p.communicate()
+ keyid = re.search(r'keyid:([0-9a-fA-F:]*)', keyid).group(1).replace(':', '').lower()
+ print "Replacing verity keyid with %s error=%s" % (keyid, stderr)
+ out_cmdline.append("veritykeyid=id:%s" % (keyid,))
+ else:
+ out_cmdline.append(param)
+
+ out_cmdline = ' '.join(out_cmdline)
+ out_cmdline = out_cmdline.strip()
+ print "out_cmdline %s" % (out_cmdline)
+ common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", out_cmdline)
+ return out_cmdline
+
def BuildKeyMap(misc_info, key_mapping_options):
for s, d in key_mapping_options:
if s is None: # -d option
@@ -541,6 +629,8 @@
OPTIONS.replace_verity_public_key = (True, a)
elif o == "--replace_verity_private_key":
OPTIONS.replace_verity_private_key = (True, a)
+ elif o == "--replace_verity_keyid":
+ OPTIONS.replace_verity_keyid = (True, a)
else:
return False
return True
@@ -553,7 +643,8 @@
"replace_ota_keys",
"tag_changes=",
"replace_verity_public_key=",
- "replace_verity_private_key="],
+ "replace_verity_private_key=",
+ "replace_verity_keyid="],
extra_option_handler=option_handler)
if len(args) != 2: