Merge "Collect all lsdump paths and write them to $(OUT_DIR)."
diff --git a/core/Makefile b/core/Makefile
index bb2f6ea..8452494 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -2480,7 +2480,7 @@
 # $1: root directory
 # $2: add prefix
 define fs_config
-(cd $(1); find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,$(2),' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC)
+(cd $(1); find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,$(2),' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) -R "$(2)"
 endef
 
 # Depending on the various images guarantees that the underlying
diff --git a/core/config.mk b/core/config.mk
index 4942be7..7448623 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -89,15 +89,6 @@
 dist_goal := $(strip $(filter dist,$(MAKECMDGOALS)))
 MAKECMDGOALS := $(strip $(filter-out dist,$(MAKECMDGOALS)))
 
-# Tell python not to spam the source tree with .pyc files.  This
-# only has an effect on python 2.6 and above.
-export PYTHONDONTWRITEBYTECODE := 1
-
-ifneq ($(filter --color=always, $(GREP_OPTIONS)),)
-$(warning The build system needs unmodified output of grep.)
-$(error Please remove --color=always from your  $$GREP_OPTIONS)
-endif
-
 UNAME := $(shell uname -sm)
 
 SRC_TARGET_DIR := $(TOPDIR)build/target
@@ -580,6 +571,7 @@
 SOONG_JAVAC_WRAPPER := $(SOONG_HOST_OUT_EXECUTABLES)/soong_javac_wrapper
 SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip
 MERGE_ZIPS := $(SOONG_HOST_OUT_EXECUTABLES)/merge_zips
+XMLLINT := $(SOONG_HOST_OUT_EXECUTABLES)/xmllint
 ZIP2ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/zip2zip
 ZIPTIME := $(prebuilt_build_tools_bin)/ziptime
 
@@ -893,12 +885,6 @@
 $(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES := default
 endif
 
-# These will come from Soong, drop the environment versions
-unexport CLANG
-unexport CLANG_CXX
-unexport CCC_CC
-unexport CCC_CXX
-
 # ###############################################################
 # Collect a list of the SDK versions that we could compile against
 # For use with the LOCAL_SDK_VERSION variable for include $(BUILD_PACKAGE)
diff --git a/core/definitions.mk b/core/definitions.mk
index 2f3f356..f6f5840 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2686,9 +2686,9 @@
 # $(1): source file
 # $(2): destination file, must end with .xml.
 define copy-xml-file-checked
-$(2): $(1)
+$(2): $(1) $(XMLLINT)
 	@echo "Copy xml: $$@"
-	$(hide) xmllint $$< >/dev/null  # Don't print the xml file to stdout.
+	$(hide) $(XMLLINT) $$< >/dev/null  # Don't print the xml file to stdout.
 	$$(copy-file-to-target)
 endef
 
diff --git a/core/dex_preopt_libart_boot.mk b/core/dex_preopt_libart_boot.mk
index 8d0539a..a5e7e88 100644
--- a/core/dex_preopt_libart_boot.mk
+++ b/core/dex_preopt_libart_boot.mk
@@ -73,6 +73,23 @@
 # Note: this is technically incorrect. Compiled code contains stack checks which may depend
 #       on ASAN settings.
 
+# Use ANDROID_LOG_TAGS to suppress most logging by default...
+ifeq (,$(ART_BOOT_IMAGE_EXTRA_ARGS))
+DEX2OAT_BOOT_IMAGE_LOG_TAGS := ANDROID_LOG_TAGS="*:e"
+else
+# ...unless the boot image is generated specifically for testing, then allow all logging.
+DEX2OAT_BOOT_IMAGE_LOG_TAGS := ANDROID_LOG_TAGS="*:v"
+endif
+
+# An additional message to print on dex2oat failure.
+DEX2OAT_FAILURE_MESSAGE := ERROR: Dex2oat failed to compile a boot image.
+DEX2OAT_FAILURE_MESSAGE += It is likely that the boot classpath is inconsistent.
+ifeq ($(ONE_SHOT_MAKEFILE),)
+  DEX2OAT_FAILURE_MESSAGE += Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.
+else
+  DEX2OAT_FAILURE_MESSAGE += Build with m, mma, or mmma instead of mm or mmm to remedy the situation.
+endif
+
 $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME): PRIVATE_BOOT_IMAGE_FLAGS := $(my_boot_image_flags)
 $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME): PRIVATE_2ND_ARCH_VAR_PREFIX := $(my_2nd_arch_prefix)
 $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME): PRIVATE_IMAGE_LOCATION := $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION)
@@ -85,7 +102,7 @@
 	@rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.art
 	@rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.oat
 	@rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.art.rel
