Merge "Don't truncate ${USER} when generating ro.build.fingerprint"
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/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/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"):