Merge "Add dependencies on classes.jar for soong modules"
diff --git a/core/Makefile b/core/Makefile
index 2389698..912bf88 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -188,9 +188,7 @@
 # The string used to uniquely identify the combined build and product; used by the OTA server.
 ifeq (,$(strip $(BUILD_FINGERPRINT)))
   ifneq ($(filter eng.%,$(BUILD_NUMBER)),)
-    # Trim down BUILD_FINGERPRINT: the default BUILD_NUMBER makes it easily exceed
-    # the Android system property length limit (PROPERTY_VALUE_MAX=92).
-    BF_BUILD_NUMBER := $(shell echo $${USER:0:6})$(shell $(DATE) +%m%d%H%M)
+    BF_BUILD_NUMBER := $(USER)$(shell $(DATE) +%m%d%H%M)
   else
     BF_BUILD_NUMBER := $(BUILD_NUMBER)
   endif
diff --git a/core/config.mk b/core/config.mk
index 2ce064f..5f94802 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -511,12 +511,6 @@
 
 USE_PREBUILT_SDK_TOOLS_IN_PLACE := true
 
-# USE_D8_BY_DEFAULT is the default behavior, use USE_D8 to override.
-USE_D8_BY_DEFAULT := false
-ifndef USE_D8
-  USE_D8 := $(USE_D8_BY_DEFAULT)
-endif
-
 #
 # Tools that are prebuilts for TARGET_BUILD_APPS
 #
@@ -530,12 +524,6 @@
   SIGNAPK_JNI_LIBRARY_PATH := $(HOST_OUT_SHARED_LIBRARIES)
   ZIPALIGN := $(HOST_OUT_EXECUTABLES)/zipalign
 
-  ifeq ($(USE_D8),true)
-    DX := $(HOST_OUT_EXECUTABLES)/d8
-  else
-    DX := $(HOST_OUT_EXECUTABLES)/dx
-  endif
-
 else # TARGET_BUILD_APPS || TARGET_BUILD_PDK
   AIDL := $(prebuilt_sdk_tools_bin)/aidl
   AAPT := $(prebuilt_sdk_tools_bin)/aapt
@@ -546,15 +534,8 @@
   SIGNAPK_JNI_LIBRARY_PATH := $(prebuilt_sdk_tools)/$(HOST_OS)/lib64
   ZIPALIGN := $(prebuilt_sdk_tools_bin)/zipalign
 
-  ifeq ($(USE_D8),true)
-    DX := $(prebuilt_build_tools_wrappers)/d8
-  else
-    DX := $(prebuilt_build_tools_wrappers)/dx
-  endif
 endif # TARGET_BUILD_APPS || TARGET_BUILD_PDK
 
-DX_COMMAND := $(DX) -JXms16M -JXmx2048M
-
 ifeq (,$(TARGET_BUILD_APPS))
   # Use RenderScript prebuilts for unbundled builds but not PDK builds
   LLVM_RS_CC := $(HOST_OUT_EXECUTABLES)/llvm-rs-cc
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index e01fbbf..f5b45db 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -137,6 +137,8 @@
     else
         $(error $(LOCAL_PATH): $(LOCAL_MODULE): TSAN cannot be used for 32-bit modules.)
     endif
+  else
+    my_shared_libraries += $(TSAN_RUNTIME_LIBRARY)
   endif
 endif
 
diff --git a/core/definitions.mk b/core/definitions.mk
index 2702fc2..99d048b 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2680,7 +2680,7 @@
 define copy-file-to-target
 @mkdir -p $(dir $@)
 $(hide) rm -f $@
-$(hide) cp $< $@
+$(hide) cp "$<" "$@"
 endef
 
 # The same as copy-file-to-target, but use the local
@@ -2688,7 +2688,7 @@
 define copy-file-to-target-with-cp
 @mkdir -p $(dir $@)
 $(hide) rm -f $@
-$(hide) cp -p $< $@
+$(hide) cp -p "$<" "$@"
 endef
 
 # The same as copy-file-to-target, but strip out "# comment"-style
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 9616036..de34d88 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -11,10 +11,6 @@
 DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
 endif
 
-# Pass special class loader context to skip the classpath and collision check.
-# Should modify build system to pass used libraries properly later.
-DEX2OAT_CLASS_LOADER_CONTEXT := "&"
-
 DEX2OAT_DEPENDENCY += $(DEX2OAT)
 
 # Use the first preloaded-classes file in PRODUCT_COPY_FILES.
