Merge "Fix RRO when LOCAL_EXPORT_PACKAGE_RESOURCES is unset"
diff --git a/core/Makefile b/core/Makefile
index 0bbaf12..ad9b452 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -474,9 +474,6 @@
 $(INSTALLED_BUILD_PROP_TARGET): $(intermediate_system_build_prop) $(INSTALLED_RECOVERYIMAGE_TARGET)
 	@echo "Target build info: $@"
 	$(hide) grep -v 'ro.product.first_api_level' $(intermediate_system_build_prop) > $@
-ifdef INSTALLED_RECOVERYIMAGE_TARGET
-	$(hide) echo ro.expect.recovery_id=`cat $(RECOVERYIMAGE_ID_FILE)` >> $@
-endif
 
 # -----------------------------------------------------------------
 # vendor build.prop
@@ -580,7 +577,12 @@
 	$(hide) build/make/tools/post_process_props.py $@
 
 # -----------------------------------------------------------------
-# product_services build.prop
+# product_services build.prop (unless it's merged into /product)
+ifdef MERGE_PRODUCT_SERVICES_INTO_PRODUCT
+  ifneq (,$(PRODUCT_PRODUCT_SERVICES_PROPERTIES))
+    $(error PRODUCT_PRODUCT_SERVICES_PROPERTIES is not supported in this build.)
+  endif
+else
 INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT_SERVICES)/build.prop
 ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET)
 
@@ -588,7 +590,6 @@
     $(call collapse-pairs, $(PRODUCT_PRODUCT_SERVICES_PROPERTIES))
 FINAL_PRODUCT_SERVICES_PROPERTIES := $(call uniq-pairs-by-first-component, \
     $(FINAL_PRODUCT_SERVICES_PROPERTIES),=)
-
 $(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH)
 	@echo Target product_services buildinfo: $@
 	@mkdir -p $(dir $@)
@@ -602,6 +603,7 @@
 	$(hide) $(foreach line,$(FINAL_PRODUCT_SERVICES_PROPERTIES), \
 	    echo "$(line)" >> $@;)
 	$(hide) build/make/tools/post_process_props.py $@
+endif # MERGE_PRODUCT_SERVICES_INTO_PRODUCT
 
 # ----------------------------------------------------------------
 
@@ -1156,8 +1158,13 @@
 	$(copy-file-to-target)
 $(installed_product_notice_xml_gz): $(target_product_notice_file_xml_gz)
 	$(copy-file-to-target)
+
+# No notice file for product_services if its contents are merged into /product.
+# The notices will be part of the /product notice file.
+ifndef MERGE_PRODUCT_SERVICES_INTO_PRODUCT
 $(installed_product_services_notice_xml_gz): $(target_product_services_notice_file_xml_gz)
 	$(copy-file-to-target)
+endif
 
 # if we've been run my mm, mmm, etc, don't reinstall this every time
 ifeq ($(ONE_SHOT_MAKEFILE),)
@@ -2559,10 +2566,9 @@
 ifdef BUILT_VENDOR_MANIFEST
 BUILT_ASSEMBLED_VENDOR_MANIFEST := $(PRODUCT_OUT)/verified_assembled_vendor_manifest.xml
 ifeq (true,$(strip $(PRODUCT_ENFORCE_VINTF_MANIFEST)))
-ifdef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
-# TODO(b/65028233): turn this on globally
+ifneq ($(strip $(DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE) $(DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE)),)
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_SYSTEM_ASSEMBLE_VINTF_ENV_VARS := VINTF_ENFORCE_NO_UNUSED_HALS=true
-endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
+endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE or DEVICE_PRODUCT_COMPATIBILITY_MATRIX_FILE
 endif # PRODUCT_ENFORCE_VINTF_MANIFEST
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(HOST_OUT_EXECUTABLES)/assemble_vintf
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(BUILT_SYSTEM_MATRIX)
diff --git a/core/android_manifest.mk b/core/android_manifest.mk
index ed759c5..560ed72 100644
--- a/core/android_manifest.mk
+++ b/core/android_manifest.mk
@@ -72,8 +72,8 @@
     my_manifest_fixer_flags += --uses-non-sdk-api
 endif
 
