Merge "releasetools: Move BuildInfo into common."
This commit is contained in:
@@ -284,6 +284,225 @@ def CloseInheritedPipes():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BuildInfo(object):
|
||||||
|
"""A class that holds the information for a given build.
|
||||||
|
|
||||||
|
This class wraps up the property querying for a given source or target build.
|
||||||
|
It abstracts away the logic of handling OEM-specific properties, and caches
|
||||||
|
the commonly used properties such as fingerprint.
|
||||||
|
|
||||||
|
There are two types of info dicts: a) build-time info dict, which is generated
|
||||||
|
at build time (i.e. included in a target_files zip); b) OEM info dict that is
|
||||||
|
specified at package generation time (via command line argument
|
||||||
|
'--oem_settings'). If a build doesn't use OEM-specific properties (i.e. not
|
||||||
|
having "oem_fingerprint_properties" in build-time info dict), all the queries
|
||||||
|
would be answered based on build-time info dict only. Otherwise if using
|
||||||
|
OEM-specific properties, some of them will be calculated from two info dicts.
|
||||||
|
|
||||||
|
Users can query properties similarly as using a dict() (e.g. info['fstab']),
|
||||||
|
or to query build properties via GetBuildProp() or GetVendorBuildProp().
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
info_dict: The build-time info dict.
|
||||||
|
is_ab: Whether it's a build that uses A/B OTA.
|
||||||
|
oem_dicts: A list of OEM dicts.
|
||||||
|
oem_props: A list of OEM properties that should be read from OEM dicts; None
|
||||||
|
if the build doesn't use any OEM-specific property.
|
||||||
|
fingerprint: The fingerprint of the build, which would be calculated based
|
||||||
|
on OEM properties if applicable.
|
||||||
|
device: The device name, which could come from OEM dicts if applicable.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_RO_PRODUCT_RESOLVE_PROPS = ["ro.product.brand", "ro.product.device",
|
||||||
|
"ro.product.manufacturer", "ro.product.model",
|
||||||
|
"ro.product.name"]
|
||||||
|
_RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = ["product", "odm", "vendor",
|
||||||
|
"system_ext", "system"]
|
||||||
|
|
||||||
|
def __init__(self, info_dict, oem_dicts):
|
||||||
|
"""Initializes a BuildInfo instance with the given dicts.
|
||||||
|
|
||||||
|
Note that it only wraps up the given dicts, without making copies.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
info_dict: The build-time info dict.
|
||||||
|
oem_dicts: A list of OEM dicts (which is parsed from --oem_settings). Note
|
||||||
|
that it always uses the first dict to calculate the fingerprint or the
|
||||||
|
device name. The rest would be used for asserting OEM properties only
|
||||||
|
(e.g. one package can be installed on one of these devices).
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: On invalid inputs.
|
||||||
|
"""
|
||||||
|
self.info_dict = info_dict
|
||||||
|
self.oem_dicts = oem_dicts
|
||||||
|
|
||||||
|
self._is_ab = info_dict.get("ab_update") == "true"
|
||||||
|
self._oem_props = info_dict.get("oem_fingerprint_properties")
|
||||||
|
|
||||||
|
if self._oem_props:
|
||||||
|
assert oem_dicts, "OEM source required for this build"
|
||||||
|
|
||||||
|
# These two should be computed only after setting self._oem_props.
|
||||||
|
self._device = self.GetOemProperty("ro.product.device")
|
||||||
|
self._fingerprint = self.CalculateFingerprint()
|
||||||
|
|
||||||
|
# Sanity check the build fingerprint.
|
||||||
|
if (' ' in self._fingerprint or
|
||||||
|
any(ord(ch) > 127 for ch in self._fingerprint)):
|
||||||
|
raise ValueError(
|
||||||
|
'Invalid build fingerprint: "{}". See the requirement in Android CDD '
|
||||||
|
'3.2.2. Build Parameters.'.format(self._fingerprint))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_ab(self):
|
||||||
|
return self._is_ab
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device(self):
|
||||||
|
return self._device
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fingerprint(self):
|
||||||
|
return self._fingerprint
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vendor_fingerprint(self):
|
||||||
|
return self._fingerprint_of("vendor")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def product_fingerprint(self):
|
||||||
|
return self._fingerprint_of("product")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def odm_fingerprint(self):
|
||||||
|
return self._fingerprint_of("odm")
|
||||||
|
|
||||||
|
def _fingerprint_of(self, partition):
|
||||||
|
if partition + ".build.prop" not in self.info_dict:
|
||||||
|
return None
|
||||||
|
build_prop = self.info_dict[partition + ".build.prop"]
|
||||||
|
if "ro." + partition + ".build.fingerprint" in build_prop:
|
||||||
|
return build_prop["ro." + partition + ".build.fingerprint"]
|
||||||
|
if "ro." + partition + ".build.thumbprint" in build_prop:
|
||||||
|
return build_prop["ro." + partition + ".build.thumbprint"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def oem_props(self):
|
||||||
|
return self._oem_props
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.info_dict[key]
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
self.info_dict[key] = value
|
||||||
|
|
||||||
|
def get(self, key, default=None):
|
||||||
|
return self.info_dict.get(key, default)
|
||||||
|
|
||||||
|
def items(self):
|
||||||
|
return self.info_dict.items()
|
||||||
|
|
||||||
|
def GetBuildProp(self, prop):
|
||||||
|
"""Returns the inquired build property."""
|
||||||
|
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,))
|
||||||
|
|
||||||
|
def _ResolveRoProductBuildProp(self, prop):
|
||||||
|
"""Resolves the inquired ro.product.* build property"""
|
||||||
|
prop_val = self.info_dict.get("build.prop", {}).get(prop)
|
||||||
|
if prop_val:
|
||||||
|
return prop_val
|
||||||
|
|
||||||
|
source_order_val = self.info_dict.get("build.prop", {}).get(
|
||||||
|
"ro.product.property_source_order")
|
||||||
|
if source_order_val:
|
||||||
|
source_order = source_order_val.split(",")
|
||||||
|
else:
|
||||||
|
source_order = BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
|
||||||
|
|
||||||
|
# Check that all sources in ro.product.property_source_order are valid
|
||||||
|
if any([x not in BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
|
||||||
|
for x in source_order]):
|
||||||
|
raise ExternalError(
|
||||||
|
"Invalid ro.product.property_source_order '{}'".format(source_order))
|
||||||
|
|
||||||
|
for source 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)
|
||||||
|
if prop_val:
|
||||||
|
return prop_val
|
||||||
|
|
||||||
|
raise ExternalError("couldn't resolve {}".format(prop))
|
||||||
|
|
||||||
|
def GetVendorBuildProp(self, prop):
|
||||||
|
"""Returns the inquired vendor build property."""
|
||||||
|
try:
|
||||||
|
return self.info_dict.get("vendor.build.prop", {})[prop]
|
||||||
|
except KeyError:
|
||||||
|
raise ExternalError(
|
||||||
|
"couldn't find %s in vendor.build.prop" % (prop,))
|
||||||
|
|
||||||
|
def GetOemProperty(self, key):
|
||||||
|
if self.oem_props is not None and key in self.oem_props:
|
||||||
|
return self.oem_dicts[0][key]
|
||||||
|
return self.GetBuildProp(key)
|
||||||
|
|
||||||
|
def CalculateFingerprint(self):
|
||||||
|
if self.oem_props is None:
|
||||||
|
try:
|
||||||
|
return self.GetBuildProp("ro.build.fingerprint")
|
||||||
|
except ExternalError:
|
||||||
|
return "{}/{}/{}:{}/{}/{}:{}/{}".format(
|
||||||
|
self.GetBuildProp("ro.product.brand"),
|
||||||
|
self.GetBuildProp("ro.product.name"),
|
||||||
|
self.GetBuildProp("ro.product.device"),
|
||||||
|
self.GetBuildProp("ro.build.version.release"),
|
||||||
|
self.GetBuildProp("ro.build.id"),
|
||||||
|
self.GetBuildProp("ro.build.version.incremental"),
|
||||||
|
self.GetBuildProp("ro.build.type"),
|
||||||
|
self.GetBuildProp("ro.build.tags"))
|
||||||
|
return "%s/%s/%s:%s" % (
|
||||||
|
self.GetOemProperty("ro.product.brand"),
|
||||||
|
self.GetOemProperty("ro.product.name"),
|
||||||
|
self.GetOemProperty("ro.product.device"),
|
||||||
|
self.GetBuildProp("ro.build.thumbprint"))
|
||||||
|
|
||||||
|
def WriteMountOemScript(self, script):
|
||||||
|
assert self.oem_props is not None
|
||||||
|
recovery_mount_options = self.info_dict.get("recovery_mount_options")
|
||||||
|
script.Mount("/oem", recovery_mount_options)
|
||||||
|
|
||||||
|
def WriteDeviceAssertions(self, script, oem_no_mount):
|
||||||
|
# Read the property directly if not using OEM properties.
|
||||||
|
if not self.oem_props:
|
||||||
|
script.AssertDevice(self.device)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Otherwise assert OEM properties.
|
||||||
|
if not self.oem_dicts:
|
||||||
|
raise ExternalError(
|
||||||
|
"No OEM file provided to answer expected assertions")
|
||||||
|
|
||||||
|
for prop in self.oem_props.split():
|
||||||
|
values = []
|
||||||
|
for oem_dict in self.oem_dicts:
|
||||||
|
if prop in oem_dict:
|
||||||
|
values.append(oem_dict[prop])
|
||||||
|
if not values:
|
||||||
|
raise ExternalError(
|
||||||
|
"The OEM file is missing the property %s" % (prop,))
|
||||||
|
script.AssertOemProperty(prop, values, oem_no_mount)
|
||||||
|
|
||||||
|
|
||||||
def LoadInfoDict(input_file, repacking=False):
|
def LoadInfoDict(input_file, repacking=False):
|
||||||
"""Loads the key/value pairs from the given input target_files.
|
"""Loads the key/value pairs from the given input target_files.
|
||||||
|
|
||||||
|
@@ -258,225 +258,6 @@ SECONDARY_PAYLOAD_SKIPPED_IMAGES = [
|
|||||||
'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor']
|
'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor']
|
||||||
|
|
||||||
|
|
||||||
class BuildInfo(object):
|
|
||||||
"""A class that holds the information for a given build.
|
|
||||||
|
|
||||||
This class wraps up the property querying for a given source or target build.
|
|
||||||
It abstracts away the logic of handling OEM-specific properties, and caches
|
|
||||||
the commonly used properties such as fingerprint.
|
|
||||||
|
|
||||||
There are two types of info dicts: a) build-time info dict, which is generated
|
|
||||||
at build time (i.e. included in a target_files zip); b) OEM info dict that is
|
|
||||||
specified at package generation time (via command line argument
|
|
||||||
'--oem_settings'). If a build doesn't use OEM-specific properties (i.e. not
|
|
||||||
having "oem_fingerprint_properties" in build-time info dict), all the queries
|
|
||||||
would be answered based on build-time info dict only. Otherwise if using
|
|
||||||
OEM-specific properties, some of them will be calculated from two info dicts.
|
|
||||||
|
|
||||||
Users can query properties similarly as using a dict() (e.g. info['fstab']),
|
|
||||||
or to query build properties via GetBuildProp() or GetVendorBuildProp().
|
|
||||||
|
|
||||||
Attributes:
|
|
||||||
info_dict: The build-time info dict.
|
|
||||||
is_ab: Whether it's a build that uses A/B OTA.
|
|
||||||
oem_dicts: A list of OEM dicts.
|
|
||||||
oem_props: A list of OEM properties that should be read from OEM dicts; None
|
|
||||||
if the build doesn't use any OEM-specific property.
|
|
||||||
fingerprint: The fingerprint of the build, which would be calculated based
|
|
||||||
on OEM properties if applicable.
|
|
||||||
device: The device name, which could come from OEM dicts if applicable.
|
|
||||||
"""
|
|
||||||
|
|
||||||
_RO_PRODUCT_RESOLVE_PROPS = ["ro.product.brand", "ro.product.device",
|
|
||||||
"ro.product.manufacturer", "ro.product.model",
|
|
||||||
"ro.product.name"]
|
|
||||||
_RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = ["product", "odm", "vendor",
|
|
||||||
"system_ext", "system"]
|
|
||||||
|
|
||||||
def __init__(self, info_dict, oem_dicts):
|
|
||||||
"""Initializes a BuildInfo instance with the given dicts.
|
|
||||||
|
|
||||||
Note that it only wraps up the given dicts, without making copies.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
info_dict: The build-time info dict.
|
|
||||||
oem_dicts: A list of OEM dicts (which is parsed from --oem_settings). Note
|
|
||||||
that it always uses the first dict to calculate the fingerprint or the
|
|
||||||
device name. The rest would be used for asserting OEM properties only
|
|
||||||
(e.g. one package can be installed on one of these devices).
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: On invalid inputs.
|
|
||||||
"""
|
|
||||||
self.info_dict = info_dict
|
|
||||||
self.oem_dicts = oem_dicts
|
|
||||||
|
|
||||||
self._is_ab = info_dict.get("ab_update") == "true"
|
|
||||||
self._oem_props = info_dict.get("oem_fingerprint_properties")
|
|
||||||
|
|
||||||
if self._oem_props:
|
|
||||||
assert oem_dicts, "OEM source required for this build"
|
|
||||||
|
|
||||||
# These two should be computed only after setting self._oem_props.
|
|
||||||
self._device = self.GetOemProperty("ro.product.device")
|
|
||||||
self._fingerprint = self.CalculateFingerprint()
|
|
||||||
|
|
||||||
# Sanity check the build fingerprint.
|
|
||||||
if (' ' in self._fingerprint or
|
|
||||||
any(ord(ch) > 127 for ch in self._fingerprint)):
|
|
||||||
raise ValueError(
|
|
||||||
'Invalid build fingerprint: "{}". See the requirement in Android CDD '
|
|
||||||
'3.2.2. Build Parameters.'.format(self._fingerprint))
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_ab(self):
|
|
||||||
return self._is_ab
|
|
||||||
|
|
||||||
@property
|
|
||||||
def device(self):
|
|
||||||
return self._device
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fingerprint(self):
|
|
||||||
return self._fingerprint
|
|
||||||
|
|
||||||
@property
|
|
||||||
def vendor_fingerprint(self):
|
|
||||||
return self._fingerprint_of("vendor")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def product_fingerprint(self):
|
|
||||||
return self._fingerprint_of("product")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def odm_fingerprint(self):
|
|
||||||
return self._fingerprint_of("odm")
|
|
||||||
|
|
||||||
def _fingerprint_of(self, partition):
|
|
||||||
if partition + ".build.prop" not in self.info_dict:
|
|
||||||
return None
|
|
||||||
build_prop = self.info_dict[partition + ".build.prop"]
|
|
||||||
if "ro." + partition + ".build.fingerprint" in build_prop:
|
|
||||||
return build_prop["ro." + partition + ".build.fingerprint"]
|
|
||||||
if "ro." + partition + ".build.thumbprint" in build_prop:
|
|
||||||
return build_prop["ro." + partition + ".build.thumbprint"]
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def oem_props(self):
|
|
||||||
return self._oem_props
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
return self.info_dict[key]
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
self.info_dict[key] = value
|
|
||||||
|
|
||||||
def get(self, key, default=None):
|
|
||||||
return self.info_dict.get(key, default)
|
|
||||||
|
|
||||||
def items(self):
|
|
||||||
return self.info_dict.items()
|
|
||||||
|
|
||||||
def GetBuildProp(self, prop):
|
|
||||||
"""Returns the inquired build property."""
|
|
||||||
if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS:
|
|
||||||
return self._ResolveRoProductBuildProp(prop)
|
|
||||||
|
|
||||||
try:
|
|
||||||
return self.info_dict.get("build.prop", {})[prop]
|
|
||||||
except KeyError:
|
|
||||||
raise common.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)
|
|
||||||
if prop_val:
|
|
||||||
return prop_val
|
|
||||||
|
|
||||||
source_order_val = self.info_dict.get("build.prop", {}).get(
|
|
||||||
"ro.product.property_source_order")
|
|
||||||
if source_order_val:
|
|
||||||
source_order = source_order_val.split(",")
|
|
||||||
else:
|
|
||||||
source_order = BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
|
|
||||||
|
|
||||||
# Check that all sources in ro.product.property_source_order are valid
|
|
||||||
if any([x not in BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
|
|
||||||
for x in source_order]):
|
|
||||||
raise common.ExternalError(
|
|
||||||
"Invalid ro.product.property_source_order '{}'".format(source_order))
|
|
||||||
|
|
||||||
for source 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)
|
|
||||||
if prop_val:
|
|
||||||
return prop_val
|
|
||||||
|
|
||||||
raise common.ExternalError("couldn't resolve {}".format(prop))
|
|
||||||
|
|
||||||
def GetVendorBuildProp(self, prop):
|
|
||||||
"""Returns the inquired vendor build property."""
|
|
||||||
try:
|
|
||||||
return self.info_dict.get("vendor.build.prop", {})[prop]
|
|
||||||
except KeyError:
|
|
||||||
raise common.ExternalError(
|
|
||||||
"couldn't find %s in vendor.build.prop" % (prop,))
|
|
||||||
|
|
||||||
def GetOemProperty(self, key):
|
|
||||||
if self.oem_props is not None and key in self.oem_props:
|
|
||||||
return self.oem_dicts[0][key]
|
|
||||||
return self.GetBuildProp(key)
|
|
||||||
|
|
||||||
def CalculateFingerprint(self):
|
|
||||||
if self.oem_props is None:
|
|
||||||
try:
|
|
||||||
return self.GetBuildProp("ro.build.fingerprint")
|
|
||||||
except common.ExternalError:
|
|
||||||
return "{}/{}/{}:{}/{}/{}:{}/{}".format(
|
|
||||||
self.GetBuildProp("ro.product.brand"),
|
|
||||||
self.GetBuildProp("ro.product.name"),
|
|
||||||
self.GetBuildProp("ro.product.device"),
|
|
||||||
self.GetBuildProp("ro.build.version.release"),
|
|
||||||
self.GetBuildProp("ro.build.id"),
|
|
||||||
self.GetBuildProp("ro.build.version.incremental"),
|
|
||||||
self.GetBuildProp("ro.build.type"),
|
|
||||||
self.GetBuildProp("ro.build.tags"))
|
|
||||||
return "%s/%s/%s:%s" % (
|
|
||||||
self.GetOemProperty("ro.product.brand"),
|
|
||||||
self.GetOemProperty("ro.product.name"),
|
|
||||||
self.GetOemProperty("ro.product.device"),
|
|
||||||
self.GetBuildProp("ro.build.thumbprint"))
|
|
||||||
|
|
||||||
def WriteMountOemScript(self, script):
|
|
||||||
assert self.oem_props is not None
|
|
||||||
recovery_mount_options = self.info_dict.get("recovery_mount_options")
|
|
||||||
script.Mount("/oem", recovery_mount_options)
|
|
||||||
|
|
||||||
def WriteDeviceAssertions(self, script, oem_no_mount):
|
|
||||||
# Read the property directly if not using OEM properties.
|
|
||||||
if not self.oem_props:
|
|
||||||
script.AssertDevice(self.device)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Otherwise assert OEM properties.
|
|
||||||
if not self.oem_dicts:
|
|
||||||
raise common.ExternalError(
|
|
||||||
"No OEM file provided to answer expected assertions")
|
|
||||||
|
|
||||||
for prop in self.oem_props.split():
|
|
||||||
values = []
|
|
||||||
for oem_dict in self.oem_dicts:
|
|
||||||
if prop in oem_dict:
|
|
||||||
values.append(oem_dict[prop])
|
|
||||||
if not values:
|
|
||||||
raise common.ExternalError(
|
|
||||||
"The OEM file is missing the property %s" % (prop,))
|
|
||||||
script.AssertOemProperty(prop, values, oem_no_mount)
|
|
||||||
|
|
||||||
|
|
||||||
class PayloadSigner(object):
|
class PayloadSigner(object):
|
||||||
"""A class that wraps the payload signing works.
|
"""A class that wraps the payload signing works.
|
||||||
|
|
||||||
@@ -904,7 +685,7 @@ def GetBlockDifferences(target_zip, source_zip, target_info, source_info,
|
|||||||
|
|
||||||
|
|
||||||
def WriteFullOTAPackage(input_zip, output_file):
|
def WriteFullOTAPackage(input_zip, output_file):
|
||||||
target_info = BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
|
target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
|
||||||
|
|
||||||
# We don't know what version it will be installed on top of. We expect the API
|
# We don't know what version it will be installed on top of. We expect the API
|
||||||
# just won't change very often. Similarly for fstab, it might have changed in
|
# just won't change very often. Similarly for fstab, it might have changed in
|
||||||
@@ -1130,8 +911,8 @@ def GetPackageMetadata(target_info, source_info=None):
|
|||||||
Returns:
|
Returns:
|
||||||
A dict to be written into package metadata entry.
|
A dict to be written into package metadata entry.
|
||||||
"""
|
"""
|
||||||
assert isinstance(target_info, BuildInfo)
|
assert isinstance(target_info, common.BuildInfo)
|
||||||
assert source_info is None or isinstance(source_info, BuildInfo)
|
assert source_info is None or isinstance(source_info, common.BuildInfo)
|
||||||
|
|
||||||
metadata = {
|
metadata = {
|
||||||
'post-build' : target_info.fingerprint,
|
'post-build' : target_info.fingerprint,
|
||||||
@@ -1544,8 +1325,8 @@ def FinalizeMetadata(metadata, input_file, output_file, needed_property_files):
|
|||||||
|
|
||||||
|
|
||||||
def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file):
|
def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file):
|
||||||
target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
|
target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
|
||||||
source_info = BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
|
source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
|
||||||
|
|
||||||
target_api_version = target_info["recovery_api_version"]
|
target_api_version = target_info["recovery_api_version"]
|
||||||
source_api_version = source_info["recovery_api_version"]
|
source_api_version = source_info["recovery_api_version"]
|
||||||
@@ -2024,10 +1805,10 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
|
|||||||
compression=zipfile.ZIP_DEFLATED)
|
compression=zipfile.ZIP_DEFLATED)
|
||||||
|
|
||||||
if source_file is not None:
|
if source_file is not None:
|
||||||
target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
|
target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
|
||||||
source_info = BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
|
source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
|
||||||
else:
|
else:
|
||||||
target_info = BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
|
target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
|
||||||
source_info = None
|
source_info = None
|
||||||
|
|
||||||
# Metadata to comply with Android OTA package format.
|
# Metadata to comply with Android OTA package format.
|
||||||
|
@@ -44,6 +44,210 @@ def get_2gb_string():
|
|||||||
yield b'\0' * (step_size - block_size)
|
yield b'\0' * (step_size - block_size)
|
||||||
|
|
||||||
|
|
||||||
|
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',
|
||||||
|
},
|
||||||
|
'vendor.build.prop' : {
|
||||||
|
'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
|
||||||
|
},
|
||||||
|
'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',
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_OEM_DICTS = [
|
||||||
|
{
|
||||||
|
'ro.product.brand' : 'brand1',
|
||||||
|
'ro.product.device' : 'device1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'ro.product.brand' : 'brand2',
|
||||||
|
'ro.product.device' : 'device2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'ro.product.brand' : 'brand3',
|
||||||
|
'ro.product.device' : 'device3',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
||||||
|
self.assertEqual('product-device', target_info.device)
|
||||||
|
self.assertEqual('build-fingerprint', target_info.fingerprint)
|
||||||
|
self.assertFalse(target_info.is_ab)
|
||||||
|
self.assertIsNone(target_info.oem_props)
|
||||||
|
|
||||||
|
def test_init_with_oem_props(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
self.TEST_OEM_DICTS)
|
||||||
|
self.assertEqual('device1', target_info.device)
|
||||||
|
self.assertEqual('brand1/product-name/device1:build-thumbprint',
|
||||||
|
target_info.fingerprint)
|
||||||
|
|
||||||
|
# Swap the order in oem_dicts, which would lead to different BuildInfo.
|
||||||
|
oem_dicts = copy.copy(self.TEST_OEM_DICTS)
|
||||||
|
oem_dicts[0], oem_dicts[2] = oem_dicts[2], oem_dicts[0]
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
oem_dicts)
|
||||||
|
self.assertEqual('device3', target_info.device)
|
||||||
|
self.assertEqual('brand3/product-name/device3:build-thumbprint',
|
||||||
|
target_info.fingerprint)
|
||||||
|
|
||||||
|
# Missing oem_dict should be rejected.
|
||||||
|
self.assertRaises(AssertionError, common.BuildInfo,
|
||||||
|
self.TEST_INFO_DICT_USES_OEM_PROPS, None)
|
||||||
|
|
||||||
|
def test_init_badFingerprint(self):
|
||||||
|
info_dict = copy.deepcopy(self.TEST_INFO_DICT)
|
||||||
|
info_dict['build.prop']['ro.build.fingerprint'] = 'bad fingerprint'
|
||||||
|
self.assertRaises(ValueError, common.BuildInfo, info_dict, None)
|
||||||
|
|
||||||
|
info_dict['build.prop']['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'])
|
||||||
|
|
||||||
|
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'])
|
||||||
|
|
||||||
|
def test___setitem__(self):
|
||||||
|
target_info = common.BuildInfo(copy.deepcopy(self.TEST_INFO_DICT), None)
|
||||||
|
self.assertEqual('value1', target_info['property1'])
|
||||||
|
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'])
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
||||||
|
self.assertEqual('value1', target_info.get('property1'))
|
||||||
|
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'])
|
||||||
|
|
||||||
|
def test_get_with_oem_props(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
self.TEST_OEM_DICTS)
|
||||||
|
self.assertEqual('value1', target_info.get('property1'))
|
||||||
|
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'])
|
||||||
|
|
||||||
|
def test_items(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
||||||
|
items = target_info.items()
|
||||||
|
self.assertIn(('property1', 'value1'), items)
|
||||||
|
self.assertIn(('property2', 4096), items)
|
||||||
|
|
||||||
|
def test_GetBuildProp(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
||||||
|
self.assertEqual('build-foo', target_info.GetBuildProp('ro.build.foo'))
|
||||||
|
self.assertRaises(common.ExternalError, target_info.GetBuildProp,
|
||||||
|
'ro.build.nonexistent')
|
||||||
|
|
||||||
|
def test_GetBuildProp_with_oem_props(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
self.TEST_OEM_DICTS)
|
||||||
|
self.assertEqual('build-bar', target_info.GetBuildProp('ro.build.bar'))
|
||||||
|
self.assertRaises(common.ExternalError, target_info.GetBuildProp,
|
||||||
|
'ro.build.nonexistent')
|
||||||
|
|
||||||
|
def test_GetVendorBuildProp(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
||||||
|
self.assertEqual('vendor-build-fingerprint',
|
||||||
|
target_info.GetVendorBuildProp(
|
||||||
|
'ro.vendor.build.fingerprint'))
|
||||||
|
self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
|
||||||
|
'ro.build.nonexistent')
|
||||||
|
|
||||||
|
def test_GetVendorBuildProp_with_oem_props(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
self.TEST_OEM_DICTS)
|
||||||
|
self.assertEqual('vendor-build-fingerprint',
|
||||||
|
target_info.GetVendorBuildProp(
|
||||||
|
'ro.vendor.build.fingerprint'))
|
||||||
|
self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
|
||||||
|
'ro.build.nonexistent')
|
||||||
|
|
||||||
|
def test_vendor_fingerprint(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
||||||
|
self.assertEqual('vendor-build-fingerprint',
|
||||||
|
target_info.vendor_fingerprint)
|
||||||
|
|
||||||
|
def test_vendor_fingerprint_blacklisted(self):
|
||||||
|
target_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
|
||||||
|
del target_info_dict['vendor.build.prop']['ro.vendor.build.fingerprint']
|
||||||
|
target_info = common.BuildInfo(target_info_dict, self.TEST_OEM_DICTS)
|
||||||
|
self.assertIsNone(target_info.vendor_fingerprint)
|
||||||
|
|
||||||
|
def test_vendor_fingerprint_without_vendor_build_prop(self):
|
||||||
|
target_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
|
||||||
|
del target_info_dict['vendor.build.prop']
|
||||||
|
target_info = common.BuildInfo(target_info_dict, self.TEST_OEM_DICTS)
|
||||||
|
self.assertIsNone(target_info.vendor_fingerprint)
|
||||||
|
|
||||||
|
def test_WriteMountOemScript(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
self.TEST_OEM_DICTS)
|
||||||
|
script_writer = test_utils.MockScriptWriter()
|
||||||
|
target_info.WriteMountOemScript(script_writer)
|
||||||
|
self.assertEqual([('Mount', '/oem', None)], script_writer.lines)
|
||||||
|
|
||||||
|
def test_WriteDeviceAssertions(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
||||||
|
script_writer = test_utils.MockScriptWriter()
|
||||||
|
target_info.WriteDeviceAssertions(script_writer, False)
|
||||||
|
self.assertEqual([('AssertDevice', 'product-device')], script_writer.lines)
|
||||||
|
|
||||||
|
def test_WriteDeviceAssertions_with_oem_props(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
self.TEST_OEM_DICTS)
|
||||||
|
script_writer = test_utils.MockScriptWriter()
|
||||||
|
target_info.WriteDeviceAssertions(script_writer, False)
|
||||||
|
self.assertEqual(
|
||||||
|
[
|
||||||
|
('AssertOemProperty', 'ro.product.device',
|
||||||
|
['device1', 'device2', 'device3'], False),
|
||||||
|
('AssertOemProperty', 'ro.product.brand',
|
||||||
|
['brand1', 'brand2', 'brand3'], False),
|
||||||
|
],
|
||||||
|
script_writer.lines)
|
||||||
|
|
||||||
|
|
||||||
class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
||||||
|
|
||||||
def _verify(self, zip_file, zip_file_name, arcname, expected_hash,
|
def _verify(self, zip_file, zip_file_name, arcname, expected_hash,
|
||||||
|
@@ -22,7 +22,7 @@ import zipfile
|
|||||||
import common
|
import common
|
||||||
import test_utils
|
import test_utils
|
||||||
from ota_from_target_files import (
|
from ota_from_target_files import (
|
||||||
_LoadOemDicts, AbOtaPropertyFiles, BuildInfo, FinalizeMetadata,
|
_LoadOemDicts, AbOtaPropertyFiles, FinalizeMetadata,
|
||||||
GetPackageMetadata, GetTargetFilesZipForSecondaryImages,
|
GetPackageMetadata, GetTargetFilesZipForSecondaryImages,
|
||||||
GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles,
|
GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles,
|
||||||
Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
|
Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
|
||||||
@@ -74,262 +74,6 @@ def construct_target_files(secondary=False):
|
|||||||
return target_files
|
return target_files
|
||||||
|
|
||||||
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
'vendor.build.prop' : {
|
|
||||||
'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
|
|
||||||
},
|
|
||||||
'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',
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_OEM_DICTS = [
|
|
||||||
{
|
|
||||||
'ro.product.brand' : 'brand1',
|
|
||||||
'ro.product.device' : 'device1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'ro.product.brand' : 'brand2',
|
|
||||||
'ro.product.device' : 'device2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'ro.product.brand' : 'brand3',
|
|
||||||
'ro.product.device' : 'device3',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
def test_init(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
self.assertEqual('product-device', target_info.device)
|
|
||||||
self.assertEqual('build-fingerprint', target_info.fingerprint)
|
|
||||||
self.assertFalse(target_info.is_ab)
|
|
||||||
self.assertIsNone(target_info.oem_props)
|
|
||||||
|
|
||||||
def test_init_with_oem_props(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
|
||||||
self.TEST_OEM_DICTS)
|
|
||||||
self.assertEqual('device1', target_info.device)
|
|
||||||
self.assertEqual('brand1/product-name/device1:build-thumbprint',
|
|
||||||
target_info.fingerprint)
|
|
||||||
|
|
||||||
# Swap the order in oem_dicts, which would lead to different BuildInfo.
|
|
||||||
oem_dicts = copy.copy(self.TEST_OEM_DICTS)
|
|
||||||
oem_dicts[0], oem_dicts[2] = oem_dicts[2], oem_dicts[0]
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, oem_dicts)
|
|
||||||
self.assertEqual('device3', target_info.device)
|
|
||||||
self.assertEqual('brand3/product-name/device3:build-thumbprint',
|
|
||||||
target_info.fingerprint)
|
|
||||||
|
|
||||||
# Missing oem_dict should be rejected.
|
|
||||||
self.assertRaises(AssertionError, BuildInfo,
|
|
||||||
self.TEST_INFO_DICT_USES_OEM_PROPS, None)
|
|
||||||
|
|
||||||
def test_init_badFingerprint(self):
|
|
||||||
info_dict = copy.deepcopy(self.TEST_INFO_DICT)
|
|
||||||
info_dict['build.prop']['ro.build.fingerprint'] = 'bad fingerprint'
|
|
||||||
self.assertRaises(ValueError, BuildInfo, info_dict, None)
|
|
||||||
|
|
||||||
info_dict['build.prop']['ro.build.fingerprint'] = 'bad\x80fingerprint'
|
|
||||||
self.assertRaises(ValueError, BuildInfo, info_dict, None)
|
|
||||||
|
|
||||||
def test___getitem__(self):
|
|
||||||
target_info = 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'])
|
|
||||||
|
|
||||||
def test___getitem__with_oem_props(self):
|
|
||||||
target_info = 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'])
|
|
||||||
|
|
||||||
def test___setitem__(self):
|
|
||||||
target_info = BuildInfo(copy.deepcopy(self.TEST_INFO_DICT), None)
|
|
||||||
self.assertEqual('value1', target_info['property1'])
|
|
||||||
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'])
|
|
||||||
|
|
||||||
def test_get(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
self.assertEqual('value1', target_info.get('property1'))
|
|
||||||
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'])
|
|
||||||
|
|
||||||
def test_get_with_oem_props(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
|
||||||
self.TEST_OEM_DICTS)
|
|
||||||
self.assertEqual('value1', target_info.get('property1'))
|
|
||||||
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'])
|
|
||||||
|
|
||||||
def test_items(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
items = target_info.items()
|
|
||||||
self.assertIn(('property1', 'value1'), items)
|
|
||||||
self.assertIn(('property2', 4096), items)
|
|
||||||
|
|
||||||
def test_GetBuildProp(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
self.assertEqual('build-foo', target_info.GetBuildProp('ro.build.foo'))
|
|
||||||
self.assertRaises(common.ExternalError, target_info.GetBuildProp,
|
|
||||||
'ro.build.nonexistent')
|
|
||||||
|
|
||||||
def test_GetBuildProp_with_oem_props(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
|
||||||
self.TEST_OEM_DICTS)
|
|
||||||
self.assertEqual('build-bar', target_info.GetBuildProp('ro.build.bar'))
|
|
||||||
self.assertRaises(common.ExternalError, target_info.GetBuildProp,
|
|
||||||
'ro.build.nonexistent')
|
|
||||||
|
|
||||||
def test_GetVendorBuildProp(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
self.assertEqual('vendor-build-fingerprint',
|
|
||||||
target_info.GetVendorBuildProp(
|
|
||||||
'ro.vendor.build.fingerprint'))
|
|
||||||
self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
|
|
||||||
'ro.build.nonexistent')
|
|
||||||
|
|
||||||
def test_GetVendorBuildProp_with_oem_props(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
|
||||||
self.TEST_OEM_DICTS)
|
|
||||||
self.assertEqual('vendor-build-fingerprint',
|
|
||||||
target_info.GetVendorBuildProp(
|
|
||||||
'ro.vendor.build.fingerprint'))
|
|
||||||
self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
|
|
||||||
'ro.build.nonexistent')
|
|
||||||
|
|
||||||
def test_vendor_fingerprint(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
self.assertEqual('vendor-build-fingerprint',
|
|
||||||
target_info.vendor_fingerprint)
|
|
||||||
|
|
||||||
def test_vendor_fingerprint_blacklisted(self):
|
|
||||||
target_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
|
|
||||||
del target_info_dict['vendor.build.prop']['ro.vendor.build.fingerprint']
|
|
||||||
target_info = BuildInfo(target_info_dict, self.TEST_OEM_DICTS)
|
|
||||||
self.assertIsNone(target_info.vendor_fingerprint)
|
|
||||||
|
|
||||||
def test_vendor_fingerprint_without_vendor_build_prop(self):
|
|
||||||
target_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
|
|
||||||
del target_info_dict['vendor.build.prop']
|
|
||||||
target_info = BuildInfo(target_info_dict, self.TEST_OEM_DICTS)
|
|
||||||
self.assertIsNone(target_info.vendor_fingerprint)
|
|
||||||
|
|
||||||
def test_WriteMountOemScript(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
|
||||||
self.TEST_OEM_DICTS)
|
|
||||||
script_writer = test_utils.MockScriptWriter()
|
|
||||||
target_info.WriteMountOemScript(script_writer)
|
|
||||||
self.assertEqual([('Mount', '/oem', None)], script_writer.lines)
|
|
||||||
|
|
||||||
def test_WriteDeviceAssertions(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
script_writer = test_utils.MockScriptWriter()
|
|
||||||
target_info.WriteDeviceAssertions(script_writer, False)
|
|
||||||
self.assertEqual([('AssertDevice', 'product-device')], script_writer.lines)
|
|
||||||
|
|
||||||
def test_WriteDeviceAssertions_with_oem_props(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
|
||||||
self.TEST_OEM_DICTS)
|
|
||||||
script_writer = test_utils.MockScriptWriter()
|
|
||||||
target_info.WriteDeviceAssertions(script_writer, False)
|
|
||||||
self.assertEqual(
|
|
||||||
[
|
|
||||||
('AssertOemProperty', 'ro.product.device',
|
|
||||||
['device1', 'device2', 'device3'], False),
|
|
||||||
('AssertOemProperty', 'ro.product.brand',
|
|
||||||
['brand1', 'brand2', 'brand3'], False),
|
|
||||||
],
|
|
||||||
script_writer.lines)
|
|
||||||
|
|
||||||
def test_WriteFingerprintAssertion_without_oem_props(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
source_info_dict = copy.deepcopy(self.TEST_INFO_DICT)
|
|
||||||
source_info_dict['build.prop']['ro.build.fingerprint'] = (
|
|
||||||
'source-build-fingerprint')
|
|
||||||
source_info = BuildInfo(source_info_dict, None)
|
|
||||||
|
|
||||||
script_writer = test_utils.MockScriptWriter()
|
|
||||||
WriteFingerprintAssertion(script_writer, target_info, source_info)
|
|
||||||
self.assertEqual(
|
|
||||||
[('AssertSomeFingerprint', 'source-build-fingerprint',
|
|
||||||
'build-fingerprint')],
|
|
||||||
script_writer.lines)
|
|
||||||
|
|
||||||
def test_WriteFingerprintAssertion_with_source_oem_props(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
source_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
|
||||||
self.TEST_OEM_DICTS)
|
|
||||||
|
|
||||||
script_writer = test_utils.MockScriptWriter()
|
|
||||||
WriteFingerprintAssertion(script_writer, target_info, source_info)
|
|
||||||
self.assertEqual(
|
|
||||||
[('AssertFingerprintOrThumbprint', 'build-fingerprint',
|
|
||||||
'build-thumbprint')],
|
|
||||||
script_writer.lines)
|
|
||||||
|
|
||||||
def test_WriteFingerprintAssertion_with_target_oem_props(self):
|
|
||||||
target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
|
||||||
self.TEST_OEM_DICTS)
|
|
||||||
source_info = BuildInfo(self.TEST_INFO_DICT, None)
|
|
||||||
|
|
||||||
script_writer = test_utils.MockScriptWriter()
|
|
||||||
WriteFingerprintAssertion(script_writer, target_info, source_info)
|
|
||||||
self.assertEqual(
|
|
||||||
[('AssertFingerprintOrThumbprint', 'build-fingerprint',
|
|
||||||
'build-thumbprint')],
|
|
||||||
script_writer.lines)
|
|
||||||
|
|
||||||
def test_WriteFingerprintAssertion_with_both_oem_props(self):
|
|
||||||
target_info = 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-build-thumbprint')
|
|
||||||
source_info = BuildInfo(source_info_dict, self.TEST_OEM_DICTS)
|
|
||||||
|
|
||||||
script_writer = test_utils.MockScriptWriter()
|
|
||||||
WriteFingerprintAssertion(script_writer, target_info, source_info)
|
|
||||||
self.assertEqual(
|
|
||||||
[('AssertSomeThumbprint', 'build-thumbprint',
|
|
||||||
'source-build-thumbprint')],
|
|
||||||
script_writer.lines)
|
|
||||||
|
|
||||||
|
|
||||||
class LoadOemDictsTest(test_utils.ReleaseToolsTestCase):
|
class LoadOemDictsTest(test_utils.ReleaseToolsTestCase):
|
||||||
|
|
||||||
def test_NoneDict(self):
|
def test_NoneDict(self):
|
||||||
@@ -387,6 +131,35 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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',
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_OEM_DICTS = [
|
||||||
|
{
|
||||||
|
'ro.product.brand' : 'brand1',
|
||||||
|
'ro.product.device' : 'device1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'ro.product.brand' : 'brand2',
|
||||||
|
'ro.product.device' : 'device2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'ro.product.brand' : 'brand3',
|
||||||
|
'ro.product.device' : 'device3',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.testdata_dir = test_utils.get_testdata_dir()
|
self.testdata_dir = test_utils.get_testdata_dir()
|
||||||
self.assertTrue(os.path.exists(self.testdata_dir))
|
self.assertTrue(os.path.exists(self.testdata_dir))
|
||||||
@@ -408,7 +181,7 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
def test_GetPackageMetadata_abOta_full(self):
|
def test_GetPackageMetadata_abOta_full(self):
|
||||||
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
|
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
|
||||||
target_info_dict['ab_update'] = 'true'
|
target_info_dict['ab_update'] = 'true'
|
||||||
target_info = BuildInfo(target_info_dict, None)
|
target_info = common.BuildInfo(target_info_dict, None)
|
||||||
metadata = GetPackageMetadata(target_info)
|
metadata = GetPackageMetadata(target_info)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
{
|
{
|
||||||
@@ -426,8 +199,8 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
def test_GetPackageMetadata_abOta_incremental(self):
|
def test_GetPackageMetadata_abOta_incremental(self):
|
||||||
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
|
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
|
||||||
target_info_dict['ab_update'] = 'true'
|
target_info_dict['ab_update'] = 'true'
|
||||||
target_info = BuildInfo(target_info_dict, None)
|
target_info = common.BuildInfo(target_info_dict, None)
|
||||||
source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
|
source_info = common.BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
|
||||||
common.OPTIONS.incremental_source = ''
|
common.OPTIONS.incremental_source = ''
|
||||||
metadata = GetPackageMetadata(target_info, source_info)
|
metadata = GetPackageMetadata(target_info, source_info)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
@@ -446,7 +219,7 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
metadata)
|
metadata)
|
||||||
|
|
||||||
def test_GetPackageMetadata_nonAbOta_full(self):
|
def test_GetPackageMetadata_nonAbOta_full(self):
|
||||||
target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
||||||
metadata = GetPackageMetadata(target_info)
|
metadata = GetPackageMetadata(target_info)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
{
|
{
|
||||||
@@ -461,8 +234,8 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
metadata)
|
metadata)
|
||||||
|
|
||||||
def test_GetPackageMetadata_nonAbOta_incremental(self):
|
def test_GetPackageMetadata_nonAbOta_incremental(self):
|
||||||
target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
||||||
source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
|
source_info = common.BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
|
||||||
common.OPTIONS.incremental_source = ''
|
common.OPTIONS.incremental_source = ''
|
||||||
metadata = GetPackageMetadata(target_info, source_info)
|
metadata = GetPackageMetadata(target_info, source_info)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
@@ -480,7 +253,7 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
metadata)
|
metadata)
|
||||||
|
|
||||||
def test_GetPackageMetadata_wipe(self):
|
def test_GetPackageMetadata_wipe(self):
|
||||||
target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
||||||
common.OPTIONS.wipe_user_data = True
|
common.OPTIONS.wipe_user_data = True
|
||||||
metadata = GetPackageMetadata(target_info)
|
metadata = GetPackageMetadata(target_info)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
@@ -497,7 +270,7 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
metadata)
|
metadata)
|
||||||
|
|
||||||
def test_GetPackageMetadata_retrofitDynamicPartitions(self):
|
def test_GetPackageMetadata_retrofitDynamicPartitions(self):
|
||||||
target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
||||||
common.OPTIONS.retrofit_dynamic_partitions = True
|
common.OPTIONS.retrofit_dynamic_partitions = True
|
||||||
metadata = GetPackageMetadata(target_info)
|
metadata = GetPackageMetadata(target_info)
|
||||||
self.assertDictEqual(
|
self.assertDictEqual(
|
||||||
@@ -526,8 +299,8 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
self._test_GetPackageMetadata_swapBuildTimestamps(
|
self._test_GetPackageMetadata_swapBuildTimestamps(
|
||||||
target_info_dict, source_info_dict)
|
target_info_dict, source_info_dict)
|
||||||
|
|
||||||
target_info = BuildInfo(target_info_dict, None)
|
target_info = common.BuildInfo(target_info_dict, None)
|
||||||
source_info = BuildInfo(source_info_dict, None)
|
source_info = common.BuildInfo(source_info_dict, None)
|
||||||
common.OPTIONS.incremental_source = ''
|
common.OPTIONS.incremental_source = ''
|
||||||
self.assertRaises(RuntimeError, GetPackageMetadata, target_info,
|
self.assertRaises(RuntimeError, GetPackageMetadata, target_info,
|
||||||
source_info)
|
source_info)
|
||||||
@@ -538,8 +311,8 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
self._test_GetPackageMetadata_swapBuildTimestamps(
|
self._test_GetPackageMetadata_swapBuildTimestamps(
|
||||||
target_info_dict, source_info_dict)
|
target_info_dict, source_info_dict)
|
||||||
|
|
||||||
target_info = BuildInfo(target_info_dict, None)
|
target_info = common.BuildInfo(target_info_dict, None)
|
||||||
source_info = BuildInfo(source_info_dict, None)
|
source_info = common.BuildInfo(source_info_dict, None)
|
||||||
common.OPTIONS.incremental_source = ''
|
common.OPTIONS.incremental_source = ''
|
||||||
common.OPTIONS.downgrade = True
|
common.OPTIONS.downgrade = True
|
||||||
common.OPTIONS.wipe_user_data = True
|
common.OPTIONS.wipe_user_data = True
|
||||||
@@ -752,6 +525,59 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
|||||||
FinalizeMetadata(metadata, zip_file, output_file, needed_property_files)
|
FinalizeMetadata(metadata, zip_file, output_file, needed_property_files)
|
||||||
self.assertIn('ota-test-property-files', metadata)
|
self.assertIn('ota-test-property-files', metadata)
|
||||||
|
|
||||||
|
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-build-fingerprint')
|
||||||
|
source_info = common.BuildInfo(source_info_dict, None)
|
||||||
|
|
||||||
|
script_writer = test_utils.MockScriptWriter()
|
||||||
|
WriteFingerprintAssertion(script_writer, target_info, source_info)
|
||||||
|
self.assertEqual(
|
||||||
|
[('AssertSomeFingerprint', 'source-build-fingerprint',
|
||||||
|
'build-fingerprint-target')],
|
||||||
|
script_writer.lines)
|
||||||
|
|
||||||
|
def test_WriteFingerprintAssertion_with_source_oem_props(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
||||||
|
source_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
self.TEST_OEM_DICTS)
|
||||||
|
|
||||||
|
script_writer = test_utils.MockScriptWriter()
|
||||||
|
WriteFingerprintAssertion(script_writer, target_info, source_info)
|
||||||
|
self.assertEqual(
|
||||||
|
[('AssertFingerprintOrThumbprint', 'build-fingerprint-target',
|
||||||
|
'build-thumbprint')],
|
||||||
|
script_writer.lines)
|
||||||
|
|
||||||
|
def test_WriteFingerprintAssertion_with_target_oem_props(self):
|
||||||
|
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
|
||||||
|
self.TEST_OEM_DICTS)
|
||||||
|
source_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
|
||||||
|
|
||||||
|
script_writer = test_utils.MockScriptWriter()
|
||||||
|
WriteFingerprintAssertion(script_writer, target_info, source_info)
|
||||||
|
self.assertEqual(
|
||||||
|
[('AssertFingerprintOrThumbprint', 'build-fingerprint-target',
|
||||||
|
'build-thumbprint')],
|
||||||
|
script_writer.lines)
|
||||||
|
|
||||||
|
def test_WriteFingerprintAssertion_with_both_oem_props(self):
|
||||||
|
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-build-thumbprint')
|
||||||
|
source_info = common.BuildInfo(source_info_dict, self.TEST_OEM_DICTS)
|
||||||
|
|
||||||
|
script_writer = test_utils.MockScriptWriter()
|
||||||
|
WriteFingerprintAssertion(script_writer, target_info, source_info)
|
||||||
|
self.assertEqual(
|
||||||
|
[('AssertSomeThumbprint', 'build-thumbprint',
|
||||||
|
'source-build-thumbprint')],
|
||||||
|
script_writer.lines)
|
||||||
|
|
||||||
|
|
||||||
class TestPropertyFiles(PropertyFiles):
|
class TestPropertyFiles(PropertyFiles):
|
||||||
"""A class that extends PropertyFiles for testing purpose."""
|
"""A class that extends PropertyFiles for testing purpose."""
|
||||||
|
Reference in New Issue
Block a user