Merge "APK signer primitive."
diff --git a/core/Makefile b/core/Makefile
index 02bd4f7..79faae1 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -533,12 +533,6 @@
 
 INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
 
-BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
-ifdef BOARD_KERNEL_CMDLINE
-  INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
-  INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS += --kernel_cmdline "$(BOARD_KERNEL_CMDLINE)"
-endif
-
 BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
 ifdef BOARD_KERNEL_BASE
   INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
@@ -549,6 +543,18 @@
   INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
 endif
 
+ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true)
+ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+VERITY_KEYID := veritykeyid=id:`openssl x509 -in $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem -text \
+                | grep keyid | sed 's/://g' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/keyid//g'`
+endif
+endif
+
+BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) $(VERITY_KEYID))
+ifdef BOARD_KERNEL_CMDLINE
+INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
+endif
+
 INTERNAL_MKBOOTIMG_VERSION_ARGS := \
     --os_version $(PLATFORM_VERSION) \
     --os_patch_level $(PLATFORM_SECURITY_PATCH)
diff --git a/core/binary.mk b/core/binary.mk
index bcf07c2..9d3ef9b 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -1251,7 +1251,7 @@
 
 my_unused_src_files := $(filter-out $(logtags_sources) $(my_tracked_src_files),$(my_src_files) $(my_gen_src_files))
 ifneq ($(my_unused_src_files),)
-  $(warning $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Unused source files: $(my_unused_src_files))
+  $(error $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Unused source files: $(my_unused_src_files))
 endif
 
 # some rules depend on asm_objects being first.  If your code depends on
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 9ca880b..7733a3e 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -189,6 +189,7 @@
 LOCAL_DPI_FILE_STEM:=
 LOCAL_SANITIZE:=
 LOCAL_SANITIZE_RECOVER:=
+LOCAL_NOSANITIZE:=
 LOCAL_DBUS_PROXY_PREFIX:=
 LOCAL_INIT_RC:=
 LOCAL_MODULE_HOST_OS:=
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 3573f0a..9602626 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -19,9 +19,33 @@
   endif
 endif
 
-# The sanitizer specified by the environment wins over the module.
 ifneq ($(my_global_sanitize),)
-  my_sanitize := $(my_global_sanitize)
+  my_sanitize := $(my_global_sanitize) $(my_sanitize)
+endif
+
+# The sanitizer specified in the product configuration wins over the previous.
+ifneq ($(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG),)
+  my_sanitize := $(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG)
+  ifeq ($(my_sanitize),never)
+    my_sanitize :=
+  endif
+endif
+
+# Add a filter point for 32-bit vs 64-bit sanitization (to lighten the burden).
+SANITIZE_ARCH ?= 32 64
+ifeq ($(filter $(SANITIZE_ARCH),$(my_32_64_bit_suffix)),)
+  my_sanitize :=
+endif
+
+# Add a filter point based on module owner (to lighten the burden). The format is a space- or
+# colon-separated list of owner names.
+ifneq (,$(SANITIZE_NEVER_BY_OWNER))
+  ifneq (,$(LOCAL_MODULE_OWNER))
+    ifneq (,$(filter $(LOCAL_MODULE_OWNER),$(subst :, ,$(SANITIZE_NEVER_BY_OWNER))))
+      $(warning Not sanitizing $(LOCAL_MODULE) based on module owner.)
+      my_sanitize :=
+    endif
+  endif
 endif
 
 # Don't apply sanitizers to NDK code.
@@ -34,6 +58,11 @@
   my_sanitize :=
 endif
 
+my_nosanitize = $(strip $(LOCAL_NOSANITIZE))
+ifneq ($(my_nosanitize),)
+  my_sanitize := $(filter-out $(my_nosanitize),$(my_sanitize))
+endif
+
 # TSAN is not supported on 32-bit architectures. For non-multilib cases, make
 # its use an error. For multilib cases, don't use it for the 32-bit case.
 ifneq ($(filter thread,$(my_sanitize)),)
@@ -46,21 +75,23 @@
   endif
 endif
 
+ifneq ($(filter safe-stack,$(my_sanitize)),)
+  ifeq ($(my_32_64_bit_suffix),32)
+    my_sanitize := $(filter-out safe-stack,$(my_sanitize))
+  endif
+endif
+
 # Undefined symbols can occur if a non-sanitized library links
 # sanitized static libraries. That's OK, because the executable
 # always depends on the ASan runtime library, which defines these
 # symbols.