-ifeq (true,$(LOCAL_PREFER_CODE_INTEGRITY))
-    my_manifest_fixer_flags += --prefer-code-integrity
+ifeq (true,$(LOCAL_USE_EMBEDDED_DEX))
+    my_manifest_fixer_flags += --use-embedded-dex
 endif
 
 $(fixed_android_manifest): PRIVATE_MANIFEST_FIXER_FLAGS := $(my_manifest_fixer_flags)
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 64e1069..fd369f2 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -389,7 +389,7 @@
 # We name both BUILT and INSTALLED in case
 # LOCAL_UNINSTALLABLE_MODULE is set.
 .PHONY: $(my_all_targets)
-$(my_all_targets): $(LOCAL_BUILT_MODULE) $(LOCAL_INSTALLED_MODULE)
+$(my_all_targets): $(LOCAL_BUILT_MODULE) $(LOCAL_INSTALLED_MODULE) $(LOCAL_ADDITIONAL_CHECKED_MODULE)
 
 .PHONY: $(my_register_name)
 $(my_register_name): $(my_all_targets)
@@ -485,6 +485,8 @@
   my_checked_module := $(LOCAL_BUILT_MODULE)
 endif
 
+my_checked_module += $(LOCAL_ADDITIONAL_CHECKED_MODULE)
+
 # If they request that this module not be checked, then don't.
 # PLEASE DON'T SET THIS.  ANY PLACES THAT SET THIS WITHOUT
 # GOOD REASON WILL HAVE IT REMOVED.
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index e190916..0f1a937 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -10,6 +10,7 @@
 LOCAL_AAPT_INCLUDE_ALL_RESOURCES:=
 LOCAL_AAPT_NAMESPACES:=
 LOCAL_ADDITIONAL_CERTIFICATES:=
+LOCAL_ADDITIONAL_CHECKED_MODULE:=
 LOCAL_ADDITIONAL_DEPENDENCIES:=
 LOCAL_ADDITIONAL_HTML_DIR:=
 LOCAL_ADDITIONAL_JAVA_DIR:=
@@ -212,7 +213,7 @@
 LOCAL_PREBUILT_OBJ_FILES:=
 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=
 LOCAL_PREBUILT_STRIP_COMMENTS:=
-LOCAL_PREFER_CODE_INTEGRITY:=
+LOCAL_USE_EMBEDDED_DEX:=
 LOCAL_PRESUBMIT_DISABLED:=
 LOCAL_PRIVATE_PLATFORM_APIS:=
 LOCAL_PRIVILEGED_MODULE:=
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 60fd8db..f102662 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -92,7 +92,7 @@
 ifeq ($(PRODUCT_DIST_BOOT_AND_SYSTEM_JARS),true)
 boot_profile_jars_zip := $(PRODUCT_OUT)/boot_profile_jars.zip
 all_boot_jars := \
-  $(foreach m,$(DEXPREOPT_BOOT_JARS_MODULES),$(PRODUCT_OUT)/system/framework/$(m).jar) \
+  $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES) \
   $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(PRODUCT_OUT)/system/framework/$(m).jar)
 
 $(boot_profile_jars_zip): PRIVATE_JARS := $(all_boot_jars)
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 58c458a..f32b7b5 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -3,7 +3,7 @@
 # Output variables: LOCAL_DEX_PREOPT, LOCAL_UNCOMPRESS_DEX, built_odex,
 #                   dexpreopt_boot_jar_module
 
-ifeq (true,$(LOCAL_PREFER_CODE_INTEGRITY))
+ifeq (true,$(LOCAL_USE_EMBEDDED_DEX))
   LOCAL_UNCOMPRESS_DEX := true
 else
   LOCAL_UNCOMPRESS_DEX :=
@@ -180,7 +180,7 @@
   $(call add_json_str,  BuildPath,                     $(LOCAL_BUILT_MODULE))
   $(call add_json_str,  DexPath,                       $$1)
   $(call add_json_str,  ExtrasOutputPath,              $$2)
-  $(call add_json_bool, PreferCodeIntegrity,           $(filter true,$(LOCAL_PREFER_CODE_INTEGRITY)))
+  $(call add_json_bool, UseEmbeddedDex,                $(filter true,$(LOCAL_USE_EMBEDDED_DEX)))
   $(call add_json_bool, Privileged,                    $(filter true,$(LOCAL_PRIVILEGED_MODULE)))
   $(call add_json_bool, UncompressedDex,               $(filter true,$(LOCAL_UNCOMPRESS_DEX)))
   $(call add_json_bool, HasApkLibraries,               $(LOCAL_APK_LIBRARIES))