-	$(hide) ANDROID_LOG_TAGS="*:e" $(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
+	$(hide) $(DEX2OAT_BOOT_IMAGE_LOG_TAGS) $(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
 		--runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
 		$(PRIVATE_BOOT_IMAGE_FLAGS) \
 		$(addprefix --dex-file=,$(LIBART_TARGET_BOOT_DEX_FILES)) \
@@ -103,11 +120,12 @@
 		--multi-image --no-inline-from=core-oj.jar \
 		--abort-on-hard-verifier-error \
 		--abort-on-soft-verifier-error \
-		$(PRODUCT_DEX_PREOPT_BOOT_FLAGS) $(GLOBAL_DEXPREOPT_FLAGS) $(ART_BOOT_IMAGE_EXTRA_ARGS) && \
-	ANDROID_ROOT=$(PRODUCT_OUT)/system ANDROID_DATA=$(dir $@) $(PATCHOAT) \
-        --input-image-location=$(PRIVATE_IMAGE_LOCATION) \
-        --output-image-relocation-directory=$(dir $@) \
-        --instruction-set=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) \
-        --base-offset-delta=0x10000000
+		$(PRODUCT_DEX_PREOPT_BOOT_FLAGS) $(GLOBAL_DEXPREOPT_FLAGS) $(ART_BOOT_IMAGE_EXTRA_ARGS) \
+		|| ( echo "$(DEX2OAT_FAILURE_MESSAGE)" ; false ) && \
+	$(DEX2OAT_BOOT_IMAGE_LOG_TAGS) ANDROID_ROOT=$(PRODUCT_OUT)/system ANDROID_DATA=$(dir $@) $(PATCHOAT) \
+		--input-image-location=$(PRIVATE_IMAGE_LOCATION) \
+		--output-image-relocation-directory=$(dir $@) \
+		--instruction-set=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) \
+		--base-offset-delta=0x10000000
 
 endif
diff --git a/core/java.mk b/core/java.mk
index 442d6cb..dc20444 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -383,7 +383,7 @@
 # Make sure there's something to build.
 ifdef full_classes_jar
 ifndef need_compile_java
-$(error $(LOCAL_PATH): Target java module does not define any source or resource files)
+$(call pretty-error,Target java module does not define any source or resource files)
 endif
 endif
 
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index cb1d401..d4f5522 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -20,19 +20,19 @@
 
 ifdef LOCAL_PREBUILT_MODULE_FILE
   my_prebuilt_src_file := $(LOCAL_PREBUILT_MODULE_FILE)
+else ifdef LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+  my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
+  LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH) :=
+else ifdef LOCAL_SRC_FILES_$(my_32_64_bit_suffix)
+  my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES_$(my_32_64_bit_suffix))
+  LOCAL_SRC_FILES_$(my_32_64_bit_suffix) :=
+else ifdef LOCAL_SRC_FILES
+  my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES)
+  LOCAL_SRC_FILES :=
+else ifdef LOCAL_REPLACE_PREBUILT_APK_INSTALLED
+  # This is handled specially below
 else
-  ifdef LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
-    my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
-    LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH) :=
-  else
-    ifdef LOCAL_SRC_FILES_$(my_32_64_bit_suffix)
-      my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES_$(my_32_64_bit_suffix))
-      LOCAL_SRC_FILES_$(my_32_64_bit_suffix) :=
-    else
-      my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES)
-      LOCAL_SRC_FILES :=
-    endif
-  endif
+  $(call pretty-error,No source files specified)
 endif
 
 LOCAL_CHECKED_MODULE := $(my_prebuilt_src_file)
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index f10da32..2242582 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -24,8 +24,8 @@
 $(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(full_classes_pre_proguard_jar)))
 
 ifdef LOCAL_DROIDDOC_STUBS_JAR
-$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_STUBS_JAR),$(OUT_DOCS)/$(LOCAL_MODULE)-stubs.jar))
-ALL_DOCS += $(OUT_DOCS)/$(LOCAL_MODULE)-stubs.jar
+$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_STUBS_JAR),$(OUT_DOCS)/$(LOCAL_MODULE)-stubs.srcjar))
+ALL_DOCS += $(OUT_DOCS)/$(LOCAL_MODULE)-stubs.srcjar
 endif
 
 ifdef LOCAL_DROIDDOC_DOC_ZIP
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index 8d93f75..67d019f 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -25,6 +25,7 @@
 TARGET_CPU_ABI2 := armeabi
 HAVE_HTC_AUDIO_DRIVER := true
 BOARD_USES_GENERIC_AUDIO := true
+TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
 
 # no hardware camera
 USE_CAMERA_STUB := true
diff --git a/target/board/generic/sepolicy/OWNERS b/target/board/generic/sepolicy/OWNERS
index 4bd7e34..3828988 100644
--- a/target/board/generic/sepolicy/OWNERS
+++ b/target/board/generic/sepolicy/OWNERS
@@ -1,6 +1,4 @@
-nnk@google.com
 jeffv@google.com
-klyubin@google.com
 dcashman@google.com
 jbires@google.com
 sspatil@google.com
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index 9d2ccbd..e066e3a 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -20,6 +20,7 @@
 TARGET_ARCH_VARIANT := armv8-a
 TARGET_CPU_VARIANT := generic
 TARGET_CPU_ABI := arm64-v8a
+TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
 
 TARGET_2ND_ARCH := arm
 TARGET_2ND_CPU_ABI := armeabi-v7a
diff --git a/target/board/generic_arm64_ab/sepolicy/OWNERS b/target/board/generic_arm64_ab/sepolicy/OWNERS
index 4bd7e34..3828988 100644
--- a/target/board/generic_arm64_ab/sepolicy/OWNERS
+++ b/target/board/generic_arm64_ab/sepolicy/OWNERS
@@ -1,6 +1,4 @@
-nnk@google.com
 jeffv@google.com
-klyubin@google.com
 dcashman@google.com
 jbires@google.com
 sspatil@google.com
diff --git a/target/board/generic_arm_ab/BoardConfig.mk b/target/board/generic_arm_ab/BoardConfig.mk
index 011bcdf..b21e907 100644
--- a/target/board/generic_arm_ab/BoardConfig.mk
+++ b/target/board/generic_arm_ab/BoardConfig.mk
@@ -28,3 +28,11 @@
 # Enable A/B update
 TARGET_NO_RECOVERY := true
 BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