-ifneq ($(strip $(SANITIZE_TARGET)),)
+ifneq ($(filter address thread,$(strip $(SANITIZE_TARGET))),)
   ifndef LOCAL_IS_HOST_MODULE
     ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
       ifeq ($(my_sanitize),)
         my_allow_undefined_symbols := true
       endif
     endif
-    # Workaround for a bug in AddressSanitizer that breaks stack unwinding.
-    # https://code.google.com/p/address-sanitizer/issues/detail?id=387
-    # Revert when external/compiler-rt is updated past r236014.
-    LOCAL_PACK_MODULE_RELOCATIONS := false
   endif
 endif
 
@@ -92,11 +123,12 @@
     my_ldflags += -fsanitize=$(fsanitize_arg)
     my_ldlibs += -lrt -ldl
   else
-    ifeq ($(filter address,$(my_sanitize)),)
-      my_cflags += -fsanitize-trap=all
-      my_cflags += -ftrap-function=abort
+    my_cflags += -fsanitize-trap=all
+    my_cflags += -ftrap-function=abort
+    ifneq ($(filter address thread,$(my_sanitize)),)
+      my_cflags += -fno-sanitize-trap=address,thread
+      my_shared_libraries += libdl
     endif
-    my_shared_libraries += libdl
   endif
 endif
 
diff --git a/core/definitions.mk b/core/definitions.mk
index de1948f..5194918 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -1084,6 +1084,19 @@
     $< $(PRIVATE_HEADER_OUTPUT_DIR) $@
 endef
 
+## Given a .aidl file path, generate the rule to compile it a .java file
+# $(1): a .aidl source file
+# $(2): a directory to place the generated .java files in
+# $(3): name of a variable to add the path to the generated source file to
+#
+# You must call this with $(eval).
+define define-aidl-java-rule
+define-aidl-java-rule-src := $(patsubst %.aidl,%.java,$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
+$$(define-aidl-java-rule-src) : $(LOCAL_PATH)/$(1) $(AIDL)
+	$$(transform-aidl-to-java)
+$(3) += $$(define-aidl-java-rule-src)
+endef
+
 ## Given a .aidl file path generate the rule to compile it a .cpp file.
 # $(1): a .aidl source file
 # $(2): a directory to place the generated .cpp files in
@@ -2232,7 +2245,7 @@
 $1/classes.dex.toc: PRIVATE_INPUT_DEX_FILES := $1/classes*.dex
 $1/classes.dex.toc: $1/classes.dex $(DEXDUMP)
 	@echo Generating TOC: $$@
-	$(hide) $(DEXDUMP) -l xml $$(PRIVATE_INPUT_DEX_FILES) > $$@.tmp
+	$(hide) ANDROID_LOG_TAGS="*:e" $(DEXDUMP) -l xml $$(PRIVATE_INPUT_DEX_FILES) > $$@.tmp
 	$$(call commit-change-for-toc,$$@)
 endef
 
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 49ca154..1df25d2 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -78,7 +78,7 @@
   HOST_2ND_ARCH := x86
   HOST_IS_64_BIT := true
 else
-ifneq (,$(findstring x86,$(UNAME)))
+ifneq (,$(findstring i686,$(UNAME))$(findstring x86,$(UNAME)))
 $(error Building on a 32-bit x86 host is not supported: $(UNAME)!)
 endif
 endif
@@ -411,9 +411,9 @@
 
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR_EXECUTABLES)
 ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(TARGET_OUT_VENDOR)/lib/$(TARGET_2ND_ARCH)
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
 else
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(TARGET_OUT_VENDOR)/lib
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib
 endif
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR_APPS)
 
diff --git a/core/java.mk b/core/java.mk
index 912ce0a..85823b7 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -277,10 +277,9 @@
 ## AIDL: Compile .aidl files to .java
 ###########################################################
 aidl_sources := $(filter %.aidl,$(LOCAL_SRC_FILES))
+aidl_java_sources :=
 
 ifneq ($(strip $(aidl_sources)),)