diff --git a/core/envsetup.mk b/core/envsetup.mk
index bd632bf..17448f1 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -444,11 +444,16 @@
 
 ###########################################
 # Now we can substitute with the real value of TARGET_COPY_OUT_PRODUCT_SERVICES
+MERGE_PRODUCT_SERVICES_INTO_PRODUCT :=
 ifeq ($(TARGET_COPY_OUT_PRODUCT_SERVICES),$(_product_services_path_placeholder))
   TARGET_COPY_OUT_PRODUCT_SERVICES := system/product_services
+else ifeq ($(TARGET_COPY_OUT_PRODUCT),$(TARGET_COPY_OUT_PRODUCT_SERVICES))
+  MERGE_PRODUCT_SERVICES_INTO_PRODUCT := true
 else ifeq ($(filter product_services system/product_services,$(TARGET_COPY_OUT_PRODUCT_SERVICES)),)
-  $(error TARGET_COPY_OUT_PRODUCT_SERVICES must be either 'product_services' or 'system/product_services', seeing '$(TARGET_COPY_OUT_PRODUCT_SERVICES)'.)
+  $(error TARGET_COPY_OUT_PRODUCT_SERVICES must be either 'product_services',\
+    '$(TARGET_COPY_OUT_PRODUCT)' or 'system/product_services', seeing '$(TARGET_COPY_OUT_PRODUCT_SERVICES)'.)
 endif
+.KATI_READONLY := MERGE_PRODUCT_SERVICES_INTO_PRODUCT
 PRODUCT_COPY_FILES := $(subst $(_product_services_path_placeholder),$(TARGET_COPY_OUT_PRODUCT_SERVICES),$(PRODUCT_COPY_FILES))
 
 BOARD_USES_PRODUCT_SERVICESIMAGE :=
diff --git a/core/main.mk b/core/main.mk
index 712b2c5..67cd3ac 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1133,7 +1133,12 @@
   static_whitelist_patterns += %__auto_generated_rro.apk
   # Auto-included targets are not considered
   static_whitelist_patterns += $(call module-installed-files,$(call auto-included-modules))
-
+  # $(PRODUCT_OUT)/apex is where shared libraries in APEXes get installed.
+  # The path can be considered as a fake path, as the shared libraries
+  # are installed there just to have symbols files for them under
+  # $(PRODUCT_OUT)/symbols/apex for debugging purpose. The /apex directory
+  # is never compiled into a filesystem image.
+  static_whitelist_patterns += $(PRODUCT_OUT)/apex/%
   ifeq (true,$(BOARD_USES_SYSTEM_OTHER_ODEX))
     # Allow system_other odex space optimization.
     static_whitelist_patterns += \
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index f8186c2..3d28ea7 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -19,14 +19,16 @@
 LOCAL_MODULE_SUFFIX := .apk
 LOCAL_BUILT_MODULE_STEM := package.apk
 
-#######################################
-include $(BUILD_SYSTEM)/base_rules.mk
-#######################################
+intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
 full_classes_jar := $(intermediates.COMMON)/classes.jar
 full_classes_pre_proguard_jar := $(intermediates.COMMON)/classes-pre-proguard.jar
 full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
 
+#######################################
+include $(BUILD_SYSTEM)/base_rules.mk
+#######################################
+
 ifdef LOCAL_SOONG_CLASSES_JAR
   $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_jar)))
   $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_pre_proguard_jar)))
@@ -102,7 +104,7 @@
 my_installed := $(call copy-many-files, $(my_built_installed))
 ALL_MODULES.$(my_register_name).INSTALLED += $(my_installed)
 ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(my_built_installed)
-$(my_register_name): $(my_installed)
+$(my_all_targets): $(my_installed)
 
 # embedded JNI will already have been handled by soong
 my_embed_jni :=
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index 66410e1..08d545d 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -13,9 +13,7 @@
 LOCAL_MODULE_SUFFIX := .jar
 LOCAL_BUILT_MODULE_STEM := javalib.jar
 
-#######################################
-include $(BUILD_SYSTEM)/base_rules.mk
-#######################################
+intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
 full_classes_jar := $(intermediates.COMMON)/classes.jar
 full_classes_pre_proguard_jar := $(intermediates.COMMON)/classes-pre-proguard.jar