+
+# TODO(jiyong) These might be SoC specific.
+BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
+BOARD_ROOT_EXTRA_SYMLINKS := /vendor/lib/dsp:/dsp
+
+# TODO(b/36764215): remove this setting when the generic system image
+# no longer has QCOM-specific directories under /.
+BOARD_SEPOLICY_DIRS += build/target/board/generic_arm64_ab/sepolicy
diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index a73a31b..f71e72b 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -10,6 +10,7 @@
 TARGET_ARCH := x86
 TARGET_ARCH_VARIANT := x86
 TARGET_PRELINK_MODULE := false
+TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
 
 #emulator now uses 64bit kernel to run 32bit x86 image
 #
diff --git a/target/board/generic_x86/sepolicy/OWNERS b/target/board/generic_x86/sepolicy/OWNERS
index 4bd7e34..3828988 100644
--- a/target/board/generic_x86/sepolicy/OWNERS
+++ b/target/board/generic_x86/sepolicy/OWNERS
@@ -1,6 +1,4 @@
-nnk@google.com
 jeffv@google.com
-klyubin@google.com
 dcashman@google.com
 jbires@google.com
 sspatil@google.com
diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk
index aea1a0a..a9c5142 100755
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -10,6 +10,7 @@
 TARGET_ARCH := x86_64
 TARGET_ARCH_VARIANT := x86_64
 TARGET_PRELINK_MODULE := false
+TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
 
 TARGET_2ND_CPU_ABI := x86
 TARGET_2ND_ARCH := x86
diff --git a/target/product/aosp_x86.mk b/target/product/aosp_x86.mk
index 811c330..96c9e33 100644
--- a/target/product/aosp_x86.mk
+++ b/target/product/aosp_x86.mk
@@ -24,7 +24,7 @@
 PRODUCT_COPY_FILES += \
     development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
     device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
-    prebuilts/qemu-kernel/x86_64/3.18/kernel-qemu2:kernel-ranchu-64
+    prebuilts/qemu-kernel/x86_64/4.4/kernel-qemu2:kernel-ranchu-64
 
 include $(SRC_TARGET_DIR)/product/full_x86.mk
 
diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk
index 693bdaf..086a76f 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -25,7 +25,7 @@
 PRODUCT_COPY_FILES += \
     development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
     device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
-    prebuilts/qemu-kernel/x86_64/3.18/kernel-qemu2:kernel-ranchu
+    prebuilts/qemu-kernel/x86_64/4.4/kernel-qemu2:kernel-ranchu
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
diff --git a/target/product/core_base.mk b/target/product/core_base.mk
index 151e8de..7dc0010 100644
--- a/target/product/core_base.mk
+++ b/target/product/core_base.mk
@@ -62,9 +62,4 @@
     mdnsd \
     requestsync \
 
-# Wifi modules
-PRODUCT_PACKAGES += \
-    wifi-service \
-    wificond \
-
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_minimal.mk)
diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk
index b9820d3..32d71eb 100644
--- a/target/product/sdk_phone_x86.mk
+++ b/target/product/sdk_phone_x86.mk
@@ -24,7 +24,7 @@
 PRODUCT_COPY_FILES += \
     development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
     device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
-    prebuilts/qemu-kernel/x86_64/3.18/kernel-qemu2:kernel-ranchu-64
+    prebuilts/qemu-kernel/x86_64/4.4/kernel-qemu2:kernel-ranchu-64
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
 
diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk
index a18c4f8..e40ebb5 100644
--- a/target/product/sdk_phone_x86_64.mk
+++ b/target/product/sdk_phone_x86_64.mk
@@ -25,7 +25,7 @@
 PRODUCT_COPY_FILES += \
     development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
     device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
-    prebuilts/qemu-kernel/x86_64/3.18/kernel-qemu2:kernel-ranchu
+    prebuilts/qemu-kernel/x86_64/4.4/kernel-qemu2:kernel-ranchu
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
diff --git a/tools/auto_gen_test_config.py b/tools/auto_gen_test_config.py
index da4443c..c7c5bdc 100755
--- a/tools/auto_gen_test_config.py
+++ b/tools/auto_gen_test_config.py
@@ -70,8 +70,9 @@
     label = module
   runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
   package = manifest.attributes[ATTRIBUTE_PACKAGE].value
-  test_type = ('AndroidJUnitTest' if runner.endswith('.AndroidJUnitRunner')
-               else 'InstrumentationTest')
+  test_type = ('InstrumentationTest'
+               if runner.endswith('.InstrumentationTestRunner')
+               else 'AndroidJUnitTest')
 
   with open(instrumentation_test_config_template) as template:
     config = template.read()
diff --git a/tools/auto_gen_test_config_test.py b/tools/auto_gen_test_config_test.py
index e70eff8..e68c27f 100644
--- a/tools/auto_gen_test_config_test.py
+++ b/tools/auto_gen_test_config_test.py
@@ -155,7 +155,7 @@
       self.assertEqual(config_file.read(), EXPECTED_JUNIT_TEST_CONFIG)
 
   def testCreateInstrumentationTestConfig(self):