-aidl_java_sources := $(patsubst %.aidl,%.java,$(addprefix $(intermediates.COMMON)/src/, $(aidl_sources)))
-aidl_sources := $(addprefix $(LOCAL_PATH)/, $(aidl_sources))
 
 aidl_preprocess_import :=
 ifdef LOCAL_SDK_VERSION
@@ -294,19 +293,17 @@
 # build against the platform.
 LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
 endif # LOCAL_SDK_VERSION
-$(aidl_java_sources): PRIVATE_AIDL_FLAGS := -b $(addprefix -p,$(aidl_preprocess_import)) -I$(LOCAL_PATH) -I$(LOCAL_PATH)/src $(addprefix -I,$(LOCAL_AIDL_INCLUDES))
 
-$(aidl_java_sources): $(intermediates.COMMON)/src/%.java: \
-        $(LOCAL_PATH)/%.aidl \
-        $(LOCAL_ADDITIONAL_DEPENDENCIES) \
-        $(AIDL) \
-        $(aidl_preprocess_import)
-	$(transform-aidl-to-java)
+$(foreach s,$(aidl_sources),\
+    $(eval $(call define-aidl-java-rule,$(s),$(intermediates.COMMON),aidl_java_sources)))
 $(foreach java,$(aidl_java_sources), \
     $(call include-depfile,$(java:%.java=%.P),$(java)))
 
-else
-aidl_java_sources :=
+$(aidl_java_sources) : $(LOCAL_ADDITIONAL_DEPENDENCIES) $(aidl_preprocess_import)
+
+$(aidl_java_sources): PRIVATE_AIDL_FLAGS := -b $(addprefix -p,$(aidl_preprocess_import)) -I$(LOCAL_PATH) -I$(LOCAL_PATH)/src $(addprefix -I,$(LOCAL_AIDL_INCLUDES))
+$(aidl_java_sources): PRIVATE_MODULE := $(LOCAL_MODULE)
+
 endif
 
 ##########################################
diff --git a/core/product.mk b/core/product.mk
index 4f780f9..7dfaa19 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -120,7 +120,12 @@
     PRODUCT_DEX_PREOPT_MODULE_CONFIGS \
     PRODUCT_DEX_PREOPT_DEFAULT_FLAGS \
     PRODUCT_DEX_PREOPT_BOOT_FLAGS \
+    PRODUCT_SANITIZER_MODULE_CONFIGS \
     PRODUCT_SHIPPING_API_LEVEL \
+    VENDOR_PRODUCT_RESTRICT_VENDOR_FILES \
+    VENDOR_EXCEPTION_MODULES \
+    VENDOR_EXCEPTION_PATHS \
+
 
 define dump-product
 $(info ==== $(1) ====)\
@@ -329,3 +334,14 @@
 $(eval PRODUCT_DEX_PREOPT_MODULE_CONFIGS += \
   $(foreach m,$(1),$(m)=$(_c)))
 endef
+
+# whitespace placeholder when we record module's sanitizer config.
+_PSMC_SP_PLACE_HOLDER := |@SP@|
+# Set up sanitizer config for a module.
+# $(1) list of module names
+# $(2) the modules' sanitizer config
+define add-product-sanitizer-module-config
+$(eval _c := $(subst $(space),$(_PSMC_SP_PLACE_HOLDER),$(strip $(2))))\
+$(eval PRODUCT_SANITIZER_MODULE_CONFIGS += \
+  $(foreach m,$(1),$(m)=$(_c)))
+endef
diff --git a/core/product_config.mk b/core/product_config.mk
index a4063f1..f00f4cd 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -390,7 +390,7 @@
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
 PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
-# Resolve and setup per-module dex-preopot configs.
+# Resolve and setup per-module dex-preopt configs.
 PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_MODULE_CONFIGS))
 # If a module has multiple setups, the first takes precedence.
