Merge changes I80341c2e,I0935f611,Ia805cb47
* changes:
Deprecate ADDITIONAL_DEFAULT_PROPERTIES
Move most of the sysprop generation rules to sysprop.mk
Add PLATFORM_VERSION_LAST_STABLE
diff --git a/core/Makefile b/core/Makefile
index f9ac849..726038f 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -607,6 +607,15 @@
BUILT_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
endif
+ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
+ BOARD_KERNEL_BOOTIMAGE_PARTITION_SIZE := $(BOARD_BOOTIMAGE_PARTITION_SIZE)
+endif
+
+# $1: boot image file name
+# $2: boot image variant (boot, boot-debug)
+define get-bootimage-partition-size
+ $(BOARD_$(call to-upper,$(subst .img,,$(subst $(2),kernel,$(notdir $(1)))))_BOOTIMAGE_PARTITION_SIZE)
+endef
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
INTERNAL_BOOTIMAGE_ARGS := \
@@ -1695,11 +1704,11 @@
$(if $(filter true,$(PRODUCT_SUPPORTS_VBOOT)), \
$(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
$(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
- $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))), \
+ $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot))), \
$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))))
$(if $(filter true,$(BOARD_AVB_ENABLE)), \
$(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
- $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS),\
+ $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(call get-bootimage-partition-size,$(1),boot) --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS),\
$(AVBTOOL) add_hash_footer --image $(1) --partition_size $(BOARD_RECOVERYIMAGE_PARTITION_SIZE) --partition_name recovery $(INTERNAL_AVB_RECOVERY_SIGNING_ARGS) $(BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS)))
endef
@@ -1886,13 +1895,13 @@
INTERNAL_AVB_BOOT_TEST_SIGNING_ARGS := --algorithm SHA256_RSA2048 --key $(BOARD_AVB_BOOT_TEST_KEY_PATH)
# $(1): the bootimage to sign
define test-key-sign-bootimage
-$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE)))
+$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot-debug)))
$(AVBTOOL) add_hash_footer \
--image $(1) \
- --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
+ --partition_size $(call get-bootimage-partition-size,$(1),boot-debug)\
--partition_name boot $(INTERNAL_AVB_BOOT_TEST_SIGNING_ARGS) \
$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
-$(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
+$(call assert-max-image-size,$(1),$(call get-bootimage-partition-size,$(1),boot-debug))
endef
# $(1): output file
@@ -2870,10 +2879,10 @@
# When building a standalone recovery image for non-A/B devices, recovery image must be self-signed
# to be verified independently, and cannot be chained into vbmeta.img. See the link below for
# details.
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(if $(BOARD_AVB_RECOVERY_KEY_PATH),,\
- $(error BOARD_AVB_RECOVERY_KEY_PATH must be defined for non-A/B devices. \
+ $(error BOARD_AVB_RECOVERY_KEY_PATH must be defined for if non-A/B is supported. \
See https://android.googlesource.com/platform/external/avb/+/master/README.md#booting-into-recovery))
endif
endif
@@ -2964,7 +2973,7 @@
# The recovery partition in non-A/B devices should be verified separately. Skip adding the chain
# partition descriptor for recovery partition into vbmeta.img.
-$(if $(or $(filter true,$(AB_OTA_UPDATER)),$(filter-out recovery,$(part))),\
+$(if $(or $(filter-out true,$(TARGET_OTA_ALLOW_NON_AB)),$(filter-out recovery,$(part))),\
$(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
--chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey))
@@ -3636,6 +3645,11 @@
endif
.KATI_READONLY := tool_extensions
+# $1: boot image file name
+define misc_boot_size
+$(subst .img,_size,$(1))=$(BOARD_KERNEL$(call to-upper,$(subst boot,,$(subst .img,,$(1))))_BOOTIMAGE_PARTITION_SIZE)
+endef
+
$(INSTALLED_MISC_INFO_TARGET):
rm -f $@
$(call pretty,"Target misc_info.txt: $@")
@@ -3644,8 +3658,9 @@
ifdef BOARD_FLASH_BLOCK_SIZE
$(hide) echo "blocksize=$(BOARD_FLASH_BLOCK_SIZE)" >> $@
endif
-ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
- $(hide) echo "boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >> $@
+ifneq ($(strip $(BOARD_BOOTIMAGE_PARTITION_SIZE))$(strip $(BOARD_KERNEL_BINARIES)),)
+ $(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),\
+ echo "$(call misc_boot_size,$(notdir $(b)))" >> $@;)
endif
ifeq ($(INSTALLED_BOOTIMAGE_TARGET),)
$(hide) echo "no_boot=true" >> $@
@@ -3753,6 +3768,9 @@
$(hide) echo "build_type=$(TARGET_BUILD_VARIANT)" >> $@
$(hide) echo "ab_update=true" >> $@
endif
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
+ $(hide) echo "allow_non_ab=true" >> $@
+endif
ifdef BOARD_PREBUILT_DTBOIMAGE
$(hide) echo "has_dtbo=true" >> $@
ifeq ($(BOARD_AVB_ENABLE),true)
@@ -3830,10 +3848,13 @@
ifeq ($(AB_OTA_UPDATER),true)
updater_dep := system/update_engine/update_engine.conf
-else
-# Build OTA tools if not using the AB Updater.
+endif
+
+# Build OTA tools if non-A/B is allowed
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
updater_dep := $(built_ota_tools)
endif
+
$(BUILT_TARGET_FILES_PACKAGE): $(updater_dep)
# If we are using recovery as boot, output recovery files to BOOT/.
@@ -4109,7 +4130,7 @@
@# Extra contents of the OTA package
$(hide) mkdir -p $(zip_root)/OTA
$(hide) cp $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(built_ota_tools),)
$(hide) mkdir -p $(zip_root)/OTA/bin
$(hide) cp $(PRIVATE_OTA_TOOLS) $(zip_root)/OTA/bin/
@@ -4146,7 +4167,7 @@
$(hide) cp $(PRODUCT_ODM_BASE_FS_PATH) \
$(zip_root)/META/$(notdir $(PRODUCT_ODM_BASE_FS_PATH))
endif
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(hide) PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH MKBOOTIMG=$(MKBOOTIMG) \
$(MAKE_RECOVERY_PATCH) $(zip_root) $(zip_root)
diff --git a/core/board_config.mk b/core/board_config.mk
index 2279c3f..0ff28c5 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -550,13 +550,31 @@
.KATI_READONLY := BUILDING_ODM_IMAGE
###########################################
-# Ensure that only TARGET_RECOVERY_UPDATER_LIBS *or* AB_OTA_UPDATER is set.
+# Ensure consistency among TARGET_RECOVERY_UPDATER_LIBS, AB_OTA_UPDATER, and PRODUCT_OTA_FORCE_NON_AB_PACKAGE.
TARGET_RECOVERY_UPDATER_LIBS ?=
AB_OTA_UPDATER ?=
.KATI_READONLY := TARGET_RECOVERY_UPDATER_LIBS AB_OTA_UPDATER
-ifeq ($(AB_OTA_UPDATER),true)
+
+# Ensure that if PRODUCT_OTA_FORCE_NON_AB_PACKAGE == true, then AB_OTA_UPDATER must be true
+ifeq ($(PRODUCT_OTA_FORCE_NON_AB_PACKAGE),true)
+ ifneq ($(AB_OTA_UPDATER),true)
+ $(error AB_OTA_UPDATER must be set to true when PRODUCT_OTA_FORCE_NON_AB_PACKAGE is true)
+ endif
+endif
+
+# In some configurations, A/B and non-A/B may coexist. Check TARGET_OTA_ALLOW_NON_AB
+# to see if non-A/B is supported.
+TARGET_OTA_ALLOW_NON_AB := false
+ifneq ($(AB_OTA_UPDATER),true)
+ TARGET_OTA_ALLOW_NON_AB := true
+else ifeq ($(PRODUCT_OTA_FORCE_NON_AB_PACKAGE),true)
+ TARGET_OTA_ALLOW_NON_AB := true
+endif
+.KATI_READONLY := TARGET_OTA_ALLOW_NON_AB
+
+ifneq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(strip $(TARGET_RECOVERY_UPDATER_LIBS)),)
- $(error Do not use TARGET_RECOVERY_UPDATER_LIBS when using AB_OTA_UPDATER)
+ $(error Do not use TARGET_RECOVERY_UPDATER_LIBS when using TARGET_OTA_ALLOW_NON_AB)
endif
endif
diff --git a/core/main.mk b/core/main.mk
index 9c7ad9f..21ec6f9 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -485,6 +485,21 @@
# brought in as requirements of other modules.
#
# Resolve the required module name to 32-bit or 64-bit variant.
+
+# TODO(b/155869107): Replace get-32-bit-modules with get-modules-for-2nd-arch
+# Get a list of corresponding module names for the second arch, if they exist.
+# $(1): TARGET, HOST or HOST_CROSS
+# $(2): A list of module names
+define get-modules-for-2nd-arch
+$(strip \
+ $(foreach m,$(2), \
+ $(if $(filter true,$(ALL_MODULES.$(m)$($(1)_2ND_ARCH_MODULE_SUFFIX).FOR_2ND_ARCH)), \
+ $(m)$($(1)_2ND_ARCH_MODULE_SUFFIX) \
+ ) \
+ ) \
+)
+endef
+
# Get a list of corresponding 32-bit module names, if one exists.
define get-32-bit-modules
$(sort $(foreach m,$(1),\
@@ -1028,6 +1043,45 @@
endef
+# Resolves module bitness for PRODUCT_PACKAGES and PRODUCT_HOST_PACKAGES.
+# The returned list of module names can be used to access
+# ALL_MODULES.<module>.<*> variables.
+# Name resolution for PRODUCT_PACKAGES / PRODUCT_HOST_PACKAGES:
+# foo:32 resolves to foo_32;
+# foo:64 resolves to foo;
+# foo resolves to both foo and foo_32 (if foo_32 is defined).
+#
+# Name resolution for HOST_CROSS modules:
+# foo:32 resolves to foo;
+# foo:64 resolves to foo_64;
+# foo resolves to both foo and foo_64 (if foo_64 is defined).
+#
+# $(1): TARGET, HOST or HOST_CROSS
+# $(2): A list of simple module names with :32 and :64 suffix
+define resolve-bitness-for-modules
+$(strip \
+ $(eval modules_32 := $(patsubst %:32,%,$(filter %:32,$(2)))) \
+ $(eval modules_64 := $(patsubst %:64,%,$(filter %:64,$(2)))) \
+ $(eval modules_both := $(filter-out %:32 %:64,$(2))) \
+ $(eval ### For host cross modules, the primary arch is windows x86 and secondary is x86_64) \
+ $(if $(filter HOST_CROSS,$(1)), \
+ $(eval modules_1st_arch := $(modules_32)) \
+ $(eval modules_2nd_arch := $(modules_64)), \
+ $(eval modules_1st_arch := $(modules_64)) \
+ $(eval modules_2nd_arch := $(modules_32))) \
+ $(eval ### Note for 32-bit product, 32 and 64 will be added as their original module names.) \
+ $(eval modules := $(modules_1st_arch)) \
+ $(if $($(1)_2ND_ARCH), \
+ $(eval modules += $(call get-modules-for-2nd-arch,$(1),$(modules_2nd_arch))), \
+ $(eval modules += $(modules_2nd_arch))) \
+ $(eval ### For the rest we add both) \
+ $(eval modules += $(modules_both)) \
+ $(if $($(1)_2ND_ARCH), \
+ $(eval modules += $(call get-modules-for-2nd-arch,$(1),$(modules_both)))) \
+ $(modules) \
+)
+endef
+
# Lists most of the files a particular product installs, including:
# - PRODUCT_PACKAGES, and their LOCAL_REQUIRED_MODULES
# - PRODUCT_COPY_FILES
@@ -1057,15 +1111,7 @@
$(eval _pif_overrides := $(call module-overrides,$(_pif_modules))) \
$(eval _pif_modules := $(filter-out $(_pif_overrides), $(_pif_modules))) \
$(eval ### Resolve the :32 :64 module name) \
- $(eval _pif_modules_32 := $(patsubst %:32,%,$(filter %:32, $(_pif_modules)))) \
- $(eval _pif_modules_64 := $(patsubst %:64,%,$(filter %:64, $(_pif_modules)))) \
- $(eval _pif_modules_rest := $(filter-out %:32 %:64,$(_pif_modules))) \
- $(eval ### Note for 32-bit product, 32 and 64 will be added as their original module names.) \
- $(eval _pif_modules := $(call get-32-bit-modules-if-we-can, $(_pif_modules_32))) \
- $(eval _pif_modules += $(_pif_modules_64)) \
- $(eval ### For the rest we add both) \
- $(eval _pif_modules += $(call get-32-bit-modules, $(_pif_modules_rest))) \
- $(eval _pif_modules += $(_pif_modules_rest)) \
+ $(eval _pif_modules := $(sort $(call resolve-bitness-for-modules,TARGET,$(_pif_modules)))) \
$(call expand-required-modules,_pif_modules,$(_pif_modules),$(_pif_overrides)) \
$(filter-out $(HOST_OUT_ROOT)/%,$(call module-installed-files, $(_pif_modules))) \
$(call resolve-product-relative-paths,\
@@ -1076,18 +1122,12 @@
# This does support the :32 / :64 syntax, but does not support module overrides.
define host-installed-files
$(eval _hif_modules := $(call get-product-var,$(1),PRODUCT_HOST_PACKAGES)) \
- $(eval ### Resolve the :32 :64 module name) \
- $(eval _hif_modules_32 := $(patsubst %:32,%,$(filter %:32, $(_hif_modules)))) \
- $(eval _hif_modules_64 := $(patsubst %:64,%,$(filter %:64, $(_hif_modules)))) \
- $(eval _hif_modules_rest := $(filter-out %:32 %:64,$(_hif_modules))) \
- $(eval _hif_modules := $(call get-host-32-bit-modules-if-we-can, $(_hif_modules_32))) \
- $(eval _hif_modules += $(_hif_modules_64)) \
- $(eval ### For the rest we add both) \
- $(eval _hif_modules += $(call get-host-32-bit-modules, $(_hif_modules_rest))) \
- $(eval _hif_modules += $(_hif_modules_rest)) \
$(eval ### Split host vs host cross modules) \
$(eval _hcif_modules := $(filter host_cross_%,$(_hif_modules))) \
$(eval _hif_modules := $(filter-out host_cross_%,$(_hif_modules))) \
+ $(eval ### Resolve the :32 :64 module name) \
+ $(eval _hif_modules := $(sort $(call resolve-bitness-for-modules,HOST,$(_hif_modules)))) \
+ $(eval _hcif_modules := $(sort $(call resolve-bitness-for-modules,HOST_CROSS,$(_hcif_modules)))) \
$(call expand-required-host-modules,_hif_modules,$(_hif_modules),HOST) \
$(call expand-required-host-modules,_hcif_modules,$(_hcif_modules),HOST_CROSS) \
$(filter $(HOST_OUT)/%,$(call module-installed-files, $(_hif_modules))) \
diff --git a/core/product.mk b/core/product.mk
index ea9be72..0aa07ef 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -393,6 +393,13 @@
# If set, device retrofits virtual A/B.
_product_single_value_vars += PRODUCT_VIRTUAL_AB_OTA_RETROFIT
+# If set, forcefully generate a non-A/B update package.
+# Note: A device configuration should inherit from virtual_ab_ota_plus_non_ab.mk
+# instead of setting this variable directly.
+# Note: Use TARGET_OTA_ALLOW_NON_AB in the build system because
+# TARGET_OTA_ALLOW_NON_AB takes the value of AB_OTA_UPDATER into account.
+_product_single_value_vars += PRODUCT_OTA_FORCE_NON_AB_PACKAGE
+
# If set, Java module in product partition cannot use hidden APIs.
_product_single_value_vars += PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
diff --git a/target/board/emulator_arm64/device.mk b/target/board/emulator_arm64/device.mk
index 6753c11..57675d0 100644
--- a/target/board/emulator_arm64/device.mk
+++ b/target/board/emulator_arm64/device.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
# Cuttlefish has GKI kernel prebuilts, so use those for the GKI boot.img.
ifeq ($(TARGET_PREBUILT_KERNEL),)
LOCAL_KERNEL := device/google/cuttlefish_kernel/5.4-arm64/kernel
diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk
index 0a32415..cfb15f0 100644
--- a/target/board/generic/device.mk
+++ b/target/board/generic/device.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
# NFC:
# Provide default libnfc-nci.conf file for devices that does not have one in
# vendor/etc because aosp system image (of aosp_$arch products) is going to
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index d793c38..16c6c6d 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -60,7 +60,9 @@
TARGET_NO_VENDOR_BOOT := true
BOARD_USES_RECOVERY_AS_BOOT := true
-BOARD_BOOTIMAGE_PARTITION_SIZE := 0x04000000
+BOARD_KERNEL-5.4_BOOTIMAGE_PARTITION_SIZE := 67108864
+BOARD_KERNEL-5.4-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
+BOARD_KERNEL-5.4-LZ4_BOOTIMAGE_PARTITION_SIZE := 53477376
BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
BOARD_BOOT_HEADER_VERSION := 3
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index bbab2b4..2b10a3d 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
ifdef NET_ETH0_STARTONBOOT
PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
endif
diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk
index bbab2b4..2b10a3d 100755
--- a/target/board/generic_x86_64/device.mk
+++ b/target/board/generic_x86_64/device.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
ifdef NET_ETH0_STARTONBOOT
PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
endif
diff --git a/target/board/generic_x86_64_arm64/device.mk b/target/board/generic_x86_64_arm64/device.mk
index fa1eb67..76242c9 100755
--- a/target/board/generic_x86_64_arm64/device.mk
+++ b/target/board/generic_x86_64_arm64/device.mk
@@ -13,3 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/board/generic_x86_arm/device.mk b/target/board/generic_x86_arm/device.mk
index fa1eb67..76242c9 100644
--- a/target/board/generic_x86_arm/device.mk
+++ b/target/board/generic_x86_arm/device.mk
@@ -13,3 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/product/generic.mk b/target/product/generic.mk
index 68130e3..a1acaab 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
# This is a generic phone product that isn't specialized for a specific device.
# It includes the base Android platform.
diff --git a/target/product/virtual_ab_ota_plus_non_ab.mk b/target/product/virtual_ab_ota_plus_non_ab.mk
new file mode 100644
index 0000000..325d75e
--- /dev/null
+++ b/target/product/virtual_ab_ota_plus_non_ab.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2020 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/virtual_ab_ota.mk)
+
+PRODUCT_OTA_FORCE_NON_AB_PACKAGE := true
+
+PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.allow_non_ab=true
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 72f065d..8b6a690 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -1558,6 +1558,7 @@
split_large_apks = []
cache_size = common.OPTIONS.cache_size
split_threshold = 0.125
+ assert cache_size is not None
max_blocks_per_transfer = int(cache_size * split_threshold /
self.tgt.blocksize)
empty = RangeSet()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 42c29c0..96f93a8 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -677,9 +677,14 @@
makeint("userdata_size")
makeint("cache_size")
makeint("recovery_size")
- makeint("boot_size")
makeint("fstab_version")
+ boot_images = "boot.img"
+ if "boot_images" in d:
+ boot_images = d["boot_images"]
+ for b in boot_images.split():
+ makeint(b.replace(".img","_size"))
+
# Load recovery fstab if applicable.
d["fstab"] = _FindAndLoadRecoveryFstab(d, input_file, read_helper)
@@ -843,12 +848,13 @@
def LoadRecoveryFSTab(read_helper, fstab_version, recovery_fstab_path,
system_root_image=False):
class Partition(object):
- def __init__(self, mount_point, fs_type, device, length, context):
+ def __init__(self, mount_point, fs_type, device, length, context, slotselect):
self.mount_point = mount_point
self.fs_type = fs_type
self.device = device
self.length = length
self.context = context
+ self.slotselect = slotselect
try:
data = read_helper(recovery_fstab_path)
@@ -876,10 +882,13 @@
# It's a good line, parse it.
length = 0
+ slotselect = False
options = options.split(",")
for i in options:
if i.startswith("length="):
length = int(i[7:])
+ elif i == "slotselect":
+ slotselect = True
else:
# Ignore all unknown options in the unified fstab.
continue
@@ -893,7 +902,8 @@
mount_point = pieces[1]
d[mount_point] = Partition(mount_point=mount_point, fs_type=pieces[2],
- device=pieces[0], length=length, context=context)
+ device=pieces[0], length=length, context=context,
+ slotselect=slotselect)
# / is used for the system mount point when the root directory is included in
# system. Other areas assume system is always at "/system" so point /system
@@ -908,7 +918,8 @@
"""Finds the path to recovery fstab and loads its contents."""
# recovery fstab is only meaningful when installing an update via recovery
# (i.e. non-A/B OTA). Skip loading fstab if device used A/B OTA.
- if info_dict.get('ab_update') == 'true':
+ if info_dict.get('ab_update') == 'true' and \
+ info_dict.get("allow_non_ab") != "true":
return None
# We changed recovery.fstab path in Q, from ../RAMDISK/etc/recovery.fstab to
@@ -1334,7 +1345,10 @@
# AVB: if enabled, calculate and add hash to boot.img or recovery.img.
if info_dict.get("avb_enable") == "true":
avbtool = info_dict["avb_avbtool"]
- part_size = info_dict[partition_name + "_size"]
+ if partition_name == "recovery":
+ part_size = info_dict["recovery_size"]
+ else:
+ part_size = info_dict[image_name.replace(".img","_size")]
cmd = [avbtool, "add_hash_footer", "--image", img.name,
"--partition_size", str(part_size), "--partition_name",
partition_name]
@@ -2672,11 +2686,12 @@
self.device = 'map_partition("%s")' % partition
else:
if OPTIONS.source_info_dict is None:
- _, device_path = GetTypeAndDevice("/" + partition, OPTIONS.info_dict)
+ _, device_expr = GetTypeAndDeviceExpr("/" + partition,
+ OPTIONS.info_dict)
else:
- _, device_path = GetTypeAndDevice("/" + partition,
- OPTIONS.source_info_dict)
- self.device = '"%s"' % device_path
+ _, device_expr = GetTypeAndDeviceExpr("/" + partition,
+ OPTIONS.source_info_dict)
+ self.device = device_expr
@property
def required_cache(self):
@@ -2908,16 +2923,51 @@
"squashfs": "EMMC"
}
-
-def GetTypeAndDevice(mount_point, info):
+def GetTypeAndDevice(mount_point, info, check_no_slot=True):
+ """
+ Use GetTypeAndDeviceExpr whenever possible. This function is kept for
+ backwards compatibility. It aborts if the fstab entry has slotselect option
+ (unless check_no_slot is explicitly set to False).
+ """
fstab = info["fstab"]
if fstab:
+ if check_no_slot:
+ assert not fstab[mount_point].slotselect, \
+ "Use GetTypeAndDeviceExpr instead"
return (PARTITION_TYPES[fstab[mount_point].fs_type],
fstab[mount_point].device)
else:
raise KeyError
+def GetTypeAndDeviceExpr(mount_point, info):
+ """
+ Return the filesystem of the partition, and an edify expression that evaluates
+ to the device at runtime.
+ """
+ fstab = info["fstab"]
+ if fstab:
+ p = fstab[mount_point]
+ device_expr = '"%s"' % fstab[mount_point].device
+ if p.slotselect:
+ device_expr = 'add_slot_suffix(%s)' % device_expr
+ return (PARTITION_TYPES[fstab[mount_point].fs_type], device_expr)
+ else:
+ raise KeyError
+
+
+def GetEntryForDevice(fstab, device):
+ """
+ Returns:
+ The first entry in fstab whose device is the given value.
+ """
+ if not fstab:
+ return None
+ for mount_point in fstab:
+ if fstab[mount_point].device == device:
+ return fstab[mount_point]
+ return None
+
def ParseCertificate(data):
"""Parses and converts a PEM-encoded certificate into DER-encoded.
@@ -3042,8 +3092,10 @@
try:
# The following GetTypeAndDevice()s need to use the path in the target
# info_dict instead of source_info_dict.
- boot_type, boot_device = GetTypeAndDevice("/boot", info_dict)
- recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict)
+ boot_type, boot_device = GetTypeAndDevice("/boot", info_dict,
+ check_no_slot=False)
+ recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict,
+ check_no_slot=False)
except KeyError:
return
@@ -3085,8 +3137,8 @@
'recovery_size': recovery_img.size,
'recovery_sha1': recovery_img.sha1,
'boot_type': boot_type,
- 'boot_device': boot_device,
- 'recovery_type': recovery_type,
+ 'boot_device': boot_device + '$(getprop ro.boot.slot_suffix)',
+ 'recovery_type': recovery_type + '$(getprop ro.boot.slot_suffix)',
'recovery_device': recovery_device,
'bonus_args': bonus_args}
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 7ed85fe..99e21f1 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -183,11 +183,30 @@
It checks the checksums of the given partitions. If none of them matches the
expected checksum, updater will additionally look for a backup on /cache.
"""
+ self._CheckSecondTokenNotSlotSuffixed(target, "PatchPartitionExprCheck")
+ self._CheckSecondTokenNotSlotSuffixed(source, "PatchPartitionExprCheck")
+ self.PatchPartitionExprCheck('"%s"' % target, '"%s"' % source)
+
+ def PatchPartitionExprCheck(self, target_expr, source_expr):
+ """Checks whether updater can patch the given partitions.
+
+ It checks the checksums of the given partitions. If none of them matches the
+ expected checksum, updater will additionally look for a backup on /cache.
+
+ Args:
+ target_expr: an Edify expression that serves as the target arg to
+ patch_partition. Must be evaluated to a string in the form of
+ foo:bar:baz:quux
+ source_expr: an Edify expression that serves as the source arg to
+ patch_partition. Must be evaluated to a string in the form of
+ foo:bar:baz:quux
+ """
self.script.append(self.WordWrap((
- 'patch_partition_check("{target}",\0"{source}") ||\n abort('
- '"E{code}: \\"{target}\\" or \\"{source}\\" has unexpected '
- 'contents.");').format(
- target=target, source=source,
+ 'patch_partition_check({target},\0{source}) ||\n abort('
+ 'concat("E{code}: \\"",{target},"\\" or \\"",{source},"\\" has '
+ 'unexpected contents."));').format(
+ target=target_expr,
+ source=source_expr,
code=common.ErrorCode.BAD_PATCH_FILE)))
def CacheFreeSpaceCheck(self, amount):
@@ -218,8 +237,9 @@
mount_flags = mount_dict.get(p.fs_type, "")
if p.context is not None:
mount_flags = p.context + ("," + mount_flags if mount_flags else "")
- self.script.append('mount("%s", "%s", "%s", "%s", "%s");' % (
- p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device,
+ self.script.append('mount("%s", "%s", %s, "%s", "%s");' % (
+ p.fs_type, common.PARTITION_TYPES[p.fs_type],
+ self._GetSlotSuffixDeviceForEntry(p),
p.mount_point, mount_flags))
self.mounts.add(p.mount_point)
@@ -242,8 +262,9 @@
raise ValueError("Partition %s cannot be tuned\n" % (partition,))
self.script.append(
'tune2fs(' + "".join(['"%s", ' % (i,) for i in options]) +
- '"%s") || abort("E%d: Failed to tune partition %s");' % (
- p.device, common.ErrorCode.TUNE_PARTITION_FAILURE, partition))
+ '%s) || abort("E%d: Failed to tune partition %s");' % (
+ self._GetSlotSuffixDeviceForEntry(p),
+ common.ErrorCode.TUNE_PARTITION_FAILURE, partition))
def FormatPartition(self, partition):
"""Format the given partition, specified by its mount point (eg,
@@ -252,18 +273,19 @@
fstab = self.fstab
if fstab:
p = fstab[partition]
- self.script.append('format("%s", "%s", "%s", "%s", "%s");' %
+ self.script.append('format("%s", "%s", %s, "%s", "%s");' %
(p.fs_type, common.PARTITION_TYPES[p.fs_type],
- p.device, p.length, p.mount_point))
+ self._GetSlotSuffixDeviceForEntry(p),
+ p.length, p.mount_point))
def WipeBlockDevice(self, partition):
if partition not in ("/system", "/vendor"):
raise ValueError(("WipeBlockDevice doesn't work on %s\n") % (partition,))
fstab = self.fstab
size = self.info.get(partition.lstrip("/") + "_size", None)
- device = fstab[partition].device
+ device = self._GetSlotSuffixDeviceForEntry(fstab[partition])
- self.script.append('wipe_block_device("%s", %s);' % (device, size))
+ self.script.append('wipe_block_device(%s, %s);' % (device, size))
def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
"""Apply binary patches (in *patchpairs) to the given srcfile to
@@ -296,14 +318,69 @@
self.PatchPartition(target, source, patch)
def PatchPartition(self, target, source, patch):
- """Applies the patch to the source partition and writes it to target."""
+ """
+ Applies the patch to the source partition and writes it to target.
+
+ Args:
+ target: the target arg to patch_partition. Must be in the form of
+ foo:bar:baz:quux
+ source: the source arg to patch_partition. Must be in the form of
+ foo:bar:baz:quux
+ patch: the patch arg to patch_partition. Must be an unquoted string.
+ """
+ self._CheckSecondTokenNotSlotSuffixed(target, "PatchPartitionExpr")
+ self._CheckSecondTokenNotSlotSuffixed(source, "PatchPartitionExpr")
+ self.PatchPartitionExpr('"%s"' % target, '"%s"' % source, '"%s"' % patch)
+
+ def PatchPartitionExpr(self, target_expr, source_expr, patch_expr):
+ """
+ Applies the patch to the source partition and writes it to target.
+
+ Args:
+ target_expr: an Edify expression that serves as the target arg to
+ patch_partition. Must be evaluated to a string in the form of
+ foo:bar:baz:quux
+ source_expr: an Edify expression that serves as the source arg to
+ patch_partition. Must be evaluated to a string in the form of
+ foo:bar:baz:quux
+ patch_expr: an Edify expression that serves as the patch arg to
+ patch_partition. Must be evaluated to a string.
+ """
self.script.append(self.WordWrap((
- 'patch_partition("{target}",\0"{source}",\0'
- 'package_extract_file("{patch}")) ||\n'
- ' abort("E{code}: Failed to apply patch to {source}");').format(
- target=target, source=source, patch=patch,
+ 'patch_partition({target},\0{source},\0'
+ 'package_extract_file({patch})) ||\n'
+ ' abort(concat('
+ ' "E{code}: Failed to apply patch to ",{source}));').format(
+ target=target_expr,
+ source=source_expr,
+ patch=patch_expr,
code=common.ErrorCode.APPLY_PATCH_FAILURE)))
+ def _GetSlotSuffixDeviceForEntry(self, entry=None):
+ """
+ Args:
+ entry: the fstab entry of device "foo"
+ Returns:
+ An edify expression. Caller must not quote result.
+ If foo is slot suffixed, it returns
+ 'add_slot_suffix("foo")'
+ Otherwise it returns
+ '"foo"' (quoted)
+ """
+ assert entry is not None
+ if entry.slotselect:
+ return 'add_slot_suffix("%s")' % entry.device
+ return '"%s"' % entry.device
+
+ def _CheckSecondTokenNotSlotSuffixed(self, s, fn):
+ lst = s.split(':')
+ assert(len(s) == 4), "{} does not contain 4 tokens".format(s)
+ if self.fstab:
+ entry = common.GetEntryForDevice(s[1])
+ if entry is not None:
+ assert not entry.slotselect, \
+ "Use %s because %s is slot suffixed" % (fn, s[1])
+
def WriteRawImage(self, mount_point, fn, mapfn=None):
"""Write the given package file into the partition for the given
mount point."""
@@ -312,15 +389,16 @@
if fstab:
p = fstab[mount_point]
partition_type = common.PARTITION_TYPES[p.fs_type]
- args = {'device': p.device, 'fn': fn}
+ device = self._GetSlotSuffixDeviceForEntry(p)
+ args = {'device': device, 'fn': fn}
if partition_type == "EMMC":
if mapfn:
args["map"] = mapfn
self.script.append(
- 'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args)
+ 'package_extract_file("%(fn)s", %(device)s, "%(map)s");' % args)
else:
self.script.append(
- 'package_extract_file("%(fn)s", "%(device)s");' % args)
+ 'package_extract_file("%(fn)s", %(device)s);' % args)
else:
raise ValueError(
"don't know how to write \"%s\" partitions" % p.fs_type)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index ad001d1..16b278a 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -78,6 +78,13 @@
Write a copy of the metadata to a separate file. Therefore, users can
read the post build fingerprint without extracting the OTA package.
+ --force_non_ab
+ This flag can only be set on an A/B device that also supports non-A/B
+ updates. Implies --two_step.
+ If set, generate that non-A/B update package.
+ If not set, generates A/B package for A/B device and non-A/B package for
+ non-A/B device.
+
Non-A/B OTA specific options
-b (--binary) <file>
@@ -251,6 +258,7 @@
OPTIONS.output_metadata_path = None
OPTIONS.disable_fec_computation = False
OPTIONS.boot_variable_values = None
+OPTIONS.force_non_ab = False
METADATA_NAME = 'META-INF/com/android/metadata'
@@ -933,7 +941,7 @@
'ro.build.version.security_patch'),
}
- if target_info.is_ab:
+ if target_info.is_ab and not OPTIONS.force_non_ab:
metadata['ota-type'] = 'AB'
metadata['ota-required-cache'] = '0'
else:
@@ -1455,7 +1463,8 @@
required_cache_sizes = [diff.required_cache for diff in
block_diff_dict.values()]
if updating_boot:
- boot_type, boot_device = common.GetTypeAndDevice("/boot", source_info)
+ boot_type, boot_device_expr = common.GetTypeAndDeviceExpr("/boot",
+ source_info)
d = common.Difference(target_boot, source_boot)
_, _, d = d.ComputePatch()
if d is None:
@@ -1470,11 +1479,11 @@
common.ZipWriteStr(output_zip, "boot.img.p", d)
- script.PatchPartitionCheck(
- "{}:{}:{}:{}".format(
- boot_type, boot_device, target_boot.size, target_boot.sha1),
- "{}:{}:{}:{}".format(
- boot_type, boot_device, source_boot.size, source_boot.sha1))
+ target_expr = 'concat("{}:",{},":{}:{}")'.format(
+ boot_type, boot_device_expr, target_boot.size, target_boot.sha1)
+ source_expr = 'concat("{}:",{},":{}:{}")'.format(
+ boot_type, boot_device_expr, source_boot.size, source_boot.sha1)
+ script.PatchPartitionExprCheck(target_expr, source_expr)
required_cache_sizes.append(target_boot.size)
@@ -1542,12 +1551,11 @@
logger.info("boot image changed; including patch.")
script.Print("Patching boot image...")
script.ShowProgress(0.1, 10)
- script.PatchPartition(
- '{}:{}:{}:{}'.format(
- boot_type, boot_device, target_boot.size, target_boot.sha1),
- '{}:{}:{}:{}'.format(
- boot_type, boot_device, source_boot.size, source_boot.sha1),
- 'boot.img.p')
+ target_expr = 'concat("{}:",{},":{}:{}")'.format(
+ boot_type, boot_device_expr, target_boot.size, target_boot.sha1)
+ source_expr = 'concat("{}:",{},":{}:{}")'.format(
+ boot_type, boot_device_expr, source_boot.size, source_boot.sha1)
+ script.PatchPartitionExpr(target_expr, source_expr, '"boot.img.p"')
else:
logger.info("boot image unchanged; skipping.")
@@ -2067,6 +2075,8 @@
OPTIONS.output_metadata_path = a
elif o == "--disable_fec_computation":
OPTIONS.disable_fec_computation = True
+ elif o == "--force_non_ab":
+ OPTIONS.force_non_ab = True
else:
return False
return True
@@ -2103,6 +2113,7 @@
"skip_compatibility_check",
"output_metadata_path=",
"disable_fec_computation",
+ "force_non_ab",
], extra_option_handler=option_handler)
if len(args) != 2:
@@ -2164,11 +2175,17 @@
OPTIONS.skip_postinstall = True
ab_update = OPTIONS.info_dict.get("ab_update") == "true"
+ allow_non_ab = OPTIONS.info_dict.get("allow_non_ab") == "true"
+ if OPTIONS.force_non_ab:
+ assert allow_non_ab, "--force_non_ab only allowed on devices that supports non-A/B"
+ assert ab_update, "--force_non_ab only allowed on A/B devices"
+
+ generate_ab = not OPTIONS.force_non_ab and ab_update
# Use the default key to sign the package if not specified with package_key.
# package_keys are needed on ab_updates, so always define them if an
- # ab_update is getting created.
- if not OPTIONS.no_signing or ab_update:
+ # A/B update is getting created.
+ if not OPTIONS.no_signing or generate_ab:
if OPTIONS.package_key is None:
OPTIONS.package_key = OPTIONS.info_dict.get(
"default_system_dev_certificate",
@@ -2176,7 +2193,7 @@
# Get signing keys
OPTIONS.key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
- if ab_update:
+ if generate_ab:
GenerateAbOtaPackage(
target_file=args[0],
output_file=args[1],