-    """Test creating test config for AndroidJUnitTest.
+    """Test creating test config for InstrumentationTest.
     """
     with open(self.manifest_file, 'w') as f:
       f.write(MANIFEST_INSTRUMENTATION_TEST)
diff --git a/tools/fs_config/fs_config.c b/tools/fs_config/fs_config.c
index 48f300b..2952875 100644
--- a/tools/fs_config/fs_config.c
+++ b/tools/fs_config/fs_config.c
@@ -67,17 +67,18 @@
 }
 
 static void usage() {
-  fprintf(stderr, "Usage: fs_config [-D product_out_path] [-S context_file] [-C]\n");
+  fprintf(stderr, "Usage: fs_config [-D product_out_path] [-S context_file] [-R root] [-C]\n");
 }
 
 int main(int argc, char** argv) {
   char buffer[1024];
   const char* context_file = NULL;
   const char* product_out_path = NULL;
+  char* root_path = NULL;
   struct selabel_handle* sehnd = NULL;
   int print_capabilities = 0;
   int opt;
-  while((opt = getopt(argc, argv, "CS:D:")) != -1) {
+  while((opt = getopt(argc, argv, "CS:R:D:")) != -1) {
     switch(opt) {
     case 'C':
       print_capabilities = 1;
@@ -85,6 +86,9 @@
     case 'S':
       context_file = optarg;
       break;
+    case 'R':
+      root_path = optarg;
+      break;
     case 'D':
       product_out_path = optarg;
       break;
@@ -98,6 +102,14 @@
     sehnd = get_sehnd(context_file);
   }
 
+  if (root_path != NULL) {
+    size_t root_len = strlen(root_path);
+    /* Trim any trailing slashes from the root path. */
+    while (root_len && root_path[--root_len] == '/') {
+      root_path[root_len] = '\0';
+    }
+  }
+
   while (fgets(buffer, 1023, stdin) != NULL) {
     int is_dir = 0;
     int i;
@@ -122,6 +134,10 @@
     unsigned uid = 0, gid = 0, mode = 0;
     uint64_t capabilities;
     fs_config(buffer, is_dir, product_out_path, &uid, &gid, &mode, &capabilities);
+    if (root_path != NULL && strcmp(buffer, root_path) == 0) {
+      /* The root of the filesystem needs to be an empty string. */
+      strcpy(buffer, "");
+    }
     printf("%s %d %d %o", buffer, uid, gid, mode);
 
     if (sehnd != NULL) {
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index a37de66..f68976e 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -96,7 +96,16 @@
 
 
 def GetCareMap(which, imgname):
-  """Generates the care_map for the given partition."""
+  """Returns the care_map string for the given partition.
+
+  Args:
+    which: The partition name, must be listed in PARTITIONS_WITH_CARE_MAP.
+    imgname: The filename of the image.
+
+  Returns:
+    (which, care_map_ranges): care_map_ranges is the raw string of the care_map
+    RangeSet.
+  """
   assert which in PARTITIONS_WITH_CARE_MAP
 
   simg = sparse_img.SparseImage(imgname)
@@ -111,13 +120,13 @@
   return [which, care_map_ranges.to_string_raw()]
 
 
-def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
+def AddSystem(output_zip, recovery_img=None, boot_img=None):
   """Turn the contents of SYSTEM into a system image and store it in
   output_zip. Returns the name of the system image file."""
 
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "system.img")
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.img")
   if os.path.exists(img.input_name):
-    print("system.img already exists in %s, no need to rebuild..." % (prefix,))
+    print("system.img already exists; no need to rebuild...")
     return img.input_name
 
   def output_sink(fn, data):
@@ -136,65 +145,66 @@
     common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
                              boot_img, info_dict=OPTIONS.info_dict)
 
-  block_list = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "system.map")
+  block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.map")
   CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system", img,
               block_list=block_list)
 
   return img.name
 
 
-def AddSystemOther(output_zip, prefix="IMAGES/"):
+def AddSystemOther(output_zip):
   """Turn the contents of SYSTEM_OTHER into a system_other image
   and store it in output_zip."""
 
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "system_other.img")
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system_other.img")
   if os.path.exists(img.input_name):
-    print("system_other.img already exists in %s, no need to rebuild..." % (
-        prefix,))
+    print("system_other.img already exists; no need to rebuild...")
     return
 
   CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system_other", img)
 
 
-def AddVendor(output_zip, prefix="IMAGES/"):
+def AddVendor(output_zip):
   """Turn the contents of VENDOR into a vendor image and store in it
   output_zip."""
 
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "vendor.img")
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.img")
   if os.path.exists(img.input_name):
-    print("vendor.img already exists in %s, no need to rebuild..." % (prefix,))
+    print("vendor.img already exists; no need to rebuild...")
     return img.input_name
 
-  block_list = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "vendor.map")
+  block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.map")
   CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "vendor", img,
               block_list=block_list)
   return img.name
 
 
-def AddProduct(output_zip, prefix="IMAGES/"):
-  """Turn the contents of PRODUCT into a product image and store it in output_zip."""
+def AddProduct(output_zip):
+  """Turn the contents of PRODUCT into a product image and store it in
+  output_zip."""
 
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "product.img")
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "product.img")
   if os.path.exists(img.input_name):
-    print("product.img already exists in %s, no need to rebuild..." % (prefix,))
+    print("product.img already exists; no need to rebuild...")
     return img.input_name
 
-  block_list = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "product.map")
-  CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "product", img,
-              block_list=block_list)
+  block_list = OutputFile(
+      output_zip, OPTIONS.input_tmp, "IMAGES", "product.map")
+  CreateImage(
+      OPTIONS.input_tmp, OPTIONS.info_dict, "product", img,
+      block_list=block_list)
   return img.name
 
 
-def AddDtbo(output_zip, prefix="IMAGES/"):
+def AddDtbo(output_zip):
   """Adds the DTBO image.
 