@@ -150,7 +146,7 @@
 $(hide) mkdir -p $(dir $(2))
 $(hide) ANDROID_LOG_TAGS="*:e" $(DEX2OAT) \
 	--runtime-arg -Xms$(DEX2OAT_XMS) --runtime-arg -Xmx$(DEX2OAT_XMX) \
-	--class-loader-context=$(DEX2OAT_CLASS_LOADER_CONTEXT) \
+	--class-loader-context=$(PRIVATE_DEX2OAT_CLASS_LOADER_CONTEXT) \
 	--boot-image=$(PRIVATE_DEX_PREOPT_IMAGE_LOCATION) \
 	--dex-file=$(1) \
 	--dex-location=$(PRIVATE_DEX_LOCATION) \
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 8c1a606..f420b18 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -36,12 +36,16 @@
 # if WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY=true and module is not in boot class path skip
 # Also preopt system server jars since selinux prevents system server from loading anything from
 # /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
-# or performance.
+# or performance. If my_preopt_for_extracted_apk is true, we ignore the only preopt boot image
+# options.
+ifneq (true,$(my_preopt_for_extracted_apk))
 ifeq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))
 ifeq ($(filter $(PRODUCT_SYSTEM_SERVER_JARS) $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE)),)
 LOCAL_DEX_PREOPT :=
 endif
 endif
+endif
+
 # if installing into system, and odex are being installed into system_other, don't strip
 ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
 ifeq ($(LOCAL_DEX_PREOPT),true)
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index b79e68b..ba10b37 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -269,6 +269,11 @@
 my_prebuilt_src_file := $(my_extracted_apk)
 my_extracted_apk :=
 my_extract_apk :=
+ifeq ($(PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK),true)
+# If the product property is set, always preopt for extracted modules to prevent executing out of
+# the APK.
+my_preopt_for_extracted_apk := true
+endif
 endif
 
 rs_compatibility_jni_libs :=
@@ -602,3 +607,4 @@
 $(built_module) : $(LOCAL_ADDITIONAL_DEPENDENCIES)
 
 my_prebuilt_src_file :=
+my_preopt_for_extracted_apk :=
diff --git a/core/product.mk b/core/product.mk
index c955ccc..4682dac 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -115,6 +115,7 @@
     PRODUCT_SYSTEM_PROPERTY_BLACKLIST \
     PRODUCT_SYSTEM_SERVER_APPS \
     PRODUCT_SYSTEM_SERVER_JARS \
+    PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK \
     PRODUCT_DEXPREOPT_SPEED_APPS \
     PRODUCT_VBOOT_SIGNING_KEY \
     PRODUCT_VBOOT_SIGNING_SUBKEY \
diff --git a/core/product_config.mk b/core/product_config.mk
index 492219b..be5ec54 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -260,6 +260,9 @@
 PRODUCT_SYSTEM_SERVER_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_APPS))
 PRODUCT_DEXPREOPT_SPEED_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEXPREOPT_SPEED_APPS))
 
+# All of the apps that we force preopt, this overrides WITH_DEXPREOPT.
+PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK))
+
 # Find the device that this product maps to.
 TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)
 
diff --git a/core/setup_one_odex.mk b/core/setup_one_odex.mk
index f0ffe81..e0d9926 100644
--- a/core/setup_one_odex.mk
+++ b/core/setup_one_odex.mk
@@ -32,6 +32,10 @@
     $(DEXPREOPT_ONE_FILE_DEPENDENCY_TOOLS) \
     $(my_dex_preopt_image_filename)
 
+# Pass special class loader context to skip the classpath and collision check.
+# Should modify build system to pass used libraries properly later.
+$(my_built_odex): PRIVATE_DEX2OAT_CLASS_LOADER_CONTEXT := \&
+
 my_installed_odex := $(call get-odex-installed-file-path,$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH),$(LOCAL_INSTALLED_MODULE))
 
 my_built_vdex := $(patsubst %.odex,%.vdex,$(my_built_odex))
diff --git a/envsetup.sh b/envsetup.sh
index 25d95f4..991fee3 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -640,11 +640,17 @@
 # Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
 function tapas()
 {
+    local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
     local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|armv5|arm64|x86_64|mips64)$' | xargs)"
     local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
     local density="$(echo $* | xargs -n 1 echo | \grep -E '^(ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
     local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|mips|armv5|arm64|x86_64|mips64|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
 
