Merge "Revert "support different boot partition sizes in aosp_arm64""
diff --git a/Changes.md b/Changes.md
index 2720a0f..453ea6c 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,18 @@
# Build System Changes for Android.mk Writers
+## ELF prebuilts in PRODUCT_COPY_FILES
+
+ELF prebuilts in PRODUCT_COPY_FILES that are installed into these paths are an
+error:
+
+* `<partition>/bin/*`
+* `<partition>/lib/*`
+* `<partition>/lib64/*`
+
+Define prebuilt modules and add them to PRODUCT_PACKAGES instead.
+To temporarily relax this check and restore the behavior prior to this change,
+set `BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES := true` in `BoardConfig.mk`.
+
## COPY_HEADERS usage now produces warnings {#copy_headers}
We've considered `BUILD_COPY_HEADERS`/`LOCAL_COPY_HEADERS` to be deprecated for
diff --git a/core/Makefile b/core/Makefile
index 69ee80f..d8f8a5e 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -40,11 +40,9 @@
)
endef
-# TODO(b/140560012): Flip BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES to default
-# false after all problematic devices are tagged.
-check_elf_prebuilt_product_copy_files :=
-ifneq (,$(filter false,$(BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES)))
check_elf_prebuilt_product_copy_files := true
+ifneq (,$(filter true,$(BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES)))
+check_elf_prebuilt_product_copy_files :=
endif
check_elf_prebuilt_product_copy_files_hint := \
found ELF prebuilt in PRODUCT_COPY_FILES, use cc_prebuilt_binary / cc_prebuilt_library_shared instead.
@@ -3524,12 +3522,8 @@
endef
ifdef INSTALLED_BOOTIMAGE_TARGET
-# multiple hashes for an image are not yet supported, fortunately this
-# only arises for GKI where the boot descriptor can be left out
-ifeq ($(strip $(BOARD_KERNEL_BINARIES)),)
$(eval $(call check-and-set-avb-args,boot))
endif
-endif
ifdef INSTALLED_VENDOR_BOOTIMAGE_TARGET
$(eval $(call check-and-set-avb-args,vendor_boot))
diff --git a/core/config.mk b/core/config.mk
index 8910c11..3d08ba4 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -863,6 +863,7 @@
27.0 \
28.0 \
29.0 \
+ 30.0 \
.KATI_READONLY := \
PLATFORM_SEPOLICY_COMPAT_VERSIONS \
diff --git a/core/tasks/vts-core-tests.mk b/core/tasks/vts-core-tests.mk
index 4e83de5..a3247da 100644
--- a/core/tasks/vts-core-tests.mk
+++ b/core/tasks/vts-core-tests.mk
@@ -12,15 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+-include external/linux-kselftest/android/kselftest_test_list.mk
+-include external/ltp/android/ltp_package_list.mk
+
test_suite_name := vts
test_suite_tradefed := vts-tradefed
test_suite_readme := test/vts/tools/vts-core-tradefed/README
-# TODO(b/149249068): Clean up after all VTS tests are converted.
-vts_test_artifact_paths :=
-# Some repo may not include vts project.
--include test/vts/tools/build/tasks/framework/vts_for_core_suite.mk
-
# Copy kernel test modules to testcases directories
kernel_test_host_out := $(HOST_OUT_TESTCASES)/vts_kernel_tests
kernel_test_vts_out := $(HOST_OUT)/$(test_suite_name)/android-$(test_suite_name)/testcases/vts_kernel_tests
@@ -44,7 +42,6 @@
$(compatibility_zip): $(copy_kernel_tests)
.PHONY: vts
-$(compatibility_zip): $(vts_test_artifact_paths)
vts: $(compatibility_zip)
$(call dist-for-goals, vts, $(compatibility_zip))
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index c89e203..49f6edc 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -40,6 +40,12 @@
BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
+# 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
+BOARD_AVB_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
+BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION := 2
+
# GSI specific System Properties
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
TARGET_SYSTEM_EXT_PROP := build/make/target/board/gsi_system_ext.prop
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index f931f4a..3e42b68 100644
--- a/target/product/go_defaults_common.mk
+++ b/target/product/go_defaults_common.mk
@@ -40,7 +40,7 @@
# Do not spin up a separate process for the network stack on go devices, use an in-process APK.
PRODUCT_PACKAGES += InProcessNetworkStack
PRODUCT_PACKAGES += CellBroadcastAppPlatform
-PRODUCT_PACKAGES += InProcessTethering
+PRODUCT_PACKAGES += com.android.tethering.inprocess
# Strip the local variable table and the local variable type table to reduce
# the size of the system image. This has no bearing on stack traces, but will
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 1bfdf0a..cd4d750 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -133,7 +133,7 @@
VNDK-core: android.hardware.input.classifier@1.0.so
VNDK-core: android.hardware.input.common@1.0.so
VNDK-core: android.hardware.ir@1.0.so
-VNDK-core: android.hardware.keymaster-V1-ndk_platform.so
+VNDK-core: android.hardware.keymaster-V2-ndk_platform.so
VNDK-core: android.hardware.keymaster@3.0.so
VNDK-core: android.hardware.keymaster@4.0.so
VNDK-core: android.hardware.keymaster@4.1.so
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 7db506c..70ea967 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -548,17 +548,19 @@
care_map_list += care_map
# adds fingerprint field to the care_map
- build_props = OPTIONS.info_dict.get(partition + ".build.prop", {})
+ # TODO(xunchang) revisit the fingerprint calculation for care_map.
+ partition_props = OPTIONS.info_dict.get(partition + ".build.prop")
prop_name_list = ["ro.{}.build.fingerprint".format(partition),
"ro.{}.build.thumbprint".format(partition)]
- present_props = [x for x in prop_name_list if x in build_props]
+ present_props = [x for x in prop_name_list if
+ partition_props and partition_props.GetProp(x)]
if not present_props:
logger.warning("fingerprint is not present for partition %s", partition)
property_id, fingerprint = "unknown", "unknown"
else:
property_id = present_props[0]
- fingerprint = build_props[property_id]
+ fingerprint = partition_props.GetProp(property_id)
care_map_list += [property_id, fingerprint]
if not care_map_list:
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index f30f787..7567346 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -509,9 +509,9 @@
d = {}
if "build.prop" in glob_dict:
- bp = glob_dict["build.prop"]
- if "ro.build.date.utc" in bp:
- d["timestamp"] = bp["ro.build.date.utc"]
+ timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc")
+ if timestamp:
+ d["timestamp"] = timestamp
def copy_prop(src_p, dest_p):
"""Copy a property from the global dictionary.
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
index b3d491f..95d09cc 100755
--- a/tools/releasetools/check_target_files_vintf.py
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -80,8 +80,9 @@
'--property', 'ro.boot.product.vendor.sku=' + vendor_sku]
for odm_sku in odm_skus for vendor_sku in vendor_skus]
+
def GetArgsForShippingApiLevel(info_dict):
- shipping_api_level = info_dict['vendor.build.prop'].get(
+ shipping_api_level = info_dict['vendor.build.prop'].GetProp(
'ro.product.first_api_level')
if not shipping_api_level:
logger.warning('Cannot determine ro.product.first_api_level')
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 1abf5a5..7805e30 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -423,6 +423,14 @@
def items(self):
return self.info_dict.items()
+ def _GetRawBuildProp(self, prop, partition):
+ prop_file = '{}.build.prop'.format(
+ partition) if partition else 'build.prop'
+ partition_props = self.info_dict.get(prop_file)
+ if not partition_props:
+ return None
+ return partition_props.GetProp(prop)
+
def GetPartitionBuildProp(self, prop, partition):
"""Returns the inquired build property for the provided partition."""
# If provided a partition for this property, only look within that
@@ -431,31 +439,33 @@
prop = prop.replace("ro.product", "ro.product.{}".format(partition))
else:
prop = prop.replace("ro.", "ro.{}.".format(partition))
- try:
- return self.info_dict.get("{}.build.prop".format(partition), {})[prop]
- except KeyError:
- raise ExternalError("couldn't find %s in %s.build.prop" %
- (prop, partition))
+
+ prop_val = self._GetRawBuildProp(prop, partition)
+ if prop_val is not None:
+ return prop_val
+ raise ExternalError("couldn't find %s in %s.build.prop" %
+ (prop, partition))
def GetBuildProp(self, prop):
"""Returns the inquired build property from the standard build.prop file."""
if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS:
return self._ResolveRoProductBuildProp(prop)
- try:
- return self.info_dict.get("build.prop", {})[prop]
- except KeyError:
- raise ExternalError("couldn't find %s in build.prop" % (prop,))
+ prop_val = self._GetRawBuildProp(prop, None)
+ if prop_val is not None:
+ return prop_val
+
+ raise ExternalError("couldn't find %s in build.prop" % (prop,))
def _ResolveRoProductBuildProp(self, prop):
"""Resolves the inquired ro.product.* build property"""
- prop_val = self.info_dict.get("build.prop", {}).get(prop)
+ prop_val = self._GetRawBuildProp(prop, None)
if prop_val:
return prop_val
default_source_order = self._GetRoProductPropsDefaultSourceOrder()
- source_order_val = self.info_dict.get("build.prop", {}).get(
- "ro.product.property_source_order")
+ source_order_val = self._GetRawBuildProp(
+ "ro.product.property_source_order", None)
if source_order_val:
source_order = source_order_val.split(",")
else:
@@ -466,11 +476,10 @@
raise ExternalError(
"Invalid ro.product.property_source_order '{}'".format(source_order))
- for source in source_order:
+ for source_partition in source_order:
source_prop = prop.replace(
- "ro.product", "ro.product.{}".format(source), 1)
- prop_val = self.info_dict.get(
- "{}.build.prop".format(source), {}).get(source_prop)
+ "ro.product", "ro.product.{}".format(source_partition), 1)
+ prop_val = self._GetRawBuildProp(source_prop, source_partition)
if prop_val:
return prop_val
@@ -479,11 +488,9 @@
def _GetRoProductPropsDefaultSourceOrder(self):
# NOTE: refer to CDDs and android.os.Build.VERSION for the definition and
# values of these properties for each Android release.
- android_codename = self.info_dict.get("build.prop", {}).get(
- "ro.build.version.codename")
+ android_codename = self._GetRawBuildProp("ro.build.version.codename", None)
if android_codename == "REL":
- android_version = self.info_dict.get("build.prop", {}).get(
- "ro.build.version.release")
+ android_version = self._GetRawBuildProp("ro.build.version.release", None)
if android_version == "10":
return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_ANDROID_10
# NOTE: float() conversion of android_version will have rounding error.
@@ -566,6 +573,20 @@
script.AssertOemProperty(prop, values, oem_no_mount)
+def ReadFromInputFile(input_file, fn):
+ """Reads the contents of fn from input zipfile or directory."""
+ if isinstance(input_file, zipfile.ZipFile):
+ return input_file.read(fn).decode()
+ else:
+ path = os.path.join(input_file, *fn.split("/"))
+ try:
+ with open(path) as f:
+ return f.read()
+ except IOError as e:
+ if e.errno == errno.ENOENT:
+ raise KeyError(fn)
+
+
def LoadInfoDict(input_file, repacking=False):
"""Loads the key/value pairs from the given input target_files.
@@ -603,16 +624,7 @@
"input_file must be a path str when doing repacking"
def read_helper(fn):
- if isinstance(input_file, zipfile.ZipFile):
- return input_file.read(fn).decode()
- else:
- path = os.path.join(input_file, *fn.split("/"))
- try:
- with open(path) as f:
- return f.read()
- except IOError as e:
- if e.errno == errno.ENOENT:
- raise KeyError(fn)
+ return ReadFromInputFile(input_file, fn)
try:
d = LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("\n"))
@@ -675,13 +687,8 @@
# system and vendor.
for partition in PARTITIONS_WITH_CARE_MAP:
partition_prop = "{}.build.prop".format(partition)
- d[partition_prop] = LoadBuildProp(
- read_helper, "{}/build.prop".format(partition.upper()))
- # Some partition might use /<partition>/etc/build.prop as the new path.
- # TODO: try new path first when majority of them switch to the new path.
- if not d[partition_prop]:
- d[partition_prop] = LoadBuildProp(
- read_helper, "{}/etc/build.prop".format(partition.upper()))
+ d[partition_prop] = PartitionBuildProps.FromInputFile(
+ input_file, partition)
d["build.prop"] = d["system.build.prop"]
# Set up the salt (based on fingerprint) that will be used when adding AVB
@@ -696,15 +703,6 @@
return d
-def LoadBuildProp(read_helper, prop_file):
- try:
- data = read_helper(prop_file)
- except KeyError:
- logger.warning("Failed to read %s", prop_file)
- data = ""
- return LoadDictionaryFromLines(data.split("\n"))
-
-
def LoadListFromFile(file_path):
with open(file_path) as f:
return f.read().splitlines()
@@ -727,6 +725,116 @@
return d
+class PartitionBuildProps(object):
+ """The class holds the build prop of a particular partition.
+
+ This class loads the build.prop and holds the build properties for a given
+ partition. It also partially recognizes the 'import' statement in the
+ build.prop; and calculates alternative values of some specific build
+ properties during runtime.
+
+ Attributes:
+ input_file: a zipped target-file or an unzipped target-file directory.
+ partition: name of the partition.
+ props_allow_override: a list of build properties to search for the
+ alternative values during runtime.
+ build_props: a dict of build properties for the given partition.
+ prop_overrides: a set of props that are overridden by import.
+ placeholder_values: A dict of runtime variables' values to replace the
+ placeholders in the build.prop file. We expect exactly one value for
+ each of the variables.
+ """
+ def __init__(self, input_file, name, placeholder_values=None):
+ self.input_file = input_file
+ self.partition = name
+ self.props_allow_override = [props.format(name) for props in [
+ 'ro.product.{}.brand', 'ro.product.{}.name', 'ro.product.{}.device']]
+ self.build_props = {}
+ self.prop_overrides = set()
+ self.placeholder_values = {}
+ if placeholder_values:
+ self.placeholder_values = copy.deepcopy(placeholder_values)
+
+ @staticmethod
+ def FromDictionary(name, build_props):
+ """Constructs an instance from a build prop dictionary."""
+
+ props = PartitionBuildProps("unknown", name)
+ props.build_props = build_props.copy()
+ return props
+
+ @staticmethod
+ def FromInputFile(input_file, name, placeholder_values=None):
+ """Loads the build.prop file and builds the attributes."""
+ data = ''
+ for prop_file in ['{}/etc/build.prop'.format(name.upper()),
+ '{}/build.prop'.format(name.upper())]:
+ try:
+ data = ReadFromInputFile(input_file, prop_file)
+ break
+ except KeyError:
+ logger.warning('Failed to read %s', prop_file)
+
+ props = PartitionBuildProps(input_file, name, placeholder_values)
+ props._LoadBuildProp(data)
+ return props
+
+ def _LoadBuildProp(self, data):
+ for line in data.split('\n'):
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ if line.startswith("import"):
+ overrides = self._ImportParser(line)
+ duplicates = self.prop_overrides.intersection(overrides.keys())
+ if duplicates:
+ raise ValueError('prop {} is overridden multiple times'.format(
+ ','.join(duplicates)))
+ self.prop_overrides = self.prop_overrides.union(overrides.keys())
+ self.build_props.update(overrides)
+ elif "=" in line:
+ name, value = line.split("=", 1)
+ if name in self.prop_overrides:
+ raise ValueError('prop {} is set again after overridden by import '
+ 'statement'.format(name))
+ self.build_props[name] = value
+
+ def _ImportParser(self, line):
+ """Parses the build prop in a given import statement."""
+
+ tokens = line.split()
+ if len(tokens) != 2 or tokens[0] != 'import':
+ raise ValueError('Unrecognized import statement {}'.format(line))
+ import_path = tokens[1]
+ if not re.match(r'^/{}/.*\.prop$'.format(self.partition), import_path):
+ raise ValueError('Unrecognized import path {}'.format(line))
+
+ # We only recognize a subset of import statement that the init process
+ # supports. And we can loose the restriction based on how the dynamic
+ # fingerprint is used in practice. The placeholder format should be
+ # ${placeholder}, and its value should be provided by the caller through
+ # the placeholder_values.
+ for prop, value in self.placeholder_values.items():
+ prop_place_holder = '${{{}}}'.format(prop)
+ if prop_place_holder in import_path:
+ import_path = import_path.replace(prop_place_holder, value)
+ if '$' in import_path:
+ logger.info('Unresolved place holder in import path %s', import_path)
+ return {}
+
+ import_path = import_path.replace('/{}'.format(self.partition),
+ self.partition.upper())
+ logger.info('Parsing build props override from %s', import_path)
+
+ lines = ReadFromInputFile(self.input_file, import_path).split('\n')
+ d = LoadDictionaryFromLines(lines)
+ return {key: val for key, val in d.items()
+ if key in self.props_allow_override}
+
+ def GetProp(self, prop):
+ return self.build_props.get(prop)
+
+
def LoadRecoveryFSTab(read_helper, fstab_version, recovery_fstab_path,
system_root_image=False):
class Partition(object):
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 92a46a2..ad001d1 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -193,6 +193,8 @@
from __future__ import print_function
import collections
+import copy
+import itertools
import logging
import multiprocessing
import os.path
@@ -229,6 +231,7 @@
OPTIONS.no_signing = False
OPTIONS.block_based = True
OPTIONS.updater_binary = None
+OPTIONS.oem_dicts = None
OPTIONS.oem_source = None
OPTIONS.oem_no_mount = False
OPTIONS.full_radio = False
@@ -247,6 +250,7 @@
OPTIONS.skip_compatibility_check = False
OPTIONS.output_metadata_path = None
OPTIONS.disable_fec_computation = False
+OPTIONS.boot_variable_values = None
METADATA_NAME = 'META-INF/com/android/metadata'
@@ -263,7 +267,8 @@
# 'system_other' and bootloader partitions.
SECONDARY_PAYLOAD_SKIPPED_IMAGES = [
'boot', 'dtbo', 'modem', 'odm', 'product', 'radio', 'recovery',
- 'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor']
+ 'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor',
+ 'vendor_boot']
class PayloadSigner(object):
@@ -1959,6 +1964,36 @@
output_file)
+def CalculateRuntimeFingerprints():
+ """Returns a set of runtime fingerprints based on the boot variables."""
+
+ build_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
+ fingerprints = {build_info.fingerprint}
+
+ if not OPTIONS.boot_variable_values:
+ return fingerprints
+
+ # Calculate all possible combinations of the values for the boot variables.
+ keys = OPTIONS.boot_variable_values.keys()
+ value_list = OPTIONS.boot_variable_values.values()
+ combinations = [dict(zip(keys, values))
+ for values in itertools.product(*value_list)]
+ for placeholder_values in combinations:
+ # Reload the info_dict as some build properties may change their values
+ # based on the value of ro.boot* properties.
+ info_dict = copy.deepcopy(OPTIONS.info_dict)
+ for partition in common.PARTITIONS_WITH_CARE_MAP:
+ partition_prop_key = "{}.build.prop".format(partition)
+ old_props = info_dict[partition_prop_key]
+ info_dict[partition_prop_key] = common.PartitionBuildProps.FromInputFile(
+ old_props.input_file, partition, placeholder_values)
+ info_dict["build.prop"] = info_dict["system.build.prop"]
+
+ build_info = common.BuildInfo(info_dict, OPTIONS.oem_dicts)
+ fingerprints.add(build_info.fingerprint)
+ return fingerprints
+
+
def main(argv):
def option_handler(o, a):
diff --git a/tools/releasetools/test_add_img_to_target_files.py b/tools/releasetools/test_add_img_to_target_files.py
index 3d0766f..c82a40b 100644
--- a/tools/releasetools/test_add_img_to_target_files.py
+++ b/tools/releasetools/test_add_img_to_target_files.py
@@ -128,13 +128,16 @@
'vendor_image_size' : 40960,
'system_verity_block_device': '/dev/block/system',
'vendor_verity_block_device': '/dev/block/vendor',
- 'system.build.prop': {
- 'ro.system.build.fingerprint':
- 'google/sailfish/12345:user/dev-keys',
- },
- 'vendor.build.prop': {
- 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys',
- },
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.system.build.fingerprint':
+ 'google/sailfish/12345:user/dev-keys'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.fingerprint':
+ 'google/sailfish/678:user/dev-keys'}
+ ),
}
# Prepare the META/ folder.
@@ -206,18 +209,21 @@
"""Tests the case for device using AVB."""
image_paths = self._test_AddCareMapForAbOta()
OPTIONS.info_dict = {
- 'extfs_sparse_flag' : '-s',
- 'system_image_size' : 65536,
- 'vendor_image_size' : 40960,
- 'avb_system_hashtree_enable' : 'true',
- 'avb_vendor_hashtree_enable' : 'true',
- 'system.build.prop': {
- 'ro.system.build.fingerprint':
- 'google/sailfish/12345:user/dev-keys',
- },
- 'vendor.build.prop': {
- 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys',
- }
+ 'extfs_sparse_flag': '-s',
+ 'system_image_size': 65536,
+ 'vendor_image_size': 40960,
+ 'avb_system_hashtree_enable': 'true',
+ 'avb_vendor_hashtree_enable': 'true',
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.system.build.fingerprint':
+ 'google/sailfish/12345:user/dev-keys'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.fingerprint':
+ 'google/sailfish/678:user/dev-keys'}
+ ),
}
AddCareMapForAbOta(None, ['system', 'vendor'], image_paths)
@@ -258,17 +264,21 @@
"""Tests the case for partitions with thumbprint."""
image_paths = self._test_AddCareMapForAbOta()
OPTIONS.info_dict = {
- 'extfs_sparse_flag' : '-s',
- 'system_image_size' : 65536,
- 'vendor_image_size' : 40960,
+ 'extfs_sparse_flag': '-s',
+ 'system_image_size': 65536,
+ 'vendor_image_size': 40960,
'system_verity_block_device': '/dev/block/system',
'vendor_verity_block_device': '/dev/block/vendor',
- 'system.build.prop': {
- 'ro.system.build.thumbprint': 'google/sailfish/123:user/dev-keys',
- },
- 'vendor.build.prop' : {
- 'ro.vendor.build.thumbprint': 'google/sailfish/456:user/dev-keys',
- },
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.system.build.thumbprint':
+ 'google/sailfish/123:user/dev-keys'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.thumbprint':
+ 'google/sailfish/456:user/dev-keys'}
+ ),
}
AddCareMapForAbOta(None, ['system', 'vendor'], image_paths)
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 665eb51..787e675 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -48,109 +48,124 @@
class BuildInfoTest(test_utils.ReleaseToolsTestCase):
TEST_INFO_DICT = {
- 'build.prop' : {
- 'ro.product.device' : 'product-device',
- 'ro.product.name' : 'product-name',
- 'ro.build.fingerprint' : 'build-fingerprint',
- 'ro.build.foo' : 'build-foo',
- },
- 'system.build.prop' : {
- 'ro.product.system.brand' : 'product-brand',
- 'ro.product.system.name' : 'product-name',
- 'ro.product.system.device' : 'product-device',
- 'ro.system.build.version.release' : 'version-release',
- 'ro.system.build.id' : 'build-id',
- 'ro.system.build.version.incremental' : 'version-incremental',
- 'ro.system.build.type' : 'build-type',
- 'ro.system.build.tags' : 'build-tags',
- 'ro.system.build.foo' : 'build-foo',
- },
- 'vendor.build.prop' : {
- 'ro.product.vendor.brand' : 'vendor-product-brand',
- 'ro.product.vendor.name' : 'vendor-product-name',
- 'ro.product.vendor.device' : 'vendor-product-device',
- 'ro.vendor.build.version.release' : 'vendor-version-release',
- 'ro.vendor.build.id' : 'vendor-build-id',
- 'ro.vendor.build.version.incremental' : 'vendor-version-incremental',
- 'ro.vendor.build.type' : 'vendor-build-type',
- 'ro.vendor.build.tags' : 'vendor-build-tags',
- },
- 'property1' : 'value1',
- 'property2' : 4096,
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.device': 'product-device',
+ 'ro.product.name': 'product-name',
+ 'ro.build.fingerprint': 'build-fingerprint',
+ 'ro.build.foo': 'build-foo'}
+ ),
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.system.brand': 'product-brand',
+ 'ro.product.system.name': 'product-name',
+ 'ro.product.system.device': 'product-device',
+ 'ro.system.build.version.release': 'version-release',
+ 'ro.system.build.id': 'build-id',
+ 'ro.system.build.version.incremental': 'version-incremental',
+ 'ro.system.build.type': 'build-type',
+ 'ro.system.build.tags': 'build-tags',
+ 'ro.system.build.foo': 'build-foo'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.product.vendor.brand': 'vendor-product-brand',
+ 'ro.product.vendor.name': 'vendor-product-name',
+ 'ro.product.vendor.device': 'vendor-product-device',
+ 'ro.vendor.build.version.release': 'vendor-version-release',
+ 'ro.vendor.build.id': 'vendor-build-id',
+ 'ro.vendor.build.version.incremental':
+ 'vendor-version-incremental',
+ 'ro.vendor.build.type': 'vendor-build-type',
+ 'ro.vendor.build.tags': 'vendor-build-tags'}
+ ),
+ 'property1': 'value1',
+ 'property2': 4096,
}
TEST_INFO_DICT_USES_OEM_PROPS = {
- 'build.prop' : {
- 'ro.product.name' : 'product-name',
- 'ro.build.thumbprint' : 'build-thumbprint',
- 'ro.build.bar' : 'build-bar',
- },
- 'vendor.build.prop' : {
- 'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
- },
- 'property1' : 'value1',
- 'property2' : 4096,
- 'oem_fingerprint_properties' : 'ro.product.device ro.product.brand',
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.name': 'product-name',
+ 'ro.build.thumbprint': 'build-thumbprint',
+ 'ro.build.bar': 'build-bar'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.fingerprint': 'vendor-build-fingerprint'}
+ ),
+ 'property1': 'value1',
+ 'property2': 4096,
+ 'oem_fingerprint_properties': 'ro.product.device ro.product.brand',
}
TEST_OEM_DICTS = [
{
- 'ro.product.brand' : 'brand1',
- 'ro.product.device' : 'device1',
+ 'ro.product.brand': 'brand1',
+ 'ro.product.device': 'device1',
},
{
- 'ro.product.brand' : 'brand2',
- 'ro.product.device' : 'device2',
+ 'ro.product.brand': 'brand2',
+ 'ro.product.device': 'device2',
},
{
- 'ro.product.brand' : 'brand3',
- 'ro.product.device' : 'device3',
+ 'ro.product.brand': 'brand3',
+ 'ro.product.device': 'device3',
},
]
TEST_INFO_DICT_PROPERTY_SOURCE_ORDER = {
- 'build.prop' : {
- 'ro.build.fingerprint' : 'build-fingerprint',
- 'ro.product.property_source_order' :
- 'product,odm,vendor,system_ext,system',
- },
- 'system.build.prop' : {
- 'ro.product.system.device' : 'system-product-device',
- },
- 'vendor.build.prop' : {
- 'ro.product.vendor.device' : 'vendor-product-device',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.build.fingerprint': 'build-fingerprint',
+ 'ro.product.property_source_order':
+ 'product,odm,vendor,system_ext,system'}
+ ),
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.system.device': 'system-product-device'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.product.vendor.device': 'vendor-product-device'}
+ ),
}
TEST_INFO_DICT_PROPERTY_SOURCE_ORDER_ANDROID_10 = {
- 'build.prop' : {
- 'ro.build.fingerprint' : 'build-fingerprint',
- 'ro.product.property_source_order' :
- 'product,product_services,odm,vendor,system',
- 'ro.build.version.release' : '10',
- 'ro.build.version.codename' : 'REL',
- },
- 'system.build.prop' : {
- 'ro.product.system.device' : 'system-product-device',
- },
- 'vendor.build.prop' : {
- 'ro.product.vendor.device' : 'vendor-product-device',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.build.fingerprint': 'build-fingerprint',
+ 'ro.product.property_source_order':
+ 'product,product_services,odm,vendor,system',
+ 'ro.build.version.release': '10',
+ 'ro.build.version.codename': 'REL'}
+ ),
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.system.device': 'system-product-device'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.product.vendor.device': 'vendor-product-device'}
+ ),
}
TEST_INFO_DICT_PROPERTY_SOURCE_ORDER_ANDROID_9 = {
- 'build.prop' : {
- 'ro.product.device' : 'product-device',
- 'ro.build.fingerprint' : 'build-fingerprint',
- 'ro.build.version.release' : '9',
- 'ro.build.version.codename' : 'REL',
- },
- 'system.build.prop' : {
- 'ro.product.system.device' : 'system-product-device',
- },
- 'vendor.build.prop' : {
- 'ro.product.vendor.device' : 'vendor-product-device',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.device': 'product-device',
+ 'ro.build.fingerprint': 'build-fingerprint',
+ 'ro.build.version.release': '9',
+ 'ro.build.version.codename': 'REL'}
+ ),
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.system.device': 'system-product-device'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.product.vendor.device': 'vendor-product-device'}
+ ),
}
def test_init(self):
@@ -178,25 +193,27 @@
def test_init_badFingerprint(self):
info_dict = copy.deepcopy(self.TEST_INFO_DICT)
- info_dict['build.prop']['ro.build.fingerprint'] = 'bad fingerprint'
+ info_dict['build.prop'].build_props[
+ 'ro.build.fingerprint'] = 'bad fingerprint'
self.assertRaises(ValueError, common.BuildInfo, info_dict, None)
- info_dict['build.prop']['ro.build.fingerprint'] = 'bad\x80fingerprint'
+ info_dict['build.prop'].build_props[
+ 'ro.build.fingerprint'] = 'bad\x80fingerprint'
self.assertRaises(ValueError, common.BuildInfo, info_dict, None)
def test___getitem__(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
self.assertEqual('value1', target_info['property1'])
self.assertEqual(4096, target_info['property2'])
- self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
+ self.assertEqual('build-foo',
+ target_info['build.prop'].GetProp('ro.build.foo'))
def test___getitem__with_oem_props(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
self.TEST_OEM_DICTS)
self.assertEqual('value1', target_info['property1'])
self.assertEqual(4096, target_info['property2'])
- self.assertRaises(KeyError,
- lambda: target_info['build.prop']['ro.build.foo'])
+ self.assertIsNone(target_info['build.prop'].GetProp('ro.build.foo'))
def test___setitem__(self):
target_info = common.BuildInfo(copy.deepcopy(self.TEST_INFO_DICT), None)
@@ -204,9 +221,11 @@
target_info['property1'] = 'value2'
self.assertEqual('value2', target_info['property1'])
- self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
- target_info['build.prop']['ro.build.foo'] = 'build-bar'
- self.assertEqual('build-bar', target_info['build.prop']['ro.build.foo'])
+ self.assertEqual('build-foo',
+ target_info['build.prop'].GetProp('ro.build.foo'))
+ target_info['build.prop'].build_props['ro.build.foo'] = 'build-bar'
+ self.assertEqual('build-bar',
+ target_info['build.prop'].GetProp('ro.build.foo'))
def test_get(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
@@ -214,7 +233,8 @@
self.assertEqual(4096, target_info.get('property2'))
self.assertEqual(4096, target_info.get('property2', 1024))
self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
- self.assertEqual('build-foo', target_info.get('build.prop')['ro.build.foo'])
+ self.assertEqual('build-foo',
+ target_info.get('build.prop').GetProp('ro.build.foo'))
def test_get_with_oem_props(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
@@ -223,9 +243,7 @@
self.assertEqual(4096, target_info.get('property2'))
self.assertEqual(4096, target_info.get('property2', 1024))
self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
- self.assertIsNone(target_info.get('build.prop').get('ro.build.foo'))
- self.assertRaises(KeyError,
- lambda: target_info.get('build.prop')['ro.build.foo'])
+ self.assertIsNone(target_info.get('build.prop').GetProp('ro.build.foo'))
def test_items(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
@@ -262,7 +280,8 @@
def test_GetPartitionFingerprint_uses_fingerprint_prop_if_available(self):
info_dict = copy.deepcopy(self.TEST_INFO_DICT)
- info_dict['vendor.build.prop']['ro.vendor.build.fingerprint'] = 'vendor:fingerprint'
+ info_dict['vendor.build.prop'].build_props[
+ 'ro.vendor.build.fingerprint'] = 'vendor:fingerprint'
target_info = common.BuildInfo(info_dict, None)
self.assertEqual(
target_info.GetPartitionFingerprint('vendor'),
@@ -303,14 +322,15 @@
def test_ResolveRoProductProperty_FromSystem(self):
info_dict = copy.deepcopy(self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER)
- del info_dict['vendor.build.prop']['ro.product.vendor.device']
+ del info_dict['vendor.build.prop'].build_props['ro.product.vendor.device']
info = common.BuildInfo(info_dict, None)
self.assertEqual('system-product-device',
info.GetBuildProp('ro.product.device'))
def test_ResolveRoProductProperty_InvalidPropertySearchOrder(self):
info_dict = copy.deepcopy(self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER)
- info_dict['build.prop']['ro.product.property_source_order'] = 'bad-source'
+ info_dict['build.prop'].build_props[
+ 'ro.product.property_source_order'] = 'bad-source'
with self.assertRaisesRegexp(common.ExternalError,
'Invalid ro.product.property_source_order'):
info = common.BuildInfo(info_dict, None)
@@ -1513,12 +1533,14 @@
common.OPTIONS.info_dict = {
'ab_update': 'true',
'avb_avbtool': 'avbtool',
- 'build.prop': {
- 'ro.build.version.incremental': '6285659',
- 'ro.product.device': 'coral',
- 'ro.build.fingerprint': 'google/coral/coral:R/RP1A.200311.002/'
- '6285659:userdebug/dev-keys'
- }
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.build.version.incremental': '6285659',
+ 'ro.product.device': 'coral',
+ 'ro.build.fingerprint':
+ 'google/coral/coral:R/RP1A.200311.002/'
+ '6285659:userdebug/dev-keys'}
+ ),
}
common.OPTIONS.aftl_tool_path = 'aftltool'
common.OPTIONS.aftl_server = 'log.endpoints.aftl-dev.cloud.goog:9000'
@@ -1551,12 +1573,14 @@
common.OPTIONS.info_dict = {
'ab_update': 'true',
'avb_avbtool': 'avbtool',
- 'build.prop': {
- 'ro.build.version.incremental': '6285659',
- 'ro.product.device': 'coral',
- 'ro.build.fingerprint': 'google/coral/coral:R/RP1A.200311.002/'
- '6285659:userdebug/dev-keys'
- }
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.build.version.incremental': '6285659',
+ 'ro.product.device': 'coral',
+ 'ro.build.fingerprint':
+ 'google/coral/coral:R/RP1A.200311.002/'
+ '6285659:userdebug/dev-keys'}
+ )
}
common.OPTIONS.aftl_tool_path = "aftltool"
common.OPTIONS.aftl_server = "log.endpoints.aftl-dev.cloud.goog:9000"
@@ -1871,3 +1895,241 @@
lines = self.get_op_list(self.output_path)
self.assertEqual(lines, ["remove foo"])
+
+
+class PartitionBuildPropsTest(test_utils.ReleaseToolsTestCase):
+ def setUp(self):
+ self.odm_build_prop = [
+ 'ro.odm.build.date.utc=1578430045',
+ 'ro.odm.build.fingerprint='
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device=coral',
+ 'import /odm/etc/build_${ro.boot.product.device_name}.prop',
+ ]
+
+ @staticmethod
+ def _BuildZipFile(entries):
+ input_file = common.MakeTempFile(prefix='target_files-', suffix='.zip')
+ with zipfile.ZipFile(input_file, 'w') as input_zip:
+ for name, content in entries.items():
+ input_zip.writestr(name, content)
+
+ return input_file
+
+ def test_parseBuildProps_noImportStatement(self):
+ build_prop = [
+ 'ro.odm.build.date.utc=1578430045',
+ 'ro.odm.build.fingerprint='
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device=coral',
+ ]
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': ['std', 'pro']
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ }, partition_props.build_props)
+
+ self.assertEqual(set(), partition_props.prop_overrides)
+
+ def test_parseBuildProps_singleImportStatement(self):
+ build_std_prop = [
+ 'ro.product.odm.device=coral',
+ 'ro.product.odm.name=product1',
+ ]
+ build_pro_prop = [
+ 'ro.product.odm.device=coralpro',
+ 'ro.product.odm.name=product2',
+ ]
+
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(self.odm_build_prop),
+ 'ODM/etc/build_std.prop': '\n'.join(build_std_prop),
+ 'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'std'
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ 'ro.product.odm.name': 'product1',
+ }, partition_props.build_props)
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'pro'
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coralpro',
+ 'ro.product.odm.name': 'product2',
+ }, partition_props.build_props)
+
+ def test_parseBuildProps_noPlaceHolders(self):
+ build_prop = copy.copy(self.odm_build_prop)
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm')
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ }, partition_props.build_props)
+
+ self.assertEqual(set(), partition_props.prop_overrides)
+
+ def test_parseBuildProps_multipleImportStatements(self):
+ build_prop = copy.deepcopy(self.odm_build_prop)
+ build_prop.append(
+ 'import /odm/etc/build_${ro.boot.product.product_name}.prop')
+
+ build_std_prop = [
+ 'ro.product.odm.device=coral',
+ ]
+ build_pro_prop = [
+ 'ro.product.odm.device=coralpro',
+ ]
+
+ product1_prop = [
+ 'ro.product.odm.name=product1',
+ 'ro.product.not_care=not_care',
+ ]
+
+ product2_prop = [
+ 'ro.product.odm.name=product2',
+ 'ro.product.not_care=not_care',
+ ]
+
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ 'ODM/etc/build_std.prop': '\n'.join(build_std_prop),
+ 'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
+ 'ODM/etc/build_product1.prop': '\n'.join(product1_prop),
+ 'ODM/etc/build_product2.prop': '\n'.join(product2_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'std',
+ 'ro.boot.product.product_name': 'product1',
+ 'ro.boot.product.not_care': 'not_care',
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ 'ro.product.odm.name': 'product1'
+ }, partition_props.build_props)
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'pro',
+ 'ro.boot.product.product_name': 'product2',
+ 'ro.boot.product.not_care': 'not_care',
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coralpro',
+ 'ro.product.odm.name': 'product2'
+ }, partition_props.build_props)
+
+ def test_parseBuildProps_defineAfterOverride(self):
+ build_prop = copy.deepcopy(self.odm_build_prop)
+ build_prop.append('ro.product.odm.device=coral')
+
+ build_std_prop = [
+ 'ro.product.odm.device=coral',
+ ]
+ build_pro_prop = [
+ 'ro.product.odm.device=coralpro',
+ ]
+
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ 'ODM/etc/build_std.prop': '\n'.join(build_std_prop),
+ 'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'std',
+ }
+
+ self.assertRaises(ValueError, common.PartitionBuildProps.FromInputFile,
+ input_zip, 'odm', placeholder_values)
+
+ def test_parseBuildProps_duplicateOverride(self):
+ build_prop = copy.deepcopy(self.odm_build_prop)
+ build_prop.append(
+ 'import /odm/etc/build_${ro.boot.product.product_name}.prop')
+
+ build_std_prop = [
+ 'ro.product.odm.device=coral',
+ 'ro.product.odm.name=product1',
+ ]
+ build_pro_prop = [
+ 'ro.product.odm.device=coralpro',
+ ]
+
+ product1_prop = [
+ 'ro.product.odm.name=product1',
+ ]
+
+ product2_prop = [
+ 'ro.product.odm.name=product2',
+ ]
+
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ 'ODM/etc/build_std.prop': '\n'.join(build_std_prop),
+ 'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
+ 'ODM/etc/build_product1.prop': '\n'.join(product1_prop),
+ 'ODM/etc/build_product2.prop': '\n'.join(product2_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'std',
+ 'ro.boot.product.product_name': 'product1',
+ }
+ self.assertRaises(ValueError, common.PartitionBuildProps.FromInputFile,
+ input_zip, 'odm', placeholder_values)
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index 38faf64..4077d06 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -26,7 +26,8 @@
GetPackageMetadata, GetTargetFilesZipForSecondaryImages,
GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles,
Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
- StreamingPropertyFiles, WriteFingerprintAssertion)
+ StreamingPropertyFiles, WriteFingerprintAssertion,
+ CalculateRuntimeFingerprints)
def construct_target_files(secondary=False):
@@ -108,55 +109,58 @@
class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
-
TEST_TARGET_INFO_DICT = {
- 'build.prop' : {
- 'ro.product.device' : 'product-device',
- 'ro.build.fingerprint' : 'build-fingerprint-target',
- 'ro.build.version.incremental' : 'build-version-incremental-target',
- 'ro.build.version.sdk' : '27',
- 'ro.build.version.security_patch' : '2017-12-01',
- 'ro.build.date.utc' : '1500000000',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.device': 'product-device',
+ 'ro.build.fingerprint': 'build-fingerprint-target',
+ 'ro.build.version.incremental': 'build-version-incremental-target',
+ 'ro.build.version.sdk': '27',
+ 'ro.build.version.security_patch': '2017-12-01',
+ 'ro.build.date.utc': '1500000000'}
+ )
}
TEST_SOURCE_INFO_DICT = {
- 'build.prop' : {
- 'ro.product.device' : 'product-device',
- 'ro.build.fingerprint' : 'build-fingerprint-source',
- 'ro.build.version.incremental' : 'build-version-incremental-source',
- 'ro.build.version.sdk' : '25',
- 'ro.build.version.security_patch' : '2016-12-01',
- 'ro.build.date.utc' : '1400000000',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.device': 'product-device',
+ 'ro.build.fingerprint': 'build-fingerprint-source',
+ 'ro.build.version.incremental': 'build-version-incremental-source',
+ 'ro.build.version.sdk': '25',
+ 'ro.build.version.security_patch': '2016-12-01',
+ 'ro.build.date.utc': '1400000000'}
+ )
}
TEST_INFO_DICT_USES_OEM_PROPS = {
- 'build.prop' : {
- 'ro.product.name' : 'product-name',
- 'ro.build.thumbprint' : 'build-thumbprint',
- 'ro.build.bar' : 'build-bar',
- },
- 'vendor.build.prop' : {
- 'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
- },
- 'property1' : 'value1',
- 'property2' : 4096,
- 'oem_fingerprint_properties' : 'ro.product.device ro.product.brand',
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.name': 'product-name',
+ 'ro.build.thumbprint': 'build-thumbprint',
+ 'ro.build.bar': 'build-bar'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.fingerprint': 'vendor-build-fingerprint'}
+ ),
+ 'property1': 'value1',
+ 'property2': 4096,
+ 'oem_fingerprint_properties': 'ro.product.device ro.product.brand',
}
TEST_OEM_DICTS = [
{
- 'ro.product.brand' : 'brand1',
- 'ro.product.device' : 'device1',
+ 'ro.product.brand': 'brand1',
+ 'ro.product.device': 'device1',
},
{
- 'ro.product.brand' : 'brand2',
- 'ro.product.device' : 'device2',
+ 'ro.product.brand': 'brand2',
+ 'ro.product.device': 'device2',
},
{
- 'ro.product.brand' : 'brand3',
- 'ro.product.device' : 'device3',
+ 'ro.product.brand': 'brand3',
+ 'ro.product.device': 'device3',
},
]
@@ -288,10 +292,10 @@
@staticmethod
def _test_GetPackageMetadata_swapBuildTimestamps(target_info, source_info):
- (target_info['build.prop']['ro.build.date.utc'],
- source_info['build.prop']['ro.build.date.utc']) = (
- source_info['build.prop']['ro.build.date.utc'],
- target_info['build.prop']['ro.build.date.utc'])
+ (target_info['build.prop'].build_props['ro.build.date.utc'],
+ source_info['build.prop'].build_props['ro.build.date.utc']) = (
+ source_info['build.prop'].build_props['ro.build.date.utc'],
+ target_info['build.prop'].build_props['ro.build.date.utc'])
def test_GetPackageMetadata_unintentionalDowngradeDetected(self):
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
@@ -528,7 +532,7 @@
def test_WriteFingerprintAssertion_without_oem_props(self):
target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
source_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
- source_info_dict['build.prop']['ro.build.fingerprint'] = (
+ source_info_dict['build.prop'].build_props['ro.build.fingerprint'] = (
'source-build-fingerprint')
source_info = common.BuildInfo(source_info_dict, None)
@@ -567,7 +571,7 @@
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
self.TEST_OEM_DICTS)
source_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
- source_info_dict['build.prop']['ro.build.thumbprint'] = (
+ source_info_dict['build.prop'].build_props['ro.build.thumbprint'] = (
'source-build-thumbprint')
source_info = common.BuildInfo(source_info_dict, self.TEST_OEM_DICTS)
@@ -1315,3 +1319,125 @@
Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT):
continue
self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
+
+
+class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
+ MISC_INFO = [
+ 'recovery_api_version=3',
+ 'fstab_version=2',
+ 'recovery_as_boot=true',
+ ]
+
+ BUILD_PROP = [
+ 'ro.build.version.release=version-release',
+ 'ro.build.id=build-id',
+ 'ro.build.version.incremental=version-incremental',
+ 'ro.build.type=build-type',
+ 'ro.build.tags=build-tags',
+ ]
+
+ VENDOR_BUILD_PROP = [
+ 'ro.product.vendor.brand=vendor-product-brand',
+ 'ro.product.vendor.name=vendor-product-name',
+ 'ro.product.vendor.device=vendor-product-device'
+ ]
+
+ def setUp(self):
+ common.OPTIONS.oem_dicts = None
+ self.test_dir = common.MakeTempDir()
+ self.writeFiles({'META/misc_info.txt': '\n'.join(self.MISC_INFO)})
+
+ def writeFiles(self, contents_dict):
+ for path, content in contents_dict.items():
+ abs_path = os.path.join(self.test_dir, path)
+ dir_name = os.path.dirname(abs_path)
+ if not os.path.exists(dir_name):
+ os.makedirs(dir_name)
+ with open(abs_path, 'w') as f:
+ f.write(content)
+
+ @staticmethod
+ def constructFingerprint(prefix):
+ return '{}:version-release/build-id/version-incremental:' \
+ 'build-type/build-tags'.format(prefix)
+
+ def test_CalculatePossibleFingerprints_no_dynamic_fingerprint(self):
+ build_prop = copy.deepcopy(self.BUILD_PROP)
+ build_prop.extend([
+ 'ro.product.brand=product-brand',
+ 'ro.product.name=product-name',
+ 'ro.product.device=product-device',
+ ])
+ self.writeFiles({
+ 'SYSTEM/build.prop': '\n'.join(build_prop),
+ 'VENDOR/build.prop': '\n'.join(self.VENDOR_BUILD_PROP),
+ })
+ common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
+
+ self.assertEqual({
+ self.constructFingerprint('product-brand/product-name/product-device')
+ }, CalculateRuntimeFingerprints())
+
+ def test_CalculatePossibleFingerprints_single_override(self):
+ vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
+ vendor_build_prop.extend([
+ 'import /vendor/etc/build_${ro.boot.sku_name}.prop',
+ ])
+ self.writeFiles({
+ 'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
+ 'VENDOR/build.prop': '\n'.join(vendor_build_prop),
+ 'VENDOR/etc/build_std.prop':
+ 'ro.product.vendor.name=vendor-product-std',
+ 'VENDOR/etc/build_pro.prop':
+ 'ro.product.vendor.name=vendor-product-pro',
+ })
+ common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
+ common.OPTIONS.boot_variable_values = {
+ 'ro.boot.sku_name': ['std', 'pro']
+ }
+
+ self.assertEqual({
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-name/vendor-product-device'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-std/vendor-product-device'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-pro/vendor-product-device'),
+ }, CalculateRuntimeFingerprints())
+
+ def test_CalculatePossibleFingerprints_multiple_overrides(self):
+ vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
+ vendor_build_prop.extend([
+ 'import /vendor/etc/build_${ro.boot.sku_name}.prop',
+ 'import /vendor/etc/build_${ro.boot.device_name}.prop',
+ ])
+ self.writeFiles({
+ 'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
+ 'VENDOR/build.prop': '\n'.join(vendor_build_prop),
+ 'VENDOR/etc/build_std.prop':
+ 'ro.product.vendor.name=vendor-product-std',
+ 'VENDOR/etc/build_product1.prop':
+ 'ro.product.vendor.device=vendor-device-product1',
+ 'VENDOR/etc/build_pro.prop':
+ 'ro.product.vendor.name=vendor-product-pro',
+ 'VENDOR/etc/build_product2.prop':
+ 'ro.product.vendor.device=vendor-device-product2',
+ })
+ common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
+ common.OPTIONS.boot_variable_values = {
+ 'ro.boot.sku_name': ['std', 'pro'],
+ 'ro.boot.device_name': ['product1', 'product2'],
+ }
+
+ self.assertEqual({
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-name/vendor-product-device'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-std/vendor-device-product1'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-pro/vendor-device-product1'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-std/vendor-device-product2'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-pro/vendor-device-product2'),
+ }, CalculateRuntimeFingerprints())