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'.