-  Uses the image under prefix if it already exists. Otherwise looks for the
+  Uses the image under IMAGES/ if it already exists. Otherwise looks for the
   image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
   """
-
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "dtbo.img")
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "dtbo.img")
   if os.path.exists(img.input_name):
-    print("dtbo.img already exists in %s, no need to rebuild..." % (prefix,))
+    print("dtbo.img already exists; no need to rebuild...")
     return img.input_name
 
   dtbo_prebuilt_path = os.path.join(
@@ -288,7 +298,7 @@
       info_dict[adjusted_blocks_key] = int(adjusted_blocks_value)/4096 - 1
 
 
-def AddUserdata(output_zip, prefix="IMAGES/"):
+def AddUserdata(output_zip):
   """Create a userdata image and store it in output_zip.
 
   In most case we just create and store an empty userdata.img;
@@ -297,10 +307,9 @@
   in OPTIONS.info_dict.
   """
 
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "userdata.img")
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "userdata.img")
   if os.path.exists(img.input_name):
-    print("userdata.img already exists in %s, no need to rebuild..." % (
-        prefix,))
+    print("userdata.img already exists; no need to rebuild...")
     return
 
   # Skip userdata.img if no size.
@@ -356,7 +365,7 @@
     cmd.extend(["--include_descriptors_from_image", img_path])
 
 
-def AddVBMeta(output_zip, partitions, prefix="IMAGES/"):
+def AddVBMeta(output_zip, partitions):
   """Creates a VBMeta image and store it in output_zip.
 
   Args:
@@ -365,9 +374,9 @@
         values. Only valid partition names are accepted, which include 'boot',
         'recovery', 'system', 'vendor', 'dtbo'.
   """
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "vbmeta.img")
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vbmeta.img")
   if os.path.exists(img.input_name):
-    print("vbmeta.img already exists in %s; not rebuilding..." % (prefix,))
+    print("vbmeta.img already exists; not rebuilding...")
     return img.input_name
 
   avbtool = os.getenv('AVBTOOL') or OPTIONS.info_dict["avb_avbtool"]
@@ -412,11 +421,13 @@
   img.Write()
 
 
-def AddPartitionTable(output_zip, prefix="IMAGES/"):
+def AddPartitionTable(output_zip):
   """Create a partition table image and store it in output_zip."""
 
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "partition-table.img")
-  bpt = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "partition-table.bpt")
+  img = OutputFile(
+      output_zip, OPTIONS.input_tmp, "IMAGES", "partition-table.img")
+  bpt = OutputFile(
+      output_zip, OPTIONS.input_tmp, "IMAGES", "partition-table.bpt")
 
   # use BPTTOOL from environ, or "bpttool" if empty or not set.
   bpttool = os.getenv("BPTTOOL") or "bpttool"
@@ -441,12 +452,12 @@
   bpt.Write()
 
 
-def AddCache(output_zip, prefix="IMAGES/"):
+def AddCache(output_zip):
   """Create an empty cache image and store it in output_zip."""
 
-  img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "cache.img")
+  img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "cache.img")
   if os.path.exists(img.input_name):
-    print("cache.img already exists in %s, no need to rebuild..." % (prefix,))
+    print("cache.img already exists; no need to rebuild...")
     return
 
   image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, "cache")
@@ -621,23 +632,26 @@
   The images will be created under IMAGES/ in the input target_files.zip.
 
   Args:
-      filename: the target_files.zip, or the zip root directory.
+    filename: the target_files.zip, or the zip root directory.
   """
   if os.path.isdir(filename):
     OPTIONS.input_tmp = os.path.abspath(filename)
-    input_zip = None
   else:
-    OPTIONS.input_tmp, input_zip = common.UnzipTemp(filename)
+    OPTIONS.input_tmp = common.UnzipTemp(filename)
 
   if not OPTIONS.add_missing:
     if os.path.isdir(os.path.join(OPTIONS.input_tmp, "IMAGES")):
       print("target_files appears to already contain images.")
       sys.exit(1)
 
-  # {vendor,product}.img is unlike system.img or system_other.img. Because it could
-  # be built from source, or dropped into target_files.zip as a prebuilt blob.
-  # We consider either of them as {vendor,product}.img being available, which could
-  # be used when generating vbmeta.img for AVB.
+  OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, OPTIONS.input_tmp)
+
+  has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
+
+  # {vendor,product}.img is unlike system.img or system_other.img. Because it
+  # could be built from source, or dropped into target_files.zip as a prebuilt
+  # blob. We consider either of them as {vendor,product}.img being available,
+  # which could be used when generating vbmeta.img for AVB.
   has_vendor = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "VENDOR")) or
                 os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES",
                                             "vendor.img")))
@@ -647,16 +661,14 @@
   has_system_other = os.path.isdir(os.path.join(OPTIONS.input_tmp,
                                                 "SYSTEM_OTHER"))
 
-  if input_zip:
-    OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp)
-
-    common.ZipClose(input_zip)
+  # Set up the output destination. It writes to the given directory for dir
+  # mode; otherwise appends to the given ZIP.
+  if os.path.isdir(filename):
+    output_zip = None
+  else:
     output_zip = zipfile.ZipFile(filename, "a",
                                  compression=zipfile.ZIP_DEFLATED,
                                  allowZip64=True)
-  else:
-    OPTIONS.info_dict = common.LoadInfoDict(filename, filename)
-    output_zip = None
 
   # Always make input_tmp/IMAGES available, since we may stage boot / recovery
   # images there even under zip mode. The directory will be cleaned up as part
@@ -665,8 +677,6 @@
   if not os.path.isdir(images_dir):
     os.makedirs(images_dir)
 