@@ -24,6 +22,14 @@
 hiddenapi_flags_csv := $(intermediates.COMMON)/hiddenapi/flags.csv
 hiddenapi_metadata_csv := $(intermediates.COMMON)/hiddenapi/greylist.csv
 
+ifdef LOCAL_SOONG_AAR
+  LOCAL_ADDITIONAL_CHECKED_MODULE += $(LOCAL_SOONG_AAR)
+endif
+
+#######################################
+include $(BUILD_SYSTEM)/base_rules.mk
+#######################################
+
 ifdef LOCAL_SOONG_CLASSES_JAR
   $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_jar)))
   $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_pre_proguard_jar)))
diff --git a/target/board/gsi_arm64/BoardConfig.mk b/target/board/gsi_arm64/BoardConfig.mk
new file mode 100644
index 0000000..90ddd0d
--- /dev/null
+++ b/target/board/gsi_arm64/BoardConfig.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include build/make/target/board/BoardConfigGsiCommon.mk
+
+TARGET_ARCH := arm64
+TARGET_ARCH_VARIANT := armv8-a
+TARGET_CPU_ABI := arm64-v8a
+TARGET_CPU_ABI2 :=
+TARGET_CPU_VARIANT := generic
+
+TARGET_2ND_ARCH := arm
+TARGET_2ND_ARCH_VARIANT := armv8-a
+TARGET_2ND_CPU_ABI := armeabi-v7a
+TARGET_2ND_CPU_ABI2 := armeabi
+TARGET_2ND_CPU_VARIANT := generic
+
+# TODO(b/111434759, b/111287060) SoC specific hacks
+BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
+BOARD_ROOT_EXTRA_SYMLINKS += /mnt/vendor/persist:/persist
+BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt:/firmware
+
+# 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/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 480b395..12fd99a 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -60,6 +60,7 @@
     $(LOCAL_DIR)/full_x86.mk \
     $(LOCAL_DIR)/generic.mk \
     $(LOCAL_DIR)/generic_x86.mk \
+    $(LOCAL_DIR)/gsi_arm64.mk \
     $(LOCAL_DIR)/mainline_arm64.mk \
     $(LOCAL_DIR)/mainline_system_arm64.mk \
     $(LOCAL_DIR)/sdk_arm64.mk \
diff --git a/target/product/base_product.mk b/target/product/base_product.mk
index bd53fb1..1ed9e83 100644
--- a/target/product/base_product.mk
+++ b/target/product/base_product.mk
@@ -18,3 +18,4 @@
 PRODUCT_PACKAGES += \
     healthd \
     ModuleMetadata \
+    product_compatibility_matrix.xml \
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index d6c8421..422683a 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -271,7 +271,7 @@
 # VINTF data for system image
 PRODUCT_PACKAGES += \
     framework_manifest.xml \
-    framework_compatibility_matrix.xml \
+    system_compatibility_matrix.xml \
 
 ifeq ($(TARGET_CORE_JARS),)
 $(error TARGET_CORE_JARS is empty; cannot initialize PRODUCT_BOOT_JARS variable)
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 269a6af..e8f9e0c 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -30,6 +30,7 @@
     android.hardware.cas@1.0-service \
     android.hardware.configstore@1.1-service \
     android.hardware.media.omx@1.0-service \
+    dumpsys_vendor \
     fs_config_files_nonsystem \
     fs_config_dirs_nonsystem \
     gralloc.default \
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index e70ab5b..c52a379 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -137,6 +137,7 @@
 VNDK-core: android.hardware.radio@1.3.so
 VNDK-core: android.hardware.radio@1.4.so
 VNDK-core: android.hardware.secure_element@1.0.so
+VNDK-core: android.hardware.secure_element@1.1.so
 VNDK-core: android.hardware.sensors@1.0.so
 VNDK-core: android.hardware.soundtrigger@2.0.so
 VNDK-core: android.hardware.soundtrigger@2.0-core.so
@@ -205,7 +206,6 @@
 VNDK-core: libnetutils.so
 VNDK-core: libnl.so
 VNDK-core: libopus.so
-VNDK-core: libpagemap.so
 VNDK-core: libpcre2.so
 VNDK-core: libpiex.so
 VNDK-core: libpng.so
