Merge "Fix init_boot partition AVB signing"
diff --git a/core/Makefile b/core/Makefile
index 9226df0..bc34305 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -2782,18 +2782,23 @@
 FSVERITY_APK_MANIFEST_PATH := system/security/fsverity/AndroidManifest.xml
 $(FSVERITY_APK_OUT): PRIVATE_FSVERITY := $(HOST_OUT_EXECUTABLES)/fsverity
 $(FSVERITY_APK_OUT): PRIVATE_AAPT2 := $(HOST_OUT_EXECUTABLES)/aapt2
+$(FSVERITY_APK_OUT): PRIVATE_MIN_SDK_VERSION := $(DEFAULT_APP_TARGET_SDK)
 $(FSVERITY_APK_OUT): PRIVATE_APKSIGNER := $(HOST_OUT_EXECUTABLES)/apksigner
 $(FSVERITY_APK_OUT): PRIVATE_MANIFEST := $(FSVERITY_APK_MANIFEST_PATH)
+$(FSVERITY_APK_OUT): PRIVATE_FRAMEWORK_RES := $(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk
 $(FSVERITY_APK_OUT): PRIVATE_KEY := $(FSVERITY_APK_KEY_PATH)
 $(FSVERITY_APK_OUT): PRIVATE_INPUTS := $(fsverity-metadata-targets)
 $(FSVERITY_APK_OUT): $(HOST_OUT_EXECUTABLES)/fsverity_manifest_generator \
     $(HOST_OUT_EXECUTABLES)/fsverity $(HOST_OUT_EXECUTABLES)/aapt2 \
     $(HOST_OUT_EXECUTABLES)/apksigner $(FSVERITY_APK_MANIFEST_PATH) \
     $(FSVERITY_APK_KEY_PATH).x509.pem $(FSVERITY_APK_KEY_PATH).pk8 \
+    $(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk \
     $(fsverity-metadata-targets)
 	$< --fsverity-path $(PRIVATE_FSVERITY) --aapt2-path $(PRIVATE_AAPT2) \
+	    --min-sdk-version $(PRIVATE_MIN_SDK_VERSION) \
 	    --apksigner-path $(PRIVATE_APKSIGNER) --apk-key-path $(PRIVATE_KEY) \
-	    --apk-manifest-path $(PRIVATE_MANIFEST) --output $@ \
+	    --apk-manifest-path $(PRIVATE_MANIFEST) --framework-res $(PRIVATE_FRAMEWORK_RES) \
+	    --output $@ \
 	    --base-dir $(PRODUCT_OUT) $(PRIVATE_INPUTS)
 
 ALL_DEFAULT_INSTALLED_MODULES += $(FSVERITY_APK_OUT)
@@ -4874,14 +4879,16 @@
 tool_extension := $(wildcard $(tool_extensions)/releasetools.py)
 $(BUILT_TARGET_FILES_PACKAGE): PRIVATE_TOOL_EXTENSION := $(tool_extension)
 
+updaer_dep :=
 ifeq ($(AB_OTA_UPDATER),true)
-updater_dep := system/update_engine/update_engine.conf
-updater_dep := external/zucchini/version_info.h
+updater_dep += system/update_engine/update_engine.conf
+updater_dep += external/zucchini/version_info.h
+updater_dep += $(HOST_OUT_SHARED_LIBRARIES)/liblz4.so
 endif
 
 # Build OTA tools if non-A/B is allowed
 ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
-updater_dep := $(built_ota_tools)
+updater_dep += $(built_ota_tools)
 endif
 
 $(BUILT_TARGET_FILES_PACKAGE): $(updater_dep)
@@ -5362,6 +5369,7 @@
 	@# When using the A/B updater, include the updater config files in the zip.
 	$(hide) cp $(TOPDIR)system/update_engine/update_engine.conf $(zip_root)/META/update_engine_config.txt
 	$(hide) cp $(TOPDIR)external/zucchini/version_info.h $(zip_root)/META/zucchini_config.txt
+	$(hide) cp $(HOST_OUT_SHARED_LIBRARIES)/liblz4.so $(zip_root)/META/liblz4.so
 	$(hide) for part in $(strip $(AB_OTA_PARTITIONS)); do \
 	  echo "$${part}" >> $(zip_root)/META/ab_partitions.txt; \
 	done
diff --git a/core/config.mk b/core/config.mk
index e146f64..3c7c5ce 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -331,6 +331,22 @@
 JAVA_TMPDIR_ARG :=
 endif
 
+# http://b/210012154 Set BIONIC_COVERAGE if coverage is enabled for bionic.  This
+# disable continuous coverage and removes '%c' from init.environ.rc:LLVM_PROFILE_FILE
+ifeq ($(NATIVE_COVERAGE_PATHS),*)
+  ifeq ($(filter bionic%,$(NATIVE_COVERAGE_EXCLUDE_PATHS)),)
+	BIONIC_COVERAGE := true
+  else
+	BIONIC_COVERAGE := false
+  endif
+else
+  ifeq ($(filter bionic%,$(NATIVE_COVERAGE_PATHS)),)
+	BIONIC_COVERAGE := false
+  else
+	BIONIC_COVERAGE := true
+  endif
+endif
+
 # ###############################################################
 # Include sub-configuration files
 # ###############################################################
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 07dafc7..a8071a3 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -207,6 +207,7 @@
 
 $(call add_json_str,  PlatformSepolicyVersion,           $(PLATFORM_SEPOLICY_VERSION))
 $(call add_json_str,  TotSepolicyVersion,                $(TOT_SEPOLICY_VERSION))
+$(call add_json_list, PlatformSepolicyCompatVersions,    $(PLATFORM_SEPOLICY_COMPAT_VERSIONS))
 
 $(call add_json_bool, Flatten_apex,                      $(filter true,$(TARGET_FLATTEN_APEX)))
 $(call add_json_bool, ForceApexSymlinkOptimization,      $(filter true,$(TARGET_FORCE_APEX_SYMLINK_OPTIMIZATION)))
diff --git a/tools/compliance/readgraph.go b/tools/compliance/readgraph.go
index 0b5ebfe..45fa134 100644
--- a/tools/compliance/readgraph.go
+++ b/tools/compliance/readgraph.go
@@ -80,7 +80,7 @@
 
 	lg := newLicenseGraph()
 	for _, f := range files {
-		if strings.HasSuffix(f, ".meta_lic") {
+		if strings.HasSuffix(f, "meta_lic") {
 			lg.rootFiles = append(lg.rootFiles, f)
 		} else {
 			lg.rootFiles = append(lg.rootFiles, f+".meta_lic")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 94ef6d8..30dcf5b 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -73,6 +73,7 @@
         self.search_path = os.environ["ANDROID_HOST_OUT"]
     self.signapk_shared_library_path = "lib64"   # Relative to search_path
     self.extra_signapk_args = []
+    self.aapt2_path = "aapt2"
     self.java_path = "java"  # Use the one on the path by default.
     self.java_args = ["-Xmx2048m"]  # The default JVM args.
     self.android_jar_path = None
@@ -2184,8 +2185,8 @@
 def GetMinSdkVersion(apk_name):
   """Gets the minSdkVersion declared in the APK.
 
-  It calls 'aapt2' to query the embedded minSdkVersion from the given APK file.
-  This can be both a decimal number (API Level) or a codename.
+  It calls OPTIONS.aapt2_path to query the embedded minSdkVersion from the given
+  APK file. This can be both a decimal number (API Level) or a codename.
 
   Args:
     apk_name: The APK filename.
@@ -2197,7 +2198,7 @@
     ExternalError: On failing to obtain the min SDK version.
   """
   proc = Run(
-      ["aapt2", "dump", "badging", apk_name], stdout=subprocess.PIPE,
+      [OPTIONS.aapt2_path, "dump", "badging", apk_name], stdout=subprocess.PIPE,
       stderr=subprocess.PIPE)
   stdoutdata, stderrdata = proc.communicate()
   if proc.returncode != 0:
@@ -2473,7 +2474,7 @@
     opts, args = getopt.getopt(
         argv, "hvp:s:x:" + extra_opts,
         ["help", "verbose", "path=", "signapk_path=",
-         "signapk_shared_library_path=", "extra_signapk_args=",
+         "signapk_shared_library_path=", "extra_signapk_args=", "aapt2_path=",
          "java_path=", "java_args=", "android_jar_path=", "public_key_suffix=",
          "private_key_suffix=", "boot_signer_path=", "boot_signer_args=",
          "verity_signer_path=", "verity_signer_args=", "device_specific=",
@@ -2497,6 +2498,8 @@
       OPTIONS.signapk_shared_library_path = a
     elif o in ("--extra_signapk_args",):
       OPTIONS.extra_signapk_args = shlex.split(a)
+    elif o in ("--aapt2_path",):
+      OPTIONS.aapt2_path = a
     elif o in ("--java_path",):
       OPTIONS.java_path = a
     elif o in ("--java_args",):
diff --git a/tools/releasetools/fsverity_manifest_generator.py b/tools/releasetools/fsverity_manifest_generator.py
index e61e257..527cddb 100644
--- a/tools/releasetools/fsverity_manifest_generator.py
+++ b/tools/releasetools/fsverity_manifest_generator.py
@@ -51,6 +51,14 @@
       help='path to the aapt2 program',
       required=True)
   p.add_argument(
+      '--min-sdk-version',
+      help='minimum supported sdk version of the generated manifest apk',
+      required=True)
+  p.add_argument(
+      '--framework-res',
+      help='path to framework-res.apk',
+      required=True)
+  p.add_argument(
       '--apksigner-path',
       help='path to the apksigner program',
       required=True)
@@ -89,6 +97,8 @@
   common.RunAndCheckOutput([args.aapt2_path, "link",
       "-A", os.path.join(temp_dir, "assets"),
       "-o", args.output,
+      "--min-sdk-version", args.min_sdk_version,
+      "-I", args.framework_res,
       "--manifest", args.apk_manifest_path])
   common.RunAndCheckOutput([args.apksigner_path, "sign", "--in", args.output,
       "--cert", args.apk_key_path + ".x509.pem",
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index c21de14..58f0e85 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -230,6 +230,9 @@
 
   --compressor_types
       A colon ':' separated list of compressors. Allowed values are bz2 and brotli.
+
+  --enable_zucchini
+      Whether to enable to zucchini feature. Will generate smaller OTA but uses more memory.
 """
 
 from __future__ import print_function
@@ -299,6 +302,7 @@
 OPTIONS.enable_vabc_xor = True
 OPTIONS.force_minor_version = None
 OPTIONS.compressor_types = None
+OPTIONS.enable_zucchini = None
 
 POSTINSTALL_CONFIG = 'META/postinstall_config.txt'
 DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt'
@@ -1141,6 +1145,14 @@
     partition_timestamps_flags = GeneratePartitionTimestampFlags(
         metadata.postcondition.partition_state)
 
+  # Auto-check for compatibility only if --enable_zucchini omitted. Otherwise
+  # let user override zucchini settings. This is useful for testing.
+  if OPTIONS.enable_zucchini is None:
+    if not ota_utils.IsZucchiniCompatible(source_file, target_file):
+      additional_args += ["--enable_zucchini", "false"]
+  else:
+    additional_args += ["--enable_zucchini", str(OPTIONS.enable_zucchini).lower()]
+
   if OPTIONS.disable_vabc:
     additional_args += ["--disable_vabc", "true"]
   if OPTIONS.enable_vabc_xor:
@@ -1326,6 +1338,8 @@
       OPTIONS.force_minor_version = a
     elif o == "--compressor_types":
       OPTIONS.compressor_types = a
+    elif o == "--enable_zucchini":
+      OPTIONS.enable_zucchini = a.lower() != "false"
     else:
       return False
     return True
@@ -1373,6 +1387,7 @@
                                  "enable_vabc_xor=",
                                  "force_minor_version=",
                                  "compressor_types=",
+                                 "enable_zucchin=",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 6c5fc05..a4ec9e2 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -638,3 +638,38 @@
       target_apex.source_version = source_apex_versions[name]
 
   return target_apex_proto.SerializeToString()
+
+
+def IsZucchiniCompatible(source_file: str, target_file: str):
+  """Check whether zucchini versions in two builds are compatible
+
+  Args:
+    source_file: Path to source build's target_file.zip
+    target_file: Path to target build's target_file.zip
+
+  Returns:
+    bool true if and only if zucchini versions are compatible
+  """
+  if source_file is None or target_file is None:
+    return False
+  assert os.path.exists(source_file)
+  assert os.path.exists(target_file)
+
+  assert zipfile.is_zipfile(source_file) or os.path.isdir(source_file)
+  assert zipfile.is_zipfile(target_file) or os.path.isdir(target_file)
+  _ZUCCHINI_CONFIG_ENTRY_NAME = "META/zucchini_config.txt"
+
+  def ReadEntry(path, entry):
+    # Read an entry inside a .zip file or extracted dir of .zip file
+    if zipfile.is_zipfile(path):
+      with zipfile.ZipFile(path, "r", allowZip64=True) as zfp:
+        if entry in zfp.namelist():
+          return zfp.read(entry).decode()
+    else:
+      entry_path = os.path.join(entry, path)
+      if os.path.exists(entry_path):
+        with open(entry_path, "r") as fp:
+          return fp.read()
+      else:
+        return ""
+  return ReadEntry(source_file, _ZUCCHINI_CONFIG_ENTRY_NAME) == ReadEntry(target_file, _ZUCCHINI_CONFIG_ENTRY_NAME)