-  has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true")
-
   # A map between partition names and their paths, which could be used when
   # generating AVB vbmeta image.
   partitions = dict()
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index db63fd3..a3a5c1c 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -248,7 +248,7 @@
     if compressed_extension:
       apk_extensions.append("*.apk" + compressed_extension)
 
-    d, z = common.UnzipTemp(filename, apk_extensions)
+    d = common.UnzipTemp(filename, apk_extensions)
     try:
       self.apks = {}
       self.apks_by_basename = {}
@@ -283,8 +283,6 @@
     finally:
       shutil.rmtree(d)
 
-    z.close()
-
   def CheckSharedUids(self):
     """Look for any instances where packages signed with different
     certs request the same sharedUserId."""
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 0c87857..743c6a0 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -221,21 +221,6 @@
             vendor_base_fs_file,))
         del d["vendor_base_fs_file"]
 
-  try:
-    data = read_helper("META/imagesizes.txt")
-    for line in data.split("\n"):
-      if not line:
-        continue
-      name, value = line.split(" ", 1)
-      if not value:
-        continue
-      if name == "blocksize":
-        d[name] = value
-      else:
-        d[name + "_size"] = value
-  except KeyError:
-    pass
-
   def makeint(key):
     if key in d:
       d[key] = int(d[key], 0)
@@ -599,8 +584,7 @@
   then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
 
   Returns:
-    (tempdir, zipobj): tempdir is the name of the temprary directory; zipobj is
-        a zipfile.ZipFile (of the main file), open for reading.
+    The name of the temporary directory.
   """
 
   def unzip_to_dir(filename, dirname):
@@ -622,7 +606,7 @@
   else:
     unzip_to_dir(filename, tmp)
 
-  return tmp, zipfile.ZipFile(filename, "r")
+  return tmp
 
 
 def GetSparseImage(which, tmpdir, input_zip, allow_shared_blocks):
@@ -1550,9 +1534,7 @@
     b = blockimgdiff.BlockImageDiff(tgt, src, threads=OPTIONS.worker_threads,
                                     version=self.version,
                                     disable_imgdiff=self.disable_imgdiff)
-    tmpdir = tempfile.mkdtemp()
-    OPTIONS.tempfiles.append(tmpdir)
-    self.path = os.path.join(tmpdir, partition)
+    self.path = os.path.join(MakeTempDir(), partition)
     b.Compute(self.path)
     self._required_cache = b.max_stashed_size
     self.touched_src_ranges = b.touched_src_ranges
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index 4422b53..e6e8c9f 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -71,8 +71,7 @@
     common.Usage(__doc__)
     sys.exit(1)
 
-  OPTIONS.input_tmp, input_zip = common.UnzipTemp(
-      args[0], ["IMAGES/*", "OTA/*"])
+  OPTIONS.input_tmp = common.UnzipTemp(args[0], ["IMAGES/*", "OTA/*"])
   output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED)
   CopyInfo(output_zip)
 
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 6e3ef0a..7d76dcb 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -1248,8 +1248,11 @@
   target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
   target_zip = zipfile.ZipFile(target_file, 'w', allowZip64=True)
 
-  input_tmp, input_zip = common.UnzipTemp(input_file, UNZIP_PATTERN)
-  for info in input_zip.infolist():
+  input_tmp = common.UnzipTemp(input_file, UNZIP_PATTERN)
+  with zipfile.ZipFile(input_file, 'r') as input_zip:
+    infolist = input_zip.infolist()
+
+  for info in infolist:
     unzipped_file = os.path.join(input_tmp, *info.filename.split('/'))
     if info.filename == 'IMAGES/system_other.img':
       common.ZipWrite(target_zip, unzipped_file, arcname='IMAGES/system.img')
@@ -1266,7 +1269,6 @@
     elif info.filename.startswith(('META/', 'IMAGES/')):
       common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
 
-  common.ZipClose(input_zip)
   common.ZipClose(target_zip)
 
   return target_file
@@ -1634,11 +1636,9 @@
 
   if OPTIONS.extracted_input is not None:
     OPTIONS.input_tmp = OPTIONS.extracted_input
-    input_zip = zipfile.ZipFile(args[0], "r")
   else:
     print("unzipping target target-files...")
-    OPTIONS.input_tmp, input_zip = common.UnzipTemp(
-        args[0], UNZIP_PATTERN)
+    OPTIONS.input_tmp = common.UnzipTemp(args[0], UNZIP_PATTERN)
   OPTIONS.target_tmp = OPTIONS.input_tmp
 
   # If the caller explicitly specified the device-specific extensions path via
@@ -1670,16 +1670,17 @@
 
   # Generate a full OTA.
   if OPTIONS.incremental_source is None:
-    WriteFullOTAPackage(input_zip, output_zip)
+    with zipfile.ZipFile(args[0], 'r') as input_zip:
+      WriteFullOTAPackage(input_zip, output_zip)
 
   # Generate an incremental OTA.
   else:
     print("unzipping source target-files...")
-    OPTIONS.source_tmp, source_zip = common.UnzipTemp(
-        OPTIONS.incremental_source,
-        UNZIP_PATTERN)
-
-    WriteBlockIncrementalOTAPackage(input_zip, source_zip, output_zip)
+    OPTIONS.source_tmp = common.UnzipTemp(
+        OPTIONS.incremental_source, UNZIP_PATTERN)
+    with zipfile.ZipFile(args[0], 'r') as input_zip, \
+        zipfile.ZipFile(OPTIONS.incremental_source, 'r') as source_zip:
+      WriteBlockIncrementalOTAPackage(input_zip, source_zip, output_zip)
 
     if OPTIONS.log_diff:
       with open(OPTIONS.log_diff, 'w') as out_file:
@@ -1687,7 +1688,6 @@
         target_files_diff.recursiveDiff(
             '', OPTIONS.source_tmp, OPTIONS.input_tmp, out_file)
 
-  common.ZipClose(input_zip)
   common.ZipClose(output_zip)
 
   # Sign the generated zip package unless no_signing is specified.
diff --git a/tools/releasetools/test_add_img_to_target_files.py b/tools/releasetools/test_add_img_to_target_files.py
index e449ca8..9a0f78e 100644
--- a/tools/releasetools/test_add_img_to_target_files.py
+++ b/tools/releasetools/test_add_img_to_target_files.py
@@ -20,7 +20,11 @@
 import zipfile
 
 import common
-from add_img_to_target_files import AddPackRadioImages, AddRadioImagesForAbOta
+import test_utils
+from add_img_to_target_files import (
+    AddCareMapTxtForAbOta, AddPackRadioImages, AddRadioImagesForAbOta,
+    GetCareMap)
+from rangelib import RangeSet
 
 
 OPTIONS = common.OPTIONS
@@ -166,3 +170,170 @@
 
     self.assertRaises(AssertionError, AddPackRadioImages, None,
                       images + ['baz'])
+
+  @staticmethod
+  def _test_AddCareMapTxtForAbOta():
+    """Helper function to set up the test for test_AddCareMapTxtForAbOta()."""
+    OPTIONS.info_dict = {
+        'system_verity_block_device' : '/dev/block/system',
+        'vendor_verity_block_device' : '/dev/block/vendor',
+    }
+
+    # Prepare the META/ folder.
+    meta_path = os.path.join(OPTIONS.input_tmp, 'META')
+    if not os.path.exists(meta_path):
+      os.mkdir(meta_path)
+
+    system_image = test_utils.construct_sparse_image([
+        (0xCAC1, 6),
+        (0xCAC3, 4),
+        (0xCAC1, 6)])
+    vendor_image = test_utils.construct_sparse_image([
+        (0xCAC2, 10)])
+
+    image_paths = {
+        'system' : system_image,
+        'vendor' : vendor_image,
+    }
+    return image_paths
+
+  def test_AddCareMapTxtForAbOta(self):
+    image_paths = self._test_AddCareMapTxtForAbOta()
+
+    AddCareMapTxtForAbOta(None, ['system', 'vendor'], image_paths)
+
+    care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+    with open(care_map_file, 'r') as verify_fp:
+      care_map = verify_fp.read()
+
+    lines = care_map.split('\n')
+    self.assertEqual(4, len(lines))
+    self.assertEqual('system', lines[0])
+    self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+    self.assertEqual('vendor', lines[2])
+    self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+  def test_AddCareMapTxtForAbOta_withNonCareMapPartitions(self):
+    """Partitions without care_map should be ignored."""
+    image_paths = self._test_AddCareMapTxtForAbOta()
+
+    AddCareMapTxtForAbOta(
+        None, ['boot', 'system', 'vendor', 'vbmeta'], image_paths)
+
+    care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+    with open(care_map_file, 'r') as verify_fp:
+      care_map = verify_fp.read()
+
+    lines = care_map.split('\n')
+    self.assertEqual(4, len(lines))
+    self.assertEqual('system', lines[0])
+    self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+    self.assertEqual('vendor', lines[2])
+    self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+  def test_AddCareMapTxtForAbOta_withAvb(self):
+    """Tests the case for device using AVB."""
+    image_paths = self._test_AddCareMapTxtForAbOta()
+    OPTIONS.info_dict = {
+        'avb_system_hashtree_enable' : 'true',
+        'avb_vendor_hashtree_enable' : 'true',
+    }
+
+    AddCareMapTxtForAbOta(None, ['system', 'vendor'], image_paths)
+
+    care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+    with open(care_map_file, 'r') as verify_fp:
+      care_map = verify_fp.read()
+
+    lines = care_map.split('\n')
+    self.assertEqual(4, len(lines))
+    self.assertEqual('system', lines[0])
+    self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+    self.assertEqual('vendor', lines[2])
+    self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+  def test_AddCareMapTxtForAbOta_verityNotEnabled(self):
+    """No care_map.txt should be generated if verity not enabled."""
+    image_paths = self._test_AddCareMapTxtForAbOta()
+    OPTIONS.info_dict = {}
+    AddCareMapTxtForAbOta(None, ['system', 'vendor'], image_paths)
+
+    care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+    self.assertFalse(os.path.exists(care_map_file))
+
+  def test_AddCareMapTxtForAbOta_missingImageFile(self):
+    """Missing image file should be considered fatal."""
+    image_paths = self._test_AddCareMapTxtForAbOta()
+    image_paths['vendor'] = ''
+    self.assertRaises(AssertionError, AddCareMapTxtForAbOta, None,
+                      ['system', 'vendor'], image_paths)
+
+  def test_AddCareMapTxtForAbOta_zipOutput(self):
+    """Tests the case with ZIP output."""
+    image_paths = self._test_AddCareMapTxtForAbOta()
+
+    output_file = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(output_file, 'w') as output_zip:
+      AddCareMapTxtForAbOta(output_zip, ['system', 'vendor'], image_paths)
+
+    with zipfile.ZipFile(output_file, 'r') as verify_zip:
+      care_map = verify_zip.read('META/care_map.txt').decode('ascii')
+
+    lines = care_map.split('\n')
+    self.assertEqual(4, len(lines))
+    self.assertEqual('system', lines[0])
+    self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+    self.assertEqual('vendor', lines[2])
+    self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+  def test_AddCareMapTxtForAbOta_zipOutput_careMapEntryExists(self):
+    """Tests the case with ZIP output which already has care_map entry."""
+    image_paths = self._test_AddCareMapTxtForAbOta()
+
+    output_file = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(output_file, 'w') as output_zip:
+      # Create an existing META/care_map.txt entry.
+      common.ZipWriteStr(output_zip, 'META/care_map.txt', 'dummy care_map.txt')
+
+      # Request to add META/care_map.txt again.
+      AddCareMapTxtForAbOta(output_zip, ['system', 'vendor'], image_paths)
+
+    # The one under OPTIONS.input_tmp must have been replaced.
+    care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+    with open(care_map_file, 'r') as verify_fp:
+      care_map = verify_fp.read()
+
+    lines = care_map.split('\n')
+    self.assertEqual(4, len(lines))
+    self.assertEqual('system', lines[0])
+    self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+    self.assertEqual('vendor', lines[2])
+    self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+    # The existing entry should be scheduled to be replaced.
+    self.assertIn('META/care_map.txt', OPTIONS.replace_updated_files_list)
+
+  def test_GetCareMap(self):
+    sparse_image = test_utils.construct_sparse_image([
+        (0xCAC1, 6),
+        (0xCAC3, 4),
+        (0xCAC1, 6)])
+    OPTIONS.info_dict = {
+        'system_adjusted_partition_size' : 12,
+    }
+    name, care_map = GetCareMap('system', sparse_image)
+    self.assertEqual('system', name)
+    self.assertEqual(RangeSet("0-5 10-12").to_string_raw(), care_map)
+
+  def test_GetCareMap_invalidPartition(self):
+    self.assertRaises(AssertionError, GetCareMap, 'oem', None)
+
+  def test_GetCareMap_invalidAdjustedPartitionSize(self):
+    sparse_image = test_utils.construct_sparse_image([
+        (0xCAC1, 6),
+        (0xCAC3, 4),
+        (0xCAC1, 6)])
+    OPTIONS.info_dict = {
+        'system_adjusted_partition_size' : -12,
+    }
+    self.assertRaises(AssertionError, GetCareMap, 'system', sparse_image)
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index c073eba..fb26b66 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -523,9 +523,9 @@
       target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 8))
       target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
 
-    tempdir, input_zip = common.UnzipTemp(target_files)
-    sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
-    input_zip.close()
+    tempdir = common.UnzipTemp(target_files)
+    with zipfile.ZipFile(target_files, 'r') as input_zip:
+      sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
 
     self.assertDictEqual(
         {
@@ -552,11 +552,11 @@
       target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 8))
       target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
 
-    tempdir, input_zip = common.UnzipTemp(target_files)
-    self.assertRaises(
-        AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
-        False)
-    input_zip.close()
+    tempdir = common.UnzipTemp(target_files)
+    with zipfile.ZipFile(target_files, 'r') as input_zip:
+      self.assertRaises(
+          AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
+          False)
 
   def test_GetSparseImage_sharedBlocks_notAllowed(self):
     """Tests the case of having overlapping blocks but disallowed."""
@@ -574,11 +574,11 @@
       target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 7))
       target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
 
-    tempdir, input_zip = common.UnzipTemp(target_files)
-    self.assertRaises(
-        AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
-        False)
-    input_zip.close()
+    tempdir = common.UnzipTemp(target_files)
+    with zipfile.ZipFile(target_files, 'r') as input_zip:
+      self.assertRaises(
+          AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
+          False)
 
   def test_GetSparseImage_sharedBlocks_allowed(self):
     """Tests the case for target using BOARD_EXT4_SHARE_DUP_BLOCKS := true."""
@@ -597,9 +597,9 @@
       target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 7))
       target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
 
-    tempdir, input_zip = common.UnzipTemp(target_files)
-    sparse_image = common.GetSparseImage('system', tempdir, input_zip, True)
-    input_zip.close()
+    tempdir = common.UnzipTemp(target_files)
+    with zipfile.ZipFile(target_files, 'r') as input_zip:
+      sparse_image = common.GetSparseImage('system', tempdir, input_zip, True)
 
     self.assertDictEqual(
         {
@@ -638,9 +638,9 @@
       # '/system/file2' has less blocks listed (2) than actual (3).
       target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
 
-    tempdir, input_zip = common.UnzipTemp(target_files)
-    sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
-    input_zip.close()
+    tempdir = common.UnzipTemp(target_files)
+    with zipfile.ZipFile(target_files, 'r') as input_zip:
+      sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
 
     self.assertFalse(sparse_image.file_map['/system/file1'].extra)
     self.assertTrue(sparse_image.file_map['/system/file2'].extra['incomplete'])
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index 1b3eb73..f417129 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -192,9 +192,10 @@
                       datefmt=date_format)
 
   logging.info("Unzipping the input target_files.zip: %s", args[0])
-  input_tmp, input_zip = common.UnzipTemp(args[0])
+  input_tmp = common.UnzipTemp(args[0])
 
-  ValidateFileConsistency(input_zip, input_tmp)
+  with zipfile.ZipFile(args[0], 'r') as input_zip:
+    ValidateFileConsistency(input_zip, input_tmp)
 
   info_dict = common.LoadInfoDict(input_tmp)
   ValidateInstallRecoveryScript(input_tmp, info_dict)