@@ -403,3 +403,17 @@
     $(eval cf := $(subst $(_PDPMC_SP_PLACE_HOLDER),$(space),$(cf)))\
     $(eval DEXPREOPT.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
 _pdpmc_modules :=
+
+# Resolve and setup per-module sanitizer configs.
+PRODUCT_SANITIZER_MODULE_CONFIGS := \
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SANITIZER_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_psmc_modules :=
+$(foreach c,$(PRODUCT_SANITIZER_MODULE_CONFIGS),\
+  $(eval m := $(firstword $(subst =,$(space),$(c))))\
+  $(if $(filter $(_psmc_modules),$(m)),,\
+    $(eval _psmc_modules += $(m))\
+    $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+    $(eval cf := $(subst $(_PSMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+    $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_psmc_modules :=
diff --git a/core/tasks/check_boot_jars/package_whitelist.txt b/core/tasks/check_boot_jars/package_whitelist.txt
index 3cb6e28..1478aae 100644
--- a/core/tasks/check_boot_jars/package_whitelist.txt
+++ b/core/tasks/check_boot_jars/package_whitelist.txt
@@ -61,6 +61,7 @@
 javax\.xml\.transform\.stream
 javax\.xml\.validation
 javax\.xml\.xpath
+jdk\.net
 org\.w3c\.dom
 org\.w3c\.dom\.ls
 org\.w3c\.dom\.traversal
diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk
index 910c8b7..2a9c3d8 100644
--- a/core/tasks/vendor_module_check.mk
+++ b/core/tasks/vendor_module_check.mk
@@ -46,19 +46,43 @@
         widevine
 
 
-ifneq (,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES))
+_restrictions := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES))
 
-_vendor_check_modules := $(product_MODULES)
+ifneq (,$(_restrictions))
+ifneq (,$(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_PRODUCT_RESTRICT_VENDOR_FILES))
+$(error Error: cannot set both PRODUCT_RESTRICT_VENDOR_FILES and VENDOR_PRODUCT_RESTRICT_VENDOR_FILES)
+endif
+_vendor_exception_path_prefix :=
+_vendor_exception_modules :=
+else
+_restrictions := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_PRODUCT_RESTRICT_VENDOR_FILES))
+_vendor_exception_path_prefix := $(patsubst %, vendor/%/%, $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_EXCEPTION_PATHS))
+_vendor_exception_modules := $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_EXCEPTION_MODULES)
+endif
+
+
+ifneq (,$(_restrictions))
+
+_vendor_check_modules := \
+$(foreach m, $(filter-out $(_vendor_exception_modules), $(product_MODULES)), \
+  $(if $(filter-out FAKE, $(ALL_MODULES.$(m).CLASS)),\
+    $(if $(filter vendor/%, $(ALL_MODULES.$(m).PATH)),\
+      $(if $(filter-out $(_vendor_exception_path_prefix), $(ALL_MODULES.$(m).PATH)),\
+        $(m)))))
 
 _vendor_module_owner_info :=
 # Restrict owners
-ifneq (,$(filter true owner all, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES)))
+ifneq (,$(filter true owner all, $(_restrictions)))
 
-ifneq (,$(filter vendor/%, $(PRODUCT_PACKAGE_OVERLAYS) $(DEVICE_PACKAGE_OVERLAYS)))
-$(error Error: Product "$(TARGET_PRODUCT)" cannot have overlay in vendor tree: \
+_vendor_package_overlays := $(filter-out $(_vendor_exception_path_prefix),\
     $(filter vendor/%, $(PRODUCT_PACKAGE_OVERLAYS) $(DEVICE_PACKAGE_OVERLAYS)))
+ifneq (,$(_vendor_package_overlays))
+$(error Error: Product "$(TARGET_PRODUCT)" cannot have overlay in vendor tree: $(_vendor_package_overlays))
 endif
-_vendor_check_copy_files := $(filter vendor/%, $(PRODUCT_COPY_FILES))
+_vendor_package_overlays :=
+
+_vendor_check_copy_files := $(filter-out $(_vendor_exception_path_prefix),\
+    $(filter vendor/%, $(PRODUCT_COPY_FILES)))
 ifneq (,$(_vendor_check_copy_files))
 $(foreach c, $(_vendor_check_copy_files), \
   $(if $(filter $(_vendor_owner_whitelist), $(call word-colon,3,$(c))),,\
@@ -68,28 +92,24 @@
 _vendor_check_copy_files :=
 
 $(foreach m, $(_vendor_check_modules), \
-  $(if $(filter vendor/%, $(ALL_MODULES.$(m).PATH)),\
-    $(if $(filter-out FAKE, $(ALL_MODULES.$(m).CLASS)),\
-      $(if $(filter $(_vendor_owner_whitelist), $(ALL_MODULES.$(m).OWNER)),,\
-        $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) with unknown owner \
-          "$(ALL_MODULES.$(m).OWNER)" in product "$(TARGET_PRODUCT)"))\
-      $(if $(ALL_MODULES.$(m).INSTALLED),\
-        $(eval _vendor_module_owner_info += $(patsubst $(PRODUCT_OUT)/%,%,$(ALL_MODULES.$(m).INSTALLED)):$(ALL_MODULES.$(m).OWNER))))))
+  $(if $(filter $(_vendor_owner_whitelist), $(ALL_MODULES.$(m).OWNER)),,\
+    $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) with unknown owner \
+      "$(ALL_MODULES.$(m).OWNER)" in product "$(TARGET_PRODUCT)"))\
+  $(if $(ALL_MODULES.$(m).INSTALLED),\
+    $(eval _vendor_module_owner_info += $(patsubst $(PRODUCT_OUT)/%,%,$(ALL_MODULES.$(m).INSTALLED)):$(ALL_MODULES.$(m).OWNER))))
 
 endif
 
 
 # Restrict paths