+    if [ "$showHelp" != "" ]; then
+      $(gettop)/build/make/tapasHelp.sh
+      return
+    fi
+
     if [ $(echo $arch | wc -w) -gt 1 ]; then
         echo "tapas: Error: Multiple build archs supplied: $arch"
         return
diff --git a/tapasHelp.sh b/tapasHelp.sh
new file mode 100755
index 0000000..058ac1d
--- /dev/null
+++ b/tapasHelp.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# locate some directories
+cd "$(dirname $0)"
+SCRIPT_DIR="${PWD}"
+cd ../..
+TOP="${PWD}"
+
+message='usage: tapas [<App1> <App2> ...] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user]
+
+tapas selects individual apps to be built by the Android build system. Unlike
+"lunch", "tapas" does not request the building of images for a device.
+Additionally, an app built with "tapas" will have its dex file inside its apk,
+which should cause it to be suitable for installing on any api-compatible
+device. In other words, "tapas" configures the build of unbundled apps.
+
+The names <App1> <App2> ... should match LOCAL_PACKAGE_NAME as defined in an
+Android.mk
+
+The usage of the other arguments matches that of the rest of the platform
+build system and can be found by running `m help`'
+
+echo "$message"
diff --git a/target/product/core_minimal.mk b/target/product/core_minimal.mk
index 523df7a..dd23a35 100644
--- a/target/product/core_minimal.mk
+++ b/target/product/core_minimal.mk
@@ -60,7 +60,6 @@
     iptables \
     gatekeeperd \
     keystore \
-    keystore.default \
     ld.config.txt \
     ld.mc \
     libaaudio \
diff --git a/target/product/core_tiny.mk b/target/product/core_tiny.mk
index 5ced1a6..e49ef19 100644
--- a/target/product/core_tiny.mk
+++ b/target/product/core_tiny.mk
@@ -59,7 +59,6 @@
     iptables \
     gatekeeperd \
     keystore \
-    keystore.default \
     ld.mc \
     libaaudio \
     libOpenMAXAL \
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 91213ba..d31a297 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -52,13 +52,13 @@
   sys.exit(1)
 
 import datetime
-import errno
 import hashlib
 import os
 import shlex
 import shutil
 import subprocess
 import tempfile
+import uuid
 import zipfile
 
 import build_image
@@ -214,22 +214,6 @@
 def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
   print("creating " + what + ".img...")
 
-  # The name of the directory it is making an image out of matters to
-  # mkyaffs2image.  It wants "system" but we have a directory named
-  # "SYSTEM", so create a symlink.
-  temp_dir = tempfile.mkdtemp()
-  OPTIONS.tempfiles.append(temp_dir)
-  try:
-    os.symlink(os.path.join(input_dir, what.upper()),
-               os.path.join(temp_dir, what))
-  except OSError as e:
-    # bogus error on my mac version?
-    #   File "./build/tools/releasetools/img_from_target_files"
-    #     os.path.join(OPTIONS.input_tmp, "system"))
-    # OSError: [Errno 17] File exists
-    if e.errno == errno.EEXIST:
-      pass
-
   image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
   fstab = info_dict["fstab"]
   mount_point = "/" + what
@@ -258,7 +242,20 @@
   if block_list:
     image_props["block_list"] = block_list.name
 