diff --git a/target/product/gsi_arm64.mk b/target/product/gsi_arm64.mk
new file mode 100644
index 0000000..cf4baba
--- /dev/null
+++ b/target/product/gsi_arm64.mk
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/gsi_common.mk)
+
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    root/init.zygote32_64.rc \
+    root/init.zygote64_32.rc \
+
+# Copy different zygote settings for vendor.img to select by setting property
+# ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
+#   1. 64-bit primary, 32-bit secondary OR
+#   2. 32-bit primary, 64-bit secondary
+# init.zygote64_32.rc is in the core_64_bit.mk below
+PRODUCT_COPY_FILES += \
+    system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
+
+PRODUCT_NAME := gsi_arm64
+PRODUCT_DEVICE := gsi_arm64
+PRODUCT_BRAND := generic
+PRODUCT_MODEL := GSI on ARM64
+
diff --git a/target/product/gsi_common.mk b/target/product/gsi_common.mk
new file mode 100644
index 0000000..0006e62
--- /dev/null
+++ b/target/product/gsi_common.mk
@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2019 The Android Open-Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
+
+# GSI includes all AOSP product packages and placed under /system/product
+$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_product.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_product.mk)
+
+# Default AOSP sounds
+$(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
+
+# Additional settings used in all AOSP builds
+PRODUCT_PROPERTY_OVERRIDES := \
+    ro.config.ringtone=Ring_Synth_04.ogg \
+    ro.config.notification_sound=pixiedust.ogg
+
+
+# Enable mainline checking and the whitelist for GSI
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST := \
+    system/app/messaging/messaging.apk \
+    system/app/PhotoTable/PhotoTable.apk \
+    system/app/WAPPushManager/WAPPushManager.apk \
+    system/bin/healthd \
+    system/etc/init/healthd.rc \
+    system/etc/vintf/manifest/manifest_healthd.xml \
+    system/lib/libframesequence.so \
+    system/lib/libgiftranscode.so \
+    system/lib64/libframesequence.so \
+    system/lib64/libgiftranscode.so \
+    system/priv-app/Dialer/Dialer.apk \
+
+# Some GSI builds enable dexpreopt, whitelist these preopt files
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += %.odex %.vdex %.art
+
+# Exclude GSI specific files
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    system/etc/init/config/skip_mount.cfg \
+    system/etc/init/init.gsi.rc \
+
+# Exclude all files under system/product
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    system/product/%
+
+
+# Split selinux policy
+PRODUCT_FULL_TREBLE_OVERRIDE := true
+
+# Enable dynamic partition size
+PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
+
+# Enable A/B update
+AB_OTA_UPDATER := true
+AB_OTA_PARTITIONS := system
+
+# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
+PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
+
+# GSI specific tasks on boot
+PRODUCT_COPY_FILES += \
+    build/make/target/product/gsi/skip_mount.cfg:system/etc/init/config/skip_mount.cfg \
+    build/make/target/product/gsi/init.gsi.rc:system/etc/init/init.gsi.rc \
+
+# Support addtional P vendor interface
+PRODUCT_EXTRA_VNDK_VERSIONS := 28
+
+# Default AOSP packages
+PRODUCT_PACKAGES += \
+    messaging \
+
+# Default AOSP packages
+PRODUCT_PACKAGES += \
+    PhotoTable \
+    WAPPushManager \
+
+# Telephony:
+#   Provide a APN configuration to GSI product
+PRODUCT_COPY_FILES += \
+    device/sample/etc/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml
+
+# NFC:
+#   Provide a libnfc-nci.conf to GSI product
+PRODUCT_COPY_FILES += \
+    device/generic/common/nfc/libnfc-nci.conf:$(TARGET_COPY_OUT_PRODUCT)/etc/libnfc-nci.conf
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 456f791..e5a9050 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -84,6 +84,7 @@
     self.extended = RangeSet()
     self.total_blocks = 0
     self.file_map = {}
+    self.hashtree_info = None
 
   def RangeSha1(self, ranges):
     return sha1().hexdigest()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index de3e3b8..5d310d2 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1770,15 +1770,21 @@
     if OPTIONS.source_info_dict is None:
       is_dynamic_build = OPTIONS.info_dict.get(
           "use_dynamic_partitions") == "true"
+      is_dynamic_source = False
     else:
       is_dynamic_build = OPTIONS.source_info_dict.get(
           "use_dynamic_partitions") == "true"
+      is_dynamic_source = partition in shlex.split(
+          OPTIONS.source_info_dict.get("dynamic_partition_list", "").strip())
 
-    # For dynamic partitions builds, always check partition list in target build
-    # because new partitions may be added.
-    is_dynamic = is_dynamic_build and partition in shlex.split(
+    is_dynamic_target = partition in shlex.split(
         OPTIONS.info_dict.get("dynamic_partition_list", "").strip())
 
+    # For dynamic partitions builds, check partition list in both source
+    # and target build because new partitions may be added, and existing
+    # partitions may be removed.
+    is_dynamic = is_dynamic_build and (is_dynamic_source or is_dynamic_target)
+
     if is_dynamic:
       self.device = 'map_partition("%s")' % partition
     else:
@@ -2226,7 +2232,7 @@
              collections.Counter(e.partition for e in block_diffs).items()
              if count > 1])
 