-ifneq (,$(filter path all, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES)))
+ifneq (,$(filter path all, $(_restrictions)))
 
 $(foreach m, $(_vendor_check_modules), \
-  $(if $(filter vendor/%, $(ALL_MODULES.$(m).PATH)),\
-    $(if $(filter-out FAKE, $(ALL_MODULES.$(m).CLASS)),\
-      $(if $(filter-out ,$(ALL_MODULES.$(m).INSTALLED)),\
-        $(if $(filter $(TARGET_OUT_VENDOR)/% $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED)),,\
-          $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) \
-            in product "$(TARGET_PRODUCT)" being installed to \
-            $(ALL_MODULES.$(m).INSTALLED) which is not in the vendor tree))))))
+  $(if $(filter-out ,$(ALL_MODULES.$(m).INSTALLED)),\
+    $(if $(filter $(TARGET_OUT_VENDOR)/% $(TARGET_OUT_ODM)/% $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED)),,\
+      $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) \
+        in product "$(TARGET_PRODUCT)" being installed to \
+        $(ALL_MODULES.$(m).INSTALLED) which is not in the vendor tree or odm tree))))
 
 endif
 
@@ -112,4 +132,7 @@
 _vendor_module_owner_info_txt :=
 _vendor_module_owner_info :=
 _vendor_check_modules :=
+_vendor_exception_path_prefix :=
+_vendor_exception_modules :=
+_restrictions :=
 endif
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 02e940e..5730019 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -396,12 +396,18 @@
   # For devices using A/B update, copy over images from RADIO/ and/or
   # VENDOR_IMAGES/ to IMAGES/ and make sure we have all the needed
   # images ready under IMAGES/. All images should have '.img' as extension.
+  banner("radio")
   ab_partitions = os.path.join(OPTIONS.input_tmp, "META", "ab_partitions.txt")
   if os.path.exists(ab_partitions):
     with open(ab_partitions, 'r') as f:
       lines = f.readlines()
     for line in lines:
       img_name = line.strip() + ".img"
+      prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
+      if os.path.exists(prebuilt_path):
+        print "%s already exists, no need to overwrite..." % (img_name,)
+        continue
+
       img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
       img_vendor_dir = os.path.join(
         OPTIONS.input_tmp, "VENDOR_IMAGES")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 9d080d9..8a5eb89 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -550,7 +550,7 @@
     cmd.extend(["--algorithm", algorithm, "--key", key_path])
   else:
     cmd.extend(["--algorithm", "SHA256_RSA4096"])
-    cmd.extend(["--key", "system/bvb/test/testkey_rsa4096.pem"])
+    cmd.extend(["--key", "external/bvb/test/testkey_rsa4096.pem"])
 
   args = info_dict.get("board_bvb_sign_boot_image_args", None)
   if args and args.strip():
diff --git a/tools/warn.py b/tools/warn.py
index a4a9e16..b61505b 100755
--- a/tools/warn.py
+++ b/tools/warn.py
@@ -1683,8 +1683,41 @@
 ]
 
 anchor = 0