-  succ = build_image.BuildImage(os.path.join(temp_dir, what),
+  # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
+  # build fingerprint).
+  uuid_seed = what + "-"
+  if "build.prop" in info_dict:
+    build_prop = info_dict["build.prop"]
+    if "ro.build.fingerprint" in build_prop:
+      uuid_seed += build_prop["ro.build.fingerprint"]
+    elif "ro.build.thumbprint" in build_prop:
+      uuid_seed += build_prop["ro.build.thumbprint"]
+  image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
+  hash_seed = "hash_seed-" + uuid_seed
+  image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
+
+  succ = build_image.BuildImage(os.path.join(input_dir, what.upper()),
                                 image_props, output_file.name)
   assert succ, "build " + what + ".img image failed"
 
@@ -308,21 +305,11 @@
   timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
   image_props["timestamp"] = int(timestamp)
 
-  # The name of the directory it is making an image out of matters to
-  # mkyaffs2image.  So we create a temp dir, and within it we create an
-  # empty dir named "data", or a symlink to the DATA dir,
-  # and build the image from that.
-  temp_dir = tempfile.mkdtemp()
-  OPTIONS.tempfiles.append(temp_dir)
-  user_dir = os.path.join(temp_dir, "data")
-  empty = (OPTIONS.info_dict.get("userdata_img_with_data") != "true")
-  if empty:
-    # Create an empty dir.
-    os.mkdir(user_dir)
+  if OPTIONS.info_dict.get("userdata_img_with_data") == "true":
+    user_dir = os.path.join(OPTIONS.input_tmp, "DATA")
   else:
-    # Symlink to the DATA dir.
-    os.symlink(os.path.join(OPTIONS.input_tmp, "DATA"),
-               user_dir)
+    user_dir = tempfile.mkdtemp()
+    OPTIONS.tempfiles.append(user_dir)
 
   fstab = OPTIONS.info_dict["fstab"]
   if fstab:
@@ -455,13 +442,8 @@
   timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
   image_props["timestamp"] = int(timestamp)
 
-  # The name of the directory it is making an image out of matters to
-  # mkyaffs2image.  So we create a temp dir, and within it we create an
-  # empty dir named "cache", and build the image from that.
-  temp_dir = tempfile.mkdtemp()
-  OPTIONS.tempfiles.append(temp_dir)
-  user_dir = os.path.join(temp_dir, "cache")
-  os.mkdir(user_dir)
+  user_dir = tempfile.mkdtemp()
+  OPTIONS.tempfiles.append(user_dir)
 
   fstab = OPTIONS.info_dict["fstab"]
   if fstab:
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index b8123c0..c95512d 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -717,6 +717,7 @@
       diff_total = len(diff_queue)
       patches = [None] * diff_total
       error_messages = []
+      warning_messages = []
       if sys.stdout.isatty():
         global diff_done
         diff_done = 0
@@ -750,16 +751,34 @@
             with open(tgt_file, "wb") as fd:
               self.tgt.WriteRangeDataToFd(tgt_ranges, fd)
 
+          message = []
           try:
             patch = compute_patch(src_file, tgt_file, imgdiff)
           except ValueError as e:
+            message.append(
+                "Failed to generate %s for %s: tgt=%s, src=%s:\n%s" % (
+                "imgdiff" if imgdiff else "bsdiff",
+                xf.tgt_name if xf.tgt_name == xf.src_name else
+                    xf.tgt_name + " (from " + xf.src_name + ")",
+                xf.tgt_ranges, xf.src_ranges, e.message))
+            # TODO(b/68016761): Better handle the holes in mke2fs created images.
+            if imgdiff:
+              try:
+                patch = compute_patch(src_file, tgt_file, imgdiff=False)
+                message.append(
+                    "Fell back and generated with bsdiff instead for %s" % (
+                    xf.tgt_name,))
+                with lock:
+                  warning_messages.extend(message)
+                del message[:]
+              except ValueError as e:
+                message.append(
+                    "Also failed to generate with bsdiff for %s:\n%s" % (
+                    xf.tgt_name, e.message))
+
+          if message:
             with lock:
-              error_messages.append(
-                  "Failed to generate %s for %s: tgt=%s, src=%s:\n%s" % (
-                      "imgdiff" if imgdiff else "bsdiff",
-                      xf.tgt_name if xf.tgt_name == xf.src_name else
-                          xf.tgt_name + " (from " + xf.src_name + ")",
-                      xf.tgt_ranges, xf.src_ranges, e.message))
+              error_messages.extend(message)
 
           with lock:
             patches[patch_index] = (xf_index, patch)
@@ -781,8 +800,15 @@
       if sys.stdout.isatty():
         print('\n')
 
+      if warning_messages:
+        print('WARNING:')
+        print('\n'.join(warning_messages))
+        print('\n\n\n')
+
       if error_messages:
+        print('ERROR:')
         print('\n'.join(error_messages))
+        print('\n\n\n')
         sys.exit(1)
     else:
       patches = []
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 816cf4e..a388f8a 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -483,6 +483,12 @@
       build_command.extend(["-e", prop_dict["flash_erase_block_size"]])
     if "flash_logical_block_size" in prop_dict:
       build_command.extend(["-o", prop_dict["flash_logical_block_size"]])
+    # Specify UUID and hash_seed if using mke2fs.
+    if prop_dict["ext_mkuserimg"] == "mkuserimg_mke2fs.sh":
+      if "uuid" in prop_dict:
+        build_command.extend(["-U", prop_dict["uuid"]])
+      if "hash_seed" in prop_dict:
+        build_command.extend(["-S", prop_dict["hash_seed"]])
     if "selinux_fc" in prop_dict:
       build_command.append(prop_dict["selinux_fc"])
   elif fs_type.startswith("squash"):