-    self._partition_updates = dict()
+    self._partition_updates = collections.OrderedDict()
 
     for p, block_diff in block_diff_dict.items():
       self._partition_updates[p] = DynamicPartitionUpdate()
@@ -2277,7 +2283,7 @@
       logger.info("Updating dynamic partitions %s",
                   self._partition_updates.keys())
 
-    self._group_updates = dict()
+    self._group_updates = collections.OrderedDict()
 
     for g in tgt_groups:
       self._group_updates[g] = DynamicGroupUpdate()
diff --git a/tools/releasetools/target_files_diff.py b/tools/releasetools/target_files_diff.py
index 7415f27..4402c8d 100755
--- a/tools/releasetools/target_files_diff.py
+++ b/tools/releasetools/target_files_diff.py
@@ -71,7 +71,6 @@
              'ro.build.user=',
              'ro.build.description=',
              'ro.build.fingerprint=',
-             'ro.expect.recovery_id=',
              'ro.vendor.build.date=',
              'ro.vendor.build.date.utc=',
              'ro.vendor.build.fingerprint=']
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 3619633..cfd070d 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -27,6 +27,7 @@
 import validate_target_files
 from rangelib import RangeSet
 
+from blockimgdiff import EmptyImage, DataImage
 
 KiB = 1024
 MiB = 1024 * KiB
@@ -1113,7 +1114,7 @@
                     "ops that remove / shrink partitions must precede ops that "
                     "grow / add partitions")
 
-  def test_inc_partitions(self):
+  def test_incremental(self):
     source_info = common.LoadDictionaryFromLines("""
 dynamic_partition_list=system vendor product product_services
 super_partition_groups=group_foo
@@ -1186,3 +1187,38 @@
                     min_idx_move_partition_in_foo,
                     "Must shrink partitions / remove partitions from group"
                     "before adding / moving partitions into group")
+
+  def test_remove_partition(self):
+    source_info = common.LoadDictionaryFromLines("""
+blockimgdiff_versions=3,4
+use_dynamic_partitions=true
+dynamic_partition_list=foo
+super_partition_groups=group_foo
+super_group_foo_group_size={group_foo_size}
+super_group_foo_partition_list=foo
+""".format(group_foo_size=4 * GiB).split("\n"))
+    target_info = common.LoadDictionaryFromLines("""
+blockimgdiff_versions=3,4
+use_dynamic_partitions=true
+super_partition_groups=group_foo
+super_group_foo_group_size={group_foo_size}
+""".format(group_foo_size=4 * GiB).split("\n"))
+
+    common.OPTIONS.info_dict = target_info
+    common.OPTIONS.target_info_dict = target_info
+    common.OPTIONS.source_info_dict = source_info
+    common.OPTIONS.cache_size = 4 * 4096
+
+    block_diffs = [common.BlockDifference("foo", EmptyImage(),
+                                          src=DataImage("source", pad=True))]
+
+    dp_diff = common.DynamicPartitionsDifference(target_info, block_diffs,
+                                                 source_info_dict=source_info)
+    with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+      dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
+
+    self.assertNotIn("block_image_update", str(self.script),
+        "Removed partition should not be patched.")
+
+    lines = self.get_op_list(self.output_path)
+    self.assertEqual(lines, ["remove foo"])