-cur_row_color = 0
-row_colors = [ 'e0e0e0', 'd0d0d0' ]
+cur_row_class = 0
+
+html_script_style = """\
+    <script type="text/javascript">
+    function expand(id) {
+      var e = document.getElementById(id);
+      var f = document.getElementById(id + "_mark");
+      if (e.style.display == 'block') {
+         e.style.display = 'none';
+         f.innerHTML = '&#x2295';
+      }
+      else {
+         e.style.display = 'block';
+         f.innerHTML = '&#x2296';
+      }
+    };
+    function expand_collapse(show) {
+      for (var id = 1; ; id++) {
+        var e = document.getElementById(id + "");
+        var f = document.getElementById(id + "_mark");
+        if (!e || !f) break;
+        e.style.display = (show ? 'block' : 'none');
+        f.innerHTML = (show ? '&#x2296' : '&#x2295');
+      }
+    };
+    </script>
+    <style type="text/css">
+    table,th,td{border-collapse:collapse; width:100%;}
+    .button{color:blue;font-size:110%;font-weight:bolder;}
+    .bt{color:black;background-color:transparent;border:none;outline:none;
+        font-size:140%;font-weight:bolder;}
+    .c0{background-color:#e0e0e0;}
+    .c1{background-color:#d0d0d0;}
+    </style>\n"""
+
 
 def output(text):
     print text,
@@ -1693,39 +1726,23 @@
     return '<font size="+2">' + param + '</font>'
 
 def dumphtmlprologue(title):
-    output('<html>\n<head>\n<title>' + title + '</title>\n<body>\n')
+    output('<html>\n<head>\n')
+    output('<title>' + title + '</title>\n')
+    output(html_script_style)
+    output('</head>\n<body>\n')
     output('<a name="PageTop">')
     output(htmlbig(title))
     output('<p>\n')
 
+def dumphtmlepilogue():
+    output('</body>\n</head>\n</html>\n')
+
 def tablerow(text):
-    global cur_row_color
-    output('<tr bgcolor="' + row_colors[cur_row_color] + '"><td colspan="2">',)
-    cur_row_color = 1 - cur_row_color
-    output(text,)
-    output('</td></tr>\n')
-
-def begintable(text, backgroundcolor, extraanchor):
-    global anchor
-    output('<table border="1" rules="cols" frame="box" width="100%" bgcolor="black"><tr bgcolor="' +
-        backgroundcolor + '"><a name="anchor' + str(anchor) + '">')
-    if extraanchor:
-        output('<a name="' + extraanchor + '">')
-    output('<td>')
-    output(htmlbig(text[0]) + '<br>')
-    for i in text[1:]:
-        output(i + '<br>')
-    output('</td>')
-    output('<td width="100" bgcolor="grey">' +
-           '<a align="right" href="#PageTop">top</a><br>' +
-           '<a align="right" href="#anchor' + str(anchor-1) + '">previous</a><br>' +
-           '<a align="right" href="#anchor' + str(anchor+1) + '">next</a>')
-    output('</td></a></tr>')
-    anchor += 1
-
-def endtable():
-    output('</table><p>')
-
+    global cur_row_class
+    output('<tr><td class="c' + str(cur_row_class) + '">')
+    cur_row_class = 1 - cur_row_class
+    output(text)
+    output('</td></tr>')
 
 # dump some stats about total number of warnings and such
 def dumpstats():
@@ -1743,38 +1760,33 @@
     output('\nTotal number of warnings: <b>' + str(total) + '</b>')
     if total < 1000:
         output('(low count may indicate incremental build)')
-    output('\n<p>\n')
+    output('<br><br>\n')
+    output('<button class="button" onclick="expand_collapse(1);">' +
+           'Expand all warnings</button> ' +
+           '<button class="button" onclick="expand_collapse(0);">' +
+           'Collapse all warnings</button>')
+    output('<br>\n')
 
-# dump count of warnings of a given severity in TOC
-def dumpcount(sev):
-    first = True
-    for i in warnpatterns:
-      if i['severity'] == sev and len(i['members']) > 0:
-          if first:
-              output(headerforseverity(sev) + ':\n<blockquote>' +
-                     '<table border="1" frame="box" width="100%">')
-          output('<tr bgcolor="' + colorforseverity(sev) + '">' +
-                 '<td><a href="#' + i['anchor'] + '">' + descriptionfor(i) +
-                 ' (' + str(len(i['members'])) + ')</a></td></tr>\n')
-          first = False
-    if not first:
-        output('</table></blockquote>\n')
-
-# dump table of content, list of all warning patterns
-def dumptoc():
-    n = 1
+# dump everything for a given severity
+def dumpseverity(sev):
+    global anchor
+    output('\n<br><span style="background-color:' + colorforseverity(sev) + '"><b>' +
+           headerforseverity(sev) + ':</b></span>\n')
     output('<blockquote>\n')
     for i in warnpatterns:
