Merge "Add minimal-runtime support for integer overflows."
diff --git a/core/Makefile b/core/Makefile
index 136690f..19e69ac 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -2775,9 +2775,15 @@
$(hide) $(call fs_config,$(zip_root)/PRODUCT,product/) > $(zip_root)/META/product_filesystem_config.txt
endif
ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+ @# When using BOARD_BUILD_SYSTEM_ROOT_IMAGE, ROOT always contains the files for the root under
+ @# normal boot. BOOT/RAMDISK exists only if additionally using BOARD_USES_RECOVERY_AS_BOOT.
$(hide) $(call fs_config,$(zip_root)/ROOT,) > $(zip_root)/META/root_filesystem_config.txt
-endif
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
$(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt
+endif
+else # BOARD_BUILD_SYSTEM_ROOT_IMAGE != true
+ $(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt
+endif
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(hide) $(call fs_config,$(zip_root)/RECOVERY/RAMDISK,) > $(zip_root)/META/recovery_filesystem_config.txt
endif
@@ -3230,3 +3236,9 @@
ifneq ($(sdk_repo_goal),)
include $(TOPDIR)development/build/tools/sdk_repo.mk
endif
+
+#------------------------------------------------------------------
+# Find lsdump paths
+FIND_LSDUMPS_FILE := $(PRODUCT_OUT)/lsdump_paths.txt
+$(FIND_LSDUMPS_FILE) : $(LSDUMP_PATHS)
+ $(hide) rm -rf $@ && echo "$^" > $@
diff --git a/core/base_rules.mk b/core/base_rules.mk
index ff48930..22e7aef 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -494,12 +494,15 @@
endif
endif
-# For modules tagged as tests but lacking a suite tag, set null-suite as the default.
+# For test modules that lack a suite tag, set null-suite as the default.
# We only support adding a default suite to native tests, native benchmarks, and instrumentation tests.
# This is because they are the only tests we currently auto-generate test configs for.
-ifneq ($(filter $(my_module_tags),tests),)
ifndef LOCAL_COMPATIBILITY_SUITE
-ifneq ($(filter NATIVE_TESTS NATIVE_BENCHMARK APPS, $(LOCAL_MODULE_CLASS)),)
+ifneq ($(filter NATIVE_TESTS NATIVE_BENCHMARK, $(LOCAL_MODULE_CLASS)),)
+LOCAL_COMPATIBILITY_SUITE := null-suite
+endif
+ifneq ($(filter APPS, $(LOCAL_MODULE_CLASS)),)
+ifneq ($(filter $(my_module_tags),tests),)
LOCAL_COMPATIBILITY_SUITE := null-suite
endif
endif
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index baa2344..3bec869 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -235,6 +235,7 @@
LOCAL_SHARED_LIBRARIES:=
LOCAL_SOONG_CLASSES_JAR :=
LOCAL_SOONG_DEX_JAR :=
+LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=
LOCAL_SOONG_HEADER_JAR :=
LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=
LOCAL_SOONG_PROGUARD_DICT :=
diff --git a/core/definitions.mk b/core/definitions.mk
index f6f5840..d3d9928 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2326,9 +2326,9 @@
$(addprefix --classpath ,$(strip \
$(call normalize-path-list,$(PRIVATE_ALL_JAVA_HEADER_LIBRARIES)))) \
|| ( rm -rf $(dir $@)/classes-turbine ; exit 41 ) && \
- $(MERGE_ZIPS) -j -stripDir META-INF $@.tmp $@.premerged $(call reverse-list,$(PRIVATE_STATIC_JAVA_HEADER_LIBRARIES)) ; \
+ $(MERGE_ZIPS) -j --ignore-duplicates -stripDir META-INF $@.tmp $@.premerged $(call reverse-list,$(PRIVATE_STATIC_JAVA_HEADER_LIBRARIES)) ; \
else \
- $(MERGE_ZIPS) -j -stripDir META-INF $@.tmp $(call reverse-list,$(PRIVATE_STATIC_JAVA_HEADER_LIBRARIES)) ; \
+ $(MERGE_ZIPS) -j --ignore-duplicates -stripDir META-INF $@.tmp $(call reverse-list,$(PRIVATE_STATIC_JAVA_HEADER_LIBRARIES)) ; \
fi
$(hide) $(ZIPTIME) $@.tmp
$(hide) $(call commit-change-for-toc,$@)
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 83c4a95..270e5f4 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -46,6 +46,16 @@
ifneq (false,$(WITH_DEXPREOPT_DEBUG_INFO))
PRODUCT_DEX_PREOPT_BOOT_FLAGS += --generate-mini-debug-info
endif
+
+ # Non eng linux builds must have preopt enabled so that system server doesn't run as interpreter
+ # only. b/74209329
+ ifeq (,$(filter eng, $(TARGET_BUILD_VARIANT)))
+ ifneq (true,$(WITH_DEXPREOPT))
+ ifneq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))
+ $(call pretty-error, DEXPREOPT must be enabled for user and userdebug builds)
+ endif
+ endif
+ endif
endif
GLOBAL_DEXPREOPT_FLAGS :=
diff --git a/core/java_common.mk b/core/java_common.mk
index 3a5c5c6..b94effa 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -428,7 +428,7 @@
endif
endif
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) $(PRODUCT_AAPT_FLAGS)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_PACKAGE_NAME := $(LOCAL_MANIFEST_PACKAGE_NAME)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_MANIFEST_INSTRUMENTATION_FOR)
diff --git a/core/main.mk b/core/main.mk
index ef55b4e..0317a89 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1256,6 +1256,9 @@
.PHONY: findbugs
findbugs: $(INTERNAL_FINDBUGS_HTML_TARGET) $(INTERNAL_FINDBUGS_XML_TARGET)
+.PHONY: findlsdumps
+findlsdumps: $(FIND_LSDUMPS_FILE)
+
#xxx scrape this from ALL_MODULE_NAME_TAGS
.PHONY: modules
modules:
diff --git a/core/ninja_config.mk b/core/ninja_config.mk
index 2256f98..ca2dcee 100644
--- a/core/ninja_config.mk
+++ b/core/ninja_config.mk
@@ -19,7 +19,9 @@
boottarball-nodeps \
brillo_tests \
btnod \
+ build-art% \
build_kernel-nodeps \
+ clean-oat% \
continuous_instrumentation_tests \
continuous_native_tests \
cts \
@@ -45,9 +47,11 @@
systemimage-nodeps \
systemtarball-nodeps \
target-files-package \
+ test-art% \
user \
userdataimage \
userdebug \
+ valgrind-test-art% \
vts \
win_sdk \
winsdk-tools
diff --git a/core/package_internal.mk b/core/package_internal.mk
index cd3a741..0938c99 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -465,7 +465,6 @@
endif # need_compile_res
framework_res_package_export :=
-framework_res_package_export_deps :=
ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
# Most packages should link against the resources defined by framework-res.
@@ -477,15 +476,9 @@
# for released sdk versions, the platform resources were built into android.jar.
framework_res_package_export := \
$(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar
-framework_res_package_export_deps := $(framework_res_package_export)
else # LOCAL_SDK_RES_VERSION
framework_res_package_export := \
$(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk
-# We can't depend directly on the export.apk file; it won't get its
-# PRIVATE_ vars set up correctly if we do. Instead, depend on the
-# corresponding R.stamp file, which lists the export.apk as a dependency.
-framework_res_package_export_deps := \
- $(dir $(framework_res_package_export))src/R.stamp
endif # LOCAL_SDK_RES_VERSION
endif # LOCAL_NO_STANDARD_LIBRARIES
@@ -495,7 +488,7 @@
$(call intermediates-dir-for,APPS,$(lib),,COMMON)/package-export.apk)
all_library_res_package_export_deps := \
- $(framework_res_package_export_deps) \
+ $(framework_res_package_export) \
$(foreach lib,$(LOCAL_RES_LIBRARIES),\
$(call intermediates-dir-for,APPS,$(lib),,COMMON)/src/R.stamp)
$(resource_export_package) $(R_file_stamp) $(LOCAL_BUILT_MODULE): $(all_library_res_package_export_deps)
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index d4f5522..96e2613 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -615,18 +615,14 @@
endif
framework_res_package_export :=
-framework_res_package_export_deps :=
# Please refer to package.mk
ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),)
framework_res_package_export := \
$(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar
-framework_res_package_export_deps := $(framework_res_package_export)
else
framework_res_package_export := \
$(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk
-framework_res_package_export_deps := \
- $(dir $(framework_res_package_export))src/R.stamp
endif
endif
@@ -644,7 +640,7 @@
$(my_res_package): PRIVATE_PRODUCT_AAPT_CONFIG :=
$(my_res_package): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
$(my_res_package): PRIVATE_TARGET_AAPT_CHARACTERISTICS :=
-$(my_res_package) : $(framework_res_package_export_deps)
+$(my_res_package) : $(framework_res_package_export)
full_android_manifest :=
my_res_resources :=
diff --git a/core/product.mk b/core/product.mk
index 6cccebf..19ede82 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -317,8 +317,7 @@
_product_stash_var_list += \
DEFAULT_SYSTEM_DEV_CERTIFICATE \
WITH_DEXPREOPT \
- WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY \
- WITH_DEXPREOPT_APP_IMAGE
+ WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
#
# Mark the variables in _product_stash_var_list as readonly
diff --git a/core/sdk_check.mk b/core/sdk_check.mk
index c5c2bc8..49ea2a8 100644
--- a/core/sdk_check.mk
+++ b/core/sdk_check.mk
@@ -2,13 +2,31 @@
# Enforcement checks that LOCAL_SDK_VERSION and LOCAL_PRIVATE_PLATFORM_APIS are
# set correctly.
# Should be included by java targets that allow specifying LOCAL_SDK_VERSION.
+# The JAVA_SDK_ENFORCEMENT_WARNING and JAVA_SDK_ENFORCEMENT_ERROR variables may
+# be set to a particular module class to enable warnings and errors for that
+# subtype.
+
+whitelisted_modules := framework-res__auto_generated_rro
ifeq ($(LOCAL_SDK_VERSION)$(LOCAL_PRIVATE_PLATFORM_APIS),)
-ifneq ($(JAVA_SDK_ENFORCEMENT_WARNING),)
-$(warning Java modules must specify LOCAL_SDK_VERSION or LOCAL_PRIVATE_PLATFORM_APIS, but $(LOCAL_MODULE) specifies neither.)
-endif
+ ifeq (,$(filter $(LOCAL_MODULE),$(whitelisted_modules)))
+ ifneq ($(JAVA_SDK_ENFORCEMENT_WARNING)$(JAVA_SDK_ENFORCEMENT_ERROR),)
+ my_message := Must specify LOCAL_SDK_VERSION or LOCAL_PRIVATE_PLATFORM_APIS,
+ ifeq ($(LOCAL_MODULE_CLASS),$(JAVA_SDK_ENFORCEMENT_ERROR))
+ $(call pretty-error,$(my_message))
+ endif
+ ifeq ($(LOCAL_MODULE_CLASS),$(JAVA_SDK_ENFORCEMENT_WARNING))
+ $(call pretty-warning,$(my_message))
+ endif
+ my_message :=
+ endif
+ endif
else ifneq ($(LOCAL_SDK_VERSION),)
-ifneq ($(LOCAL_PRIVATE_PLATFORM_APIS),)
-$(error $(LOCAL_MODULE) specifies both LOCAL_SDK_VERSION ($(LOCAL_SDK_VERSION)) and LOCAL_PRIVATE_PLATFORM_APIS ($(LOCAL_PRIVATE_PLATFORM_APIS)), but should specify only one.)
-endif
+ ifneq ($(LOCAL_PRIVATE_PLATFORM_APIS),)
+ my_message := Specifies both LOCAL_SDK_VERSION ($(LOCAL_SDK_VERSION)) and
+ my_message += LOCAL_PRIVATE_PLATFORM_APIS ($(LOCAL_PRIVATE_PLATFORM_APIS))
+ my_message += but should specify only one
+ $(call pretty-error,$(my_message))
+ my_message :=
+ endif
endif
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index c553c4c..83982b7 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -34,13 +34,13 @@
$(intermediates.COMMON)/proguard_dictionary)
endif
-ifneq ($(TURBINE_DISABLED),false)
+ifneq ($(TURBINE_ENABLED),false)
ifdef LOCAL_SOONG_HEADER_JAR
$(eval $(call copy-one-file,$(LOCAL_SOONG_HEADER_JAR),$(full_classes_header_jar)))
else
$(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_header_jar)))
endif
-endif # TURBINE_DISABLED != false
+endif # TURBINE_ENABLED != false
$(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_BUILT_MODULE)))
@@ -55,6 +55,7 @@
@echo "Copy: $$@"
$(copy-file-to-target)
touch $(PRIVATE_STAMP)
+$(call add-dependency,$(LOCAL_BUILT_MODULE),$(resource_export_package))
endif # LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index 2242582..309854c 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -39,13 +39,31 @@
$(intermediates.COMMON)/jacoco-report-classes.jar)
endif
-ifneq ($(TURBINE_DISABLED),false)
+ifdef LOCAL_SOONG_EXPORT_PROGUARD_FLAGS
+ $(eval $(call copy-one-file,$(LOCAL_SOONG_EXPORT_PROGUARD_FLAGS),\
+ $(intermediates.COMMON)/export_proguard_flags))
+ $(call add-dependency,$(LOCAL_BUILT_MODULE),\
+ $(intermediates.COMMON)/export_proguard_flags)
+endif
+
+ifdef LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
+my_res_package := $(intermediates.COMMON)/package-res.apk
+
+$(my_res_package): $(LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE)
+ @echo "Copy: $$@"
+ $(copy-file-to-target)
+
+$(call add-dependency,$(LOCAL_BUILT_MODULE),$(my_res_package))
+
+endif # LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
+
+ifneq ($(TURBINE_ENABLED),false)
ifdef LOCAL_SOONG_HEADER_JAR
$(eval $(call copy-one-file,$(LOCAL_SOONG_HEADER_JAR),$(full_classes_header_jar)))
else
$(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_header_jar)))
endif
-endif # TURBINE_DISABLED != false
+endif # TURBINE_ENABLED != false
ifdef LOCAL_SOONG_DEX_JAR
ifndef LOCAL_IS_HOST_MODULE
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index 1dc0e71..77bb498 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -103,18 +103,14 @@
endif
framework_res_package_export :=
-framework_res_package_export_deps :=
# Please refer to package.mk
ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),)
framework_res_package_export := \
$(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar
-framework_res_package_export_deps := $(framework_res_package_export)
else
framework_res_package_export := \
$(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk
-framework_res_package_export_deps := \
- $(dir $(framework_res_package_export))src/R.stamp
endif
endif
@@ -175,10 +171,10 @@
endif # renderscript_target_api < 21
endif # renderscript_target_api is set
include $(BUILD_SYSTEM)/aapt2.mk
-$(my_res_package) : $(framework_res_package_export_deps)
+$(my_res_package) : $(framework_res_package_export)
else
$(R_file_stamp): PRIVATE_RESOURCE_LIST := $(all_resources)
-$(R_file_stamp) : $(all_resources) $(full_android_manifest) $(AAPT) $(framework_res_package_export_deps)
+$(R_file_stamp) : $(all_resources) $(full_android_manifest) $(AAPT) $(framework_res_package_export)
@echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
$(create-resource-java-files)
$(hide) find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name R.java | xargs cat > $@
diff --git a/core/tasks/check_boot_jars/check_boot_jars.py b/core/tasks/check_boot_jars/check_boot_jars.py
index 1b4540c..9d71553 100755
--- a/core/tasks/check_boot_jars/check_boot_jars.py
+++ b/core/tasks/check_boot_jars/check_boot_jars.py
@@ -39,7 +39,7 @@
return True
-def CheckJar(jar):
+def CheckJar(whitelist_path, jar):
"""Check a jar file.
"""
# Get the list of files inside the jar file.
@@ -55,8 +55,9 @@
package_name = package_name.replace('/', '.')
# Skip class without a package name
if package_name and not whitelist_re.match(package_name):
- print >> sys.stderr, ('Error: %s contains class file %s, which is not in the whitelist'
- % (jar, f))
+ print >> sys.stderr, ('Error: %s contains class file %s, whose package name %s is not '
+ 'in the whitelist %s of packages allowed on the bootclasspath.'
+ % (jar, f, package_name, whitelist_path))
return False
return True
@@ -65,13 +66,14 @@
if len(argv) < 2:
print __doc__
return 1
+ whitelist_path = argv[0]
- if not LoadWhitelist(argv[0]):
+ if not LoadWhitelist(whitelist_path):
return 1
passed = True
for jar in argv[1:]:
- if not CheckJar(jar):
+ if not CheckJar(whitelist_path, jar):
passed = False
if not passed:
return 1
diff --git a/target/product/core_tiny.mk b/target/product/core_tiny.mk
index c86b862..122f5c7 100644
--- a/target/product/core_tiny.mk
+++ b/target/product/core_tiny.mk
@@ -59,6 +59,7 @@
iptables \
gatekeeperd \
keystore \
+ ld.config.txt \
ld.mc \
libaaudio \
libOpenMAXAL \
diff --git a/target/product/sdk_base.mk b/target/product/sdk_base.mk
index a641be3..b79b8c6 100644
--- a/target/product/sdk_base.mk
+++ b/target/product/sdk_base.mk
@@ -17,7 +17,6 @@
PRODUCT_PROPERTY_OVERRIDES :=
PRODUCT_PACKAGES := \
- ApiDemos \
CellBroadcastReceiver \
CubeLiveWallpapers \
CustomLocale \
@@ -25,7 +24,6 @@
Dialer \
EmulatorSmokeTests \
Gallery2 \
- GestureBuilder \
Launcher3 \
Camera2 \
librs_jni \
@@ -40,8 +38,6 @@
rild \
screenrecord \
SdkSetup \
- SmokeTest \
- SmokeTestApp \
SoftKeyboard \
sqlite3 \
SystemUI \
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index a3a5c1c..b9f39a6 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -39,19 +39,18 @@
"""
+import os
+import re
+import subprocess
import sys
+import zipfile
+
+import common
if sys.hexversion < 0x02070000:
print >> sys.stderr, "Python 2.7 or newer is required."
sys.exit(1)
-import os
-import re
-import shutil
-import subprocess
-import zipfile
-
-import common
# Work around a bug in Python's zipfile module that prevents opening of zipfiles
# if any entry has an extra field of between 1 and 3 bytes (which is common with
@@ -244,44 +243,41 @@
# This is the list of wildcards of files we extract from |filename|.
apk_extensions = ['*.apk']
- self.certmap, compressed_extension = common.ReadApkCerts(zipfile.ZipFile(filename, "r"))
+ self.certmap, compressed_extension = common.ReadApkCerts(
+ zipfile.ZipFile(filename, "r"))
if compressed_extension:
apk_extensions.append("*.apk" + compressed_extension)
d = common.UnzipTemp(filename, apk_extensions)
- try:
- self.apks = {}
- self.apks_by_basename = {}
- for dirpath, _, filenames in os.walk(d):
- for fn in filenames:
- # Decompress compressed APKs before we begin processing them.
- if compressed_extension and fn.endswith(compressed_extension):
- # First strip the compressed extension from the file.
- uncompressed_fn = fn[:-len(compressed_extension)]
+ self.apks = {}
+ self.apks_by_basename = {}
+ for dirpath, _, filenames in os.walk(d):
+ for fn in filenames:
+ # Decompress compressed APKs before we begin processing them.
+ if compressed_extension and fn.endswith(compressed_extension):
+ # First strip the compressed extension from the file.
+ uncompressed_fn = fn[:-len(compressed_extension)]
- # Decompress the compressed file to the output file.
- common.Gunzip(os.path.join(dirpath, fn),
- os.path.join(dirpath, uncompressed_fn))
+ # Decompress the compressed file to the output file.
+ common.Gunzip(os.path.join(dirpath, fn),
+ os.path.join(dirpath, uncompressed_fn))
- # Finally, delete the compressed file and use the uncompressed file
- # for further processing. Note that the deletion is not strictly required,
- # but is done here to ensure that we're not using too much space in
- # the temporary directory.
- os.remove(os.path.join(dirpath, fn))
- fn = uncompressed_fn
+ # Finally, delete the compressed file and use the uncompressed file
+ # for further processing. Note that the deletion is not strictly
+ # required, but is done here to ensure that we're not using too much
+ # space in the temporary directory.
+ os.remove(os.path.join(dirpath, fn))
+ fn = uncompressed_fn
+ if fn.endswith(".apk"):
+ fullname = os.path.join(dirpath, fn)
+ displayname = fullname[len(d)+1:]
+ apk = APK(fullname, displayname)
+ self.apks[apk.filename] = apk
+ self.apks_by_basename[os.path.basename(apk.filename)] = apk
- if fn.endswith(".apk"):
- fullname = os.path.join(dirpath, fn)
- displayname = fullname[len(d)+1:]
- apk = APK(fullname, displayname)
- self.apks[apk.filename] = apk
- self.apks_by_basename[os.path.basename(apk.filename)] = apk
-
- self.max_pkg_len = max(self.max_pkg_len, len(apk.package))
- self.max_fn_len = max(self.max_fn_len, len(apk.filename))
- finally:
- shutil.rmtree(d)
+ self.max_pkg_len = max(self.max_pkg_len, len(apk.package))
+ self.max_fn_len = max(self.max_fn_len, len(apk.filename))
def CheckSharedUids(self):
"""Look for any instances where packages signed with different
@@ -291,7 +287,7 @@
if apk.shared_uid:
apks_by_uid.setdefault(apk.shared_uid, []).append(apk)
- for uid in sorted(apks_by_uid.keys()):
+ for uid in sorted(apks_by_uid):
apks = apks_by_uid[uid]
for apk in apks[1:]:
if apk.certs != apks[0].certs:
@@ -466,3 +462,5 @@
print " ERROR: %s" % (e,)
print
sys.exit(1)
+ finally:
+ common.Cleanup()
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 7d76dcb..7ef522c 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -955,6 +955,119 @@
return metadata
+def ComputeStreamingMetadata(zip_file, reserve_space=False,
+ expected_length=None):
+ """Computes the streaming metadata for a given zip.
+
+ When 'reserve_space' is True, we reserve extra space for the offset and
+ length of the metadata entry itself, although we don't know the final
+ values until the package gets signed. This function will be called again
+ after signing. We then write the actual values and pad the string to the
+ length we set earlier. Note that we can't use the actual length of the
+ metadata entry in the second run. Otherwise the offsets for other entries
+ will be changing again.
+ """
+
+ def ComputeEntryOffsetSize(name):
+ """Compute the zip entry offset and size."""
+ info = zip_file.getinfo(name)
+ offset = info.header_offset + len(info.FileHeader())
+ size = info.file_size
+ return '%s:%d:%d' % (os.path.basename(name), offset, size)
+
+ # payload.bin and payload_properties.txt must exist.
+ offsets = [ComputeEntryOffsetSize('payload.bin'),
+ ComputeEntryOffsetSize('payload_properties.txt')]
+
+ # care_map.txt is available only if dm-verity is enabled.
+ if 'care_map.txt' in zip_file.namelist():
+ offsets.append(ComputeEntryOffsetSize('care_map.txt'))
+
+ if 'compatibility.zip' in zip_file.namelist():
+ offsets.append(ComputeEntryOffsetSize('compatibility.zip'))
+
+ # 'META-INF/com/android/metadata' is required. We don't know its actual
+ # offset and length (as well as the values for other entries). So we
+ # reserve 10-byte as a placeholder, which is to cover the space for metadata
+ # entry ('xx:xxx', since it's ZIP_STORED which should appear at the
+ # beginning of the zip), as well as the possible value changes in other
+ # entries.
+ if reserve_space:
+ offsets.append('metadata:' + ' ' * 10)
+ else:
+ offsets.append(ComputeEntryOffsetSize(METADATA_NAME))
+
+ value = ','.join(offsets)
+ if expected_length is not None:
+ assert len(value) <= expected_length, \
+ 'Insufficient reserved space: reserved=%d, actual=%d' % (
+ expected_length, len(value))
+ value += ' ' * (expected_length - len(value))
+ return value
+
+
+def FinalizeMetadata(metadata, input_file, output_file):
+ """Finalizes the metadata and signs an A/B OTA package.
+
+ In order to stream an A/B OTA package, we need 'ota-streaming-property-files'
+ that contains the offsets and sizes for the ZIP entries. An example
+ property-files string is as follows.
+
+ "payload.bin:679:343,payload_properties.txt:378:45,metadata:69:379"
+
+ OTA server can pass down this string, in addition to the package URL, to the
+ system update client. System update client can then fetch individual ZIP
+ entries (ZIP_STORED) directly at the given offset of the URL.
+
+ Args:
+ metadata: The metadata dict for the package.
+ input_file: The input ZIP filename that doesn't contain the package METADATA
+ entry yet.
+ output_file: The final output ZIP filename.
+ """
+ output_zip = zipfile.ZipFile(
+ input_file, 'a', compression=zipfile.ZIP_DEFLATED)
+
+ # Write the current metadata entry with placeholders.
+ metadata['ota-streaming-property-files'] = ComputeStreamingMetadata(
+ output_zip, reserve_space=True)
+ WriteMetadata(metadata, output_zip)
+ common.ZipClose(output_zip)
+
+ # SignOutput(), which in turn calls signapk.jar, will possibly reorder the
+ # ZIP entries, as well as padding the entry headers. We do a preliminary
+ # signing (with an incomplete metadata entry) to allow that to happen. Then
+ # compute the ZIP entry offsets, write back the final metadata and do the
+ # final signing.
+ prelim_signing = common.MakeTempFile(suffix='.zip')
+ SignOutput(input_file, prelim_signing)
+
+ # Open the signed zip. Compute the final metadata that's needed for streaming.
+ prelim_signing_zip = zipfile.ZipFile(prelim_signing, 'r')
+ expected_length = len(metadata['ota-streaming-property-files'])
+ metadata['ota-streaming-property-files'] = ComputeStreamingMetadata(
+ prelim_signing_zip, reserve_space=False, expected_length=expected_length)
+ common.ZipClose(prelim_signing_zip)
+
+ # Replace the METADATA entry.
+ common.ZipDelete(prelim_signing, METADATA_NAME)
+ output_zip = zipfile.ZipFile(prelim_signing, 'a',
+ compression=zipfile.ZIP_DEFLATED)
+ WriteMetadata(metadata, output_zip)
+ common.ZipClose(output_zip)
+
+ # Re-sign the package after updating the metadata entry.
+ SignOutput(prelim_signing, output_file)
+
+ # Reopen the final signed zip to double check the streaming metadata.
+ output_zip = zipfile.ZipFile(output_file, 'r')
+ actual = metadata['ota-streaming-property-files'].strip()
+ expected = ComputeStreamingMetadata(output_zip)
+ assert actual == expected, \
+ "Mismatching streaming metadata: %s vs %s." % (actual, expected)
+ common.ZipClose(output_zip)
+
+
def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip):
target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
source_info = BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
@@ -1301,61 +1414,10 @@
def WriteABOTAPackageWithBrilloScript(target_file, output_file,
source_file=None):
- """Generate an Android OTA package that has A/B update payload."""
-
- def ComputeStreamingMetadata(zip_file, reserve_space=False,
- expected_length=None):
- """Compute the streaming metadata for a given zip.
-
- When 'reserve_space' is True, we reserve extra space for the offset and
- length of the metadata entry itself, although we don't know the final
- values until the package gets signed. This function will be called again
- after signing. We then write the actual values and pad the string to the
- length we set earlier. Note that we can't use the actual length of the
- metadata entry in the second run. Otherwise the offsets for other entries
- will be changing again.
- """
-
- def ComputeEntryOffsetSize(name):
- """Compute the zip entry offset and size."""
- info = zip_file.getinfo(name)
- offset = info.header_offset + len(info.FileHeader())
- size = info.file_size
- return '%s:%d:%d' % (os.path.basename(name), offset, size)
-
- # payload.bin and payload_properties.txt must exist.
- offsets = [ComputeEntryOffsetSize('payload.bin'),
- ComputeEntryOffsetSize('payload_properties.txt')]
-
- # care_map.txt is available only if dm-verity is enabled.
- if 'care_map.txt' in zip_file.namelist():
- offsets.append(ComputeEntryOffsetSize('care_map.txt'))
-
- if 'compatibility.zip' in zip_file.namelist():
- offsets.append(ComputeEntryOffsetSize('compatibility.zip'))
-
- # 'META-INF/com/android/metadata' is required. We don't know its actual
- # offset and length (as well as the values for other entries). So we
- # reserve 10-byte as a placeholder, which is to cover the space for metadata
- # entry ('xx:xxx', since it's ZIP_STORED which should appear at the
- # beginning of the zip), as well as the possible value changes in other
- # entries.
- if reserve_space:
- offsets.append('metadata:' + ' ' * 10)
- else:
- offsets.append(ComputeEntryOffsetSize(METADATA_NAME))
-
- value = ','.join(offsets)
- if expected_length is not None:
- assert len(value) <= expected_length, \
- 'Insufficient reserved space: reserved=%d, actual=%d' % (
- expected_length, len(value))
- value += ' ' * (expected_length - len(value))
- return value
-
+ """Generates an Android OTA package that has A/B update payload."""
# Stage the output zip package for package signing.
- temp_zip_file = tempfile.NamedTemporaryFile()
- output_zip = zipfile.ZipFile(temp_zip_file, "w",
+ staging_file = common.MakeTempFile(suffix='.zip')
+ output_zip = zipfile.ZipFile(staging_file, "w",
compression=zipfile.ZIP_DEFLATED)
if source_file is not None:
@@ -1410,54 +1472,16 @@
else:
print("Warning: cannot find care map file in target_file package")
- # source_info must be None for full OTAs.
- if source_file is None:
- assert source_info is None
-
AddCompatibilityArchiveIfTrebleEnabled(
target_zip, output_zip, target_info, source_info)
common.ZipClose(target_zip)
- # Write the current metadata entry with placeholders.
- metadata['ota-streaming-property-files'] = ComputeStreamingMetadata(
- output_zip, reserve_space=True)
- WriteMetadata(metadata, output_zip)
+ # We haven't written the metadata entry yet, which will be handled in
+ # FinalizeMetadata().
common.ZipClose(output_zip)
- # SignOutput(), which in turn calls signapk.jar, will possibly reorder the
- # ZIP entries, as well as padding the entry headers. We do a preliminary
- # signing (with an incomplete metadata entry) to allow that to happen. Then
- # compute the ZIP entry offsets, write back the final metadata and do the
- # final signing.
- prelim_signing = common.MakeTempFile(suffix='.zip')
- SignOutput(temp_zip_file.name, prelim_signing)
- common.ZipClose(temp_zip_file)
-
- # Open the signed zip. Compute the final metadata that's needed for streaming.
- prelim_signing_zip = zipfile.ZipFile(prelim_signing, 'r')
- expected_length = len(metadata['ota-streaming-property-files'])
- metadata['ota-streaming-property-files'] = ComputeStreamingMetadata(
- prelim_signing_zip, reserve_space=False, expected_length=expected_length)
- common.ZipClose(prelim_signing_zip)
-
- # Replace the METADATA entry.
- common.ZipDelete(prelim_signing, METADATA_NAME)
- output_zip = zipfile.ZipFile(prelim_signing, 'a',
- compression=zipfile.ZIP_DEFLATED)
- WriteMetadata(metadata, output_zip)
- common.ZipClose(output_zip)
-
- # Re-sign the package after updating the metadata entry.
- SignOutput(prelim_signing, output_file)
-
- # Reopen the final signed zip to double check the streaming metadata.
- output_zip = zipfile.ZipFile(output_file, 'r')
- actual = metadata['ota-streaming-property-files'].strip()
- expected = ComputeStreamingMetadata(output_zip)
- assert actual == expected, \
- "Mismatching streaming metadata: %s vs %s." % (actual, expected)
- common.ZipClose(output_zip)
+ FinalizeMetadata(metadata, staging_file, output_file)
def main(argv):
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index ee5bc53..ed25f13 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -23,7 +23,7 @@
import common
import test_utils
from ota_from_target_files import (
- _LoadOemDicts, BuildInfo, GetPackageMetadata,
+ _LoadOemDicts, BuildInfo, ComputeStreamingMetadata, GetPackageMetadata,
GetTargetFilesZipForSecondaryImages,
GetTargetFilesZipWithoutPostinstallConfig,
Payload, PayloadSigner, POSTINSTALL_CONFIG,
@@ -378,6 +378,9 @@
common.OPTIONS.timestamp = False
common.OPTIONS.wipe_user_data = False
+ def tearDown(self):
+ common.Cleanup()
+
def test_GetPackageMetadata_abOta_full(self):
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
target_info_dict['ab_update'] = 'true'
@@ -586,6 +589,119 @@
with zipfile.ZipFile(target_file) as verify_zip:
self.assertNotIn(POSTINSTALL_CONFIG, verify_zip.namelist())
+ @staticmethod
+ def _construct_zip_package(entries):
+ zip_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(zip_file, 'w') as zip_fp:
+ for entry in entries:
+ zip_fp.writestr(
+ entry,
+ entry.replace('.', '-').upper(),
+ zipfile.ZIP_STORED)
+ return zip_file
+
+ @staticmethod
+ def _parse_streaming_metadata_string(data):
+ result = {}
+ for token in data.split(','):
+ name, info = token.split(':', 1)
+ result[name] = info
+ return result
+
+ def _verify_entries(self, input_file, tokens, entries):
+ for entry in entries:
+ offset, size = map(int, tokens[entry].split(':'))
+ with open(input_file, 'rb') as input_fp:
+ input_fp.seek(offset)
+ if entry == 'metadata':
+ expected = b'META-INF/COM/ANDROID/METADATA'
+ else:
+ expected = entry.replace('.', '-').upper().encode()
+ self.assertEqual(expected, input_fp.read(size))
+
+ def test_ComputeStreamingMetadata_reserveSpace(self):
+ entries = (
+ 'payload.bin',
+ 'payload_properties.txt',
+ )
+ zip_file = self._construct_zip_package(entries)
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ streaming_metadata = ComputeStreamingMetadata(zip_fp, reserve_space=True)
+ tokens = self._parse_streaming_metadata_string(streaming_metadata)
+
+ self.assertEqual(3, len(tokens))
+ self._verify_entries(zip_file, tokens, entries)
+
+ def test_ComputeStreamingMetadata_reserveSpace_withCareMapTxtAndCompatibilityZip(self):
+ entries = (
+ 'payload.bin',
+ 'payload_properties.txt',
+ 'care_map.txt',
+ 'compatibility.zip',
+ )
+ zip_file = self._construct_zip_package(entries)
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ streaming_metadata = ComputeStreamingMetadata(zip_fp, reserve_space=True)
+ tokens = self._parse_streaming_metadata_string(streaming_metadata)
+
+ self.assertEqual(5, len(tokens))
+ self._verify_entries(zip_file, tokens, entries)
+
+ def test_ComputeStreamingMetadata(self):
+ entries = [
+ 'payload.bin',
+ 'payload_properties.txt',
+ 'META-INF/com/android/metadata',
+ ]
+ zip_file = self._construct_zip_package(entries)
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ streaming_metadata = ComputeStreamingMetadata(zip_fp, reserve_space=False)
+ tokens = self._parse_streaming_metadata_string(streaming_metadata)
+
+ self.assertEqual(3, len(tokens))
+ # 'META-INF/com/android/metadata' will be key'd as 'metadata' in the
+ # streaming metadata.
+ entries[2] = 'metadata'
+ self._verify_entries(zip_file, tokens, entries)
+
+ def test_ComputeStreamingMetadata_withExpectedLength(self):
+ entries = (
+ 'payload.bin',
+ 'payload_properties.txt',
+ 'care_map.txt',
+ 'META-INF/com/android/metadata',
+ )
+ zip_file = self._construct_zip_package(entries)
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ # First get the raw metadata string (i.e. without padding space).
+ raw_metadata = ComputeStreamingMetadata(
+ zip_fp,
+ reserve_space=False)
+ raw_length = len(raw_metadata)
+
+ # Now pass in the exact expected length.
+ streaming_metadata = ComputeStreamingMetadata(
+ zip_fp,
+ reserve_space=False,
+ expected_length=raw_length)
+ self.assertEqual(raw_length, len(streaming_metadata))
+
+ # Or pass in insufficient length.
+ self.assertRaises(
+ AssertionError,
+ ComputeStreamingMetadata,
+ zip_fp,
+ reserve_space=False,
+ expected_length=raw_length - 1)
+
+ # Or pass in a much larger size.
+ streaming_metadata = ComputeStreamingMetadata(
+ zip_fp,
+ reserve_space=False,
+ expected_length=raw_length + 20)
+ self.assertEqual(raw_length + 20, len(streaming_metadata))
+ self.assertEqual(' ' * 20, streaming_metadata[raw_length:])
+
class PayloadSignerTest(unittest.TestCase):
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index f417129..db1ba2e 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -27,6 +27,7 @@
import os.path
import re
import sys
+import zipfile
import common
@@ -61,7 +62,10 @@
def CheckAllFiles(which):
logging.info('Checking %s image.', which)
- image = common.GetSparseImage(which, input_tmp, input_zip)
+ # Allow having shared blocks when loading the sparse image, because allowing
+ # that doesn't affect the checks below (we will have all the blocks on file,
+ # unless it's skipped due to the holes).
+ image = common.GetSparseImage(which, input_tmp, input_zip, True)
prefix = '/' + which
for entry in image.file_map:
# Skip entries like '__NONZERO-0'.