-        i['anchor'] = 'Warning' + str(n)
-        n += 1
-    dumpcount(severity.FIXMENOW)
-    dumpcount(severity.HIGH)
-    dumpcount(severity.MEDIUM)
-    dumpcount(severity.LOW)
-    dumpcount(severity.TIDY)
-    dumpcount(severity.HARMLESS)
-    dumpcount(severity.UNKNOWN)
-    output('</blockquote>\n<p>\n')
+      if i['severity'] == sev and len(i['members']) > 0:
+          output('\n<table frame="box">\n')
+          anchor += 1
+          i['anchor'] = str(anchor)
+          mark = str(anchor) + '_mark'
+          output('<tr bgcolor="' + colorforseverity(sev) + '">' +
+                 '<td><button class="bt" id="' + mark +
+                 '" onclick="expand(\'' + str(anchor) + '\');">' +
+                 '&#x2295</button> ' + descriptionfor(i) +
+                 ' (' + str(len(i['members'])) + ')</td></tr>\n')
+          output('</table>\n')
+          dumpcategory(i)
+    output('</blockquote>\n')
 
 def allpatterns(cat):
     pats = ''
@@ -1791,15 +1803,28 @@
 
 # show which warnings no longer occur
 def dumpfixed():
-    tablestarted = False
+    global anchor
+    anchor += 1
+    mark = str(anchor) + '_mark'
+    output('\n<br><p style="background-color:lightblue"><b>' +
+           '<button id="' + mark + '" ' +
+           'class="bt" onclick="expand(' + str(anchor) + ');">' +
+           '&#x2295</button> Fixed warnings. ' +
+           'No more occurences. Please consider turning these into ' +
+           'errors if possible, before they are reintroduced in to the build' +
+           ':</b></p>\n')
+    output('<blockquote>\n')
+    fixed_patterns = []
     for i in warnpatterns:
         if len(i['members']) == 0 and i['severity'] != severity.SKIP:
-            if tablestarted == False:
-                tablestarted = True
-                begintable(['Fixed warnings', 'No more occurences. Please consider turning these in to errors if possible, before they are reintroduced in to the build'], 'blue', '')
-            tablerow(i['description'] + ' (' + allpatterns(i) + ') ' + i['option'])
-    if tablestarted:
-        endtable()
+            fixed_patterns.append(i['description'] + ' (' +
+                                  allpatterns(i) + ') ' + i['option'])
+    fixed_patterns.sort()
+    output('<div id="' + str(anchor) + '" style="display:none;"><table>\n')
+    for i in fixed_patterns:
+        tablerow(i)
+    output('</table></div>\n')
+    output('</blockquote>\n')
 
 def warningwithurl(line):
     if not args.url:
@@ -1821,17 +1846,12 @@
         header = [descriptionfor(cat),str(len(cat['members'])) + ' occurences:']
         if cat['option'] != '':
             header[1:1] = [' (related option: ' + cat['option'] +')']
-        begintable(header, colorforseverity(cat['severity']), cat['anchor'])
+
+        output('<div id="' + cat['anchor'] + '" style="display:none;">')
+        output('<table>\n')
         for i in cat['members']:
             tablerow(warningwithurl(i))
-        endtable()
-
-
-# dump everything for a given severity
-def dumpseverity(sev):
-    for i in warnpatterns:
-        if i['severity'] == sev:
-            dumpcategory(i)
+        output('</table></div>\n')
 
 
 def classifywarning(line):
@@ -1895,7 +1915,6 @@
 # sort table based on number of members once dumpstats has deduplicated the
 # members.
 warnpatterns.sort(reverse=True, key=lambda i: len(i['members']))
-dumptoc()
 dumpseverity(severity.FIXMENOW)
 dumpseverity(severity.HIGH)
 dumpseverity(severity.MEDIUM)
@@ -1904,3 +1923,4 @@
 dumpseverity(severity.HARMLESS)
 dumpseverity(severity.UNKNOWN)
 dumpfixed()
+dumphtmlepilogue()