aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-10-04 15:03:26 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2023-10-04 15:03:26 +0000
commit21561fc09f5ed287dc663d0ae27af58800f4541e (patch)
tree575442f1e7cad22c298d7dfaf2cf08bce8754979
parent4cb1f72f1a8c68b032d68cce479d6b6c26bf3afb (diff)
parentb871f0edfb7cc9322bdfcdfe6fc9e1bb49d4d0b2 (diff)
downloadbuild-platform-tools-34.0.5.tar.gz
Merge "Snap for 10900817 from f81405aab0972f62d9af44e682227a787da2e4e3 to sdk-release" into sdk-releaseplatform-tools-34.0.5
-rw-r--r--Changes.md23
-rw-r--r--CleanSpec.mk6
-rw-r--r--cogsetup.sh92
-rw-r--r--core/BUILD.bazel24
-rw-r--r--core/Makefile820
-rw-r--r--core/OWNERS2
-rw-r--r--core/aapt2.mk5
-rw-r--r--core/android_soong_config_vars.mk15
-rw-r--r--core/app_prebuilt_internal.mk4
-rw-r--r--core/base_rules.mk45
-rw-r--r--core/board_config.mk24
-rw-r--r--core/build_id.mk2
-rw-r--r--core/clear_vars.mk2
-rw-r--r--core/combo/HOST_darwin.mk (renamed from core/combo/HOST_darwin-x86_64.mk)2
-rw-r--r--core/combo/HOST_linux-x86_64.mk22
-rw-r--r--core/combo/HOST_linux.mk (renamed from core/combo/HOST_linux-x86.mk)2
-rw-r--r--core/combo/select.mk8
-rw-r--r--core/config.mk94
-rw-r--r--core/config_sanitizers.mk13
-rw-r--r--core/definitions.mk46
-rw-r--r--core/dex_preopt.mk8
-rw-r--r--core/dex_preopt_config.mk1
-rw-r--r--core/dex_preopt_odex_install.mk65
-rwxr-xr-xcore/dupcheck.sh118
-rw-r--r--core/envsetup.mk4
-rw-r--r--core/java_common.mk12
-rw-r--r--core/main.mk88
-rw-r--r--core/package_internal.mk2
-rw-r--r--core/packaging/flags.mk139
-rw-r--r--core/product.mk26
-rw-r--r--core/product_config.mk64
-rw-r--r--core/proguard.flags9
-rw-r--r--core/proguard_basic_keeps.flags6
-rw-r--r--core/release_config.bzl50
-rw-r--r--core/rust_device_benchmark_config_template.xml2
-rw-r--r--core/soong_app_prebuilt.mk37
-rw-r--r--core/soong_config.mk106
-rw-r--r--core/soong_java_prebuilt.mk44
-rw-r--r--core/static_java_library.mk6
-rw-r--r--core/sysprop.mk38
-rw-r--r--core/tasks/cts.mk22
-rw-r--r--core/tasks/module-info.mk60
-rw-r--r--core/tasks/tools/package-modules.mk1
-rw-r--r--core/version_defaults.mk4
-rw-r--r--core/version_util.mk23
-rw-r--r--envsetup.sh56
-rw-r--r--target/board/Android.mk26
-rw-r--r--target/board/emulator_arm64/BoardConfig.mk3
-rw-r--r--target/board/generic/BoardConfig.mk17
-rw-r--r--target/board/generic/device.mk2
-rw-r--r--target/board/generic_64bitonly_x86_64/BoardConfig.mk20
-rw-r--r--target/board/generic_x86/BoardConfig.mk20
-rw-r--r--target/board/generic_x86/device.mk3
-rw-r--r--[-rwxr-xr-x]target/board/generic_x86_64/BoardConfig.mk20
-rw-r--r--[-rwxr-xr-x]target/board/generic_x86_64_arm64/BoardConfig.mk15
-rw-r--r--[-rwxr-xr-x]target/board/generic_x86_64_arm64/device.mk2
-rw-r--r--target/board/generic_x86_arm/BoardConfig.mk15
-rw-r--r--target/board/generic_x86_arm/device.mk2
-rw-r--r--target/product/aosp_64bitonly_x86_64.mk1
-rw-r--r--target/product/aosp_arm.mk1
-rw-r--r--target/product/aosp_arm64.mk1
-rw-r--r--target/product/aosp_riscv64.mk1
-rw-r--r--target/product/aosp_x86.mk1
-rw-r--r--target/product/aosp_x86_64.mk1
-rw-r--r--target/product/aosp_x86_arm.mk1
-rw-r--r--target/product/base_system.mk27
-rw-r--r--target/product/base_vendor.mk3
-rw-r--r--target/product/cfi-common.mk2
-rw-r--r--target/product/default_art_config.mk16
-rw-r--r--target/product/full.manifest.xml2
-rw-r--r--target/product/full.mk3
-rw-r--r--target/product/full_x86.mk3
-rw-r--r--target/product/generic.mk3
-rw-r--r--target/product/generic_system.mk9
-rw-r--r--target/product/gsi/Android.bp23
-rw-r--r--target/product/gsi/Android.mk48
-rw-r--r--target/product/gsi_release.mk8
-rw-r--r--target/product/mainline_sdk.mk2
-rw-r--r--target/product/sdk.mk7
-rw-r--r--target/product/sdk_arm64.mk9
-rw-r--r--target/product/sdk_phone_arm64.mk2
-rw-r--r--target/product/sdk_phone_armv7.mk2
-rw-r--r--target/product/sdk_phone_x86.mk2
-rw-r--r--target/product/sdk_phone_x86_64.mk2
-rw-r--r--target/product/sdk_x86.mk11
-rw-r--r--target/product/sdk_x86_64.mk12
-rw-r--r--target/product/updatable_apex.mk22
-rw-r--r--tools/Android.bp14
-rw-r--r--tools/BUILD.bazel8
-rw-r--r--tools/aconfig/Android.bp94
-rw-r--r--tools/aconfig/TEST_MAPPING6
-rw-r--r--tools/aconfig/fake_device_config/Android.bp21
-rw-r--r--tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java29
-rw-r--r--tools/aconfig/printflags/Android.bp27
-rw-r--r--tools/aconfig/printflags/src/main.rs110
-rw-r--r--tools/aconfig/protos/aconfig.proto2
-rw-r--r--tools/aconfig/src/codegen_cpp.rs462
-rw-r--r--tools/aconfig/src/codegen_java.rs200
-rw-r--r--tools/aconfig/src/codegen_rust.rs291
-rw-r--r--tools/aconfig/src/commands.rs177
-rw-r--r--tools/aconfig/src/main.rs65
-rw-r--r--tools/aconfig/src/protos.rs154
-rw-r--r--tools/aconfig/src/test.rs27
-rw-r--r--tools/aconfig/templates/FakeFeatureFlagsImpl.java.template47
-rw-r--r--tools/aconfig/templates/FeatureFlags.java.template8
-rw-r--r--tools/aconfig/templates/FeatureFlagsImpl.java.template87
-rw-r--r--tools/aconfig/templates/Flags.java.template15
-rw-r--r--tools/aconfig/templates/cpp_exported_header.template63
-rw-r--r--tools/aconfig/templates/cpp_prod_flag_provider.template22
-rw-r--r--tools/aconfig/templates/cpp_source_file.template99
-rw-r--r--tools/aconfig/templates/cpp_test_flag_provider.template49
-rw-r--r--tools/aconfig/templates/rust.template29
-rw-r--r--tools/aconfig/templates/rust_prod.template38
-rw-r--r--tools/aconfig/templates/rust_test.template61
-rw-r--r--tools/aconfig/tests/AconfigHostTest.java88
-rw-r--r--tools/aconfig/tests/AconfigTest.java30
-rw-r--r--tools/aconfig/tests/aconfig_prod_mode_test.rs9
-rw-r--r--tools/aconfig/tests/aconfig_test.cpp43
-rw-r--r--tools/aconfig/tests/aconfig_test_mode_test.rs24
-rw-r--r--tools/aconfig/tests/first.values6
-rw-r--r--tools/aconfig/tests/test.aconfig45
-rwxr-xr-xtools/auto_gen_test_config.py109
-rw-r--r--tools/auto_gen_test_config_test.py148
-rwxr-xr-xtools/buildinfo.sh10
-rw-r--r--tools/releasetools/Android.bp27
-rw-r--r--tools/releasetools/add_img_to_target_files.py82
-rwxr-xr-xtools/releasetools/build_image.py90
-rw-r--r--tools/releasetools/common.py79
-rwxr-xr-xtools/releasetools/img_from_target_files.py14
-rw-r--r--tools/releasetools/merge/merge_meta.py28
-rwxr-xr-xtools/releasetools/merge/merge_target_files.py4
-rw-r--r--tools/releasetools/merge/merge_utils.py2
-rw-r--r--tools/releasetools/merge_ota.py29
-rw-r--r--tools/releasetools/ota_from_raw_img.py120
-rwxr-xr-xtools/releasetools/ota_from_target_files.py133
-rw-r--r--tools/releasetools/ota_signing_utils.py38
-rw-r--r--tools/releasetools/ota_utils.py69
-rw-r--r--tools/releasetools/payload_signer.py23
-rwxr-xr-xtools/releasetools/sign_target_files_apks.py4
-rw-r--r--tools/releasetools/test_common.py139
-rw-r--r--tools/sbom/Android.bp22
-rw-r--r--tools/sbom/sbom_data.py2
-rw-r--r--tools/sbom/sbom_data_test.py139
-rw-r--r--tools/zipalign/Android.bp1
-rw-r--r--tools/zipalign/ZipAlign.cpp25
-rw-r--r--tools/zipalign/ZipAlignMain.cpp51
-rw-r--r--tools/zipalign/ZipEntry.cpp44
-rw-r--r--tools/zipalign/include/ZipAlign.h12
-rw-r--r--tools/zipalign/tests/data/apkWithUncompressedSharedLibs.zipbin0 -> 1680 bytes
-rw-r--r--tools/zipalign/tests/src/align_test.cpp86
150 files changed, 4772 insertions, 1820 deletions
diff --git a/Changes.md b/Changes.md
index fc6701d7e5..6c0cf7020e 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,4 +1,19 @@
-# Build System Changes for Android.mk Writers
+# Build System Changes for Android.mk/Android.bp Writers
+
+## Partitions are no longer affected by previous builds
+
+Partition builds used to include everything in their staging directories, and building an
+individual module will install it to the staging directory. Thus, previously, `m mymodule` followed
+by `m` would cause `mymodule` to be presinstalled on the device, even if it wasn't listed in
+`PRODUCT_PACKAGES`.
+
+This behavior has been changed, and now the partition images only include what they'd have if you
+did a clean build. This behavior can be disabled by setting the
+`BUILD_BROKEN_INCORRECT_PARTITION_IMAGES` environment variable or board config variable.
+
+Manually adding make rules that build to the staging directories without going through the make
+module system will not be compatible with this change. This includes many usages of
+`LOCAL_POST_INSTALL_CMD`.
## Perform validation of Soong plugins
@@ -10,8 +25,9 @@ If you need to extend the build system via a plugin, please reach out to the
build team via email android-building@googlegroups.com (external) for any
questions, or see [go/soong](http://go/soong) (internal).
-To omit the validation, `BUILD_BROKEN_PLUGIN_VALIDATION` expects a list of
-plugins to omit from the validation.
+To omit the validation, `BUILD_BROKEN_PLUGIN_VALIDATION` expects a
+space-separated list of plugins to omit from the validation. This must be set
+within a product configuration .mk file, board config .mk file, or buildspec.mk.
## Python 2 to 3 migration
@@ -28,6 +44,7 @@ overridden by setting the `BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES` product conf
variable to `true`.
Python 2 is slated for complete removal in V.
+
## Stop referencing sysprop_library directly from cc modules
For the migration to Bazel, we are no longer mapping sysprop_library targets
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 957da92f63..dfc0cd0fff 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -773,6 +773,12 @@ $(call add-clean-step, rm -rf $(SOONG_HOST_OUT))
# Don't use SOONG_HOST_OUT, it is now an alias for HOST_OUT.
$(call add-clean-step, rm -rf $(OUT_DIR)/soong/host)
+# Clear out tools/metalava Bazel output dir
+$(call add-clean-step, rm -rf $(OUT_DIR)/bazel/output/execroot/__main__/bazel-out/mixed_builds_product-*/bin/tools/metalava)
+
+# Clear out rustc compiler intermediates after reverting rust compiler/linker split.
+$(call add-clean-step, find $(OUT_DIR) -name "*.rsp.whole.a" -print0 | xargs -0 /bin/bash -c 'rm -f $$$${@}; rm -f $$$${@/.rsp.whole.a/.rsp.a}; rm -f $$$${@/.rsp.whole.a/.rsp}')
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/cogsetup.sh b/cogsetup.sh
new file mode 100644
index 0000000000..3005d587ae
--- /dev/null
+++ b/cogsetup.sh
@@ -0,0 +1,92 @@
+#
+# Copyright (C) 2023 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.
+#
+
+# This file is executed by build/envsetup.sh, and can use anything
+# defined in envsetup.sh.
+function _create_out_symlink_for_cog() {
+ if [[ "${OUT_DIR}" == "" ]]; then
+ OUT_DIR="out"
+ fi
+
+ if [[ -L "${OUT_DIR}" ]]; then
+ return
+ fi
+ if [ -d "${OUT_DIR}" ]; then
+ echo -e "\tOutput directory ${OUT_DIR} cannot be present in a Cog workspace."
+ echo -e "\tDelete \"${OUT_DIR}\" or create a symlink from \"${OUT_DIR}\" to a directory outside your workspace."
+ return 1
+ fi
+
+ DEFAULT_OUTPUT_DIR="${HOME}/.cog/android-build-out"
+ mkdir -p ${DEFAULT_OUTPUT_DIR}
+ ln -s ${DEFAULT_OUTPUT_DIR} `pwd`/out
+}
+
+# This function moves the reclient binaries into a directory that exists in a
+# non-cog part of the overall filesystem. This is to workaround the problem
+# described in b/289391270.
+function _copy_reclient_binaries_from_cog() {
+ if [[ "${OUT_DIR}" == "" ]]; then
+ OUT_DIR="out"
+ fi
+ local RECLIENT_VERSION=`readlink prebuilts/remoteexecution-client/live`
+
+ local NONCOG_RECLIENT_BIN_DIR_BASE="${OUT_DIR}/.reclient"
+ local NONCOG_RECLIENT_BIN_DIR="${NONCOG_RECLIENT_BIN_DIR_BASE}/${RECLIENT_VERSION}"
+
+ # Create the non cog directory and setup live symlink.
+ mkdir -p ${NONCOG_RECLIENT_BIN_DIR}
+
+ if [ `ls ${NONCOG_RECLIENT_BIN_DIR} | wc -l` -lt 8 ]; then
+ # Not all binaries exist, copy them from the Cog directory.
+ local TOP=$(gettop)
+ cp ${TOP}/prebuilts/remoteexecution-client/live/* ${NONCOG_RECLIENT_BIN_DIR}
+ fi
+
+ ln -sfn ${RECLIENT_VERSION} ${NONCOG_RECLIENT_BIN_DIR_BASE}/live
+ export RBE_DIR="${NONCOG_RECLIENT_BIN_DIR_BASE}/live"
+}
+
+# This function sets up the build environment to be appropriate for Cog.
+function _setup_cog_env() {
+ _create_out_symlink_for_cog
+ if [ "$?" -eq "1" ]; then
+ echo -e "\e[0;33mWARNING:\e[00m Cog environment setup failed!"
+ return 1
+ fi
+ _copy_reclient_binaries_from_cog
+
+ export ANDROID_BUILD_ENVIRONMENT_CONFIG="googler-cog"
+
+ # Running repo command within Cog workspaces is not supported, so override
+ # it with this function. If the user is running repo within a Cog workspace,
+ # we'll fail with an error, otherwise, we run the original repo command with
+ # the given args.
+ ORIG_REPO_PATH=`which repo`
+ function repo {
+ if [[ "${PWD}" == /google/cog/* ]]; then
+ echo "\e[01;31mERROR:\e[0mrepo command is disallowed within Cog workspaces."
+ return 1
+ fi
+ ${ORIG_REPO_PATH} "$@"
+ }
+}
+
+if [[ "${PWD}" != /google/cog/* ]]; then
+ echo -e "\e[01;31mERROR:\e[0m This script must be run from a Cog workspace."
+fi
+
+_setup_cog_env \ No newline at end of file
diff --git a/core/BUILD.bazel b/core/BUILD.bazel
index 3e69e62702..f4869d4833 100644
--- a/core/BUILD.bazel
+++ b/core/BUILD.bazel
@@ -1,4 +1,28 @@
+# Copyright (C) 2023 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
+
# Export tradefed templates for tests.
exports_files(
glob(["*.xml"]),
)
+
+# Export proguard flag files for r8.
+filegroup(
+ name = "global_proguard_flags",
+ srcs = [
+ "proguard.flags",
+ "proguard_basic_keeps.flags",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/core/Makefile b/core/Makefile
index 649982d818..fc2a132670 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -16,53 +16,93 @@ VENDOR_DLKM_NOTICE_DEPS :=
ODM_DLKM_NOTICE_DEPS :=
SYSTEM_DLKM_NOTICE_DEPS :=
-# -----------------------------------------------------------------
-# Release Config Flags
-
-# Create a summary file of build flags for each partition
-# $(1): build flags json file
-# $(2): flag names
-define generate-partition-build-flag-file
-$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
-$(eval $(strip $(1)): PRIVATE_FLAG_NAMES := $(strip $(2)))
-$(strip $(1)):
- mkdir -p $$(dir $$(PRIVATE_OUT))
- echo '{' > $$(PRIVATE_OUT)
- echo '"flags": [' >> $$(PRIVATE_OUT)
- $$(foreach flag, $$(PRIVATE_FLAG_NAMES), \
- ( \
- printf ' { "name": "%s", "value": "%s", ' \
- '$$(flag)' \
- '$$(_ALL_RELEASE_FLAGS.$$(flag).VALUE)' \
- ; \
- printf '"set": "%s", "default": "%s", "declared": "%s" }' \
- '$$(_ALL_RELEASE_FLAGS.$$(flag).SET_IN)' \
- '$$(_ALL_RELEASE_FLAGS.$$(flag).DEFAULT)' \
- '$$(_ALL_RELEASE_FLAGS.$$(flag).DECLARED_IN)' \
- ; \
- printf '$$(if $$(filter $$(lastword $$(PRIVATE_FLAG_NAMES)),$$(flag)),,$$(comma))\n' ; \
- ) >> $$(PRIVATE_OUT) \
- )
- echo "]" >> $$(PRIVATE_OUT)
- echo "}" >> $$(PRIVATE_OUT)
+
+# IMAGES_TO_BUILD is a list of the partition .img files that will be created.
+IMAGES_TO_BUILD:=
+ifneq ($(BUILDING_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += boot
+endif
+ifneq ($(BUILDING_CACHE_IMAGE),)
+ IMAGES_TO_BUILD += cache
+endif
+ifneq ($(BUILDING_DEBUG_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += debug_boot
+endif
+ifneq ($(BUILDING_DEBUG_VENDOR_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += debug_vendor_boot
+endif
+ifneq ($(BUILDING_INIT_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += init_boot
+endif
+ifneq ($(BUILDING_ODM_DLKM_IMAGE),)
+ IMAGES_TO_BUILD += odm_dlkm
+endif
+ifneq ($(BUILDING_ODM_IMAGE),)
+ IMAGES_TO_BUILD += odm
+endif
+ifneq ($(BUILDING_PRODUCT_IMAGE),)
+ IMAGES_TO_BUILD += product
+endif
+ifneq ($(BUILDING_RAMDISK_IMAGE),)
+ IMAGES_TO_BUILD += ramdisk
+endif
+ifneq ($(BUILDING_RECOVERY_IMAGE),)
+ IMAGES_TO_BUILD += recovery
+endif
+ifneq ($(BUILDING_SUPER_EMPTY_IMAGE),)
+ IMAGES_TO_BUILD += super_empty
+endif
+ifneq ($(BUILDING_SYSTEM_DLKM_IMAGE),)
+ IMAGES_TO_BUILD += system_dlkm
+endif
+ifneq ($(BUILDING_SYSTEM_EXT_IMAGE),)
+ IMAGES_TO_BUILD += system_ext
+endif
+ifneq ($(BUILDING_SYSTEM_IMAGE),)
+ IMAGES_TO_BUILD += system
+endif
+ifneq ($(BUILDING_SYSTEM_OTHER_IMAGE),)
+ IMAGES_TO_BUILD += system_other
+endif
+ifneq ($(BUILDING_USERDATA_IMAGE),)
+ IMAGES_TO_BUILD += userdata
+endif
+ifneq ($(BUILDING_VBMETA_IMAGE),)
+ IMAGES_TO_BUILD += vbmeta
+endif
+ifneq ($(BUILDING_VENDOR_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += vendor_boot
+endif
+ifneq ($(BUILDING_VENDOR_DLKM_IMAGE),)
+ IMAGES_TO_BUILD += vendor_dlkm
+endif
+ifneq ($(BUILDING_VENDOR_IMAGE),)
+ IMAGES_TO_BUILD += vendor
+endif
+ifneq ($(BUILDING_VENDOR_KERNEL_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += vendor_kernel_boot
+endif
+
+
+###########################################################
+# Get the module names suitable for ALL_MODULES.* variables that are installed
+# for a given partition
+#
+# $(1): Partition
+###########################################################
+define register-names-for-partition
+$(sort $(foreach m,$(product_MODULES),\
+ $(if $(filter $(PRODUCT_OUT)/$(strip $(1))/%, $(ALL_MODULES.$(m).INSTALLED)), \
+ $(m)
+ ) \
+))
endef
-_FLAG_PARTITIONS := product system system_ext vendor
-$(foreach partition, $(_FLAG_PARTITIONS), \
- $(eval BUILD_FLAG_SUMMARIES.$(partition) \
- := $(TARGET_OUT_FLAGS)/$(partition)/etc/build_flags.json) \
- $(eval $(call generate-partition-build-flag-file, \
- $(BUILD_FLAG_SUMMARIES.$(partition)), \
- $(_ALL_RELEASE_FLAGS.PARTITIONS.$(partition)) \
- ) \
- ) \
-)
+# Release & Aconfig Flags
+# -----------------------------------------------------------------
+include $(BUILD_SYSTEM)/packaging/flags.mk
-# TODO: Remove
-.PHONY: flag-files
-flag-files: $(foreach partition, $(_FLAG_PARTITIONS), \
- $(TARGET_OUT_FLAGS)/$(partition)/etc/build_flags.json)
# -----------------------------------------------------------------
# Define rules to copy PRODUCT_COPY_FILES defined by the product.
@@ -323,6 +363,10 @@ $(foreach vendor_ramdisk_fragment,$(BOARD_VENDOR_RAMDISK_FRAGMENTS), \
)
INTERNAL_VENDOR_RAMDISK_FRAGMENTS += $(BOARD_VENDOR_RAMDISK_FRAGMENTS)
+ifneq ($(BOARD_KERNEL_MODULES_16K),)
+INTERNAL_VENDOR_RAMDISK_FRAGMENTS += 16K
+endif
+
# Strip the list in case of any whitespace.
INTERNAL_VENDOR_RAMDISK_FRAGMENTS := \
$(strip $(INTERNAL_VENDOR_RAMDISK_FRAGMENTS))
@@ -1010,16 +1054,32 @@ TARGET_OUT_RAMDISK_16K := $(PRODUCT_OUT)/ramdisk_16k
BUILT_RAMDISK_16K_TARGET := $(PRODUCT_OUT)/ramdisk_16k.img
RAMDISK_16K_STAGING_DIR := $(call intermediates-dir-for,PACKAGING,depmod_ramdisk_16k)
-$(BUILT_RAMDISK_16K_TARGET): $(DEPMOD) $(MKBOOTFS)
-$(BUILT_RAMDISK_16K_TARGET): $(call copy-many-files,$(foreach file,$(BOARD_KERNEL_MODULES_16K),$(file):$(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0/$(notdir $(file))))
+$(foreach \
+ file,\
+ $(BOARD_KERNEL_MODULES_16K),\
+ $(eval \
+ $(call copy-and-strip-kernel-module,\
+ $(file),\
+ $(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0/$(notdir $(file)) \
+ ) \
+ ) \
+)
+
+BOARD_VENDOR_RAMDISK_FRAGMENT.16K.PREBUILT := $(BUILT_RAMDISK_16K_TARGET)
+
+$(BUILT_RAMDISK_16K_TARGET): $(DEPMOD) $(MKBOOTFS) $(EXTRACT_KERNEL) $(COMPRESSION_COMMAND_DEPS)
+$(BUILT_RAMDISK_16K_TARGET): $(foreach file,$(BOARD_KERNEL_MODULES_16K),$(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0/$(notdir $(file)))
$(DEPMOD) -b $(RAMDISK_16K_STAGING_DIR) 0.0
for MODULE in $(BOARD_KERNEL_MODULES_16K); do \
basename $$MODULE >> $(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0/modules.load ; \
done;
- mkdir -p $(TARGET_OUT_RAMDISK_16K)/lib
rm -rf $(TARGET_OUT_RAMDISK_16K)/lib/modules
- cp -r $(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0 $(TARGET_OUT_RAMDISK_16K)/lib/modules
- $(MKBOOTFS) $(TARGET_OUT_RAMDISK_16K) > $@
+ mkdir -p $(TARGET_OUT_RAMDISK_16K)/lib/modules
+ KERNEL_RELEASE=`$(EXTRACT_KERNEL) --tools lz4:$(LZ4) --input $(BOARD_KERNEL_PATH_16K) --output-release` ;\
+ IS_16K_KERNEL=`$(EXTRACT_KERNEL) --tools lz4:$(LZ4) --input $(BOARD_KERNEL_PATH_16K) --output-config` ;\
+ if [[ "$$IS_16K_KERNEL" == *"CONFIG_ARM64_16K_PAGES=y"* ]]; then SUFFIX=_16k; fi ;\
+ cp -r $(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0 $(TARGET_OUT_RAMDISK_16K)/lib/modules/$$KERNEL_RELEASE$$SUFFIX
+ $(MKBOOTFS) $(TARGET_OUT_RAMDISK_16K) | $(COMPRESSION_COMMAND) > $@
# Builds a ramdisk using modules defined in BOARD_KERNEL_MODULES_16K
ramdisk_16k: $(BUILT_RAMDISK_16K_TARGET)
@@ -1036,6 +1096,30 @@ $(eval $(call copy-one-file,$(BOARD_KERNEL_PATH_16K),$(BUILT_KERNEL_16K_TARGET))
kernel_16k: $(BUILT_KERNEL_16K_TARGET)
.PHONY: kernel_16k
+BUILT_BOOTIMAGE_16K_TARGET := $(PRODUCT_OUT)/boot_16k.img
+
+BOARD_KERNEL_16K_BOOTIMAGE_PARTITION_SIZE := $(BOARD_BOOTIMAGE_PARTITION_SIZE)
+
+$(BUILT_BOOTIMAGE_16K_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH) $(INTERNAL_GKI_CERTIFICATE_DEPS) $(BUILT_KERNEL_16K_TARGET)
+ $(call pretty,"Target boot 16k image: $@")
+ $(call build_boot_from_kernel_avb_enabled,$@,$(BUILT_KERNEL_16K_TARGET))
+
+
+bootimage_16k: $(BUILT_BOOTIMAGE_16K_TARGET)
+.PHONY: bootimage_16k
+
+BUILT_BOOT_OTA_PACKAGE_16K := $(PRODUCT_OUT)/boot_ota_16k.zip
+$(BUILT_BOOT_OTA_PACKAGE_16K): $(OTA_FROM_RAW_IMG) $(BUILT_BOOTIMAGE_16K_TARGET) $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8
+ $(OTA_FROM_RAW_IMG) --package_key $(DEFAULT_SYSTEM_DEV_CERTIFICATE) \
+ --max_timestamp `cat $(BUILD_DATETIME_FILE)` \
+ --path $(HOST_OUT) \
+ --partition_name boot \
+ --output $@ \
+ $(BUILT_BOOTIMAGE_16K_TARGET)
+
+boototapackage_16k: $(BUILT_BOOT_OTA_PACKAGE_16K)
+.PHONY: boototapackage_16k
+
endif
@@ -1045,8 +1129,8 @@ COMPRESSION_COMMAND_DEPS := $(LZ4)
COMPRESSION_COMMAND := $(LZ4) -l -12 --favor-decSpeed
RAMDISK_EXT := .lz4
else
-COMPRESSION_COMMAND_DEPS := $(MINIGZIP)
-COMPRESSION_COMMAND := $(MINIGZIP)
+COMPRESSION_COMMAND_DEPS := $(GZIP)
+COMPRESSION_COMMAND := $(GZIP)
RAMDISK_EXT := .gz
endif
@@ -1131,6 +1215,29 @@ define get-partition-size-argument
$(if $(1),--partition_size $(1),--dynamic_partition_size)
endef
+# $1: output boot image target
+# $2: input path to kernel binary
+define build_boot_from_kernel_avb_enabled
+ $(eval kernel := $(2))
+ $(MKBOOTIMG) --kernel $(kernel) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
+ $(if $(BOARD_GKI_SIGNING_KEY_PATH), \
+ $(eval boot_signature := $(call intermediates-dir-for,PACKAGING,generic_boot)/$(notdir $(1)).boot_signature) \
+ $(eval kernel_signature := $(call intermediates-dir-for,PACKAGING,generic_kernel)/$(notdir $(kernel)).boot_signature) \
+ $(call generate_generic_boot_image_certificate,$(1),$(boot_signature),boot,$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)) $(newline) \
+ $(call generate_generic_boot_image_certificate,$(kernel),$(kernel_signature),generic_kernel,$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)) $(newline) \
+ cat $(kernel_signature) >> $(boot_signature) $(newline) \
+ $(call assert-max-image-size,$(boot_signature),16 << 10) $(newline) \
+ truncate -s $$(( 16 << 10 )) $(boot_signature) $(newline) \
+ cat "$(boot_signature)" >> $(1))
+ $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot)))
+ $(AVBTOOL) add_hash_footer \
+ --image $(1) \
+ $(call get-partition-size-argument,$(call get-bootimage-partition-size,$(1),boot)) \
+ --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \
+ $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
+endef
+
+
ifndef BOARD_PREBUILT_BOOTIMAGE
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
@@ -1235,22 +1342,7 @@ ifeq (true,$(BOARD_AVB_ENABLE))
# $1: boot image target
define build_boot_board_avb_enabled
$(eval kernel := $(call bootimage-to-kernel,$(1)))
- $(MKBOOTIMG) --kernel $(kernel) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
- $(if $(BOARD_GKI_SIGNING_KEY_PATH), \
- $(eval boot_signature := $(call intermediates-dir-for,PACKAGING,generic_boot)/$(notdir $(1)).boot_signature) \
- $(eval kernel_signature := $(call intermediates-dir-for,PACKAGING,generic_kernel)/$(notdir $(kernel)).boot_signature) \
- $(call generate_generic_boot_image_certificate,$(1),$(boot_signature),boot,$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)) $(newline) \
- $(call generate_generic_boot_image_certificate,$(kernel),$(kernel_signature),generic_kernel,$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)) $(newline) \
- cat $(kernel_signature) >> $(boot_signature) $(newline) \
- $(call assert-max-image-size,$(boot_signature),16 << 10) $(newline) \
- truncate -s $$(( 16 << 10 )) $(boot_signature) $(newline) \
- cat "$(boot_signature)" >> $(1))
- $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot)))
- $(AVBTOOL) add_hash_footer \
- --image $(1) \
- $(call get-partition-size-argument,$(call get-bootimage-partition-size,$(1),boot)) \
- --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \
- $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
+ $(call build_boot_from_kernel_avb_enabled,$(1),$(kernel))
endef
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH) $(INTERNAL_GKI_CERTIFICATE_DEPS)
@@ -1346,6 +1438,28 @@ endif # BOARD_PREBUILT_BOOTIMAGE
endif # my_installed_prebuilt_gki_apex not defined
+ifneq ($(BOARD_KERNEL_PATH_16K),)
+BUILT_BOOT_OTA_PACKAGE_4K := $(PRODUCT_OUT)/boot_ota_4k.zip
+$(BUILT_BOOT_OTA_PACKAGE_4K): $(OTA_FROM_RAW_IMG) $(INSTALLED_BOOTIMAGE_TARGET) $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8
+ $(OTA_FROM_RAW_IMG) --package_key $(DEFAULT_SYSTEM_DEV_CERTIFICATE) \
+ --max_timestamp `cat $(BUILD_DATETIME_FILE)` \
+ --path $(HOST_OUT) \
+ --partition_name boot \
+ --output $@ \
+ $(INSTALLED_BOOTIMAGE_TARGET)
+
+boototapackage_4k: $(BUILT_BOOT_OTA_PACKAGE_4K)
+.PHONY: boototapackage_4k
+
+$(eval $(call copy-one-file,$(BUILT_BOOT_OTA_PACKAGE_4K),$(TARGET_OUT)/boot_otas/boot_ota_4k.zip))
+$(eval $(call copy-one-file,$(BUILT_BOOT_OTA_PACKAGE_16K),$(TARGET_OUT)/boot_otas/boot_ota_16k.zip))
+
+ALL_DEFAULT_INSTALLED_MODULES += $(TARGET_OUT)/boot_otas/boot_ota_4k.zip
+ALL_DEFAULT_INSTALLED_MODULES += $(TARGET_OUT)/boot_otas/boot_ota_16k.zip
+
+
+endif
+
my_apex_extracted_boot_image :=
my_installed_prebuilt_gki_apex :=
@@ -2096,73 +2210,71 @@ $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCT_VBOOT_SIGNING_K
$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "futility=$(notdir $(FUTILITY))" >> $(1))
$(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_signer_cmd=$(VBOOT_SIGNER)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_avbtool=$(notdir $(AVBTOOL))" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
- $(if $(BOARD_AVB_SYSTEM_KEY_PATH),\
- $(hide) echo "avb_system_key_path=$(BOARD_AVB_SYSTEM_KEY_PATH)" >> $(1)
- $(hide) echo "avb_system_algorithm=$(BOARD_AVB_SYSTEM_ALGORITHM)" >> $(1)
- $(hide) echo "avb_system_rollback_index_location=$(BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_other_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_other_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_OTHER_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+$(if $(BOARD_AVB_ENABLE), \
+ $(hide) echo "avb_avbtool=$(notdir $(AVBTOOL))" >> $(1)$(newline) \
+ $(if $(filter $(2),system), \
+ $(hide) echo "avb_system_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
+ $(if $(BOARD_AVB_SYSTEM_KEY_PATH), \
+ $(hide) echo "avb_system_key_path=$(BOARD_AVB_SYSTEM_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_algorithm=$(BOARD_AVB_SYSTEM_ALGORITHM)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_rollback_index_location=$(BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+ $(if $(filter $(2),system_other), \
+ $(hide) echo "avb_system_other_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_other_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_OTHER_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
$(if $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH),\
- $(hide) echo "avb_system_other_key_path=$(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)" >> $(1)
- $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+ $(hide) echo "avb_system_other_key_path=$(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)$(newline))) \
+ $(if $(filter $(2),vendor), \
+ $(hide) echo "avb_vendor_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_vendor_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
$(if $(BOARD_AVB_VENDOR_KEY_PATH),\
- $(hide) echo "avb_vendor_key_path=$(BOARD_AVB_VENDOR_KEY_PATH)" >> $(1)
- $(hide) echo "avb_vendor_algorithm=$(BOARD_AVB_VENDOR_ALGORITHM)" >> $(1)
- $(hide) echo "avb_vendor_rollback_index_location=$(BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_product_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_product_add_hashtree_footer_args=$(BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+ $(hide) echo "avb_vendor_key_path=$(BOARD_AVB_VENDOR_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_vendor_algorithm=$(BOARD_AVB_VENDOR_ALGORITHM)" >> $(1)$(newline) \
+ $(hide) echo "avb_vendor_rollback_index_location=$(BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+ $(if $(filter $(2),product), \
+ $(hide) echo "avb_product_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_product_add_hashtree_footer_args=$(BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
$(if $(BOARD_AVB_PRODUCT_KEY_PATH),\
- $(hide) echo "avb_product_key_path=$(BOARD_AVB_PRODUCT_KEY_PATH)" >> $(1)
- $(hide) echo "avb_product_algorithm=$(BOARD_AVB_PRODUCT_ALGORITHM)" >> $(1)
- $(hide) echo "avb_product_rollback_index_location=$(BOARD_AVB_PRODUCT_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_ext_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
- $(hide) echo "avb_system_ext_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+ $(hide) echo "avb_product_key_path=$(BOARD_AVB_PRODUCT_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_product_algorithm=$(BOARD_AVB_PRODUCT_ALGORITHM)" >> $(1)$(newline) \
+ $(hide) echo "avb_product_rollback_index_location=$(BOARD_AVB_PRODUCT_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+ $(if $(filter $(2),system_ext), \
+ $(hide) echo "avb_system_ext_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_ext_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
$(if $(BOARD_AVB_SYSTEM_EXT_KEY_PATH),\
- $(hide) echo "avb_system_ext_key_path=$(BOARD_AVB_SYSTEM_EXT_KEY_PATH)" >> $(1)
- $(hide) echo "avb_system_ext_algorithm=$(BOARD_AVB_SYSTEM_EXT_ALGORITHM)" >> $(1)
- $(hide) echo "avb_system_ext_rollback_index_location=$(BOARD_AVB_SYSTEM_EXT_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_add_hashtree_footer_args=$(BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+ $(hide) echo "avb_system_ext_key_path=$(BOARD_AVB_SYSTEM_EXT_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_ext_algorithm=$(BOARD_AVB_SYSTEM_EXT_ALGORITHM)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_ext_rollback_index_location=$(BOARD_AVB_SYSTEM_EXT_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+ $(if $(filter $(2),odm), \
+ $(hide) echo "avb_odm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_odm_add_hashtree_footer_args=$(BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
$(if $(BOARD_AVB_ODM_KEY_PATH),\
- $(hide) echo "avb_odm_key_path=$(BOARD_AVB_ODM_KEY_PATH)" >> $(1)
- $(hide) echo "avb_odm_algorithm=$(BOARD_AVB_ODM_ALGORITHM)" >> $(1)
- $(hide) echo "avb_odm_rollback_index_location=$(BOARD_AVB_ODM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
- $(hide) echo "avb_vendor_dlkm_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+ $(hide) echo "avb_odm_key_path=$(BOARD_AVB_ODM_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_odm_algorithm=$(BOARD_AVB_ODM_ALGORITHM)" >> $(1)$(newline) \
+ $(hide) echo "avb_odm_rollback_index_location=$(BOARD_AVB_ODM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+ $(if $(filter $(2),vendor_dlkm), \
+ $(hide) echo "avb_vendor_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_vendor_dlkm_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
$(if $(BOARD_AVB_VENDOR_DLKM_KEY_PATH),\
- $(hide) echo "avb_vendor_dlkm_key_path=$(BOARD_AVB_VENDOR_DLKM_KEY_PATH)" >> $(1)
- $(hide) echo "avb_vendor_dlkm_algorithm=$(BOARD_AVB_VENDOR_DLKM_ALGORITHM)" >> $(1)
- $(hide) echo "avb_vendor_dlkm_rollback_index_location=$(BOARD_AVB_VENDOR_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
- $(hide) echo "avb_odm_dlkm_add_hashtree_footer_args=$(BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+ $(hide) echo "avb_vendor_dlkm_key_path=$(BOARD_AVB_VENDOR_DLKM_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_vendor_dlkm_algorithm=$(BOARD_AVB_VENDOR_DLKM_ALGORITHM)" >> $(1)$(newline) \
+ $(hide) echo "avb_vendor_dlkm_rollback_index_location=$(BOARD_AVB_VENDOR_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+ $(if $(filter $(2),odm_dlkm), \
+ $(hide) echo "avb_odm_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_odm_dlkm_add_hashtree_footer_args=$(BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
$(if $(BOARD_AVB_ODM_DLKM_KEY_PATH),\
- $(hide) echo "avb_odm_dlkm_key_path=$(BOARD_AVB_ODM_DLKM_KEY_PATH)" >> $(1)
- $(hide) echo "avb_odm_dlkm_algorithm=$(BOARD_AVB_ODM_DLKM_ALGORITHM)" >> $(1)
- $(hide) echo "avb_odm_dlkm_rollback_index_location=$(BOARD_AVB_ODM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
- $(hide) echo "avb_system_dlkm_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
-$(if $(BOARD_AVB_ENABLE),\
+ $(hide) echo "avb_odm_dlkm_key_path=$(BOARD_AVB_ODM_DLKM_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_odm_dlkm_algorithm=$(BOARD_AVB_ODM_DLKM_ALGORITHM)" >> $(1)$(newline) \
+ $(hide) echo "avb_odm_dlkm_rollback_index_location=$(BOARD_AVB_ODM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+ $(if $(filter $(2),system_dlkm), \
+ $(hide) echo "avb_system_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_dlkm_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)$(newline) \
$(if $(BOARD_AVB_SYSTEM_DLKM_KEY_PATH),\
- $(hide) echo "avb_system_dlkm_key_path=$(BOARD_AVB_SYSTEM_DLKM_KEY_PATH)" >> $(1)
- $(hide) echo "avb_system_dlkm_algorithm=$(BOARD_AVB_SYSTEM_DLKM_ALGORITHM)" >> $(1)
- $(hide) echo "avb_system_dlkm_rollback_index_location=$(BOARD_SYSTEM_SYSTEM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)))
+ $(hide) echo "avb_system_dlkm_key_path=$(BOARD_AVB_SYSTEM_DLKM_KEY_PATH)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_dlkm_algorithm=$(BOARD_AVB_SYSTEM_DLKM_ALGORITHM)" >> $(1)$(newline) \
+ $(hide) echo "avb_system_dlkm_rollback_index_location=$(BOARD_SYSTEM_SYSTEM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1)$(newline))) \
+)
$(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\
$(hide) echo "recovery_as_boot=true" >> $(1))
$(if $(filter true,$(BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK)),\
@@ -2170,7 +2282,10 @@ $(if $(filter true,$(BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK)),\
$(hide) echo "root_dir=$(TARGET_ROOT_OUT)" >> $(1)
$(if $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)),\
$(hide) echo "use_dynamic_partition_size=true" >> $(1))
+$(if $(COPY_IMAGES_FOR_TARGET_FILES_ZIP),\
+ $(hide) echo "use_fixed_timestamp=true" >> $(1))
$(if $(3),$(hide) $(foreach kv,$(3),echo "$(kv)" >> $(1);))
+$(hide) sort -o $(1) $(1)
endef
# $(1): the path of the output dictionary file
@@ -3309,9 +3424,21 @@ $(eval $(call declare-0p-target,$(INSTALLED_FILES_JSON)))
.PHONY: installed-file-list
installed-file-list: $(INSTALLED_FILES_FILE)
-systemimage_intermediates := \
- $(call intermediates-dir-for,PACKAGING,systemimage)
-BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img
+systemimage_intermediates :=$= $(call intermediates-dir-for,PACKAGING,systemimage)
+BUILT_SYSTEMIMAGE :=$= $(systemimage_intermediates)/system.img
+
+
+# Used by the bazel sandwich to request the staging dir be built
+$(systemimage_intermediates)/staging_dir.stamp: $(FULL_SYSTEMIMAGE_DEPS)
+ touch $@
+
+define write-file-lines
+$(1):
+ @echo Writing $$@
+ rm -f $$@
+ echo -n > $$@
+ $$(foreach f,$(2),echo "$$(f)" >> $$@$$(newline))
+endef
# $(1): output file
define build-systemimage-target
@@ -3321,16 +3448,19 @@ define build-systemimage-target
skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(systemimage_intermediates)/file_list.txt) \
$(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) $(TARGET_OUT) \
|| ( mkdir -p $${DIST_DIR}; \
cp $(INSTALLED_FILES_FILE) $${DIST_DIR}/installed-files-rescued.txt; \
exit 1 )
endef
+$(eval $(call write-file-lines,$(systemimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT)/,,$(filter $(TARGET_OUT)/%,$(FULL_SYSTEMIMAGE_DEPS)))))
+
ifeq ($(BOARD_AVB_ENABLE),true)
$(BUILT_SYSTEMIMAGE): $(BOARD_AVB_SYSTEM_KEY_PATH)
endif
-$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
+$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE) $(systemimage_intermediates)/file_list.txt
$(call build-systemimage-target,$@)
$(call declare-1p-container,$(BUILT_SYSTEMIMAGE),system/extras)
@@ -3386,7 +3516,7 @@ SYSTEM_NOTICE_DEPS += $(INSTALLED_SYSTEMIMAGE_TARGET)
.PHONY: systemimage-nodeps snod
systemimage-nodeps snod: $(filter-out systemimage-nodeps snod,$(MAKECMDGOALS)) \
- | $(INTERNAL_USERIMAGES_DEPS)
+ | $(INTERNAL_USERIMAGES_DEPS) $(systemimage_intermediates)/file_list.txt
@echo "make $@: ignoring dependencies"
$(call build-systemimage-target,$(INSTALLED_SYSTEMIMAGE_TARGET))
$(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
@@ -3427,6 +3557,7 @@ define build-userdataimage-target
$(call generate-image-prop-dictionary, $(userdataimage_intermediates)/userdata_image_info.txt,userdata,skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(userdataimage_intermediates)/file_list.txt) \
$(TARGET_OUT_DATA) $(userdataimage_intermediates)/userdata_image_info.txt \
$(INSTALLED_USERDATAIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE))
@@ -3437,7 +3568,10 @@ INSTALLED_USERDATAIMAGE_TARGET := $(BUILT_USERDATAIMAGE_TARGET)
INSTALLED_USERDATAIMAGE_TARGET_DEPS := \
$(INTERNAL_USERIMAGES_DEPS) \
$(INTERNAL_USERDATAIMAGE_FILES)
-$(INSTALLED_USERDATAIMAGE_TARGET): $(INSTALLED_USERDATAIMAGE_TARGET_DEPS)
+
+$(eval $(call write-file-lines,$(userdataimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_DATA)/,,$(filter $(TARGET_OUT_DATA)/%,$(INSTALLED_USERDATAIMAGE_TARGET_DEPS)))))
+
+$(INSTALLED_USERDATAIMAGE_TARGET): $(INSTALLED_USERDATAIMAGE_TARGET_DEPS) $(userdataimage_intermediates)/file_list.txt
$(build-userdataimage-target)
$(call declare-1p-container,$(INSTALLED_USERDATAIMAGE_TARGET),)
@@ -3446,7 +3580,7 @@ $(call declare-container-license-deps,$(INSTALLED_USERDATAIMAGE_TARGET),$(INSTAL
UNMOUNTED_NOTICE_VENDOR_DEPS+= $(INSTALLED_USERDATAIMAGE_TARGET)
.PHONY: userdataimage-nodeps
-userdataimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
+userdataimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS) $(userdataimage_intermediates)/file_list.txt
$(build-userdataimage-target)
endif # BUILDING_USERDATA_IMAGE
@@ -3465,45 +3599,6 @@ $(ASAN_IN_SYSTEM_INSTALLED): $(INSTALLED_USERDATAIMAGE_TARGET_DEPS)
tar cfj $(ASAN_IN_SYSTEM_INSTALLED) $(ASAN_SYSTEM_INSTALL_OPTIONS) -C $(TARGET_OUT_DATA)/.. $(ASAN_OUT_DIRS_FOR_SYSTEM_INSTALL) >/dev/null
# -----------------------------------------------------------------
-# partition table image
-ifdef BOARD_BPT_INPUT_FILES
-
-BUILT_BPTIMAGE_TARGET := $(PRODUCT_OUT)/partition-table.img
-BUILT_BPTJSON_TARGET := $(PRODUCT_OUT)/partition-table.bpt
-
-INTERNAL_BVBTOOL_MAKE_TABLE_ARGS := \
- --output_gpt $(BUILT_BPTIMAGE_TARGET) \
- --output_json $(BUILT_BPTJSON_TARGET) \
- $(foreach file, $(BOARD_BPT_INPUT_FILES), --input $(file))
-
-ifdef BOARD_BPT_DISK_SIZE
-INTERNAL_BVBTOOL_MAKE_TABLE_ARGS += --disk_size $(BOARD_BPT_DISK_SIZE)
-endif
-
-define build-bptimage-target
- $(call pretty,"Target partition table image: $(INSTALLED_BPTIMAGE_TARGET)")
- $(hide) $(BPTTOOL) make_table $(INTERNAL_BVBTOOL_MAKE_TABLE_ARGS) $(BOARD_BPT_MAKE_TABLE_ARGS)
-endef
-
-INSTALLED_BPTIMAGE_TARGET := $(BUILT_BPTIMAGE_TARGET)
-$(BUILT_BPTJSON_TARGET): $(INSTALLED_BPTIMAGE_TARGET)
- $(hide) touch -c $(BUILT_BPTJSON_TARGET)
-
-$(INSTALLED_BPTIMAGE_TARGET): $(BPTTOOL) $(BOARD_BPT_INPUT_FILES)
- $(build-bptimage-target)
-
-$(call declare-1p-container,$(INSTALLED_BPTIMAGE_TARGET),)
-$(call declare-container-license-deps,$(INSTALLED_BPTIMAGE_TARGET),$(BOARD_BPT_INPUT_FILES),$(PRODUCT_OUT)/:/)
-
-UNMOUNTED_NOTICE_VENDOR_DEPS+= $(INSTALLED_BPTIMAGE_TARGET)
-
-.PHONY: bptimage-nodeps
-bptimage-nodeps:
- $(build-bptimage-target)
-
-endif # BOARD_BPT_INPUT_FILES
-
-# -----------------------------------------------------------------
# cache partition image
INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_CACHE)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_CACHE_IMAGE
@@ -3521,14 +3616,17 @@ define build-cacheimage-target
$(call generate-image-prop-dictionary, $(cacheimage_intermediates)/cache_image_info.txt,cache,skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(cacheimage_intermediates)/file_list.txt) \
$(TARGET_OUT_CACHE) $(cacheimage_intermediates)/cache_image_info.txt \
$(INSTALLED_CACHEIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_CACHEIMAGE_TARGET),$(BOARD_CACHEIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(cacheimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_CACHE)/,,$(filter $(TARGET_OUT_CACHE)/%,$(INTERNAL_CACHEIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_CACHEIMAGE_TARGET := $(BUILT_CACHEIMAGE_TARGET)
-$(INSTALLED_CACHEIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_CACHEIMAGE_FILES)
+$(INSTALLED_CACHEIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_CACHEIMAGE_FILES) $(cacheimage_intermediates)/file_list.txt
$(build-cacheimage-target)
$(call declare-1p-container,$(INSTALLED_CACHEIMAGE_TARGET),)
@@ -3537,7 +3635,7 @@ $(call declare-container-license-deps,$(INSTALLED_CACHEIMAGE_TARGET),$(INTERNAL_
UNMOUNTED_NOTICE_VENDOR_DEPS+= $(INSTALLED_CACHEIMAGE_TARGET)
.PHONY: cacheimage-nodeps
-cacheimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
+cacheimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS) $(cacheimage_intermediates)/file_list.txt
$(build-cacheimage-target)
else # BUILDING_CACHE_IMAGE
@@ -3602,16 +3700,19 @@ define build-systemotherimage-target
$(call generate-image-prop-dictionary, $(systemotherimage_intermediates)/system_other_image_info.txt,system,skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(systemotherimage_intermediates)/file_list.txt) \
$(TARGET_OUT_SYSTEM_OTHER) $(systemotherimage_intermediates)/system_other_image_info.txt \
$(INSTALLED_SYSTEMOTHERIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(systemotherimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_OTHER)/,,$(filter $(TARGET_OUT_SYSTEM_OTHER)/%,$(INTERNAL_SYSTEMOTHERIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_SYSTEMOTHERIMAGE_TARGET := $(BUILT_SYSTEMOTHERIMAGE_TARGET)
ifneq (true,$(SANITIZE_LITE))
# Only create system_other when not building the second stage of a SANITIZE_LITE build.
-$(INSTALLED_SYSTEMOTHERIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEMOTHER)
+$(INSTALLED_SYSTEMOTHERIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEMOTHER) $(systemotherimage_intermediates)/file_list.txt
$(build-systemotherimage-target)
$(call declare-1p-container,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),)
@@ -3621,7 +3722,7 @@ UNMOUNTED_NOTICE_DEPS += $(INSTALLED_SYSTEMOTHERIMAGE_TARGET)
endif
.PHONY: systemotherimage-nodeps
-systemotherimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
+systemotherimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS) $(systemotherimage_intermediates)/file_list.txt
$(build-systemotherimage-target)
endif # BUILDING_SYSTEM_OTHER_IMAGE
@@ -3702,18 +3803,22 @@ define build-vendorimage-target
$(call generate-image-prop-dictionary, $(vendorimage_intermediates)/vendor_image_info.txt,vendor,skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(vendorimage_intermediates)/file_list.txt) \
$(TARGET_OUT_VENDOR) $(vendorimage_intermediates)/vendor_image_info.txt \
$(INSTALLED_VENDORIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_VENDORIMAGE_TARGET) $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_VENDORIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(vendorimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_VENDOR)/,,$(filter $(TARGET_OUT_VENDOR)/%,$(INTERNAL_VENDORIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_VENDORIMAGE_TARGET := $(BUILT_VENDORIMAGE_TARGET)
$(INSTALLED_VENDORIMAGE_TARGET): \
$(INTERNAL_USERIMAGES_DEPS) \
$(INTERNAL_VENDORIMAGE_FILES) \
$(INSTALLED_FILES_FILE_VENDOR) \
- $(RECOVERY_FROM_BOOT_PATCH)
+ $(RECOVERY_FROM_BOOT_PATCH) \
+ $(vendorimage_intermediates)/file_list.txt
$(build-vendorimage-target)
VENDOR_NOTICE_DEPS += $(INSTALLED_VENDORIMAGE_TARGET)
@@ -3722,7 +3827,7 @@ $(call declare-container-license-metadata,$(INSTALLED_VENDORIMAGE_TARGET),legacy
$(call declare-container-license-deps,$(INSTALLED_VENDORIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_VENDORIMAGE_FILES) $(RECOVERY_FROM_BOOT_PATH),$(PRODUCT_OUT)/:/)
.PHONY: vendorimage-nodeps vnod
-vendorimage-nodeps vnod: | $(INTERNAL_USERIMAGES_DEPS)
+vendorimage-nodeps vnod: | $(INTERNAL_USERIMAGES_DEPS) $(vendorimage_intermediates)/file_list.txt
$(build-vendorimage-target)
.PHONY: sync_vendor
@@ -3768,17 +3873,21 @@ define build-productimage-target
$(call generate-image-prop-dictionary, $(productimage_intermediates)/product_image_info.txt,product,skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(productimage_intermediates)/file_list.txt) \
$(TARGET_OUT_PRODUCT) $(productimage_intermediates)/product_image_info.txt \
$(INSTALLED_PRODUCTIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_PRODUCTIMAGE_TARGET),$(BOARD_PRODUCTIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(productimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_PRODUCT)/,,$(filter $(TARGET_OUT_PRODUCT)/%,$(INTERNAL_PRODUCTIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_PRODUCTIMAGE_TARGET := $(BUILT_PRODUCTIMAGE_TARGET)
$(INSTALLED_PRODUCTIMAGE_TARGET): \
$(INTERNAL_USERIMAGES_DEPS) \
$(INTERNAL_PRODUCTIMAGE_FILES) \
- $(INSTALLED_FILES_FILE_PRODUCT)
+ $(INSTALLED_FILES_FILE_PRODUCT) \
+ $(productimage_intermediates)/file_list.txt
$(build-productimage-target)
PRODUCT_NOTICE_DEPS += $(INSTALLED_PRODUCTIMAGE_TARGET)
@@ -3787,7 +3896,7 @@ $(call declare-1p-container,$(INSTALLED_PRODUCTIMAGE_TARGET),)
$(call declare-container-license-deps,$(INSTALLED_PRODUCTIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_PRODUCTIMAGE_FILES) $(INSTALLED_FILES_FILE_PRODUCT),$(PRODUCT_OUT)/:/)
.PHONY: productimage-nodeps pnod
-productimage-nodeps pnod: | $(INTERNAL_USERIMAGES_DEPS)
+productimage-nodeps pnod: | $(INTERNAL_USERIMAGES_DEPS) $(productimage_intermediates)/file_list.txt
$(build-productimage-target)
.PHONY: sync_product
@@ -3829,6 +3938,7 @@ define build-system_extimage-target
$(call generate-image-prop-dictionary, $(system_extimage_intermediates)/system_ext_image_info.txt,system_ext, skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(system_extimage_intermediates)/file_list.txt) \
$(TARGET_OUT_SYSTEM_EXT) \
$(system_extimage_intermediates)/system_ext_image_info.txt \
$(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
@@ -3836,12 +3946,15 @@ define build-system_extimage-target
$(call assert-max-image-size,$(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET),$(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(system_extimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_EXT)/,,$(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(INTERNAL_SYSTEM_EXTIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_SYSTEM_EXTIMAGE_TARGET := $(BUILT_SYSTEM_EXTIMAGE_TARGET)
$(INSTALLED_SYSTEM_EXTIMAGE_TARGET): \
$(INTERNAL_USERIMAGES_DEPS) \
$(INTERNAL_SYSTEM_EXTIMAGE_FILES) \
- $(INSTALLED_FILES_FILE_SYSTEM_EXT)
+ $(INSTALLED_FILES_FILE_SYSTEM_EXT) \
+ $(system_extimage_intermediates)/file_list.txt
$(build-system_extimage-target)
SYSTEM_EXT_NOTICE_DEPS += $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
@@ -3850,7 +3963,7 @@ $(call declare-1p-container,$(INSTALLED_SYSTEM_EXTIMAGE_TARGET),)
$(call declare-container-license-deps,$(INSTALLED_SYSTEM_EXTIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEM_EXTIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEM_EXT),$(PRODUCT_OUT)/:/)
.PHONY: systemextimage-nodeps senod
-systemextimage-nodeps senod: | $(INTERNAL_USERIMAGES_DEPS)
+systemextimage-nodeps senod: | $(INTERNAL_USERIMAGES_DEPS) $(system_extimage_intermediates)/file_list.txt
$(build-system_extimage-target)
.PHONY: sync_system_ext
@@ -3913,17 +4026,21 @@ define build-odmimage-target
skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(odmimage_intermediates)/file_list.txt) \
$(TARGET_OUT_ODM) $(odmimage_intermediates)/odm_image_info.txt \
$(INSTALLED_ODMIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_ODMIMAGE_TARGET),$(BOARD_ODMIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(odmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_ODM)/,,$(filter $(TARGET_OUT_ODM)/%,$(INTERNAL_ODMIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_ODMIMAGE_TARGET := $(BUILT_ODMIMAGE_TARGET)
$(INSTALLED_ODMIMAGE_TARGET): \
$(INTERNAL_USERIMAGES_DEPS) \
$(INTERNAL_ODMIMAGE_FILES) \
- $(INSTALLED_FILES_FILE_ODM)
+ $(INSTALLED_FILES_FILE_ODM) \
+ $(odmimage_intermediates)/file_list.txt
$(build-odmimage-target)
ODM_NOTICE_DEPS += $(INSTALLED_ODMIMAGE_TARGET)
@@ -3932,7 +4049,7 @@ $(call declare-1p-container,$(INSTALLED_ODMIMAGE_TARGET),)
$(call declare-container-license-deps,$(INSTALLED_ODMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_ODMIMAGE_FILES) $(INSTALLED_FILES_FILE_ODM),$(PRODUCT_OUT)/:/)
.PHONY: odmimage-nodeps onod
-odmimage-nodeps onod: | $(INTERNAL_USERIMAGES_DEPS)
+odmimage-nodeps onod: | $(INTERNAL_USERIMAGES_DEPS) $(odmimage_intermediates)/file_list.txt
$(build-odmimage-target)
.PHONY: sync_odm
@@ -3975,17 +4092,21 @@ define build-vendor_dlkmimage-target
vendor_dlkm, skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(vendor_dlkmimage_intermediates)/file_list.txt) \
$(TARGET_OUT_VENDOR_DLKM) $(vendor_dlkmimage_intermediates)/vendor_dlkm_image_info.txt \
$(INSTALLED_VENDOR_DLKMIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),$(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(vendor_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_VENDOR_DLKM)/,,$(filter $(TARGET_OUT_VENDOR_DLKM)/%,$(INTERNAL_VENDOR_DLKMIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_VENDOR_DLKMIMAGE_TARGET := $(BUILT_VENDOR_DLKMIMAGE_TARGET)
$(INSTALLED_VENDOR_DLKMIMAGE_TARGET): \
$(INTERNAL_USERIMAGES_DEPS) \
$(INTERNAL_VENDOR_DLKMIMAGE_FILES) \
- $(INSTALLED_FILES_FILE_VENDOR_DLKM)
+ $(INSTALLED_FILES_FILE_VENDOR_DLKM) \
+ $(vendor_dlkmimage_intermediates)/file_list.txt
$(build-vendor_dlkmimage-target)
VENDOR_DLKM_NOTICE_DEPS += $(INSTALLED_VENDOR_DLKMIMAGE_TARGET)
@@ -3994,7 +4115,7 @@ $(call declare-1p-container,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),)
$(call declare-container-license-deps,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_VENDOR_DLKMIMAGE_FILES) $(INSTALLED_FILES_FILE_VENDOR_DLKM),$(PRODUCT_OUT)/:/)
.PHONY: vendor_dlkmimage-nodeps vdnod
-vendor_dlkmimage-nodeps vdnod: | $(INTERNAL_USERIMAGES_DEPS)
+vendor_dlkmimage-nodeps vdnod: | $(INTERNAL_USERIMAGES_DEPS) $(vendor_dlkmimage_intermediates)/file_list.txt
$(build-vendor_dlkmimage-target)
.PHONY: sync_vendor_dlkm
@@ -4037,17 +4158,21 @@ define build-odm_dlkmimage-target
odm_dlkm, skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(odm_dlkmimage_intermediates)/file_list.txt) \
$(TARGET_OUT_ODM_DLKM) $(odm_dlkmimage_intermediates)/odm_dlkm_image_info.txt \
$(INSTALLED_ODM_DLKMIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_ODM_DLKMIMAGE_TARGET),$(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(odm_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_ODM_DLKM)/,,$(filter $(TARGET_OUT_ODM_DLKM)/%,$(INTERNAL_ODM_DLKMIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_ODM_DLKMIMAGE_TARGET := $(BUILT_ODM_DLKMIMAGE_TARGET)
$(INSTALLED_ODM_DLKMIMAGE_TARGET): \
$(INTERNAL_USERIMAGES_DEPS) \
$(INTERNAL_ODM_DLKMIMAGE_FILES) \
- $(INSTALLED_FILES_FILE_ODM_DLKM)
+ $(INSTALLED_FILES_FILE_ODM_DLKM) \
+ $(odm_dlkmimage_intermediates)/file_list.txt
$(build-odm_dlkmimage-target)
ODM_DLKM_NOTICE_DEPS += $(INSTALLED_ODM_DLKMIMAGE_TARGET)
@@ -4056,7 +4181,7 @@ $(call declare-1p-container,$(INSTALLED_ODM_DLKMIMAGE_TARGET),)
$(call declare-container-license-deps,$(INSTALLED_ODM_DLKMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_ODM_DLKMIMAGE_FILES) $(INSTALLED_FILES_FILE_ODM_DLKM),$(PRODUCT_OUT)/:/)
.PHONY: odm_dlkmimage-nodeps odnod
-odm_dlkmimage-nodeps odnod: | $(INTERNAL_USERIMAGES_DEPS)
+odm_dlkmimage-nodeps odnod: | $(INTERNAL_USERIMAGES_DEPS) $(odm_dlkmimage_intermediates)/file_list.txt
$(build-odm_dlkmimage-target)
.PHONY: sync_odm_dlkm
@@ -4101,17 +4226,21 @@ define build-system_dlkmimage-target
system_dlkm, skip_fsck=true)
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
$(BUILD_IMAGE) \
+ $(if $(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES),,--input-directory-filter-file $(system_dlkmimage_intermediates)/file_list.txt) \
$(TARGET_OUT_SYSTEM_DLKM) $(system_dlkmimage_intermediates)/system_dlkm_image_info.txt \
$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET) $(TARGET_OUT)
$(call assert-max-image-size,$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET),$(BOARD_SYSTEM_DLKMIMAGE_PARTITION_SIZE))
endef
+$(eval $(call write-file-lines,$(system_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_DLKM)/,,$(filter $(TARGET_OUT_SYSTEM_DLKM)/%,$(INTERNAL_SYSTEM_DLKMIMAGE_FILES)))))
+
# We just build this directly to the install location.
INSTALLED_SYSTEM_DLKMIMAGE_TARGET := $(BUILT_SYSTEM_DLKMIMAGE_TARGET)
$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET): \
$(INTERNAL_USERIMAGES_DEPS) \
$(INTERNAL_SYSTEM_DLKMIMAGE_FILES) \
- $(INSTALLED_FILES_FILE_SYSTEM_DLKM)
+ $(INSTALLED_FILES_FILE_SYSTEM_DLKM) \
+ $(system_dlkmimage_intermediates)/file_list.txt
$(build-system_dlkmimage-target)
SYSTEM_DLKM_NOTICE_DEPS += $(INSTALLED_SYSTEM_DLKMIMAGE_TARGET)
@@ -4120,7 +4249,7 @@ $(call declare-1p-container,$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET),)
$(call declare-container-license-deps,$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEM_DLKMIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEM_DLKM),$(PRODUCT_OUT)/:/)
.PHONY: system_dlkmimage-nodeps sdnod
-system_dlkmimage-nodeps sdnod: | $(INTERNAL_USERIMAGES_DEPS)
+system_dlkmimage-nodeps sdnod: | $(INTERNAL_USERIMAGES_DEPS) $(system_dlkmimage_intermediates)/file_list.txt
$(build-system_dlkmimage-target)
.PHONY: sync_system_dlkm
@@ -4166,7 +4295,7 @@ pvmfwimage: $(INSTALLED_PVMFWIMAGE_TARGET)
INSTALLED_PVMFWIMAGE_TARGET := $(PRODUCT_OUT)/pvmfw.img
INSTALLED_PVMFW_EMBEDDED_AVBKEY_TARGET := $(PRODUCT_OUT)/pvmfw_embedded.avbpubkey
-INSTALLED_PVMFW_BINARY_TARGET := $(call module-installed-files,pvmfw_bin)
+INSTALLED_PVMFW_BINARY_TARGET := $(call module-target-built-files,pvmfw_bin)
INTERNAL_PVMFWIMAGE_FILES := $(call module-target-built-files,pvmfw_img)
INTERNAL_PVMFW_EMBEDDED_AVBKEY := $(call module-target-built-files,pvmfw_embedded_key)
INTERNAL_PVMFW_SYMBOL := $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)/pvmfw
@@ -4204,6 +4333,13 @@ INSTALLED_CUSTOMIMAGES_TARGET :=
ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
INTERNAL_AVB_CUSTOMIMAGES_SIGNING_ARGS :=
+BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST :=
+# If BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH is set, the image will be included in
+# BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST, otherwise the image won't be AVB signed.
+$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(if $(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH), \
+ $(eval BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST += $(partition)) \
+ $(eval BOARD_$(call to-upper,$(partition))_IMAGE_LIST := $(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST))))
# Sign custom image.
# $(1): the prebuilt custom image.
@@ -4228,9 +4364,26 @@ endif
INSTALLED_CUSTOMIMAGES_TARGET += $(3)
endef
-$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+# Copy unsigned custom image.
+# $(1): the prebuilt custom image.
+# $(2): the signed custom image target.
+define copy_custom_image
+$(2): $(1) $(INTERNAL_USERIMAGES_DEPS)
+ @echo Target custom image: $(2)
+ mkdir -p $(dir $(2))
+ cp $(1) $(2)
+INSTALLED_CUSTOMIMAGES_TARGET += $(2)
+endef
+
+# Add AVB custom image to droid target
+$(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
$(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST), \
$(eval $(call sign_custom_image,$(image),$(partition),$(PRODUCT_OUT)/$(notdir $(image))))))
+
+# Add unsigned custom image to droid target
+$(foreach partition,$(filter-out $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), $(BOARD_CUSTOMIMAGES_PARTITION_LIST)), \
+ $(foreach image,$(BOARD_$(call to-upper,$(partition))_IMAGE_LIST), \
+ $(eval $(call copy_custom_image,$(image),$(PRODUCT_OUT)/$(notdir $(image))))))
endif
# -----------------------------------------------------------------
@@ -4507,7 +4660,9 @@ define check-and-set-custom-avb-chain-args
$(eval part := $(1))
$(eval PART=$(call to-upper,$(part)))
$(eval _rollback_index_location := BOARD_AVB_$(PART)_ROLLBACK_INDEX_LOCATION)
+$(eval _key_path := BOARD_AVB_$(PART)_KEY_PATH)
$(if $($(_rollback_index_location)),,$(error $(_rollback_index_location) is not defined))
+$(if $($(_key_path)),,$(error $(_key_path) is not defined))
INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
--chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey
@@ -4587,8 +4742,8 @@ $(foreach partition,$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS),$(eval $(call check-an
$(foreach partition,$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS),$(eval BOARD_AVB_MAKE_VBMETA_$(call to-upper,$(partition))_IMAGE_ARGS += --padding_size 4096))
endif
-ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
-$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ifneq ($(strip $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST)),)
+$(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
$(eval $(call check-and-set-custom-avb-chain-args,$(partition))))
endif
@@ -4675,8 +4830,8 @@ define extract-avb-chain-public-keys
$(if $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH),\
$(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \
--output $(1)/vbmeta_vendor.avbpubkey)
- $(if $(BOARD_CUSTOMIMAGES_PARTITION_LIST),\
- $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(if $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST),\
+ $(hide) $(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
$(AVBTOOL) extract_public_key --key $(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH) \
--output $(1)/$(partition).avbpubkey;)) \
$(if $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS),\
@@ -4823,6 +4978,50 @@ INTERNAL_ALLIMAGES_FILES := \
$(INTERNAL_PVMFWIMAGE_FILES) \
# -----------------------------------------------------------------
+# Run apex_sepolicy_tests for all installed APEXes
+
+ifeq (,$(TARGET_BUILD_UNBUNDLED))
+intermediate := $(call intermediates-dir-for,PACKAGING,apex_sepolicy_tests)
+apex_dirs := \
+ $(TARGET_OUT)/apex/% \
+ $(TARGET_OUT_SYSTEM_EXT)/apex/% \
+ $(TARGET_OUT_VENDOR)/apex/% \
+ $(TARGET_OUT_PRODUCT)/apex/% \
+
+apex_files := $(sort $(filter $(apex_dirs), $(INTERNAL_ALLIMAGES_FILES)))
+apex_dirs :=
+
+# $1: apex file
+# $2: output file
+define _run_apex_sepolicy_tests
+$2: $1 \
+ $(HOST_OUT_EXECUTABLES)/apex_sepolicy_tests \
+ $(HOST_OUT_EXECUTABLES)/deapexer \
+ $(HOST_OUT_EXECUTABLES)/debugfs_static
+ @rm -rf $$@
+ @mkdir -p $(dir $$@)
+ $(HOST_OUT_EXECUTABLES)/apex_sepolicy_tests --all -f <($(HOST_OUT_EXECUTABLES)/deapexer --debugfs_path $(HOST_OUT_EXECUTABLES)/debugfs_static list -Z $$<)
+ @touch $$@
+endef
+
+# $1: apex file list
+define run_apex_sepolicy_tests
+$(foreach apex_file,$1, \
+ $(eval passfile := $(patsubst $(PRODUCT_OUT)/%,$(intermediate)/%.pass,$(apex_file))) \
+ $(eval $(call _run_apex_sepolicy_tests,$(apex_file),$(passfile))) \
+ $(passfile))
+endef
+
+.PHONY: run_apex_sepolicy_tests
+run_apex_sepolicy_tests: $(call run_apex_sepolicy_tests,$(apex_files))
+
+droid_targets: run_apex_sepolicy_tests
+
+apex_files :=
+intermediate :=
+endif # TARGET_BUILD_UNBUNDLED
+
+# -----------------------------------------------------------------
# Check VINTF of build
# Note: vendor_dlkm, odm_dlkm, and system_dlkm does not have VINTF files.
@@ -4937,40 +5136,48 @@ BUILT_KERNEL_VERSION_FILE := $(intermediates)/kernel_version.txt
my_board_extracted_kernel :=
+# Tools for decompression that is not in PATH.
+# Check $(EXTRACT_KERNEL) for decompression algorithms supported by the script.
+# Algorithms that are in the script but not in this list will be found in PATH.
+my_decompress_tools := \
+ lz4:$(HOST_OUT_EXECUTABLES)/lz4 \
+
+
# BOARD_KERNEL_CONFIG_FILE and BOARD_KERNEL_VERSION can be used to override the values extracted
# from INSTALLED_KERNEL_TARGET.
-ifdef BOARD_KERNEL_CONFIG_FILE
ifdef BOARD_KERNEL_VERSION
+$(BUILT_KERNEL_VERSION_FILE): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
+$(BUILT_KERNEL_VERSION_FILE): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
+$(BUILT_KERNEL_VERSION_FILE): $(EXTRACT_KERNEL) $(firstword $(INSTALLED_KERNEL_TARGET))
+ KERNEL_RELEASE=`$(EXTRACT_KERNEL) --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(firstword $(INSTALLED_KERNEL_TARGET)) \
+ --output-release` ;\
+ if [ "$$KERNEL_RELEASE" != '$(BOARD_KERNEL_VERSION)' ]; then \
+ echo "Specified kernel version '$(BOARD_KERNEL_VERSION)' does not match actual kernel version '$$KERNEL_RELEASE' " ; exit 1; fi;
+ echo '$(BOARD_KERNEL_VERSION)' > $@
+
+ifdef BOARD_KERNEL_CONFIG_FILE
$(BUILT_KERNEL_CONFIGS_FILE): $(BOARD_KERNEL_CONFIG_FILE)
cp $< $@
-$(BUILT_KERNEL_VERSION_FILE):
- echo $(BOARD_KERNEL_VERSION) > $@
$(call declare-license-metadata,$(BUILT_KERNEL_CONFIGS_FILE),SPDX-license-identifier-GPL-2.0-only,restricted,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,"Kernel",kernel)
$(call declare-license-metadata,$(BUILT_KERNEL_VERSION_FILE),SPDX-license-identifier-GPL-2.0-only,restricted,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,"Kernel",kernel)
my_board_extracted_kernel := true
-endif # BOARD_KERNEL_VERSION
endif # BOARD_KERNEL_CONFIG_FILE
+endif # BOARD_KERNEL_VERSION
-ifneq ($(my_board_extracted_kernel),true)
-# Tools for decompression that is not in PATH.
-# Check $(EXTRACT_KERNEL) for decompression algorithms supported by the script.
-# Algorithms that are in the script but not in this list will be found in PATH.
-my_decompress_tools := \
- lz4:$(HOST_OUT_EXECUTABLES)/lz4 \
-
-endif # my_board_extracted_kernel
ifneq ($(my_board_extracted_kernel),true)
ifdef INSTALLED_KERNEL_TARGET
+ifndef BOARD_KERNEL_VERSION
$(BUILT_KERNEL_CONFIGS_FILE): .KATI_IMPLICIT_OUTPUTS := $(BUILT_KERNEL_VERSION_FILE)
+endif
$(BUILT_KERNEL_CONFIGS_FILE): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
$(BUILT_KERNEL_CONFIGS_FILE): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
$(BUILT_KERNEL_CONFIGS_FILE): $(EXTRACT_KERNEL) $(firstword $(INSTALLED_KERNEL_TARGET))
$< --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(firstword $(INSTALLED_KERNEL_TARGET)) \
--output-configs $@ \
- --output-release $(BUILT_KERNEL_VERSION_FILE)
+ $(if $(BOARD_KERNEL_VERSION),,--output-release $(BUILT_KERNEL_VERSION_FILE))
$(call declare-license-metadata,$(BUILT_KERNEL_CONFIGS_FILE),SPDX-license-identifier-GPL-2.0-only,restricted,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,"Kernel",kernel)
@@ -4999,7 +5206,9 @@ my_board_extracted_kernel := true
endif # INSTALLED_BOOTIMAGE_TARGET
endif # my_board_extracted_kernel
-ifneq ($(my_board_extracted_kernel),true)
+ifeq ($(my_board_extracted_kernel),true)
+$(call dist-for-goals, droid_targets, $(BUILT_KERNEL_VERSION_FILE))
+else
$(warning Neither INSTALLED_KERNEL_TARGET nor INSTALLED_BOOTIMAGE_TARGET is defined when \
PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS is true. Information about the updated kernel \
cannot be built into OTA update package. You can fix this by: \
@@ -5262,7 +5471,6 @@ INTERNAL_OTATOOLS_MODULES := \
make_f2fs_casefold \
merge_ota \
merge_target_files \
- minigzip \
mk_combined_img \
mkbootfs \
mkbootimg \
@@ -5289,6 +5497,7 @@ INTERNAL_OTATOOLS_MODULES := \
toybox \
tune2fs \
unpack_bootimg \
+ update_device \
update_host_simulator \
validate_target_files \
verity_signer \
@@ -5419,6 +5628,9 @@ endif
ifeq ($(BOARD_USES_PVMFWIMAGE),true)
$(hide) echo "flash pvmfw" >> $@
endif
+ifneq ($(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
+ $(hide) echo "flash vendor_boot" >> $@
+endif
ifeq ($(BOARD_AVB_ENABLE),true)
ifeq ($(BUILDING_VBMETA_IMAGE),true)
$(hide) echo "flash --apply-vbmeta vbmeta" >> $@
@@ -5427,10 +5639,7 @@ ifneq (,$(strip $(BOARD_AVB_VBMETA_SYSTEM)))
$(hide) echo "flash vbmeta_system" >> $@
endif
ifneq (,$(strip $(BOARD_AVB_VBMETA_VENDOR)))
- $(hide) echo "flash --apply-vbmeta vbmeta_vendor" >> $@
-endif
-ifneq ($(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
- $(hide) echo "flash vendor_boot" >> $@
+ $(hide) echo "flash vbmeta_vendor" >> $@
endif
ifneq (,$(strip $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS)))
$(hide) $(foreach partition,$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS), \
@@ -5595,15 +5804,20 @@ ifdef BOARD_AVB_RECOVERY_KEY_PATH
$(hide) echo "avb_recovery_rollback_index_location=$(BOARD_AVB_RECOVERY_ROLLBACK_INDEX_LOCATION)" >> $@
endif # BOARD_AVB_RECOVERY_KEY_PATH
ifneq (,$(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)))
- $(hide) echo "avb_custom_images_partition_list=$(BOARD_CUSTOMIMAGES_PARTITION_LIST)" >> $@
- $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(hide) echo "custom_images_partition_list=$(filter-out $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), $(BOARD_CUSTOMIMAGES_PARTITION_LIST))" >> $@
+ $(hide) $(foreach partition,$(filter-out $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), $(BOARD_CUSTOMIMAGES_PARTITION_LIST)), \
+ echo "$(partition)_image_list=$(foreach image,$(BOARD_$(call to-upper,$(partition))_IMAGE_LIST),$(notdir $(image)))" >> $@;)
+endif # BOARD_CUSTOMIMAGES_PARTITION_LIST
+ifneq (,$(strip $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST)))
+ $(hide) echo "avb_custom_images_partition_list=$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST)" >> $@
+ $(hide) $(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
echo "avb_$(partition)_key_path=$(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH)" >> $@; \
echo "avb_$(partition)_algorithm=$(BOARD_AVB_$(call to-upper,$(partition))_ALGORITHM)" >> $@; \
echo "avb_$(partition)_add_hashtree_footer_args=$(BOARD_AVB_$(call to-upper,$(partition))_ADD_HASHTREE_FOOTER_ARGS)" >> $@; \
echo "avb_$(partition)_rollback_index_location=$(BOARD_AVB_$(call to-upper,$(partition))_ROLLBACK_INDEX_LOCATION)" >> $@; \
echo "avb_$(partition)_partition_size=$(BOARD_AVB_$(call to-upper,$(partition))_PARTITION_SIZE)" >> $@; \
echo "avb_$(partition)_image_list=$(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST),$(notdir $(image)))" >> $@;)
-endif # BOARD_CUSTOMIMAGES_PARTITION_LIST
+endif # BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST
ifneq (,$(strip $(BOARD_AVB_VBMETA_SYSTEM)))
$(hide) echo "avb_vbmeta_system=$(BOARD_AVB_VBMETA_SYSTEM)" >> $@
$(hide) echo "avb_vbmeta_system_args=$(BOARD_AVB_MAKE_VBMETA_SYSTEM_IMAGE_ARGS)" >> $@
@@ -5628,14 +5842,6 @@ ifneq (,$(strip $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS)))
echo "avb_vbmeta_$(partition)_rollback_index_location=$(BOARD_AVB_VBMETA_$(call to-upper,$(partition))_ROLLBACK_INDEX_LOCATION)" >> $@ ;)
endif # BOARD_AVB_VBMETA_CUSTOM_PARTITIONS
endif # BOARD_AVB_ENABLE
-ifdef BOARD_BPT_INPUT_FILES
- $(hide) echo "board_bpt_enable=true" >> $@
- $(hide) echo "board_bpt_make_table_args=$(BOARD_BPT_MAKE_TABLE_ARGS)" >> $@
- $(hide) echo "board_bpt_input_files=$(BOARD_BPT_INPUT_FILES)" >> $@
-endif
-ifdef BOARD_BPT_DISK_SIZE
- $(hide) echo "board_bpt_disk_size=$(BOARD_BPT_DISK_SIZE)" >> $@
-endif
$(call generate-userimage-prop-dictionary, $@)
ifeq ($(AB_OTA_UPDATER),true)
@# Include the build type in META/misc_info.txt so the server can easily differentiate production builds.
@@ -5698,9 +5904,6 @@ endif
ifeq ($(BUILDING_WITH_VSDK),true)
$(hide) echo "building_with_vsdk=true" >> $@
endif
-ifeq ($(TARGET_FLATTEN_APEX),false)
- $(hide) echo "target_flatten_apex=false" >> $@
-endif
$(call declare-0p-target,$(INSTALLED_FASTBOOT_INFO_TARGET))
@@ -5737,11 +5940,11 @@ $(BUILT_TARGET_FILES_DIR): intermediates := $(intermediates)
# $(1): Directory to copy
# $(2): Location to copy it to
-# The "ls -A" is to prevent "acp s/* d" from failing if s is empty.
+# The "ls -A" is to skip if $(1) is empty.
define package_files-copy-root
if [ -d "$(strip $(1))" -a "$$(ls -A $(1))" ]; then \
mkdir -p $(2) && \
- $(ACP) -rd $(strip $(1))/* $(2); \
+ $(ACP) -rd $(strip $(1))/. $(strip $(2))/; \
fi
endef
@@ -5902,17 +6105,19 @@ endef
# $(2): target out directory
# $(3): image name to generate a map file. skip generating map file if empty
define copy-image-and-generate-map
- $(eval _supported_fs_for_map_file_generator := erofs ext%)
- $(eval _img := $(call to-upper,$(3)))
- $(if $(3),$(eval _map_fs_type := $(BOARD_$(_img)IMAGE_FILE_SYSTEM_TYPE)),\
- $(eval _no_map_file := "true"))
- $(if $(filter $(_supported_fs_for_map_file_generator),$(_map_fs_type))$(_no_map_file),\
- mkdir -p $(2); \
- cp $(1) $(2); \
- $(if $(3),$(HOST_OUT_EXECUTABLES)/map_file_generator $(1) $(2)/$(3).map))
- $(eval _img :=)
- $(eval _map_fs_type :=)
- $(eval _no_map_file :=)
+ $(if $(COPY_IMAGES_FOR_TARGET_FILES_ZIP), \
+ $(eval _supported_fs_for_map_file_generator := erofs ext%) \
+ $(eval _img := $(call to-upper,$(3))) \
+ $(if $(3),$(eval _map_fs_type := $(BOARD_$(_img)IMAGE_FILE_SYSTEM_TYPE)),\
+ $(eval _no_map_file := "true")) \
+ $(if $(filter $(_supported_fs_for_map_file_generator),$(_map_fs_type))$(_no_map_file),\
+ mkdir -p $(2); \
+ cp $(1) $(2); \
+ $(if $(3),$(HOST_OUT_EXECUTABLES)/map_file_generator $(1) $(2)/$(3).map)) \
+ $(eval _img :=) \
+ $(eval _map_fs_type :=) \
+ $(eval _no_map_file :=) \
+ )
endef
# By conditionally including the dependency of the target files package on the
@@ -5920,7 +6125,9 @@ endef
# image.
ifdef BUILDING_SYSTEM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(FULL_SYSTEMIMAGE_DEPS)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEMIMAGE)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEMIMAGE)
+ endif
else
# releasetools may need the system build.prop even when building a
# system-image-less product.
@@ -5933,7 +6140,9 @@ endif
ifdef BUILDING_SYSTEM_OTHER_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_SYSTEMOTHERIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEMOTHERIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEMOTHERIMAGE_TARGET)
+ endif
endif
ifdef BUILDING_VENDOR_BOOT_IMAGE
@@ -5965,21 +6174,27 @@ endif
ifdef BUILDING_VENDOR_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_VENDORIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_VENDORIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_VENDORIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_VENDORIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_VENDORIMAGE_TARGET)
endif
ifdef BUILDING_PRODUCT_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_PRODUCTIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_PRODUCTIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_PRODUCTIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_PRODUCTIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_PRODUCTIMAGE_TARGET)
endif
ifdef BUILDING_SYSTEM_EXT_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_SYSTEM_EXTIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEM_EXTIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEM_EXTIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_SYSTEM_EXTIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
endif
@@ -5994,28 +6209,36 @@ endif
ifdef BUILDING_ODM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_ODMIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_ODMIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_ODMIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_ODMIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_ODMIMAGE_TARGET)
endif
ifdef BUILDING_VENDOR_DLKM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_VENDOR_DLKMIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_VENDOR_DLKMIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_VENDOR_DLKMIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_VENDOR_DLKMIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_VENDOR_DLKMIMAGE_TARGET)
endif
ifdef BUILDING_ODM_DLKM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_ODM_DLKMIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_ODM_DLKMIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_ODM_DLKMIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_ODM_DLKMIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_ODM_DLKMIMAGE_TARGET)
endif
ifdef BUILDING_SYSTEM_DLKM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_SYSTEM_DLKMIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEM_DLKMIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEM_DLKMIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_SYSTEM_DLKMIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_SYSTEM_DLKMIMAGE_TARGET)
endif
@@ -6414,7 +6637,7 @@ endif
ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
$(hide) mkdir -p $(zip_root)/PREBUILT_IMAGES
$(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
- $(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST),cp $(image) $(zip_root)/PREBUILT_IMAGES/;))
+ $(foreach image,$(BOARD_$(call to-upper,$(partition))_IMAGE_LIST),cp $(image) $(zip_root)/PREBUILT_IMAGES/;))
endif # BOARD_CUSTOMIMAGES_PARTITION_LIST
@# The radio images in BOARD_PACK_RADIOIMAGES will be additionally copied from RADIO/ into
@# IMAGES/, which then will be added into <product>-img.zip. Such images must be listed in
@@ -6781,7 +7004,7 @@ SYSTEM_NOTICE_DEPS += $(COVERAGE_ZIP)
ifeq (true,$(CLANG_COVERAGE))
LLVM_PROFDATA := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/bin/llvm-profdata
LLVM_COV := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/bin/llvm-cov
- LIBCXX := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/lib/x86_64-unknown-linux-gnu/libc++.so.1
+ LIBCXX := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/lib/x86_64-unknown-linux-gnu/libc++.so
# Use llvm-profdata.zip for backwards compatibility with tradefed code.
LLVM_COVERAGE_TOOLS_ZIP := $(PRODUCT_OUT)/llvm-profdata.zip
@@ -6838,6 +7061,14 @@ $(JACOCO_REPORT_CLASSES_ALL) :
ifeq (,$(TARGET_BUILD_UNBUNDLED))
$(JACOCO_REPORT_CLASSES_ALL): $(INTERNAL_ALLIMAGES_FILES)
endif
+
+# This is not ideal, but it is difficult to correctly figure out the actual jacoco report
+# jars we need to add here as dependencies, so we add the device-tests as a dependency when
+# the env variable is set and this should guarantee thaat all the jacoco report jars are ready
+# when we package the final report jar here.
+ifeq ($(JACOCO_PACKAGING_INCLUDE_DEVICE_TESTS),true)
+ $(JACOCO_REPORT_CLASSES_ALL): $(COMPATIBILITY.device-tests.FILES)
+endif
endif # EMMA_INSTRUMENT=true
@@ -6849,29 +7080,34 @@ endif # EMMA_INSTRUMENT=true
# finding the appropriate dictionary to deobfuscate a stack trace frame.
#
-# The path to the zip file containing proguard dictionaries.
-PROGUARD_DICT_ZIP := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict.zip
-# The path to the zip file containing mappings from dictionary hashes to filenames.
-PROGUARD_DICT_MAPPING := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict-mapping.textproto
-.KATI_READONLY := PROGUARD_DICT_ZIP PROGUARD_DICT_MAPPING
-# For apps_only build we'll establish the dependency later in build/make/core/main.mk.
ifeq (,$(TARGET_BUILD_UNBUNDLED))
-$(PROGUARD_DICT_ZIP): $(INTERNAL_ALLIMAGES_FILES) $(updater_dep)
+ _proguard_dict_zip_modules := $(call product-installed-modules,$(INTERNAL_PRODUCT))
+else
+ _proguard_dict_zip_modules := $(unbundled_build_modules)
endif
-$(PROGUARD_DICT_ZIP): PRIVATE_PACKAGING_DIR := $(call intermediates-dir-for,PACKAGING,proguard_dictionary)
-$(PROGUARD_DICT_ZIP): PRIVATE_MAPPING_PACKAGING_DIR := $(call intermediates-dir-for,PACKAGING,proguard_dictionary_mapping)
-$(PROGUARD_DICT_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,proguard_dictionary_filelist)/filelist
-$(PROGUARD_DICT_ZIP): $(SOONG_ZIP) $(SYMBOLS_MAP)
+
+# The path to the zip file containing proguard dictionaries.
+PROGUARD_DICT_ZIP :=$= $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict.zip
+$(PROGUARD_DICT_ZIP): PRIVATE_SOONG_ZIP_ARGUMENTS := $(foreach m,$(_proguard_dict_zip_modules),$(ALL_MODULES.$(m).PROGUARD_DICTIONARY_SOONG_ZIP_ARGUMENTS))
+$(PROGUARD_DICT_ZIP): $(SOONG_ZIP) $(foreach m,$(_proguard_dict_zip_modules),$(ALL_MODULES.$(m).PROGUARD_DICTIONARY_FILES))
@echo "Packaging Proguard obfuscation dictionary files."
- rm -rf $@ $(PRIVATE_LIST_FILE)
- mkdir -p $(PRIVATE_PACKAGING_DIR) $(PRIVATE_MAPPING_PACKAGING_DIR) $(dir $(PRIVATE_LIST_FILE))
- # Zip all of the files in the proguard dictionary directory.
- $(SOONG_ZIP) --ignore_missing_files -d -o $@ -C $(PRIVATE_PACKAGING_DIR) -D $(PRIVATE_PACKAGING_DIR)
- # Find all of the files in the proguard dictionary mapping directory and merge them into the mapping textproto.
- # Strip the PRIVATE_PACKAGING_DIR off the filenames to match soong_zip's -C argument.
- $(hide) find -L $(PRIVATE_MAPPING_PACKAGING_DIR) -type f | sort >$(PRIVATE_LIST_FILE)
- $(SYMBOLS_MAP) -merge $(PROGUARD_DICT_MAPPING) -strip_prefix $(PRIVATE_PACKAGING_DIR)/ -ignore_missing_files @$(PRIVATE_LIST_FILE)
-$(PROGUARD_DICT_ZIP): .KATI_IMPLICIT_OUTPUTS := $(PROGUARD_DICT_MAPPING)
+ # Zip all of the files in PROGUARD_DICTIONARY_FILES.
+ echo -n > $@.tmparglist
+ $(foreach arg,$(PRIVATE_SOONG_ZIP_ARGUMENTS),printf "%s\n" "$(arg)" >> $@.tmparglist$(newline))
+ $(SOONG_ZIP) -d -o $@ @$@.tmparglist
+ rm -f $@.tmparglist
+
+# The path to the zip file containing mappings from dictionary hashes to filenames.
+PROGUARD_DICT_MAPPING :=$= $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict-mapping.textproto
+_proguard_dict_mapping_files := $(foreach m,$(_proguard_dict_zip_modules),$(ALL_MODULES.$(m).PROGUARD_DICTIONARY_MAPPING))
+$(PROGUARD_DICT_MAPPING): PRIVATE_MAPPING_FILES := $(_proguard_dict_mapping_files)
+$(PROGUARD_DICT_MAPPING): $(SYMBOLS_MAP) $(_proguard_dict_mapping_files)
+ @echo "Packaging Proguard obfuscation dictionary mapping files."
+ # Merge all the mapping files together
+ echo -n > $@.tmparglist
+ $(foreach mf,$(PRIVATE_MAPPING_FILES),echo "$(mf)" >> $@.tmparglist$(newline))
+ $(SYMBOLS_MAP) -merge $(PROGUARD_DICT_MAPPING) @$@.tmparglist
+ rm -f $@.tmparglist
$(call declare-1p-container,$(PROGUARD_DICT_ZIP),)
ifeq (,$(TARGET_BUILD_UNBUNDLED))
@@ -6881,31 +7117,19 @@ endif
#------------------------------------------------------------------
# A zip of Proguard usage files.
#
-PROGUARD_USAGE_ZIP := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-usage.zip
-# For apps_only build we'll establish the dependency later in build/make/core/main.mk.
-ifeq (,$(TARGET_BUILD_UNBUNDLED))
-$(PROGUARD_USAGE_ZIP): \
- $(INSTALLED_SYSTEMIMAGE_TARGET) \
- $(INSTALLED_RAMDISK_TARGET) \
- $(INSTALLED_BOOTIMAGE_TARGET) \
- $(INSTALLED_INIT_BOOT_IMAGE_TARGET) \
- $(INSTALLED_USERDATAIMAGE_TARGET) \
- $(INSTALLED_VENDORIMAGE_TARGET) \
- $(INSTALLED_PRODUCTIMAGE_TARGET) \
- $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
- $(INSTALLED_ODMIMAGE_TARGET) \
- $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) \
- $(INSTALLED_ODM_DLKMIMAGE_TARGET) \
- $(INSTALLED_SYSTEM_DLKMIMAGE_TARGET) \
- $(updater_dep)
-endif
-$(PROGUARD_USAGE_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,proguard_usage.zip)/filelist
-$(PROGUARD_USAGE_ZIP): PRIVATE_PACKAGING_DIR := $(call intermediates-dir-for,PACKAGING,proguard_usage)
-$(PROGUARD_USAGE_ZIP): $(MERGE_ZIPS)
+PROGUARD_USAGE_ZIP :=$= $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-usage.zip
+_proguard_usage_zips := $(foreach m,$(_proguard_dict_zip_modules),$(ALL_MODULES.$(m).PROGUARD_USAGE_ZIP))
+$(PROGUARD_USAGE_ZIP): PRIVATE_ZIPS := $(_proguard_usage_zips)
+$(PROGUARD_USAGE_ZIP): $(MERGE_ZIPS) $(_proguard_usage_zips)
@echo "Packaging Proguard usage files."
- mkdir -p $(dir $@) $(PRIVATE_PACKAGING_DIR) $(dir $(PRIVATE_LIST_FILE))
- find $(PRIVATE_PACKAGING_DIR) -name proguard_usage.zip > $(PRIVATE_LIST_FILE)
- $(MERGE_ZIPS) $@ @$(PRIVATE_LIST_FILE)
+ echo -n > $@.tmparglist
+ $(foreach z,$(PRIVATE_ZIPS),echo "$(z)" >> $@.tmparglist$(newline))
+ $(MERGE_ZIPS) $@ @$@.tmparglist
+ rm -rf $@.tmparglist
+
+_proguard_dict_mapping_files :=
+_proguard_usage_zips :=
+_proguard_dict_zip_modules :=
$(call declare-1p-container,$(PROGUARD_USAGE_ZIP),)
ifeq (,$(TARGET_BUILD_UNBUNDLED))
@@ -7067,6 +7291,7 @@ $(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(IMG_FROM_TARG
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$(dir $(ZIP2ZIP)):$$PATH \
$(IMG_FROM_TARGET_FILES) \
--additional IMAGES/VerifiedBootParams.textproto:VerifiedBootParams.textproto \
+ --build_super_image $(BUILD_SUPER_IMAGE) \
$(BUILT_TARGET_FILES_PACKAGE) $@
$(call declare-1p-container,$(INTERNAL_UPDATE_PACKAGE_TARGET),)
@@ -7412,6 +7637,9 @@ $(call dist-for-goals,haiku-java,$(SOONG_JAVA_FUZZ_PACKAGING_ARCH_MODULES))
haiku-rust: $(SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES) $(ALL_RUST_FUZZ_TARGETS)
$(call dist-for-goals,haiku-rust,$(SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES))
$(call dist-for-goals,haiku-rust,$(PRODUCT_OUT)/module-info.json)
+.PHONY: haiku-presubmit
+haiku-presubmit: $(SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES) $(ALL_PRESUBMIT_FUZZ_TARGETS)
+$(call dist-for-goals,haiku-presubmit,$(SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES))
# -----------------------------------------------------------------
# Extract platform fonts used in Layoutlib
diff --git a/core/OWNERS b/core/OWNERS
index eb1d5c3c46..88f6d068bb 100644
--- a/core/OWNERS
+++ b/core/OWNERS
@@ -5,3 +5,5 @@ per-file proguard*.flags = jdduke@google.com
# For version updates
per-file version_defaults.mk = aseaton@google.com,lubomir@google.com,pscovanner@google.com,bkhalife@google.com,jainne@google.com
+# For sdk extensions version updates
+per-file version_defaults.mk = amhk@google.com,gurpreetgs@google.com,mkhokhlova@google.com,robertogil@google.com
diff --git a/core/aapt2.mk b/core/aapt2.mk
index 7b17df4a9c..0e23477967 100644
--- a/core/aapt2.mk
+++ b/core/aapt2.mk
@@ -68,6 +68,8 @@ $(my_res_resources_flat) $(my_overlay_resources_flat) $(my_resources_flata) $(my
# support for it.
my_static_library_resources := $(foreach l, $(call reverse-list,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/package-res.apk)
+my_static_library_transitive_resource_packages_lists := $(foreach l, $(call reverse-list,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),\
+ $(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/transitive-res-packages)
my_static_library_extra_packages := $(foreach l, $(call reverse-list,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/extra_packages)
my_shared_library_resources := $(foreach l, $(LOCAL_SHARED_ANDROID_LIBRARIES),\
@@ -95,6 +97,7 @@ $(my_res_package): PRIVATE_ASSET_DIRS := $(my_asset_dirs)
$(my_res_package): PRIVATE_JAVA_GEN_DIR := $(intermediates.COMMON)/aapt2
$(my_res_package): PRIVATE_SRCJAR := $(my_srcjar)
$(my_res_package): PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES := $(my_static_library_extra_packages)
+$(my_res_package): PRIVATE_STATIC_LIBRARY_TRANSITIVE_RES_PACKAGES_LISTS := $(my_static_library_transitive_resource_packages_lists)
$(my_res_package): PRIVATE_AAPT_EXTRA_PACKAGES := $(aapt_extra_packages)
$(my_res_package): .KATI_IMPLICIT_OUTPUTS := $(my_srcjar) $(aapt_extra_packages)
@@ -117,7 +120,7 @@ ifdef proguard_options_file
$(my_res_package): .KATI_IMPLICIT_OUTPUTS += $(proguard_options_file)
endif
-$(my_res_package): $(full_android_manifest) $(my_static_library_resources) $(my_shared_library_resources)
+$(my_res_package): $(full_android_manifest) $(my_static_library_resources) $(my_static_library_transitive_resource_packages_lists) $(my_shared_library_resources)
$(my_res_package): $(my_full_asset_paths)
$(my_res_package): $(my_res_resources_flat) $(my_overlay_resources_flat) \
$(my_resources_flata) $(my_static_library_resources) $(my_static_library_extra_packages) \
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index f132d13775..6d64f97780 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -29,10 +29,6 @@ $(call add_soong_config_namespace,ANDROID)
$(call add_soong_config_var,ANDROID,TARGET_DYNAMIC_64_32_MEDIASERVER)
$(call add_soong_config_var,ANDROID,TARGET_DYNAMIC_64_32_DRMSERVER)
$(call add_soong_config_var,ANDROID,TARGET_ENABLE_MEDIADRM_64)
-$(call add_soong_config_var,ANDROID,IS_TARGET_MIXED_SEPOLICY)
-ifeq ($(IS_TARGET_MIXED_SEPOLICY),true)
-$(call add_soong_config_var_value,ANDROID,MIXED_SEPOLICY_VERSION,$(BOARD_SEPOLICY_VERS))
-endif
$(call add_soong_config_var,ANDROID,BOARD_USES_ODMIMAGE)
$(call add_soong_config_var,ANDROID,BOARD_USES_RECOVERY_AS_BOOT)
$(call add_soong_config_var,ANDROID,PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT)
@@ -115,6 +111,7 @@ endif
# default.
INDIVIDUALLY_TOGGLEABLE_PREBUILT_MODULES := \
btservices \
+ devicelock \
permission \
rkpd \
uwb \
@@ -158,6 +155,16 @@ ifdef PRODUCT_AVF_KERNEL_MODULES_ENABLED
$(call add_soong_config_var_value,ANDROID,avf_kernel_modules_enabled,$(PRODUCT_AVF_KERNEL_MODULES_ENABLED))
endif
+$(call add_soong_config_var_value,ANDROID,release_avf_allow_preinstalled_apps,$(RELEASE_AVF_ALLOW_PREINSTALLED_APPS))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_device_assignment,$(RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_dice_changes,$(RELEASE_AVF_ENABLE_DICE_CHANGES))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_llpvm_changes,$(RELEASE_AVF_ENABLE_LLPVM_CHANGES))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_multi_tenant_microdroid_vm,$(RELEASE_AVF_ENABLE_MULTI_TENANT_MICRODROID_VM))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_remote_attestation,$(RELEASE_AVF_ENABLE_REMOTE_ATTESTATION))
+$(call add_soong_config_var_value,ANDROID,release_avf_enable_vendor_modules,$(RELEASE_AVF_ENABLE_VENDOR_MODULES))
+
+$(call add_soong_config_var_value,ANDROID,release_binder_death_recipient_weak_from_jni,$(RELEASE_BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI))
+
# Enable system_server optimizations by default unless explicitly set or if
# there may be dependent runtime jars.
# TODO(b/240588226): Remove the off-by-default exceptions after handling
diff --git a/core/app_prebuilt_internal.mk b/core/app_prebuilt_internal.mk
index 9fab44d7c9..b141a98525 100644
--- a/core/app_prebuilt_internal.mk
+++ b/core/app_prebuilt_internal.mk
@@ -227,7 +227,7 @@ endif
$(built_module): PRIVATE_EMBEDDED_JNI_LIBS := $(embedded_prebuilt_jni_libs)
ifdef LOCAL_COMPRESSED_MODULE
-$(built_module) : $(MINIGZIP)
+$(built_module) : $(GZIP)
endif
ifeq ($(module_run_appcompat),true)
@@ -305,4 +305,4 @@ endif # LOCAL_PACKAGE_SPLITS
###########################################################
## SBOM generation
###########################################################
-include $(BUILD_SBOM_GEN) \ No newline at end of file
+include $(BUILD_SBOM_GEN)
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 9ad1cc5251..3313b5fa8c 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -521,10 +521,6 @@ ifneq (,$(LOCAL_SOONG_INSTALLED_MODULE))
# copy of the intermediates for now, as some rules that collect intermediates may expect
# them to exist.
$(LOCAL_INSTALLED_MODULE): $(LOCAL_BUILT_MODULE)
-
- $(foreach symlink, $(LOCAL_SOONG_INSTALL_SYMLINKS), \
- $(call declare-0p-target,$(symlink)))
- $(my_all_targets) : | $(LOCAL_SOONG_INSTALL_SYMLINKS)
else ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
$(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD)
$(LOCAL_INSTALLED_MODULE): $(LOCAL_BUILT_MODULE)
@@ -546,6 +542,15 @@ else ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
endif # !LOCAL_UNINSTALLABLE_MODULE
+# Add dependencies on LOCAL_SOONG_INSTALL_SYMLINKS if we're installing any kind of module, not just
+# ones that set LOCAL_SOONG_INSTALLED_MODULE. This is so we can have a soong module that only
+# installs symlinks (e.g. install_symlink). We can't set LOCAL_SOONG_INSTALLED_MODULE to a symlink
+# because cp commands will fail on symlinks.
+ifneq (,$(or $(LOCAL_SOONG_INSTALLED_MODULE),$(call boolean-not,$(LOCAL_UNINSTALLABLE_MODULE))))
+ $(foreach symlink, $(LOCAL_SOONG_INSTALL_SYMLINKS), $(call declare-0p-target,$(symlink)))
+ $(my_all_targets) : | $(LOCAL_SOONG_INSTALL_SYMLINKS)
+endif
+
###########################################################
## VINTF manifest fragment and init.rc goals
###########################################################
@@ -578,7 +583,9 @@ ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
ALL_VINTF_MANIFEST_FRAGMENTS_LIST += $(my_vintf_new_pairs)
- $(my_all_targets) : $(my_vintf_new_installed)
+ $(my_all_targets) : $(my_vintf_installed)
+ # Install fragments together with the target
+ $(LOCAL_INSTALLED_MODULE) : | $(my_vintf_installed)
endif # my_vintf_fragments
# Rule to install the module's companion init.rc.
@@ -615,6 +622,8 @@ ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
ALL_INIT_RC_INSTALLED_PAIRS += $(my_init_rc_new_pairs)
$(my_all_targets) : $(my_init_rc_installed)
+ # Install init_rc together with the target
+ $(LOCAL_INSTALLED_MODULE) : | $(my_init_rc_installed)
endif # my_init_rc
endif # !LOCAL_IS_HOST_MODULE
@@ -961,6 +970,9 @@ ifneq (,$(LOCAL_SOONG_INSTALLED_MODULE))
$(my_init_rc_installed) \
$(my_installed_test_data) \
$(my_vintf_installed))
+
+ ALL_MODULES.$(my_register_name).INSTALLED_SYMLINKS := $(LOCAL_SOONG_INSTALL_SYMLINKS)
+
# Store the list of colon-separated pairs of the built and installed locations
# of files provided by this module. Used by custom packaging rules like
# package-modules.mk that need to copy the built files to a custom install
@@ -975,6 +987,11 @@ ifneq (,$(LOCAL_SOONG_INSTALLED_MODULE))
$(my_init_rc_pairs) \
$(my_test_data_pairs) \
$(my_vintf_pairs))
+ # Store the list of vintf/init_rc as order-only dependencies
+ ALL_MODULES.$(my_register_name).ORDERONLY_INSTALLED := \
+ $(strip $(ALL_MODULES.$(my_register_name).ORDERONLY_INSTALLED) \
+ $(my_init_rc_installed) \
+ $(my_vintf_installed))
else ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
ALL_MODULES.$(my_register_name).INSTALLED := \
$(strip $(ALL_MODULES.$(my_register_name).INSTALLED) \
@@ -984,7 +1001,21 @@ else ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
$(strip $(ALL_MODULES.$(my_register_name).BUILT_INSTALLED) \
$(LOCAL_BUILT_MODULE):$(LOCAL_INSTALLED_MODULE) \
$(my_init_rc_pairs) $(my_test_data_pairs) $(my_vintf_pairs))
+ ALL_MODULES.$(my_register_name).ORDERONLY_INSTALLED := \
+ $(strip $(ALL_MODULES.$(my_register_name).ORDERONLY_INSTALLED) \
+ $(my_init_rc_installed) \
+ $(my_vintf_installed))
+endif
+
+# Mark LOCAL_SOONG_INSTALL_SYMLINKS as installed if we're installing any kind of module, not just
+# ones that set LOCAL_SOONG_INSTALLED_MODULE. This is so we can have a soong module that only
+# installs symlinks (e.g. installed_symlink). We can't set LOCAL_SOONG_INSTALLED_MODULE to a symlink
+# because cp commands will fail on symlinks.
+ifneq (,$(or $(LOCAL_SOONG_INSTALLED_MODULE),$(call boolean-not,$(LOCAL_UNINSTALLABLE_MODULE))))
+ ALL_MODULES.$(my_register_name).INSTALLED += $(LOCAL_SOONG_INSTALL_SYMLINKS)
+ ALL_MODULES.$(my_register_name).INSTALLED_SYMLINKS := $(LOCAL_SOONG_INSTALL_SYMLINKS)
endif
+
ifdef LOCAL_PICKUP_FILES
# Files or directories ready to pick up by the build system
# when $(LOCAL_BUILT_MODULE) is done.
@@ -1045,6 +1076,10 @@ ALL_MODULES.$(my_register_name).SUPPORTED_VARIANTS := \
$(ALL_MODULES.$(my_register_name).SUPPORTED_VARIANTS) \
$(filter-out $(ALL_MODULES.$(my_register_name).SUPPORTED_VARIANTS),$(my_supported_variant))
+ALL_MODULES.$(my_register_name).ACONFIG_FILES := \
+ $(ALL_MODULES.$(my_register_name).ACONFIG_FILES) $(LOCAL_ACONFIG_FILES)
+
+
##########################################################################
## When compiling against API imported module, use API import stub
## libraries.
diff --git a/core/board_config.mk b/core/board_config.mk
index 663ec7c1cd..eb4c5ecfd1 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -144,9 +144,6 @@ _board_strip_list += BOARD_AVB_PVMFW_KEY_PATH
_board_strip_list += BOARD_AVB_PVMFW_ALGORITHM
_board_strip_list += BOARD_AVB_PVMFW_ROLLBACK_INDEX_LOCATION
_board_strip_list += BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST
-_board_strip_list += BOARD_BPT_DISK_SIZE
-_board_strip_list += BOARD_BPT_INPUT_FILES
-_board_strip_list += BOARD_BPT_MAKE_TABLE_ARGS
_board_strip_list += BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION
_board_strip_list += BOARD_AVB_VBMETA_VENDOR_ALGORITHM
_board_strip_list += BOARD_AVB_VBMETA_VENDOR_KEY_PATH
@@ -174,7 +171,6 @@ _board_strip_list += ODM_MANIFEST_SKUS
_build_broken_var_list := \
- BUILD_BROKEN_PLUGIN_VALIDATION \
BUILD_BROKEN_CLANG_PROPERTY \
BUILD_BROKEN_CLANG_ASFLAGS \
BUILD_BROKEN_CLANG_CFLAGS \
@@ -189,9 +185,9 @@ _build_broken_var_list := \
BUILD_BROKEN_PREBUILT_ELF_FILES \
BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW \
BUILD_BROKEN_USES_NETWORK \
- BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES \
BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE \
BUILD_BROKEN_VINTF_PRODUCT_COPY_FILES \
+ BUILD_BROKEN_INCORRECT_PARTITION_IMAGES \
_build_broken_var_list += \
$(foreach m,$(AVAILABLE_BUILD_MODULE_TYPES) \
@@ -976,24 +972,6 @@ ifneq ($(BOARD_VNDK_VERSION),current)
endif
TARGET_VENDOR_TEST_SUFFIX := /vendor
-###########################################
-# APEXes are by default not flattened, i.e. updatable.
-#
-# APEX flattening can also be forcibly enabled (resp. disabled) by
-# setting OVERRIDE_TARGET_FLATTEN_APEX to true (resp. false), e.g. by
-# setting the OVERRIDE_TARGET_FLATTEN_APEX environment variable.
-ifdef OVERRIDE_TARGET_FLATTEN_APEX
- TARGET_FLATTEN_APEX := $(OVERRIDE_TARGET_FLATTEN_APEX)
-endif
-
-# TODO(b/278826656) Remove the following message
-ifeq (true,$(TARGET_FLATTEN_APEX))
- $(warning ********************************************************************************)
- $(warning Flattened APEX will be deprecated soon. Please stop using flattened APEX and use)
- $(warning "image" APEX instead.)
- $(warning ********************************************************************************)
-endif
-
ifeq (,$(TARGET_BUILD_UNBUNDLED))
ifdef PRODUCT_EXTRA_VNDK_VERSIONS
$(foreach v,$(PRODUCT_EXTRA_VNDK_VERSIONS),$(call check_vndk_version,$(v)))
diff --git a/core/build_id.mk b/core/build_id.mk
index ba5ca42dc7..4c2c7fa244 100644
--- a/core/build_id.mk
+++ b/core/build_id.mk
@@ -18,4 +18,4 @@
# (like "CRB01"). It must be a single word, and is
# capitalized by convention.
-BUILD_ID=AOSP.MASTER
+BUILD_ID=AOSP.MAIN
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index bb7ba1b377..409e559ddd 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -9,6 +9,7 @@ LOCAL_AAPT2_ONLY:=
LOCAL_AAPT_FLAGS:=
LOCAL_AAPT_INCLUDE_ALL_RESOURCES:=
LOCAL_AAPT_NAMESPACES:=
+LOCAL_ACONFIG_FILES:=
LOCAL_ADDITIONAL_CERTIFICATES:=
LOCAL_ADDITIONAL_CHECKED_MODULE:=
LOCAL_ADDITIONAL_DEPENDENCIES:=
@@ -297,6 +298,7 @@ LOCAL_SOONG_MODULE_TYPE :=
LOCAL_SOONG_PROGUARD_DICT :=
LOCAL_SOONG_PROGUARD_USAGE_ZIP :=
LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=
+LOCAL_SOONG_TRANSITIVE_RES_PACKAGES :=
LOCAL_SOONG_DEVICE_RRO_DIRS :=
LOCAL_SOONG_PRODUCT_RRO_DIRS :=
LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=
diff --git a/core/combo/HOST_darwin-x86_64.mk b/core/combo/HOST_darwin.mk
index dac3bbf5cd..11063e6d25 100644
--- a/core/combo/HOST_darwin-x86_64.mk
+++ b/core/combo/HOST_darwin.mk
@@ -14,7 +14,7 @@
# limitations under the License.
#
-# Configuration for Darwin (Mac OS X) on x86_64.
+# Configuration for Darwin (Mac OS X).
# Included by combo/select.mk
define $(combo_var_prefix)transform-shared-lib-to-toc
diff --git a/core/combo/HOST_linux-x86_64.mk b/core/combo/HOST_linux-x86_64.mk
deleted file mode 100644
index 845733f74d..0000000000
--- a/core/combo/HOST_linux-x86_64.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2006 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.
-#
-
-# Configuration for builds hosted on linux-x86_64.
-# Included by combo/select.mk
-
-define $(combo_var_prefix)transform-shared-lib-to-toc
-$(call _gen_toc_command_for_elf,$(1),$(2))
-endef
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux.mk
index 3f4ec0aed1..bfdd3eb701 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux.mk
@@ -14,7 +14,7 @@
# limitations under the License.
#
-# Configuration for builds hosted on linux-x86.
+# Configuration for builds hosted on linux.
# Included by combo/select.mk
define $(combo_var_prefix)transform-shared-lib-to-toc
diff --git a/core/combo/select.mk b/core/combo/select.mk
index 9c7e69e439..a836ed8d68 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -21,8 +21,12 @@
# combo_2nd_arch_prefix -- it's defined if this is loaded for the 2nd arch.
#
-# Build a target string like "linux-arm" or "darwin-x86".
-combo_os_arch := $($(combo_target)OS)-$($(combo_target)$(combo_2nd_arch_prefix)ARCH)
+ifeq ($(combo_target),HOST_)
+ combo_os_arch := $(HOST_OS)
+else
+ # Build a target string like "linux-arm" or "darwin-x86".
+ combo_os_arch := $($(combo_target)OS)-$($(combo_target)$(combo_2nd_arch_prefix)ARCH)
+endif
combo_var_prefix := $(combo_2nd_arch_prefix)$(combo_target)
diff --git a/core/config.mk b/core/config.mk
index c166ef713c..c33959022d 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -342,6 +342,23 @@ else
JAVA_TMPDIR_ARG :=
endif
+# These build broken variables are intended to be set in a buildspec file,
+# while other build broken flags are expected to be set in a board config.
+# These are build broken variables that are expected to apply across board
+# configs, generally for cross-cutting features.
+
+# Build broken variables that should be treated as booleans
+_build_broken_bool_vars := \
+ BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES \
+
+# Build broken variables that should be treated as lists
+_build_broken_list_vars := \
+ BUILD_BROKEN_PLUGIN_VALIDATION \
+
+_build_broken_var_names := $(_build_broken_bool_vars)
+_build_broken_var_names += $(_build_broken_list_vars)
+$(foreach v,$(_build_broken_var_names),$(eval $(v) :=))
+
# ###############################################################
# Include sub-configuration files
# ###############################################################
@@ -371,6 +388,13 @@ endif
# are specific to the user's build configuration.
include $(BUILD_SYSTEM)/envsetup.mk
+
+$(foreach var,$(_build_broken_bool_vars), \
+ $(if $(filter-out true false,$($(var))), \
+ $(error Valid values of $(var) are "true", "false", and "". Not "$($(var))")))
+
+.KATI_READONLY := $(_build_broken_var_names)
+
# Returns true if it is a low memory device, otherwise it returns false.
define is-low-mem-device
$(if $(findstring ro.config.low_ram=true,$(PRODUCT_PROPERTY_OVERRIDES)),true,\
@@ -384,23 +408,8 @@ $(if $(findstring ro.config.low_ram=true,$(PRODUCT_VENDOR_PROPERTIES)),true,\
$(if $(findstring ro.config.low_ram=true,$(PRODUCT_ODM_PROPERTIES)),true,false)))))))))
endef
-# Get the board API level.
-board_api_level := $(PLATFORM_SDK_VERSION)
-ifdef BOARD_API_LEVEL
- board_api_level := $(BOARD_API_LEVEL)
-else ifdef BOARD_SHIPPING_API_LEVEL
- # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
- board_api_level := $(BOARD_SHIPPING_API_LEVEL)
-endif
-
-# Calculate the VSR vendor API level.
-vsr_vendor_api_level := $(board_api_level)
-
-ifdef PRODUCT_SHIPPING_API_LEVEL
- vsr_vendor_api_level := $(call math_min,$(PRODUCT_SHIPPING_API_LEVEL),$(board_api_level))
-endif
-
# Set TARGET_MAX_PAGE_SIZE_SUPPORTED.
+# TARGET_MAX_PAGE_SIZE_SUPPORTED indicates the alignment of the ELF segments.
ifdef PRODUCT_MAX_PAGE_SIZE_SUPPORTED
TARGET_MAX_PAGE_SIZE_SUPPORTED := $(PRODUCT_MAX_PAGE_SIZE_SUPPORTED)
else ifeq ($(strip $(call is-low-mem-device)),true)
@@ -410,12 +419,34 @@ else
# The default binary alignment for userspace is 4096.
TARGET_MAX_PAGE_SIZE_SUPPORTED := 4096
# When VSR vendor API level >= 34, binary alignment will be 65536.
- ifeq ($(call math_gt_or_eq,$(vsr_vendor_api_level),34),true)
+ ifeq ($(call math_gt_or_eq,$(VSR_VENDOR_API_LEVEL),34),true)
+ ifeq ($(TARGET_ARCH),arm64)
TARGET_MAX_PAGE_SIZE_SUPPORTED := 65536
+ endif
endif
endif
.KATI_READONLY := TARGET_MAX_PAGE_SIZE_SUPPORTED
+# Only arm64 arch supports TARGET_MAX_PAGE_SIZE_SUPPORTED greater than 4096.
+ifneq ($(TARGET_MAX_PAGE_SIZE_SUPPORTED),4096)
+ ifneq ($(TARGET_ARCH),arm64)
+ $(error TARGET_MAX_PAGE_SIZE_SUPPORTED=$(TARGET_MAX_PAGE_SIZE_SUPPORTED) is greater than 4096. Only supported in arm64 arch)
+ endif
+endif
+
+# Boolean variable determining if AOSP is page size agnostic. This means
+# that AOSP can use a kernel configured with 4k/16k/64k PAGE SIZES.
+TARGET_PAGE_SIZE_AGNOSTIC := false
+ifdef PRODUCT_PAGE_SIZE_AGNOSTIC
+ TARGET_PAGE_SIZE_AGNOSTIC := $(PRODUCT_PAGE_SIZE_AGNOSTIC)
+ ifeq ($(TARGET_PAGE_SIZE_AGNOSTIC),true)
+ ifneq ($(TARGET_MAX_PAGE_SIZE_SUPPORTED),65536)
+ $(error TARGET_MAX_PAGE_SIZE_SUPPORTED has to be 65536 to support page size agnostic)
+ endif
+ endif
+endif
+.KATI_READONLY := TARGET_PAGE_SIZE_AGNOSTIC
+
# Pruned directory options used when using findleaves.py
# See envsetup.mk for a description of SCAN_EXCLUDE_DIRS
FIND_LEAVES_EXCLUDES := $(addprefix --prune=, $(SCAN_EXCLUDE_DIRS) .repo .git)
@@ -625,6 +656,7 @@ FILESLIST := $(HOST_OUT_EXECUTABLES)/fileslist
FILESLIST_UTIL :=$= build/make/tools/fileslist_util.py
HOST_INIT_VERIFIER := $(HOST_OUT_EXECUTABLES)/host_init_verifier
XMLLINT := $(HOST_OUT_EXECUTABLES)/xmllint
+ACONFIG := $(HOST_OUT_EXECUTABLES)/aconfig
# SOONG_ZIP is exported by Soong, but needs to be defined early for
# $OUT/dexpreopt.global. It will be verified against the Soong version.
@@ -645,10 +677,11 @@ else
# For non-supported hosts, do not generate breakpad symbols.
BREAKPAD_GENERATE_SYMBOLS := false
endif
+GZIP := prebuilts/build-tools/path/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/gzip
PROTOC := $(HOST_OUT_EXECUTABLES)/aprotoc$(HOST_EXECUTABLE_SUFFIX)
NANOPB_SRCS := $(HOST_OUT_EXECUTABLES)/protoc-gen-nanopb
MKBOOTFS := $(HOST_OUT_EXECUTABLES)/mkbootfs$(HOST_EXECUTABLE_SUFFIX)
-MINIGZIP := $(HOST_OUT_EXECUTABLES)/minigzip$(HOST_EXECUTABLE_SUFFIX)
+MINIGZIP := $(GZIP)
LZ4 := $(HOST_OUT_EXECUTABLES)/lz4$(HOST_EXECUTABLE_SUFFIX)
GENERATE_GKI_CERTIFICATE := $(HOST_OUT_EXECUTABLES)/generate_gki_certificate$(HOST_EXECUTABLE_SUFFIX)
ifeq (,$(strip $(BOARD_CUSTOM_MKBOOTIMG)))
@@ -691,6 +724,7 @@ endif
IMG_FROM_TARGET_FILES := $(HOST_OUT_EXECUTABLES)/img_from_target_files$(HOST_EXECUTABLE_SUFFIX)
MAKE_RECOVERY_PATCH := $(HOST_OUT_EXECUTABLES)/make_recovery_patch$(HOST_EXECUTABLE_SUFFIX)
OTA_FROM_TARGET_FILES := $(HOST_OUT_EXECUTABLES)/ota_from_target_files$(HOST_EXECUTABLE_SUFFIX)
+OTA_FROM_RAW_IMG := $(HOST_OUT_EXECUTABLES)/ota_from_raw_img$(HOST_EXECUTABLE_SUFFIX)
SPARSE_IMG := $(HOST_OUT_EXECUTABLES)/sparse_img$(HOST_EXECUTABLE_SUFFIX)
CHECK_PARTITION_SIZES := $(HOST_OUT_EXECUTABLES)/check_partition_sizes$(HOST_EXECUTABLE_SUFFIX)
SYMBOLS_MAP := $(HOST_OUT_EXECUTABLES)/symbols_map
@@ -722,7 +756,7 @@ EXTRACT_KERNEL := build/make/tools/extract_kernel.py
# Path to tools.jar
HOST_JDK_TOOLS_JAR := $(ANDROID_JAVA8_HOME)/lib/tools.jar
-APICHECK_COMMAND := $(JAVA) -Xmx4g -jar $(APICHECK) --no-banner
+APICHECK_COMMAND := $(JAVA) -Xmx4g -jar $(APICHECK)
# Boolean variable determining if the allow list for compatible properties is enabled
PRODUCT_COMPATIBLE_PROPERTY := true
@@ -777,6 +811,9 @@ $(KATI_obsolete_var $(foreach req,$(requirements),$(req)_OVERRIDE) \
requirements :=
+# Set default value of KEEP_VNDK.
+KEEP_VNDK ?= true
+
# BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED can be true only if early-mount of
# partitions is supported. But the early-mount must be supported for full
# treble products, and so BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED should be set
@@ -884,22 +921,15 @@ ifndef BOARD_SEPOLICY_VERS
BOARD_SEPOLICY_VERS := $(PLATFORM_SEPOLICY_VERSION)
endif
-ifeq ($(BOARD_SEPOLICY_VERS),$(PLATFORM_SEPOLICY_VERSION))
-IS_TARGET_MIXED_SEPOLICY :=
-else
-IS_TARGET_MIXED_SEPOLICY := true
-endif
-
-.KATI_READONLY := IS_TARGET_MIXED_SEPOLICY
-
# A list of SEPolicy versions, besides PLATFORM_SEPOLICY_VERSION, that the framework supports.
-PLATFORM_SEPOLICY_COMPAT_VERSIONS := \
+PLATFORM_SEPOLICY_COMPAT_VERSIONS := $(filter-out $(PLATFORM_SEPOLICY_VERSION), \
29.0 \
30.0 \
31.0 \
32.0 \
33.0 \
34.0 \
+ )
.KATI_READONLY := \
PLATFORM_SEPOLICY_COMPAT_VERSIONS \
@@ -1194,8 +1224,12 @@ TARGET_AVAILABLE_SDK_VERSIONS := $(patsubst %/test,test_%,$(TARGET_AVAILABLE_SDK
TARGET_AVAILABLE_SDK_VERSIONS := $(filter-out %/module-lib %/system-server,$(TARGET_AVAILABLE_SDK_VERSIONS))
TARGET_AVAIALBLE_SDK_VERSIONS := $(call numerically_sort,$(TARGET_AVAILABLE_SDK_VERSIONS))
-TARGET_SDK_VERSIONS_WITHOUT_JAVA_18_SUPPORT := $(call numbers_less_than,24,$(TARGET_AVAILABLE_SDK_VERSIONS))
-TARGET_SDK_VERSIONS_WITHOUT_JAVA_19_SUPPORT := $(call numbers_less_than,30,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_1_8_SUPPORT := $(call numbers_less_than,24,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_1_9_SUPPORT := $(call numbers_less_than,30,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_11_SUPPORT := $(call numbers_less_than,32,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_17_SUPPORT := $(call numbers_less_than,34,$(TARGET_AVAILABLE_SDK_VERSIONS))
+
+JAVA_LANGUAGE_VERSIONS_WITHOUT_SYSTEM_MODULES := 1.7 1.8
# This is the standard way to name a directory containing prebuilt target
# objects. E.g., prebuilt/$(TARGET_PREBUILT_TAG)/libc.so
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 7fa190f7b3..049e7ff5d2 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -65,6 +65,18 @@ ifneq ($(filter memtag_heap, $(my_global_sanitize)),)
endif
endif
+# Disable global HWASan in excluded paths
+ifneq ($(filter hwaddress, $(my_global_sanitize)),)
+ combined_exclude_paths := $(HWASAN_EXCLUDE_PATHS) \
+ $(PRODUCT_HWASAN_EXCLUDE_PATHS)
+
+ ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_exclude_paths)),\
+ $(filter $(dir)%,$(LOCAL_PATH)))),)
+ my_global_sanitize := $(filter-out hwaddress,$(my_global_sanitize))
+ my_global_sanitize_diag := $(filter-out hwaddress,$(my_global_sanitize_diag))
+ endif
+endif
+
ifneq ($(my_global_sanitize),)
my_sanitize := $(my_global_sanitize) $(my_sanitize)
endif
@@ -413,7 +425,6 @@ ifneq ($(filter cfi,$(my_sanitize)),)
my_cflags += -fvisibility=default
endif
my_ldflags += $(CFI_EXTRA_LDFLAGS)
- my_arflags += --plugin $(LLVM_PREBUILTS_PATH)/../lib64/LLVMgold.so
ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
my_ldflags := $(filter-out -fsanitize-cfi-cross-dso,$(my_ldflags))
diff --git a/core/definitions.mk b/core/definitions.mk
index be40584e5f..b6b0d69ed2 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -147,6 +147,10 @@ define true-or-empty
$(filter true, $(1))
endef
+define boolean-not
+$(if $(filter true,$(1)),,true)
+endef
+
###########################################################
## Rule for touching GCNO files.
###########################################################
@@ -1547,10 +1551,10 @@ endef
#
# You must call this with $(eval).
define define-aidl-java-rule
-define-aidl-java-rule-src := $(patsubst %.aidl,%.java,$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
-$$(define-aidl-java-rule-src) : $(call clean-path,$(LOCAL_PATH)/$(1)) $(AIDL)
+define_aidl_java_rule_src := $(patsubst %.aidl,%.java,$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
+$$(define_aidl_java_rule_src) : $(call clean-path,$(LOCAL_PATH)/$(1)) $(AIDL)
$$(transform-aidl-to-java)
-$(3) += $$(define-aidl-java-rule-src)
+$(3) += $$(define_aidl_java_rule_src)
endef
## Given a .aidl file path generate the rule to compile it a .cpp file.
@@ -1560,10 +1564,10 @@ endef
#
# You must call this with $(eval).
define define-aidl-cpp-rule
-define-aidl-cpp-rule-src := $(patsubst %.aidl,%$(LOCAL_CPP_EXTENSION),$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
-$$(define-aidl-cpp-rule-src) : $(call clean-path,$(LOCAL_PATH)/$(1)) $(AIDL_CPP)
+define_aidl_cpp_rule_src := $(patsubst %.aidl,%$(LOCAL_CPP_EXTENSION),$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
+$$(define_aidl_cpp_rule_src) : $(call clean-path,$(LOCAL_PATH)/$(1)) $(AIDL_CPP)
$$(transform-aidl-to-cpp)
-$(3) += $$(define-aidl-cpp-rule-src)
+$(3) += $$(define_aidl_cpp_rule_src)
endef
###########################################################
@@ -1585,10 +1589,10 @@ endef
#
# You must call this with $(eval).
define define-vts-cpp-rule
-define-vts-cpp-rule-src := $(patsubst %.vts,%$(LOCAL_CPP_EXTENSION),$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
-$$(define-vts-cpp-rule-src) : $(LOCAL_PATH)/$(1) $(VTSC)
+define_vts_cpp_rule_src := $(patsubst %.vts,%$(LOCAL_CPP_EXTENSION),$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
+$$(define_vts_cpp_rule_src) : $(LOCAL_PATH)/$(1) $(VTSC)
$$(transform-vts-to-cpp)
-$(3) += $$(define-vts-cpp-rule-src)
+$(3) += $$(define_vts_cpp_rule_src)
endef
###########################################################
@@ -2377,6 +2381,7 @@ rm -rf $(PRIVATE_JAVA_GEN_DIR)
mkdir -p $(PRIVATE_JAVA_GEN_DIR)
$(call dump-words-to-file,$(PRIVATE_RES_FLAT),$(dir $@)aapt2-flat-list)
$(call dump-words-to-file,$(PRIVATE_OVERLAY_FLAT),$(dir $@)aapt2-flat-overlay-list)
+cat $(PRIVATE_STATIC_LIBRARY_TRANSITIVE_RES_PACKAGES_LISTS) | sort -u | tr '\n' ' ' > $(dir $@)aapt2-transitive-overlay-list
$(hide) $(AAPT2) link -o $@ \
$(PRIVATE_AAPT_FLAGS) \
$(if $(PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES),$$(cat $(PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES))) \
@@ -2396,6 +2401,7 @@ $(hide) $(AAPT2) link -o $@ \
$(addprefix --rename-manifest-package ,$(PRIVATE_MANIFEST_PACKAGE_NAME)) \
$(addprefix --rename-instrumentation-target-package ,$(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
-R \@$(dir $@)aapt2-flat-overlay-list \
+ -R \@$(dir $@)aapt2-transitive-overlay-list \
\@$(dir $@)aapt2-flat-list
$(SOONG_ZIP) -o $(PRIVATE_SRCJAR) -C $(PRIVATE_JAVA_GEN_DIR) -D $(PRIVATE_JAVA_GEN_DIR)
$(EXTRACT_JAR_PACKAGES) -i $(PRIVATE_SRCJAR) -o $(PRIVATE_AAPT_EXTRA_PACKAGES) --prefix '--extra-packages '
@@ -2941,7 +2947,7 @@ endef
define compress-package
$(hide) \
mv $@ $@.uncompressed; \
- $(MINIGZIP) -9 -c $@.uncompressed > $@.compressed; \
+ $(GZIP) -9 -c $@.uncompressed > $@.compressed; \
rm -f $@.uncompressed; \
mv $@.compressed $@;
endef
@@ -3201,8 +3207,9 @@ endef
define copy-vintf-manifest-checked
$(2): $(1) $(HOST_OUT_EXECUTABLES)/assemble_vintf
@echo "Copy xml: $$@"
- $(hide) $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $$< >/dev/null # Don't print the xml file to stdout.
- $$(copy-file-to-target)
+ $(hide) mkdir -p "$$(dir $$@)"
+ $(hide) VINTF_IGNORE_TARGET_FCM_VERSION=true\
+ $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $$< -o $$@
endef
# Copies many vintf manifest files checked.
@@ -3415,6 +3422,10 @@ endef
# $(2): path in symbols directory
# $(3): file type (elf or r8)
# $(4): path in the mappings directory
+#
+# Regarding the restats at the end: I think you should only need to use KATI_RESTAT on $(2), but
+# there appears to be a bug in kati where it was not adding restat=true in the ninja file unless we
+# also added 4 to KATI_RESTAT.
define _copy-symbols-file-with-mapping
$(2): .KATI_IMPLICIT_OUTPUTS := $(4)
$(2): $(SYMBOLS_MAP)
@@ -3423,16 +3434,7 @@ $(2): $(1)
$$(copy-file-to-target)
$(SYMBOLS_MAP) -$(strip $(3)) $(2) -write_if_changed $(4)
.KATI_RESTAT: $(2)
-endef
-
-# Returns the directory to copy proguard dictionaries into
-define local-proguard-dictionary-directory
-$(call intermediates-dir-for,PACKAGING,proguard_dictionary)/out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates
-endef
-
-# Returns the directory to copy proguard dictionary mappings into
-define local-proguard-dictionary-mapping-directory
-$(call intermediates-dir-for,PACKAGING,proguard_dictionary_mapping)/out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates
+.KATI_RESTAT: $(4)
endef
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 6ac169b701..67911259b2 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -90,8 +90,8 @@ DEXPREOPT_INFIX := $(if $(filter true,$(DEX_PREOPT_WITH_UPDATABLE_BCP)),mainline
# The input variables are written by build/soong/java/dexpreopt_bootjars.go. Examples can be found
# at the bottom of build/soong/java/dexpreopt_config_testing.go.
dexpreopt_root_dir := $(dir $(patsubst %/,%,$(dir $(firstword $(bootclasspath_jars)))))
-booclasspath_arg := $(subst $(space),:,$(patsubst $(dexpreopt_root_dir)%,%,$(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)))
-booclasspath_locations_arg := $(subst $(space),:,$(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS))
+bootclasspath_arg := $(subst $(space),:,$(patsubst $(dexpreopt_root_dir)%,%,$(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)))
+bootclasspath_locations_arg := $(subst $(space),:,$(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS))
boot_images := $(subst :,$(space),$(DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE$(DEXPREOPT_INFIX)))
boot_image_arg := $(subst $(space),:,$(patsubst /%,%,$(boot_images)))
dex2oat_extra_args := $(if $(filter true,$(ENABLE_UFFD_GC)),--runtime-arg -Xgc:CMC)
@@ -99,8 +99,8 @@ dex2oat_extra_args := $(if $(filter true,$(ENABLE_UFFD_GC)),--runtime-arg -Xgc:C
boot_zip_metadata_txt := $(dir $(boot_zip))boot_zip/METADATA.txt
$(boot_zip_metadata_txt):
rm -f $@
- echo "booclasspath = $(booclasspath_arg)" >> $@
- echo "booclasspath-locations = $(booclasspath_locations_arg)" >> $@
+ echo "bootclasspath = $(bootclasspath_arg)" >> $@
+ echo "bootclasspath-locations = $(bootclasspath_locations_arg)" >> $@
echo "boot-image = $(boot_image_arg)" >> $@
echo "extra-args = $(dex2oat_extra_args)" >> $@
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index 7b9c4dbac0..67394595f6 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -111,6 +111,7 @@ ifeq ($(WRITE_SOONG_VARIABLES),true)
$(call add_json_list, BootJars, $(PRODUCT_BOOT_JARS))
$(call add_json_list, ApexBootJars, $(PRODUCT_APEX_BOOT_JARS))
$(call add_json_list, ArtApexJars, $(filter $(PRODUCT_BOOT_JARS),$(ART_APEX_JARS)))
+ $(call add_json_list, TestOnlyArtBootImageJars, $(PRODUCT_TEST_ONLY_ART_BOOT_IMAGE_JARS))
$(call add_json_list, SystemServerJars, $(PRODUCT_SYSTEM_SERVER_JARS))
$(call add_json_list, SystemServerApps, $(PRODUCT_SYSTEM_SERVER_APPS))
$(call add_json_list, ApexSystemServerJars, $(PRODUCT_APEX_SYSTEM_SERVER_JARS))
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 288f81fcb6..54a57d1292 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -468,8 +468,6 @@ ifdef LOCAL_DEX_PREOPT
rsync --checksum $(PRIVATE_STAGING) $@
my_dexpreopt_script := $(intermediates)/dexpreopt.sh
- my_dexpreopt_zip := $(intermediates)/dexpreopt.zip
- DEXPREOPT.$(LOCAL_MODULE).POST_INSTALLED_DEXPREOPT_ZIP := $(my_dexpreopt_zip)
.KATI_RESTAT: $(my_dexpreopt_script)
$(my_dexpreopt_script): PRIVATE_MODULE := $(LOCAL_MODULE)
$(my_dexpreopt_script): PRIVATE_GLOBAL_SOONG_CONFIG := $(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE)
@@ -499,38 +497,71 @@ ifdef LOCAL_DEX_PREOPT
my_dexpreopt_deps += $(intermediates)/enforce_uses_libraries.status
endif
+ # We need to add all the installed files to ALL_MODULES.$(my_register_name).INSTALLED in order
+ # for the build system to properly track installed files. (for sbom, installclean, etc)
+ # We install all the files in a zip file generated at execution time, which means we have to guess
+ # what's going to be in that zip file before it's created. We then check at executation time that
+ # our guess is correct.
+ # _system_other corresponds to OdexOnSystemOtherByName() in soong.
+ # The other paths correspond to dexpreoptCommand()
+ _dexlocation := $(patsubst $(PRODUCT_OUT)/%,%,$(LOCAL_INSTALLED_MODULE))
+ _dexname := $(basename $(notdir $(_dexlocation)))
+ _system_other := $(strip $(if $(strip $(BOARD_USES_SYSTEM_OTHER_ODEX)), \
+ $(if $(strip $(SANITIZE_LITE)),, \
+ $(if $(filter $(_dexname),$(PRODUCT_DEXPREOPT_SPEED_APPS))$(filter $(_dexname),$(PRODUCT_SYSTEM_SERVER_APPS)),, \
+ $(if $(strip $(foreach myfilter,$(SYSTEM_OTHER_ODEX_FILTER),$(filter system/$(myfilter),$(_dexlocation)))), \
+ system_other/)))))
+ # _dexdir has a trailing /
+ _dexdir := $(_system_other)$(dir $(_dexlocation))
+ my_dexpreopt_zip_contents := $(sort \
+ $(foreach arch,$(my_dexpreopt_archs), \
+ $(_dexdir)oat/$(arch)/$(_dexname).odex \
+ $(_dexdir)oat/$(arch)/$(_dexname).vdex \
+ $(if $(filter false,$(LOCAL_DEX_PREOPT_APP_IMAGE)),, \
+ $(if $(my_process_profile)$(filter true,$(LOCAL_DEX_PREOPT_APP_IMAGE)), \
+ $(_dexdir)oat/$(arch)/$(_dexname).art))) \
+ $(if $(my_process_profile),$(_dexlocation).prof))
+ _dexlocation :=
+ _dexdir :=
+ _dexname :=
+ _system_other :=
+
+ my_dexpreopt_zip := $(intermediates)/dexpreopt.zip
$(my_dexpreopt_zip): PRIVATE_MODULE := $(LOCAL_MODULE)
$(my_dexpreopt_zip): $(my_dexpreopt_deps)
$(my_dexpreopt_zip): | $(DEXPREOPT_GEN_DEPS)
$(my_dexpreopt_zip): .KATI_DEPFILE := $(my_dexpreopt_zip).d
$(my_dexpreopt_zip): PRIVATE_DEX := $(my_dex_jar)
$(my_dexpreopt_zip): PRIVATE_SCRIPT := $(my_dexpreopt_script)
+ $(my_dexpreopt_zip): PRIVATE_ZIP_CONTENTS := $(my_dexpreopt_zip_contents)
$(my_dexpreopt_zip): $(my_dexpreopt_script)
@echo "$(PRIVATE_MODULE) dexpreopt"
+ rm -f $@
+ echo -n > $@.contents
+ $(foreach f,$(PRIVATE_ZIP_CONTENTS),echo "$(f)" >> $@.contents$(newline))
bash $(PRIVATE_SCRIPT) $(PRIVATE_DEX) $@
+ if ! diff <(zipinfo -1 $@ | sort) $@.contents >&2; then \
+ echo "Contents of $@ did not match what make was expecting." >&2 && exit 1; \
+ fi
- ifdef LOCAL_POST_INSTALL_CMD
- # Add a shell command separator
- LOCAL_POST_INSTALL_CMD += &&
- endif
-
- LOCAL_POST_INSTALL_CMD += \
- for i in $$(zipinfo -1 $(my_dexpreopt_zip)); \
- do mkdir -p $(PRODUCT_OUT)/$$(dirname $$i); \
- done && \
- ( unzip -qoDD -d $(PRODUCT_OUT) $(my_dexpreopt_zip) 2>&1 | grep -v "zipfile is empty"; exit $${PIPESTATUS[0]} ) || \
- ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )
+ $(foreach installed_dex_file,$(my_dexpreopt_zip_contents),\
+ $(eval $(PRODUCT_OUT)/$(installed_dex_file): $(my_dexpreopt_zip) \
+$(newline) unzip -qoDD -d $(PRODUCT_OUT) $(my_dexpreopt_zip) $(installed_dex_file)))
- $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD)
- $(LOCAL_INSTALLED_MODULE): $(my_dexpreopt_zip)
+ ALL_MODULES.$(my_register_name).INSTALLED += $(addprefix $(PRODUCT_OUT)/,$(my_dexpreopt_zip_contents))
- $(my_all_targets): $(my_dexpreopt_zip)
+ # Normally this happens in sbom.mk, which is included from base_rules.mk. But since
+ # dex_preopt_odex_install.mk is included after base_rules.mk, it misses these odex files.
+ $(foreach installed_file,$(addprefix $(PRODUCT_OUT)/,$(my_dexpreopt_zip_contents)), \
+ $(eval ALL_INSTALLED_FILES.$(installed_file) := $(my_register_name)))
my_dexpreopt_config :=
+ my_dexpreopt_config_for_postprocessing :=
+ my_dexpreopt_jar_copy :=
my_dexpreopt_product_packages :=
my_dexpreopt_script :=
my_dexpreopt_zip :=
- my_dexpreopt_config_for_postprocessing :=
+ my_dexpreopt_zip_contents :=
endif # LOCAL_DEX_PREOPT
endif # my_create_dexpreopt_config
diff --git a/core/dupcheck.sh b/core/dupcheck.sh
new file mode 100755
index 0000000000..13ab78211e
--- /dev/null
+++ b/core/dupcheck.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+
+# Find duplicate shared libraries by md5 checksum and possible duplicates by size.
+# Results will be available in the out directory of the build.
+# Usage:
+# ./dupcheck.sh <out_dir> <image>
+
+OUT_DIR="$1"
+IMG="$2"
+TMP_MD5="${OUT_DIR}/_dup_md5"
+TMP_SIZE="${OUT_DIR}/_dup_size"
+TMP_CHECK="${OUT_DIR}/_dup_tmp_check"
+TMP_SIZE_REAL="${OUT_DIR}/_dup_size_real"
+TMP_FILE1="${OUT_DIR}/_dup_f1"
+TMP_FILE2="${OUT_DIR}/_dup_f2"
+MD5_DUPLICATES="${OUT_DIR}/duplicate-libs-md5-${IMG}.txt"
+SIZE_DUPLICATES="${OUT_DIR}/duplicate-libs-size-${IMG}.txt"
+
+# Check arguments
+if [ "$#" -ne 2 ]; then
+ echo "Usage: ./dupcheck.sh <out_dir> <image>"
+ exit 1
+fi
+
+# Check host and toolchain version
+CHECK_HOST=$(uname)
+if [ "${CHECK_HOST}" == "Linux" ]; then
+ ARCH="linux-x86"
+else
+ ARCH="darwin-x86"
+fi
+BINUTILS_PATH="./prebuilts/clang/host/${ARCH}/llvm-binutils-stable"
+
+# Remove any old files if they exist.
+if [ -f "${MD5_DUPLICATES}" ]; then
+ rm "${MD5_DUPLICATES}"
+fi
+
+if [ -f "${SIZE_DUPLICATES}" ]; then
+ rm "${SIZE_DUPLICATES}"
+fi
+
+# Find all .so files and calculate their md5.
+find ./"${OUT_DIR}"/${IMG}/ -name "lib*.so" -type f -print0 | xargs -0 md5sum | sed -e "s# .*/# #" | sort | uniq -c | sort -g | sed "/^.*1 /d" | sed "s/^. *[0-9] //" > "${TMP_MD5}" 2>&1
+
+if [ -s "${TMP_MD5}" ]; then
+ while read -r list; do
+ checksum=$(echo "${list}" | cut -f1 -d ' ')
+ filename=$(echo "${list}" | cut -f2 -d ' ')
+ # For each md5, list the file paths that match.
+ {
+ echo "MD5: ${checksum}"; \
+ find ./"${OUT_DIR}"/${IMG}/ -name "${filename}" -type f -print0 | xargs -0 md5sum | grep "${checksum}" | sed 's/^.* //'; \
+ echo ""; \
+ } >> "${MD5_DUPLICATES}"
+ done <"${TMP_MD5}"
+else
+ echo "No duplicate files by md5 found." >> "${MD5_DUPLICATES}"
+fi
+
+# Cleanup
+rm "${TMP_MD5}"
+
+# Find possible duplicate .so files by size.
+find ./"${OUT_DIR}"/${IMG}/ -name "*.so" -type f -print0 | xargs -0 stat --format="%s %n" 2>/dev/null | sed -e "s# .*/# #" | sort | uniq -c | sort -g | sed "/^.*1 /d" > "${TMP_SIZE}" 2>&1
+if [ -s "${TMP_SIZE}" ]; then
+ while read -r list; do
+ size=$(echo "${list}" | cut -f2 -d ' ')
+ filename=$(echo "${list}" | cut -f3 -d ' ')
+ # Check if the files are not in the md5sum list and do nothing if that is the case.
+ find ./"${OUT_DIR}"/${IMG}/ -name "${filename}" -type f -print0 | xargs -0 stat --format="%s %n" 2>/dev/null | grep "${size}" | sed "s/^.* //" | sort > "${TMP_CHECK}" 2>&1
+ while read -r filepath; do
+ found=$(grep -F "${filepath}" "${MD5_DUPLICATES}")
+ if [ -z "${found}" ]; then
+ echo "${filepath}" >> "${TMP_SIZE_REAL}"
+ fi
+ done<"${TMP_CHECK}"
+ # For every duplication found, diff the .note and .text sections.
+ if [ -s "${TMP_SIZE_REAL}" ]; then
+ {
+ echo "File: ${filename}, Size: ${size}"; \
+ cat "${TMP_SIZE_REAL}"; \
+ echo ""; \
+ } >> "${SIZE_DUPLICATES}"
+ count=$(wc -l "${TMP_SIZE_REAL}" | cut -f1 -d ' ')
+ # Limitation: this only works for file pairs. If more than two possible duplications are found, the user need to check manually
+ # all the possible combinations using the llvm-readelf and llvm-objdump commands below.
+ if [ "${count}" = 2 ]; then
+ file1=$(head -n 1 "${TMP_SIZE_REAL}")
+ file2=$(tail -n 1 "${TMP_SIZE_REAL}")
+ # Check .note section
+ ${BINUTILS_PATH}/llvm-readelf --wide --notes "${file1}" > "${TMP_FILE1}" 2>&1
+ ${BINUTILS_PATH}/llvm-readelf --wide --notes "${file2}" > "${TMP_FILE2}" 2>&1
+ {
+ diff -u "${TMP_FILE1}" "${TMP_FILE2}" | sed "1d;2d;3d"; \
+ echo "";
+ } >> "${SIZE_DUPLICATES}"
+ # Check .text section
+ ${BINUTILS_PATH}/llvm-objdump --line-numbers --disassemble --demangle --reloc --no-show-raw-insn --section=.text "${file1}" | sed "1d;2d"> "${TMP_FILE1}" 2>&1
+ ${BINUTILS_PATH}/llvm-objdump --line-numbers --disassemble --demangle --reloc --no-show-raw-insn --section=.text "${file2}" | sed "1d;2d"> "${TMP_FILE2}" 2>&1
+ {
+ diff -u "${TMP_FILE1}" "${TMP_FILE2}" | sed "1d;2d;3d"; \
+ echo "";
+ } >> "${SIZE_DUPLICATES}"
+ # Cleanup
+ rm "${TMP_FILE1}" "${TMP_FILE2}"
+ else
+ echo "*Note: more than one duplicate. Manually verify all possible combinations." >> "${SIZE_DUPLICATES}"
+ fi
+ rm "${TMP_SIZE_REAL}"
+ echo "" >> "${SIZE_DUPLICATES}"
+ fi
+ done <"${TMP_SIZE}"
+ # Cleanup
+ rm "${TMP_SIZE}" "${TMP_CHECK}"
+else
+ echo "No duplicate files by size found." >> "${SIZE_DUPLICATES}"
+fi
diff --git a/core/envsetup.mk b/core/envsetup.mk
index f5a2022cda..091c2e3050 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -720,6 +720,7 @@ TARGET_OUT_VENDOR_JAVA_LIBRARIES := $(TARGET_OUT_VENDOR)/framework
TARGET_OUT_VENDOR_APPS := $(target_out_vendor_app_base)/app
TARGET_OUT_VENDOR_APPS_PRIVILEGED := $(target_out_vendor_app_base)/priv-app
TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc
+TARGET_OUT_VENDOR_FAKE := $(PRODUCT_OUT)/vendor_fake_packages
.KATI_READONLY := \
TARGET_OUT_VENDOR_EXECUTABLES \
TARGET_OUT_VENDOR_OPTIONAL_EXECUTABLES \
@@ -728,7 +729,8 @@ TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc
TARGET_OUT_VENDOR_JAVA_LIBRARIES \
TARGET_OUT_VENDOR_APPS \
TARGET_OUT_VENDOR_APPS_PRIVILEGED \
- TARGET_OUT_VENDOR_ETC
+ TARGET_OUT_VENDOR_ETC \
+ TARGET_OUT_VENDOR_FAKE
$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR_EXECUTABLES)
$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib
diff --git a/core/java_common.mk b/core/java_common.mk
index 0e03d0b7b5..a5ed057993 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -25,15 +25,19 @@ ifeq (,$(LOCAL_JAVA_LANGUAGE_VERSION))
# Host modules always default to 1.9
LOCAL_JAVA_LANGUAGE_VERSION := 1.9
else
- ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_18_SUPPORT)))
+ ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_1_8_SUPPORT)))
LOCAL_JAVA_LANGUAGE_VERSION := 1.7
- else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_19_SUPPORT)))
+ else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_1_9_SUPPORT)))
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+ else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_11_SUPPORT)))
+ LOCAL_JAVA_LANGUAGE_VERSION := 1.9
+ else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_17_SUPPORT)))
+ LOCAL_JAVA_LANGUAGE_VERSION := 11
else ifneq (,$(LOCAL_SDK_VERSION)$(TARGET_BUILD_USE_PREBUILT_SDKS))
# TODO(ccross): allow 1.9 for current and unbundled once we have SDK system modules
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
else
- LOCAL_JAVA_LANGUAGE_VERSION := 1.9
+ LOCAL_JAVA_LANGUAGE_VERSION := 17
endif
endif
endif
@@ -410,7 +414,7 @@ endif
full_java_system_modules_deps :=
my_system_modules_dir :=
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_USE_SYSTEM_MODULES :=
-ifeq ($(LOCAL_JAVA_LANGUAGE_VERSION),1.9)
+ifeq (,$(filter $(LOCAL_JAVA_LANGUAGE_VERSION),$(JAVA_LANGUAGE_VERSIONS_WITHOUT_SYSTEM_MODULES)))
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_USE_SYSTEM_MODULES := true
ifdef my_system_modules
ifneq ($(my_system_modules),none)
diff --git a/core/main.mk b/core/main.mk
index 5a591f914f..7c25862530 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -191,6 +191,13 @@ ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
ADDITIONAL_PRODUCT_PROPERTIES += dalvik.vm.systemservercompilerfilter=$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)
endif
+# Add the 16K developer option if it is defined for the product.
+ifeq ($(PRODUCT_16K_DEVELOPER_OPTION),true)
+ADDITIONAL_PRODUCT_PROPERTIES += ro.product.build.16k_page.enabled=true
+else
+ADDITIONAL_PRODUCT_PROPERTIES += ro.product.build.16k_page.enabled=false
+endif
+
# Enable core platform API violation warnings on userdebug and eng builds.
ifneq ($(TARGET_BUILD_VARIANT),user)
ADDITIONAL_SYSTEM_PROPERTIES += persist.debug.dalvik.vm.core_platform_api_policy=just-warn
@@ -213,11 +220,19 @@ ADDITIONAL_SYSTEM_PROPERTIES += ro.postinstall.fstab.prefix=/system
# property_overrides_split_enabled is true. Otherwise it will be installed in
# /system/build.prop
ifdef BOARD_VNDK_VERSION
+ ifeq ($(KEEP_VNDK),true)
ifeq ($(BOARD_VNDK_VERSION),current)
ADDITIONAL_VENDOR_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION)
else
ADDITIONAL_VENDOR_PROPERTIES := ro.vndk.version=$(BOARD_VNDK_VERSION)
endif
+ endif
+
+ # TODO(b/290159430): ro.vndk.deprecate is a temporal variable for deprecating VNDK.
+ # This variable will be removed once ro.vndk.version can be removed.
+ ifneq ($(KEEP_VNDK),true)
+ ADDITIONAL_SYSTEM_PROPERTIES += ro.vndk.deprecate=true
+ endif
endif
# Add cpu properties for bionic and ART.
@@ -324,12 +339,14 @@ endif
# modules. It uses the version in PRODUCT_PRODUCT_VNDK_VERSION. If the value
# is "current", use PLATFORM_VNDK_VERSION.
ifdef PRODUCT_PRODUCT_VNDK_VERSION
+ifeq ($(KEEP_VNDK),true)
ifeq ($(PRODUCT_PRODUCT_VNDK_VERSION),current)
ADDITIONAL_PRODUCT_PROPERTIES += ro.product.vndk.version=$(PLATFORM_VNDK_VERSION)
else
ADDITIONAL_PRODUCT_PROPERTIES += ro.product.vndk.version=$(PRODUCT_PRODUCT_VNDK_VERSION)
endif
endif
+endif
ADDITIONAL_PRODUCT_PROPERTIES += ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)
@@ -810,12 +827,14 @@ $(call add-all-host-cross-to-host-cross-required-modules-deps)
# Sets up dependencies such that whenever a target module is installed,
# any other target modules listed in $(ALL_MODULES.$(m).REQUIRED_FROM_TARGET) will also be installed
+# This doesn't apply to ORDERONLY_INSTALLED items.
define add-all-target-to-target-required-modules-deps
$(foreach m,$(ALL_MODULES), \
$(eval r := $(ALL_MODULES.$(m).REQUIRED_FROM_TARGET)) \
$(if $(r), \
$(eval r := $(call module-installed-files,$(r))) \
$(eval t_m := $(filter $(TARGET_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
+ $(eval t_m := $(filter-out $(ALL_MODULES.$(m).ORDERONLY_INSTALLED), $(ALL_MODULES.$(m).INSTALLED))) \
$(eval t_r := $(filter $(TARGET_OUT_ROOT)/%, $(r))) \
$(eval t_r := $(filter-out $(t_m), $(t_r))) \
$(if $(t_m), $(eval $(call add-required-deps, $(t_m),$(t_r)))) \
@@ -1216,7 +1235,8 @@ endef
# Returns modules included automatically as a result of certain BoardConfig
# variables being set.
define auto-included-modules
- $(if $(BOARD_VNDK_VERSION),vndk_package) \
+ $(if $(and $(BOARD_VNDK_VERSION),$(filter true,$(KEEP_VNDK))),vndk_package) \
+ $(if $(filter true,$(KEEP_VNDK)),,llndk_in_system) \
$(if $(DEVICE_MANIFEST_FILE),vendor_manifest.xml) \
$(if $(DEVICE_MANIFEST_SKUS),$(foreach sku, $(DEVICE_MANIFEST_SKUS),vendor_manifest_$(sku).xml)) \
$(if $(ODM_MANIFEST_FILES),odm_manifest.xml) \
@@ -1224,9 +1244,7 @@ define auto-included-modules
endef
-# Lists most of the files a particular product installs, including:
-# - PRODUCT_PACKAGES, and their LOCAL_REQUIRED_MODULES
-# - PRODUCT_COPY_FILES
+# Lists the modules particular product installs.
# The base list of modules to build for this product is specified
# by the appropriate product definition file, which was included
# by product_config.mk.
@@ -1238,8 +1256,7 @@ endef
# Name resolution for LOCAL_REQUIRED_MODULES:
# See the select-bitness-of-required-modules definition.
# $(1): product makefile
-
-define product-installed-files
+define product-installed-modules
$(eval _pif_modules := \
$(call get-product-var,$(1),PRODUCT_PACKAGES) \
$(if $(filter eng,$(tags_to_install)),$(call get-product-var,$(1),PRODUCT_PACKAGES_ENG)) \
@@ -1256,7 +1273,14 @@ define product-installed-files
$(eval ### Resolve the :32 :64 module name) \
$(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))) \
+ $(_pif_modules)
+endef
+
+# Lists most of the files a particular product installs.
+# It gives all the installed files for all modules returned by product-installed-modules,
+# and also includes PRODUCT_COPY_FILES.
+define product-installed-files
+ $(filter-out $(HOST_OUT_ROOT)/%,$(call module-installed-files, $(call product-installed-modules,$(1)))) \
$(call resolve-product-relative-paths,\
$(foreach cf,$(call get-product-var,$(1),PRODUCT_COPY_FILES),$(call word-colon,2,$(cf))))
endef
@@ -1356,6 +1380,7 @@ else ifdef FULL_BUILD
product_host_FILES := $(call host-installed-files,$(INTERNAL_PRODUCT))
product_target_FILES := $(call product-installed-files, $(INTERNAL_PRODUCT))
# WARNING: The product_MODULES variable is depended on by external files.
+ # It contains the list of register names that will be installed on the device
product_MODULES := $(_pif_modules)
# Verify the artifact path requirements made by included products.
@@ -1428,6 +1453,16 @@ ifdef is_sdk_build
$(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_TESTS has nothing to install!)))
endif
+ifneq ($(TARGET_BUILD_APPS),)
+ # If this build is just for apps, only build apps and not the full system by default.
+ ifneq ($(filter all,$(TARGET_BUILD_APPS)),)
+ # If they used the magic goal "all" then build all apps in the source tree.
+ unbundled_build_modules := $(foreach m,$(sort $(ALL_MODULES)),$(if $(filter APPS,$(ALL_MODULES.$(m).CLASS)),$(m)))
+ else
+ unbundled_build_modules := $(sort $(TARGET_BUILD_APPS))
+ endif
+endif
+
# build/make/core/Makefile contains extra stuff that we don't want to pollute this
# top-level makefile with. It expects that ALL_DEFAULT_INSTALLED_MODULES
# contains everything that's built during the current make, but it also further
@@ -1703,16 +1738,10 @@ ifeq ($(HOST_OS),darwin)
else ifneq ($(TARGET_BUILD_APPS),)
# If this build is just for apps, only build apps and not the full system by default.
- unbundled_build_modules :=
- ifneq ($(filter all,$(TARGET_BUILD_APPS)),)
- # If they used the magic goal "all" then build all apps in the source tree.
- unbundled_build_modules := $(foreach m,$(sort $(ALL_MODULES)),$(if $(filter APPS,$(ALL_MODULES.$(m).CLASS)),$(m)))
- else
- unbundled_build_modules := $(TARGET_BUILD_APPS)
- endif
-
- # Dist the installed files if they exist.
- apps_only_installed_files := $(foreach m,$(unbundled_build_modules),$(ALL_MODULES.$(m).INSTALLED))
+ # Dist the installed files if they exist, except the installed symlinks. dist-for-goals emits
+ # `cp src dest` commands, which will fail to copy dangling symlinks.
+ apps_only_installed_files := $(foreach m,$(unbundled_build_modules),\
+ $(filter-out $(ALL_MODULES.$(m).INSTALLED_SYMLINKS),$(ALL_MODULES.$(m).INSTALLED)))
$(call dist-for-goals,apps_only, $(apps_only_installed_files))
# Dist the bundle files if they exist.
@@ -2159,10 +2188,7 @@ endif # TARGET_BUILD_APPS
metadata_list := $(OUT_DIR)/.module_paths/METADATA.list
metadata_files := $(subst $(newline),$(space),$(file <$(metadata_list)))
-# (TODO: b/272358583 find another way of always rebuilding this target)
-# Remove the sbom-metadata.csv whenever makefile is evaluated
-$(shell rm $(PRODUCT_OUT)/sbom-metadata.csv >/dev/null 2>&1)
-$(PRODUCT_OUT)/sbom-metadata.csv: $(installed_files) $(metadata_list) $(metadata_files)
+$(PRODUCT_OUT)/sbom-metadata.csv:
rm -f $@
echo installed_file,module_path,soong_module_type,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,build_output_path,static_libraries,whole_static_libraries,is_static_lib >> $@
$(eval _all_static_libs :=)
@@ -2173,7 +2199,6 @@ $(PRODUCT_OUT)/sbom-metadata.csv: $(installed_files) $(metadata_list) $(metadata
$(eval _module_path := $(strip $(sort $(ALL_MODULES.$(_module_name).PATH)))) \
$(eval _soong_module_type := $(strip $(sort $(ALL_MODULES.$(_module_name).SOONG_MODULE_TYPE)))) \
$(eval _is_prebuilt_make_module := $(ALL_MODULES.$(_module_name).IS_PREBUILT_MAKE_MODULE)) \
- $(eval _post_installed_dexpreopt_zip := $(DEXPREOPT.$(_module_name).POST_INSTALLED_DEXPREOPT_ZIP)) \
$(eval _product_copy_files := $(sort $(filter %:$(_path_on_device),$(product_copy_files_without_owner)))) \
$(eval _kernel_module_copy_files := $(sort $(filter %$(_path_on_device),$(KERNEL_MODULE_COPY_FILES)))) \
$(eval _is_build_prop := $(call is-build-prop,$f)) \
@@ -2186,15 +2211,14 @@ $(PRODUCT_OUT)/sbom-metadata.csv: $(installed_files) $(metadata_list) $(metadata
$(eval _is_fsverity_build_manifest_apk := $(if $(findstring $f,$(ALL_FSVERITY_BUILD_MANIFEST_APK)),Y)) \
$(eval _is_linker_config := $(if $(findstring $f,$(SYSTEM_LINKER_CONFIG) $(vendor_linker_config_file)),Y)) \
$(eval _is_partition_compat_symlink := $(if $(findstring $f,$(PARTITION_COMPAT_SYMLINKS)),Y)) \
- $(eval _is_platform_generated := $(_is_build_prop)$(_is_notice_file)$(_is_dexpreopt_image_profile)$(_is_product_system_other_avbkey)$(_is_event_log_tags_file)$(_is_system_other_odex_marker)$(_is_kernel_modules_blocklist)$(_is_fsverity_build_manifest_apk)$(_is_linker_config)$(_is_partition_compat_symlink)) \
+ $(eval _is_flags_file := $(if $(findstring $f, $(ALL_FLAGS_FILES)),Y)) \
+ $(eval _is_rootdir_symlink := $(if $(findstring $f, $(ALL_ROOTDIR_SYMLINKS)),Y)) \
+ $(eval _is_platform_generated := $(_is_build_prop)$(_is_notice_file)$(_is_dexpreopt_image_profile)$(_is_product_system_other_avbkey)$(_is_event_log_tags_file)$(_is_system_other_odex_marker)$(_is_kernel_modules_blocklist)$(_is_fsverity_build_manifest_apk)$(_is_linker_config)$(_is_partition_compat_symlink)$(_is_flags_file)$(_is_rootdir_symlink)) \
$(eval _static_libs := $(ALL_INSTALLED_FILES.$f.STATIC_LIBRARIES)) \
$(eval _whole_static_libs := $(ALL_INSTALLED_FILES.$f.WHOLE_STATIC_LIBRARIES)) \
$(foreach l,$(_static_libs),$(eval _all_static_libs += $l:$(strip $(sort $(ALL_MODULES.$l.PATH))):$(strip $(sort $(ALL_MODULES.$l.SOONG_MODULE_TYPE))):$(ALL_STATIC_LIBRARIES.$l.BUILT_FILE))) \
$(foreach l,$(_whole_static_libs),$(eval _all_static_libs += $l:$(strip $(sort $(ALL_MODULES.$l.PATH))):$(strip $(sort $(ALL_MODULES.$l.SOONG_MODULE_TYPE))):$(ALL_STATIC_LIBRARIES.$l.BUILT_FILE))) \
echo /$(_path_on_device),$(_module_path),$(_soong_module_type),$(_is_prebuilt_make_module),$(_product_copy_files),$(_kernel_module_copy_files),$(_is_platform_generated),$(_build_output_path),$(_static_libs),$(_whole_static_libs), >> $@; \
- $(if $(_post_installed_dexpreopt_zip), \
- for i in $$(zipinfo -1 $(_post_installed_dexpreopt_zip)); do echo /$$i$(comma)$(_module_path)$(comma)$(_soong_module_type)$(comma)$(_is_prebuilt_make_module)$(comma)$(_product_copy_files)$(comma)$(_kernel_module_copy_files)$(comma)$(_is_platform_generated)$(comma)$(PRODUCT_OUT)/$$i$(comma)$(_static_libs)$(comma)$(_whole_static_libs)$(comma) >> $@ ; done ; \
- ) \
)
$(foreach l,$(sort $(_all_static_libs)), \
$(eval _lib_stem := $(call word-colon,1,$l)) \
@@ -2207,11 +2231,17 @@ $(PRODUCT_OUT)/sbom-metadata.csv: $(installed_files) $(metadata_list) $(metadata
echo $(_lib_stem).a,$(_module_path),$(_soong_module_type),,,,,$(_built_file),$(_static_libs),$(_whole_static_libs),$(_is_static_lib) >> $@; \
)
+# (TODO: b/272358583 find another way of always rebuilding sbom.spdx)
+# Remove the always_dirty_file.txt whenever the makefile is evaluated
+$(shell rm -f $(PRODUCT_OUT)/always_dirty_file.txt)
+$(PRODUCT_OUT)/always_dirty_file.txt:
+ touch $@
+
.PHONY: sbom
ifeq ($(TARGET_BUILD_APPS),)
sbom: $(PRODUCT_OUT)/sbom.spdx.json
$(PRODUCT_OUT)/sbom.spdx.json: $(PRODUCT_OUT)/sbom.spdx
-$(PRODUCT_OUT)/sbom.spdx: $(PRODUCT_OUT)/sbom-metadata.csv $(GEN_SBOM)
+$(PRODUCT_OUT)/sbom.spdx: $(PRODUCT_OUT)/sbom-metadata.csv $(GEN_SBOM) $(installed_files) $(metadata_list) $(metadata_files) $(PRODUCT_OUT)/always_dirty_file.txt
rm -rf $@
$(GEN_SBOM) --output_file $@ --metadata $(PRODUCT_OUT)/sbom-metadata.csv --build_version $(BUILD_FINGERPRINT_FROM_FILE) --product_mfr "$(PRODUCT_MANUFACTURER)" --json
@@ -2230,7 +2260,7 @@ $(eval _soong_module_type := $(strip $(sort $(ALL_MODULES.$(_module_name).SOONG_
$(eval _dep_modules := $(filter %.$(_module_name),$(ALL_MODULES)) $(filter %.$(_module_name)$(TARGET_2ND_ARCH_MODULE_SUFFIX),$(ALL_MODULES)))
$(eval _is_apex := $(filter %.apex,$(3)))
-$(4): $(3) $(metadata_list) $(metadata_files)
+$(4):
rm -rf $$@
echo installed_file,module_path,soong_module_type,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,build_output_path,static_libraries,whole_static_libraries,is_static_lib >> $$@
echo /$(_path_on_device),$(_module_path),$(_soong_module_type),,,,,$(3),,, >> $$@
@@ -2239,7 +2269,7 @@ $(4): $(3) $(metadata_list) $(metadata_files)
echo $(patsubst $(PRODUCT_OUT)/apex/$(_module_name)/%,%,$(ALL_MODULES.$m.INSTALLED)),$(sort $(ALL_MODULES.$m.PATH)),$(sort $(ALL_MODULES.$m.SOONG_MODULE_TYPE)),,,,,$(strip $(ALL_MODULES.$m.BUILT)),,, >> $$@;))
$(2): $(1)
-$(1): $(4) $(GEN_SBOM)
+$(1): $(4) $(3) $(GEN_SBOM) $(installed_files) $(metadata_list) $(metadata_files)
rm -rf $$@
$(GEN_SBOM) --output_file $$@ --metadata $(4) --build_version $$(BUILD_FINGERPRINT_FROM_FILE) --product_mfr "$(PRODUCT_MANUFACTURER)" --json $(if $(filter %.apk,$(3)),--unbundled_apk,--unbundled_apex)
endef
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 7cfab5b789..a03a62b7fa 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -531,7 +531,7 @@ $(LOCAL_BUILT_MODULE) : $(JAR_ARGS) $(SOONG_ZIP) $(MERGE_ZIPS) $(ZIP2ZIP)
$(LOCAL_BUILT_MODULE): PRIVATE_RES_PACKAGE := $(my_res_package)
$(LOCAL_BUILT_MODULE) : $(my_res_package) $(AAPT2)
ifdef LOCAL_COMPRESSED_MODULE
-$(LOCAL_BUILT_MODULE) : $(MINIGZIP)
+$(LOCAL_BUILT_MODULE) : $(GZIP)
endif
ifeq (true, $(LOCAL_UNCOMPRESS_DEX))
$(LOCAL_BUILT_MODULE) : $(ZIP2ZIP)
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
new file mode 100644
index 0000000000..ca319ce1ec
--- /dev/null
+++ b/core/packaging/flags.mk
@@ -0,0 +1,139 @@
+# Copyright (C) 2023 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.
+
+#
+# This file is included by build/make/core/Makefile, and contains the logic for
+# the combined flags files.
+#
+
+# TODO: Should we do all of the images in $(IMAGES_TO_BUILD)?
+_FLAG_PARTITIONS := product system system_ext vendor
+
+
+# -----------------------------------------------------------------
+# Release Config Flags
+
+# Create a summary file of build flags for each partition
+# $(1): built build flags json file
+# $(2): installed build flags json file
+# $(3): flag names
+define generate-partition-build-flag-file
+$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
+$(eval $(strip $(1)): PRIVATE_FLAG_NAMES := $(strip $(3)))
+$(strip $(1)):
+ mkdir -p $$(dir $$(PRIVATE_OUT))
+ echo '{' > $$(PRIVATE_OUT)
+ echo '"flags": [' >> $$(PRIVATE_OUT)
+ $$(foreach flag, $$(PRIVATE_FLAG_NAMES), \
+ ( \
+ printf ' { "name": "%s", "value": "%s", ' \
+ '$$(flag)' \
+ '$$(_ALL_RELEASE_FLAGS.$$(flag).VALUE)' \
+ ; \
+ printf '"set": "%s", "default": "%s", "declared": "%s" }' \
+ '$$(_ALL_RELEASE_FLAGS.$$(flag).SET_IN)' \
+ '$$(_ALL_RELEASE_FLAGS.$$(flag).DEFAULT)' \
+ '$$(_ALL_RELEASE_FLAGS.$$(flag).DECLARED_IN)' \
+ ; \
+ printf '$$(if $$(filter $$(lastword $$(PRIVATE_FLAG_NAMES)),$$(flag)),,$$(comma))\n' ; \
+ ) >> $$(PRIVATE_OUT) ; \
+ )
+ echo "]" >> $$(PRIVATE_OUT)
+ echo "}" >> $$(PRIVATE_OUT)
+$(call copy-one-file, $(1), $(2))
+endef
+
+$(foreach partition, $(_FLAG_PARTITIONS), \
+ $(eval build_flag_summaries.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/build_flags.json) \
+ $(eval $(call generate-partition-build-flag-file, \
+ $(TARGET_OUT_FLAGS)/$(partition)/build_flags.json, \
+ $(build_flag_summaries.$(partition)), \
+ $(_ALL_RELEASE_FLAGS.PARTITIONS.$(partition)) \
+ ) \
+ ) \
+)
+
+
+# -----------------------------------------------------------------
+# Aconfig Flags
+
+# Create a summary file of build flags for each partition
+# $(1): built aconfig flags file (out)
+# $(2): installed aconfig flags file (out)
+# $(3): input aconfig files for the partition (in)
+# $(4): file format, passed to `aconfig dump` (in)
+# $(5): text placed in aconfig file when no flags present (out)
+define generate-partition-aconfig-flag-file
+$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
+$(eval $(strip $(1)): PRIVATE_IN := $(strip $(3)))
+$(strip $(1)): $(ACONFIG) $(strip $(3))
+ mkdir -p $$(dir $$(PRIVATE_OUT))
+ $$(if $$(PRIVATE_IN), \
+ $$(ACONFIG) dump --format $(4) --out $$(PRIVATE_OUT) \
+ $$(addprefix --cache ,$$(PRIVATE_IN)), \
+ echo $(5) > $$(PRIVATE_OUT) \
+ )
+$(call copy-one-file, $(1), $(2))
+endef
+
+
+$(foreach partition, $(_FLAG_PARTITIONS), \
+ $(eval aconfig_flag_summaries_textproto.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.textproto) \
+ $(eval aconfig_flag_summaries_protobuf.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.pb) \
+ $(eval $(call generate-partition-aconfig-flag-file, \
+ $(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.textproto, \
+ $(aconfig_flag_summaries_textproto.$(partition)), \
+ $(sort $(foreach m,$(call register-names-for-partition, $(partition)), \
+ $(ALL_MODULES.$(m).ACONFIG_FILES) \
+ )), \
+ textproto, \
+ "# No aconfig flags" \
+ )) \
+ $(eval $(call generate-partition-aconfig-flag-file, \
+ $(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.pb, \
+ $(aconfig_flag_summaries_protobuf.$(partition)), \
+ $(sort $(foreach m,$(call register-names-for-partition, $(partition)), \
+ $(ALL_MODULES.$(m).ACONFIG_FILES) \
+ )), \
+ protobuf, \
+ "" \
+ )) \
+)
+
+
+# -----------------------------------------------------------------
+# Install the ones we need for the configured product
+required_flags_files := \
+ $(sort $(foreach partition, $(filter $(IMAGES_TO_BUILD), $(_FLAG_PARTITIONS)), \
+ $(build_flag_summaries.$(partition)) \
+ $(aconfig_flag_summaries_textproto.$(partition)) \
+ $(aconfig_flag_summaries_protobuf.$(partition)) \
+ ))
+
+ALL_DEFAULT_INSTALLED_MODULES += $(required_flags_files)
+ALL_FLAGS_FILES := $(required_flags_files)
+
+# TODO: Remove
+.PHONY: flag-files
+flag-files: $(required_flags_files)
+
+
+# Clean up
+required_flags_files:=
+$(foreach partition, $(_FLAG_PARTITIONS), \
+ $(eval build_flag_summaries.$(partition):=) \
+ $(eval aconfig_flag_summaries_textproto.$(partition):=) \
+ $(eval aconfig_flag_summaries_protobuf.$(partition):=) \
+)
+
diff --git a/core/product.mk b/core/product.mk
index 8f4db38038..ca65948a03 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -33,6 +33,10 @@ _product_single_value_vars += PRODUCT_MODEL_FOR_ATTESTATION
# 4096, 16384 and 65536.
_product_single_value_vars += PRODUCT_MAX_PAGE_SIZE_SUPPORTED
+# Indicates that AOSP can use a kernel configured with 4k/16k/64k page sizes.
+# The possible values are true or false.
+_product_single_value_vars += PRODUCT_PAGE_SIZE_AGNOSTIC
+
# The resource configuration options to use for this product.
_product_list_vars += PRODUCT_LOCALES
_product_list_vars += PRODUCT_AAPT_CONFIG
@@ -43,6 +47,13 @@ _product_list_vars += PRODUCT_PACKAGES
_product_list_vars += PRODUCT_PACKAGES_DEBUG
_product_list_vars += PRODUCT_PACKAGES_DEBUG_ASAN
_product_list_vars += PRODUCT_PACKAGES_ARM64
+
+# packages that are added to PRODUCT_PACKAGES based on the PRODUCT_SHIPPING_API_LEVEL
+# These are only added if the shipping API level is that level or lower
+_product_list_vars += PRODUCT_PACKAGES_SHIPPING_API_LEVEL_29
+_product_list_vars += PRODUCT_PACKAGES_SHIPPING_API_LEVEL_33
+_product_list_vars += PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34
+
# Packages included only for eng/userdebug builds, when building with EMMA_INSTRUMENT=true
_product_list_vars += PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE
_product_list_vars += PRODUCT_PACKAGES_ENG
@@ -146,6 +157,9 @@ _product_list_vars += PRODUCT_BOOT_JARS
# PRODUCT_BOOT_JARS, so that device-specific jars go after common jars.
_product_list_vars += PRODUCT_BOOT_JARS_EXTRA
+# List of jars to be included in the ART boot image for testing.
+_product_list_vars += PRODUCT_TEST_ONLY_ART_BOOT_IMAGE_JARS
+
_product_single_value_vars += PRODUCT_SUPPORTS_VBOOT
_product_list_vars += PRODUCT_SYSTEM_SERVER_APPS
# List of system_server classpath jars on the platform.
@@ -247,6 +261,9 @@ _product_list_vars += PRODUCT_CFI_EXCLUDE_PATHS
# Whether any paths should have HWASan enabled for components
_product_list_vars += PRODUCT_HWASAN_INCLUDE_PATHS
+# Whether any paths are excluded from sanitization when SANITIZE_TARGET=hwaddress
+_product_list_vars += PRODUCT_HWASAN_EXCLUDE_PATHS
+
# Whether any paths should have Memtag_heap enabled for components
_product_list_vars += PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS
_product_list_vars += PRODUCT_MEMTAG_HEAP_ASYNC_DEFAULT_INCLUDE_PATHS
@@ -317,6 +334,10 @@ _product_list_vars += PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
_product_list_vars += PRODUCT_PACKAGE_NAME_OVERRIDES
_product_list_vars += PRODUCT_CERTIFICATE_OVERRIDES
+# Overrides the (apex, jar) pairs above when determining the on-device location. The format is:
+# <old_apex>:<old_jar>:<new_apex>:<new_jar>
+_product_list_vars += PRODUCT_CONFIGURED_JAR_LOCATION_OVERRIDES
+
# Controls for whether different partitions are built for the current product.
_product_single_value_vars += PRODUCT_BUILD_SYSTEM_IMAGE
_product_single_value_vars += PRODUCT_BUILD_SYSTEM_OTHER_IMAGE
@@ -419,8 +440,13 @@ _product_single_value_vars += PRODUCT_ENABLE_UFFD_GC
# specified we default to COW version 2 in update_engine for backwards compatibility
_product_single_value_vars += PRODUCT_VIRTUAL_AB_COW_VERSION
+# If set, determines whether the build system checks vendor seapp contexts violations.
+_product_single_value_vars += PRODUCT_CHECK_VENDOR_SEAPP_VIOLATIONS
+
_product_list_vars += PRODUCT_AFDO_PROFILES
+_product_single_value_vars += PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API
+
.KATI_READONLY := _product_single_value_vars _product_list_vars
_product_var_list :=$= $(_product_single_value_vars) $(_product_list_vars)
diff --git a/core/product_config.mk b/core/product_config.mk
index 3f9eb24ab2..b475d7570c 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -282,7 +282,11 @@ current_product_makefile :=
#############################################################################
# Check product include tag allowlist
-BLUEPRINT_INCLUDE_TAGS_ALLOWLIST := com.android.mainline_go com.android.mainline
+BLUEPRINT_INCLUDE_TAGS_ALLOWLIST := \
+ com.android.mainline_go \
+ com.android.mainline \
+ mainline_module_prebuilt_nightly \
+ mainline_module_prebuilt_monthly_release
.KATI_READONLY := BLUEPRINT_INCLUDE_TAGS_ALLOWLIST
$(foreach include_tag,$(PRODUCT_INCLUDE_TAGS), \
$(if $(filter $(include_tag),$(BLUEPRINT_INCLUDE_TAGS_ALLOWLIST)),,\
@@ -293,7 +297,8 @@ ifeq (, $(PRODUCT_INCLUDE_TAGS))
# we still analyse it.
# This means that in setups where we two have two prebuilts of module_sdk, we need a "default" to use in analysis
# This should be a no-op in aosp and internal since no Android.bp file contains blueprint_package_includes
-PRODUCT_INCLUDE_TAGS += com.android.mainline # Use the big android one by default
+# Use the big android one and main-based prebuilts by default
+PRODUCT_INCLUDE_TAGS += com.android.mainline mainline_module_prebuilt_nightly
endif
#############################################################################
@@ -500,6 +505,9 @@ ifdef PRODUCT_SHIPPING_API_LEVEL
ifneq (,$(call math_gt_or_eq,33,$(PRODUCT_SHIPPING_API_LEVEL)))
PRODUCT_PACKAGES += $(PRODUCT_PACKAGES_SHIPPING_API_LEVEL_33)
endif
+ ifneq (,$(call math_gt_or_eq,34,$(PRODUCT_SHIPPING_API_LEVEL)))
+ PRODUCT_PACKAGES += $(PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34)
+ endif
endif
# If build command defines OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS,
@@ -543,35 +551,43 @@ endif
$(KATI_obsolete_var OVERRIDE_PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE,Use PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE instead)
-# If build command defines PRODUCT_USE_PRODUCT_VNDK_OVERRIDE as `false`,
-# PRODUCT_PRODUCT_VNDK_VERSION will not be defined automatically.
-# PRODUCT_USE_PRODUCT_VNDK_OVERRIDE can be used for testing only.
-PRODUCT_USE_PRODUCT_VNDK := false
-ifneq ($(PRODUCT_USE_PRODUCT_VNDK_OVERRIDE),)
- PRODUCT_USE_PRODUCT_VNDK := $(PRODUCT_USE_PRODUCT_VNDK_OVERRIDE)
-else ifeq ($(PRODUCT_SHIPPING_API_LEVEL),)
- # No shipping level defined. Enforce the product interface by default.
- PRODUCT_USE_PRODUCT_VNDK := true
-else ifeq ($(call math_gt,$(PRODUCT_SHIPPING_API_LEVEL),29),true)
- # Enforce product interface for VNDK if PRODUCT_SHIPPING_API_LEVEL is greater
- # than 29.
- PRODUCT_USE_PRODUCT_VNDK := true
-endif
-
-ifeq ($(PRODUCT_USE_PRODUCT_VNDK),true)
- ifndef PRODUCT_PRODUCT_VNDK_VERSION
- PRODUCT_PRODUCT_VNDK_VERSION := current
- endif
+# From Android V, Define PRODUCT_PRODUCT_VNDK_VERSION as current by default.
+# This is required to make all devices have product variants.
+ifndef PRODUCT_PRODUCT_VNDK_VERSION
+ PRODUCT_PRODUCT_VNDK_VERSION := current
endif
-$(KATI_obsolete_var PRODUCT_USE_PRODUCT_VNDK,Use PRODUCT_PRODUCT_VNDK_VERSION instead)
-$(KATI_obsolete_var PRODUCT_USE_PRODUCT_VNDK_OVERRIDE,Use PRODUCT_PRODUCT_VNDK_VERSION instead)
-
ifdef PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS
$(error PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS is deprecated, consider using RRO for \
$(PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS))
endif
+# Get the board API level.
+board_api_level := $(PLATFORM_SDK_VERSION)
+ifdef BOARD_API_LEVEL
+ board_api_level := $(BOARD_API_LEVEL)
+else ifdef BOARD_SHIPPING_API_LEVEL
+ # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
+ board_api_level := $(BOARD_SHIPPING_API_LEVEL)
+endif
+
+# Calculate the VSR vendor API level.
+VSR_VENDOR_API_LEVEL := $(board_api_level)
+
+ifdef PRODUCT_SHIPPING_API_LEVEL
+ VSR_VENDOR_API_LEVEL := $(call math_min,$(PRODUCT_SHIPPING_API_LEVEL),$(board_api_level))
+endif
+.KATI_READONLY := VSR_VENDOR_API_LEVEL
+
+# Boolean variable determining if vendor seapp contexts is enforced
+CHECK_VENDOR_SEAPP_VIOLATIONS := false
+ifneq ($(call math_gt,$(VSR_VENDOR_API_LEVEL),34),)
+ CHECK_VENDOR_SEAPP_VIOLATIONS := true
+else ifneq ($(PRODUCT_CHECK_VENDOR_SEAPP_VIOLATIONS),)
+ CHECK_VENDOR_SEAPP_VIOLATIONS := $(PRODUCT_CHECK_VENDOR_SEAPP_VIOLATIONS)
+endif
+.KATI_READONLY := CHECK_VENDOR_SEAPP_VIOLATIONS
+
define product-overrides-config
$$(foreach rule,$$(PRODUCT_$(1)_OVERRIDES),\
$$(if $$(filter 2,$$(words $$(subst :,$$(space),$$(rule)))),,\
diff --git a/core/proguard.flags b/core/proguard.flags
index d790061524..6dbee84c1d 100644
--- a/core/proguard.flags
+++ b/core/proguard.flags
@@ -51,4 +51,13 @@
@**android**.annotation*.Keep <init>(...);
}
+# Keep Dalvik optimization annotations. These annotations are special in that
+# 1) we want them preserved for visibility with ART, but 2) they don't have
+# RUNTIME retention. These minimal keep rules ensure they're not stripped by R8.
+# TODO(b/215417388): Export this rule from the owning library, core-libart,
+# via export_proguard_flags_files.
+-keepclassmembers,allowshrinking,allowoptimization,allowobfuscation,allowaccessmodification class * {
+ @dalvik.annotation.optimization.** *;
+}
+
-include proguard_basic_keeps.flags
diff --git a/core/proguard_basic_keeps.flags b/core/proguard_basic_keeps.flags
index b59527a8cd..f6b34b8217 100644
--- a/core/proguard_basic_keeps.flags
+++ b/core/proguard_basic_keeps.flags
@@ -10,6 +10,12 @@
# and RuntimeVisibleTypeAnnotations, as well as associated defaults.
-keepattributes RuntimeVisible*Annotation*,AnnotationDefault
+# With R8 full mode, certain attributes are only kept when matched with an
+# explicit keep rule for that target, even with a global -keepattributes rule.
+# As such, we can add the global keep rule here with minimal cost while
+# simplifying incremental development.
+-keepattributes Exceptions
+
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
diff --git a/core/release_config.bzl b/core/release_config.bzl
index 805106f4e7..a2f59e63a8 100644
--- a/core/release_config.bzl
+++ b/core/release_config.bzl
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+load("//build/bazel/utils:schema_validation.bzl", "validate")
+
# Partitions that get build system flag summaries
_flag_partitions = [
"product",
@@ -28,6 +30,48 @@ VENDOR = ["vendor"]
_valid_types = ["NoneType", "bool", "list", "string", "int"]
+_all_flags_schema = {
+ "type": "list",
+ "of": {
+ "type": "dict",
+ "required_keys": {
+ "name": {"type": "string"},
+ "partitions": {
+ "type": "list",
+ "of": {
+ "type": "string",
+ "choices": _flag_partitions + ["all"],
+ },
+ "unique": True,
+ },
+ "default": {
+ "or": [
+ {"type": t}
+ for t in _valid_types
+ ],
+ },
+ "declared_in": {"type": "string"},
+ },
+ },
+}
+
+_all_values_schema = {
+ "type": "list",
+ "of": {
+ "type": "dict",
+ "required_keys": {
+ "name": {"type": "string"},
+ "value": {
+ "or": [
+ {"type": t}
+ for t in _valid_types
+ ],
+ },
+ "set_in": {"type": "string"},
+ },
+ },
+}
+
def flag(name, partitions, default):
"Declare a flag."
if not partitions:
@@ -69,6 +113,8 @@ def _format_value(val):
def release_config(all_flags, all_values):
"Return the make variables that should be set for this release config."
+ validate(all_flags, _all_flags_schema)
+ validate(all_values, _all_values_schema)
# Validate flags
flag_names = []
@@ -82,6 +128,8 @@ def release_config(all_flags, all_values):
for flag in all_flags:
for partition in flag["partitions"]:
if partition == "all":
+ if len(flag["partitions"]) > 1:
+ fail("\"all\" can't be combined with other partitions: " + str(flag["partitions"]))
for partition in _flag_partitions:
partitions.setdefault(partition, []).append(flag["name"])
else:
@@ -105,8 +153,6 @@ def release_config(all_flags, all_values):
if flag["name"] in values:
val = values[flag["name"]]["value"]
set_in = values[flag["name"]]["set_in"]
- if type(val) not in _valid_types:
- fail("Invalid type of value for flag \"" + flag["name"] + "\" (" + type(val) + ")")
else:
val = flag["default"]
set_in = flag["declared_in"]
diff --git a/core/rust_device_benchmark_config_template.xml b/core/rust_device_benchmark_config_template.xml
index 2055df2096..541630cc68 100644
--- a/core/rust_device_benchmark_config_template.xml
+++ b/core/rust_device_benchmark_config_template.xml
@@ -16,7 +16,7 @@
<!-- This test config file is auto-generated. -->
<configuration description="Config to run {MODULE} rust benchmark tests.">
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="false" />
+ <option name="cleanup" value="true" />
<option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
</target_preparer>
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index ccc54494f7..3aa244c77f 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -73,12 +73,14 @@ endif
# We skip it for unbundled app builds where we cannot build veridex.
module_run_appcompat :=
ifeq (true,$(non_system_module))
-ifeq (,$(TARGET_BUILD_APPS)) # ! unbundled app build
+ifeq (,$(TARGET_BUILD_APPS)) # not unbundled app build
+ifeq (,$(filter sdk,$(MAKECMDGOALS))) # not sdk build (which is another form of unbundled build)
ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true)
module_run_appcompat := true
endif
endif
endif
+endif
ifeq ($(module_run_appcompat),true)
$(LOCAL_BUILT_MODULE): $(appcompat-files)
@@ -100,31 +102,24 @@ ifdef LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR
endif
ifdef LOCAL_SOONG_PROGUARD_DICT
- my_proguard_dictionary_directory := $(local-proguard-dictionary-directory)
- my_proguard_dictionary_mapping_directory := $(local-proguard-dictionary-mapping-directory)
- $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_DICT),\
- $(intermediates.COMMON)/proguard_dictionary))
$(eval $(call copy-r8-dictionary-file-with-mapping,\
$(LOCAL_SOONG_PROGUARD_DICT),\
- $(my_proguard_dictionary_directory)/proguard_dictionary,\
- $(my_proguard_dictionary_mapping_directory)/proguard_dictionary.textproto))
- $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),\
- $(my_proguard_dictionary_directory)/classes.jar))
- $(call add-dependency,$(LOCAL_BUILT_MODULE),\
- $(intermediates.COMMON)/proguard_dictionary)
- $(call add-dependency,$(LOCAL_BUILT_MODULE),\
- $(my_proguard_dictionary_directory)/proguard_dictionary)
- $(call add-dependency,$(LOCAL_BUILT_MODULE),\
- $(my_proguard_dictionary_mapping_directory)/proguard_dictionary.textproto)
- $(call add-dependency,$(LOCAL_BUILT_MODULE),\
- $(my_proguard_dictionary_directory)/classes.jar)
+ $(intermediates.COMMON)/proguard_dictionary,\
+ $(intermediates.COMMON)/proguard_dictionary.textproto))
+
+ ALL_MODULES.$(my_register_name).PROGUARD_DICTIONARY_FILES := \
+ $(intermediates.COMMON)/proguard_dictionary \
+ $(LOCAL_SOONG_CLASSES_JAR)
+ ALL_MODULES.$(my_register_name).PROGUARD_DICTIONARY_SOONG_ZIP_ARGUMENTS := \
+ -e out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/proguard_dictionary \
+ -f $(intermediates.COMMON)/proguard_dictionary \
+ -e out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/classes.jar \
+ -f $(LOCAL_SOONG_CLASSES_JAR)
+ ALL_MODULES.$(my_register_name).PROGUARD_DICTIONARY_MAPPING := $(intermediates.COMMON)/proguard_dictionary.textproto
endif
ifdef LOCAL_SOONG_PROGUARD_USAGE_ZIP
- $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_USAGE_ZIP),\
- $(call local-packaging-dir,proguard_usage)/proguard_usage.zip))
- $(call add-dependency,$(LOCAL_BUILT_MODULE),\
- $(call local-packaging-dir,proguard_usage)/proguard_usage.zip)
+ ALL_MODULES.$(my_register_name).PROGUARD_USAGE_ZIP := $(LOCAL_SOONG_PROGUARD_USAGE_ZIP)
endif
ifdef LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 0d5799c6a9..90b47a0e6b 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -41,6 +41,9 @@ $(call add_json_str, Platform_base_os, $(PLATFORM_BASE_OS))
$(call add_json_str, Platform_version_last_stable, $(PLATFORM_VERSION_LAST_STABLE))
$(call add_json_str, Platform_version_known_codenames, $(PLATFORM_VERSION_KNOWN_CODENAMES))
+$(call add_json_bool, Release_aidl_use_unfrozen, $(RELEASE_AIDL_USE_UNFROZEN))
+$(call add_json_bool, Release_expose_flagged_api, $(RELEASE_EXPOSE_FLAGGED_API))
+
$(call add_json_str, Platform_min_supported_target_sdk_version, $(PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION))
$(call add_json_bool, Allow_missing_dependencies, $(filter true,$(ALLOW_MISSING_DEPENDENCIES)))
@@ -114,6 +117,7 @@ $(call add_json_list, CFIExcludePaths, $(CFI_EXCLUDE_PATHS) $(
$(call add_json_list, CFIIncludePaths, $(CFI_INCLUDE_PATHS) $(PRODUCT_CFI_INCLUDE_PATHS))
$(call add_json_list, IntegerOverflowExcludePaths, $(INTEGER_OVERFLOW_EXCLUDE_PATHS) $(PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS))
$(call add_json_list, HWASanIncludePaths, $(HWASAN_INCLUDE_PATHS) $(PRODUCT_HWASAN_INCLUDE_PATHS))
+$(call add_json_list, HWASanExcludePaths, $(HWASAN_EXCLUDE_PATHS) $(PRODUCT_HWASAN_EXCLUDE_PATHS))
$(call add_json_list, MemtagHeapExcludePaths, $(MEMTAG_HEAP_EXCLUDE_PATHS) $(PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS))
$(call add_json_list, MemtagHeapAsyncIncludePaths, $(MEMTAG_HEAP_ASYNC_INCLUDE_PATHS) $(PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS) $(if $(filter true,$(PRODUCT_MEMTAG_HEAP_SKIP_DEFAULT_PATHS)),,$(PRODUCT_MEMTAG_HEAP_ASYNC_DEFAULT_INCLUDE_PATHS)))
@@ -140,7 +144,6 @@ $(call add_json_str, BtConfigIncludeDir, $(BOARD_BLUETOOTH_BDROI
$(call add_json_list, DeviceKernelHeaders, $(TARGET_DEVICE_KERNEL_HEADERS) $(TARGET_BOARD_KERNEL_HEADERS) $(TARGET_PRODUCT_KERNEL_HEADERS))
$(call add_json_str, DeviceVndkVersion, $(BOARD_VNDK_VERSION))
$(call add_json_str, Platform_vndk_version, $(PLATFORM_VNDK_VERSION))
-$(call add_json_str, ProductVndkVersion, $(PRODUCT_PRODUCT_VNDK_VERSION))
$(call add_json_list, ExtraVndkVersions, $(PRODUCT_EXTRA_VNDK_VERSIONS))
$(call add_json_list, DeviceSystemSdkVersions, $(BOARD_SYSTEMSDK_VERSIONS))
$(call add_json_str, RecoverySnapshotVersion, $(RECOVERY_SNAPSHOT_VERSION))
@@ -150,6 +153,7 @@ $(call add_json_bool, Malloc_zero_contents, $(call invert_bool,$(fi
$(call add_json_bool, Malloc_pattern_fill_contents, $(MALLOC_PATTERN_FILL_CONTENTS))
$(call add_json_str, Override_rs_driver, $(OVERRIDE_RS_DRIVER))
$(call add_json_str, DeviceMaxPageSizeSupported, $(TARGET_MAX_PAGE_SIZE_SUPPORTED))
+$(call add_json_bool, DevicePageSizeAgnostic, $(filter true,$(TARGET_PAGE_SIZE_AGNOSTIC)))
$(call add_json_bool, UncompressPrivAppDex, $(call invert_bool,$(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS))))
$(call add_json_list, ModulesLoadedByPrivilegedModules, $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
@@ -204,17 +208,8 @@ $(call add_json_list, NamespacesToExport, $(PRODUCT_SOONG_NAMESPA
$(call add_json_list, PgoAdditionalProfileDirs, $(PGO_ADDITIONAL_PROFILE_DIRS))
-$(call add_json_list, BoardPlatVendorPolicy, $(BOARD_PLAT_VENDOR_POLICY))
-$(call add_json_list, BoardReqdMaskPolicy, $(BOARD_REQD_MASK_POLICY))
-$(call add_json_list, BoardSystemExtPublicPrebuiltDirs, $(BOARD_SYSTEM_EXT_PUBLIC_PREBUILT_DIRS))
-$(call add_json_list, BoardSystemExtPrivatePrebuiltDirs, $(BOARD_SYSTEM_EXT_PRIVATE_PREBUILT_DIRS))
-$(call add_json_list, BoardProductPublicPrebuiltDirs, $(BOARD_PRODUCT_PUBLIC_PREBUILT_DIRS))
-$(call add_json_list, BoardProductPrivatePrebuiltDirs, $(BOARD_PRODUCT_PRIVATE_PREBUILT_DIRS))
$(call add_json_list, BoardVendorSepolicyDirs, $(BOARD_VENDOR_SEPOLICY_DIRS) $(BOARD_SEPOLICY_DIRS))
$(call add_json_list, BoardOdmSepolicyDirs, $(BOARD_ODM_SEPOLICY_DIRS))
-$(call add_json_list, BoardVendorDlkmSepolicyDirs, $(BOARD_VENDOR_DLKM_SEPOLICY_DIRS))
-$(call add_json_list, BoardOdmDlkmSepolicyDirs, $(BOARD_ODM_DLKM_SEPOLICY_DIRS))
-$(call add_json_list, BoardSystemDlkmSepolicyDirs, $(BOARD_SYSTEM_DLKM_SEPOLICY_DIRS))
$(call add_json_list, SystemExtPublicSepolicyDirs, $(SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS))
$(call add_json_list, SystemExtPrivateSepolicyDirs, $(SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS))
$(call add_json_list, BoardSepolicyM4Defs, $(BOARD_SEPOLICY_M4DEFS))
@@ -235,6 +230,7 @@ $(call add_json_bool, WithDexpreopt, $(filter true,$(WITH_DE
$(call add_json_list, ManifestPackageNameOverrides, $(PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES))
$(call add_json_list, PackageNameOverrides, $(PRODUCT_PACKAGE_NAME_OVERRIDES))
$(call add_json_list, CertificateOverrides, $(PRODUCT_CERTIFICATE_OVERRIDES))
+$(call add_json_list, ConfiguredJarLocationOverrides, $(PRODUCT_CONFIGURED_JAR_LOCATION_OVERRIDES))
$(call add_json_str, ApexGlobalMinSdkVersionOverride, $(APEX_GLOBAL_MIN_SDK_VERSION_OVERRIDE))
@@ -280,16 +276,17 @@ $(call add_json_str, PrebuiltHiddenApiDir, $(BOARD_PREBUILT_HIDDENAPI_DIR))
$(call add_json_str, ShippingApiLevel, $(PRODUCT_SHIPPING_API_LEVEL))
-$(call add_json_list, BuildBrokenPluginValidation, $(BUILD_BROKEN_PLUGIN_VALIDATION))
-$(call add_json_bool, BuildBrokenClangProperty, $(filter true,$(BUILD_BROKEN_CLANG_PROPERTY)))
-$(call add_json_bool, BuildBrokenClangAsFlags, $(filter true,$(BUILD_BROKEN_CLANG_ASFLAGS)))
-$(call add_json_bool, BuildBrokenClangCFlags, $(filter true,$(BUILD_BROKEN_CLANG_CFLAGS)))
-$(call add_json_bool, GenruleSandboxing, $(filter true,$(GENRULE_SANDBOXING)))
-$(call add_json_bool, BuildBrokenEnforceSyspropOwner, $(filter true,$(BUILD_BROKEN_ENFORCE_SYSPROP_OWNER)))
-$(call add_json_bool, BuildBrokenTrebleSyspropNeverallow, $(filter true,$(BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW)))
-$(call add_json_bool, BuildBrokenUsesSoongPython2Modules, $(filter true,$(BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES)))
-$(call add_json_bool, BuildBrokenVendorPropertyNamespace, $(filter true,$(BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE)))
-$(call add_json_list, BuildBrokenInputDirModules, $(BUILD_BROKEN_INPUT_DIR_MODULES))
+$(call add_json_list, BuildBrokenPluginValidation, $(BUILD_BROKEN_PLUGIN_VALIDATION))
+$(call add_json_bool, BuildBrokenClangProperty, $(filter true,$(BUILD_BROKEN_CLANG_PROPERTY)))
+$(call add_json_bool, BuildBrokenClangAsFlags, $(filter true,$(BUILD_BROKEN_CLANG_ASFLAGS)))
+$(call add_json_bool, BuildBrokenClangCFlags, $(filter true,$(BUILD_BROKEN_CLANG_CFLAGS)))
+$(call add_json_bool, GenruleSandboxing, $(filter true,$(GENRULE_SANDBOXING)))
+$(call add_json_bool, BuildBrokenEnforceSyspropOwner, $(filter true,$(BUILD_BROKEN_ENFORCE_SYSPROP_OWNER)))
+$(call add_json_bool, BuildBrokenTrebleSyspropNeverallow, $(filter true,$(BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW)))
+$(call add_json_bool, BuildBrokenUsesSoongPython2Modules, $(filter true,$(BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES)))
+$(call add_json_bool, BuildBrokenVendorPropertyNamespace, $(filter true,$(BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE)))
+$(call add_json_bool, BuildBrokenIncorrectPartitionImages, $(filter true,$(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES)))
+$(call add_json_list, BuildBrokenInputDirModules, $(BUILD_BROKEN_INPUT_DIR_MODULES))
$(call add_json_list, BuildWarningBadOptionalUsesLibsAllowlist, $(BUILD_WARNING_BAD_OPTIONAL_USES_LIBS_ALLOWLIST))
@@ -316,7 +313,74 @@ $(call add_json_str, ProductBrand, $(PRODUCT_BRAND))
$(call add_json_list, BuildVersionTags, $(BUILD_VERSION_TAGS))
$(call add_json_str, ReleaseVersion, $(_RELEASE_VERSION))
-$(call add_json_list, ReleaseAconfigValueSets, $(RELEASE_ACONFIG_VALUE_SETS))
+$(call add_json_str, ReleaseAconfigValueSets, $(RELEASE_ACONFIG_VALUE_SETS))
+$(call add_json_str, ReleaseAconfigFlagDefaultPermission, $(RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION))
+
+$(call add_json_bool, KeepVndk, $(filter true,$(KEEP_VNDK)))
+
+$(call add_json_bool, CheckVendorSeappViolations, $(filter true,$(CHECK_VENDOR_SEAPP_VIOLATIONS)))
+
+$(call add_json_map, PartitionVarsForBazelMigrationOnlyDoNotUse)
+ $(call add_json_str, ProductDirectory, $(dir $(INTERNAL_PRODUCT)))
+
+ $(call add_json_map,PartitionQualifiedVariables)
+ $(foreach image_type,SYSTEM VENDOR CACHE USERDATA PRODUCT SYSTEM_EXT OEM ODM VENDOR_DLKM ODM_DLKM SYSTEM_DLKM, \
+ $(call add_json_map,$(call to-lower,$(image_type))) \
+ $(call add_json_bool, BuildingImage, $(filter true,$(BUILDING_$(image_type)_IMAGE))) \
+ $(call add_json_str, BoardErofsCompressor, $(BOARD_$(image_type)IMAGE_EROFS_COMPRESSOR)) \
+ $(call add_json_str, BoardErofsCompressHints, $(BOARD_$(image_type)IMAGE_EROFS_COMPRESS_HINTS)) \
+ $(call add_json_str, BoardErofsPclusterSize, $(BOARD_$(image_type)IMAGE_EROFS_PCLUSTER_SIZE)) \
+ $(call add_json_str, BoardExtfsInodeCount, $(BOARD_$(image_type)IMAGE_EXTFS_INODE_COUNT)) \
+ $(call add_json_str, BoardExtfsRsvPct, $(BOARD_$(image_type)IMAGE_EXTFS_RSV_PCT)) \
+ $(call add_json_str, BoardF2fsSloadCompressFlags, $(BOARD_$(image_type)IMAGE_F2FS_SLOAD_COMPRESS_FLAGS)) \
+ $(call add_json_str, BoardFileSystemCompress, $(BOARD_$(image_type)IMAGE_FILE_SYSTEM_COMPRESS)) \
+ $(call add_json_str, BoardFileSystemType, $(BOARD_$(image_type)IMAGE_FILE_SYSTEM_TYPE)) \
+ $(call add_json_str, BoardJournalSize, $(BOARD_$(image_type)IMAGE_JOURNAL_SIZE)) \
+ $(call add_json_str, BoardPartitionReservedSize, $(BOARD_$(image_type)IMAGE_PARTITION_RESERVED_SIZE)) \
+ $(call add_json_str, BoardPartitionSize, $(BOARD_$(image_type)IMAGE_PARTITION_SIZE)) \
+ $(call add_json_str, BoardSquashfsBlockSize, $(BOARD_$(image_type)IMAGE_SQUASHFS_BLOCK_SIZE)) \
+ $(call add_json_str, BoardSquashfsCompressor, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR)) \
+ $(call add_json_str, BoardSquashfsCompressorOpt, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR_OPT)) \
+ $(call add_json_str, BoardSquashfsDisable4kAlign, $(BOARD_$(image_type)IMAGE_SQUASHFS_DISABLE_4K_ALIGN)) \
+ $(call add_json_str, ProductBaseFsPath, $(PRODUCT_$(image_type)_BASE_FS_PATH)) \
+ $(call add_json_str, ProductHeadroom, $(PRODUCT_$(image_type)_HEADROOM)) \
+ $(call add_json_str, ProductVerityPartition, $(PRODUCT_$(image_type)_VERITY_PARTITION)) \
+ $(call add_json_str, BoardAvbAddHashtreeFooterArgs, $(BOARD_AVB_$(image_type)_ADD_HASHTREE_FOOTER_ARGS)) \
+ $(call add_json_str, BoardAvbKeyPath, $(BOARD_AVB_$(image_type)_KEY_PATH)) \
+ $(call add_json_str, BoardAvbAlgorithm, $(BOARD_AVB_$(image_type)_ALGORITHM)) \
+ $(call add_json_str, BoardAvbRollbackIndex, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX)) \
+ $(call add_json_str, BoardAvbRollbackIndexLocation, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX_LOCATION)) \
+ $(call end_json_map) \
+ )
+ $(call end_json_map)
+
+ $(call add_json_bool, TargetUserimagesUseExt2, $(filter true,$(TARGET_USERIMAGES_USE_EXT2)))
+ $(call add_json_bool, TargetUserimagesUseExt3, $(filter true,$(TARGET_USERIMAGES_USE_EXT3)))
+ $(call add_json_bool, TargetUserimagesUseExt4, $(filter true,$(TARGET_USERIMAGES_USE_EXT4)))
+
+ $(call add_json_bool, TargetUserimagesSparseExtDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED)))
+ $(call add_json_bool, TargetUserimagesSparseErofsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_EROFS_DISABLED)))
+ $(call add_json_bool, TargetUserimagesSparseSquashfsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_SQUASHFS_DISABLED)))
+ $(call add_json_bool, TargetUserimagesSparseF2fsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_F2FS_DISABLED)))
+
+ $(call add_json_str, BoardErofsCompressor, $(BOARD_EROFS_COMPRESSOR))
+ $(call add_json_str, BoardErofsCompressorHints, $(BOARD_EROFS_COMPRESS_HINTS))
+ $(call add_json_str, BoardErofsPclusterSize, $(BOARD_EROFS_PCLUSTER_SIZE))
+ $(call add_json_str, BoardErofsShareDupBlocks, $(BOARD_EROFS_SHARE_DUP_BLOCKS))
+ $(call add_json_str, BoardErofsUseLegacyCompression, $(BOARD_EROFS_USE_LEGACY_COMPRESSION))
+ $(call add_json_str, BoardExt4ShareDupBlocks, $(BOARD_EXT4_SHARE_DUP_BLOCKS))
+ $(call add_json_str, BoardFlashLogicalBlockSize, $(BOARD_FLASH_LOGICAL_BLOCK_SIZE))
+ $(call add_json_str, BoardFlashEraseBlockSize, $(BOARD_FLASH_ERASE_BLOCK_SIZE))
+
+ $(call add_json_bool, BoardUsesRecoveryAsBoot, $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
+ $(call add_json_bool, BoardBuildGkiBootImageWithoutRamdisk, $(filter true,$(BOARD_BUILD_GKI_BOOT_IMAGE_WITHOUT_RAMDISK)))
+ $(call add_json_bool, ProductUseDynamicPartitionSize, $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)))
+ $(call add_json_bool, CopyImagesForTargetFilesZip, $(filter true,$(COPY_IMAGES_FOR_TARGET_FILES_ZIP)))
+
+ $(call add_json_bool, BoardAvbEnable, $(filter true,$(BOARD_AVB_ENABLE)))
+$(call end_json_map)
+
+$(call add_json_bool, NextReleaseHideFlaggedApi, $(filter true,$(PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API)))
$(call json_end)
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index a8f475fd9a..9744abf3b8 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -62,31 +62,24 @@ ifdef LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR
endif
ifdef LOCAL_SOONG_PROGUARD_DICT
- my_proguard_dictionary_directory := $(local-proguard-dictionary-directory)
- my_proguard_dictionary_mapping_directory := $(local-proguard-dictionary-mapping-directory)
- $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_DICT),\
- $(intermediates.COMMON)/proguard_dictionary))
$(eval $(call copy-r8-dictionary-file-with-mapping,\
$(LOCAL_SOONG_PROGUARD_DICT),\
- $(my_proguard_dictionary_directory)/proguard_dictionary,\
- $(my_proguard_dictionary_mapping_directory)/proguard_dictionary.textproto))
- $(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),\
- $(my_proguard_dictionary_directory)/classes.jar))
- $(call add-dependency,$(common_javalib.jar),\
- $(intermediates.COMMON)/proguard_dictionary)
- $(call add-dependency,$(common_javalib.jar),\
- $(my_proguard_dictionary_directory)/proguard_dictionary)
- $(call add-dependency,$(common_javalib.jar),\
- $(my_proguard_dictionary_mapping_directory)/proguard_dictionary.textproto)
- $(call add-dependency,$(common_javalib.jar),\
- $(my_proguard_dictionary_directory)/classes.jar)
+ $(intermediates.COMMON)/proguard_dictionary,\
+ $(intermediates.COMMON)/proguard_dictionary.textproto))
+
+ ALL_MODULES.$(my_register_name).PROGUARD_DICTIONARY_FILES := \
+ $(intermediates.COMMON)/proguard_dictionary \
+ $(LOCAL_SOONG_CLASSES_JAR)
+ ALL_MODULES.$(my_register_name).PROGUARD_DICTIONARY_SOONG_ZIP_ARGUMENTS := \
+ -e out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/proguard_dictionary \
+ -f $(intermediates.COMMON)/proguard_dictionary \
+ -e out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/classes.jar \
+ -f $(LOCAL_SOONG_CLASSES_JAR)
+ ALL_MODULES.$(my_register_name).PROGUARD_DICTIONARY_MAPPING := $(intermediates.COMMON)/proguard_dictionary.textproto
endif
ifdef LOCAL_SOONG_PROGUARD_USAGE_ZIP
- $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_USAGE_ZIP),\
- $(call local-packaging-dir,proguard_usage)/proguard_usage.zip))
- $(call add-dependency,$(common_javalib.jar),\
- $(call local-packaging-dir,proguard_usage)/proguard_usage.zip)
+ ALL_MODULES.$(my_register_name).PROGUARD_USAGE_ZIP := $(LOCAL_SOONG_PROGUARD_USAGE_ZIP)
endif
@@ -99,6 +92,17 @@ ifdef LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
$(call add-dependency,$(LOCAL_BUILT_MODULE),$(my_res_package))
+ my_transitive_res_packages := $(intermediates.COMMON)/transitive-res-packages
+ $(my_transitive_res_packages): PRIVATE_TRANSITIVE_RES_PACKAGES := $(filter-out $(LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE),$(LOCAL_SOONG_TRANSITIVE_RES_PACKAGES))
+ $(my_transitive_res_packages):
+ @echo Write transitive resource package list $@
+ rm -f $@
+ touch $@
+ $(foreach f,$(PRIVATE_TRANSITIVE_RES_PACKAGES),\
+ echo "$f" >> $@; )
+
+ $(call add-dependency,$(my_res_package),$(my_transitive_res_packages))
+
my_proguard_flags := $(intermediates.COMMON)/export_proguard_flags
$(my_proguard_flags): $(LOCAL_SOONG_EXPORT_PROGUARD_FLAGS)
@echo "Export proguard flags: $@"
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index 4053985a3a..4a72a1fc31 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -127,6 +127,12 @@ framework_res_package_export := \
endif
endif
+# transitive-res-packages is only populated for Soong modules for now, but needs
+# to exist so that other Make modules can depend on it. Create an empty file.
+my_transitive_res_packages := $(intermediates.COMMON)/transitive-res-packages
+$(my_transitive_res_packages):
+ touch $@
+
import_proguard_flag_files := $(strip $(foreach l,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/export_proguard_flags))
$(intermediates.COMMON)/export_proguard_flags: $(import_proguard_flag_files) $(addprefix $(LOCAL_PATH)/,$(LOCAL_EXPORT_PROGUARD_FLAG_FILES))
diff --git a/core/sysprop.mk b/core/sysprop.mk
index a2296a8925..a37fd050a9 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -47,9 +47,21 @@ define generate-common-build-props
echo "ro.product.$(1).model=$(PRODUCT_MODEL)" >> $(2);\
echo "ro.product.$(1).name=$(TARGET_PRODUCT)" >> $(2);\
# Attestation specific properties for AOSP/GSI build running on device.
- echo "ro.product.model_for_attestation=$(PRODUCT_MODEL_FOR_ATTESTATION)" >> $(2);\
- echo "ro.product.brand_for_attestation=$(PRODUCT_BRAND_FOR_ATTESTATION)" >> $(2);\
- echo "ro.product.name_for_attestation=$(PRODUCT_NAME_FOR_ATTESTATION)" >> $(2);\
+ if [ -n "$(strip $(PRODUCT_MODEL_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.model_for_attestation=$(PRODUCT_MODEL_FOR_ATTESTATION)" >> $(2);\
+ fi; \
+ if [ -n "$(strip $(PRODUCT_BRAND_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.brand_for_attestation=$(PRODUCT_BRAND_FOR_ATTESTATION)" >> $(2);\
+ fi; \
+ if [ -n "$(strip $(PRODUCT_NAME_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.name_for_attestation=$(PRODUCT_NAME_FOR_ATTESTATION)" >> $(2);\
+ fi; \
+ if [ -n "$(strip $(PRODUCT_DEVICE_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.device_for_attestation=$(PRODUCT_DEVICE_FOR_ATTESTATION)" >> $(2);\
+ fi; \
+ if [ -n "$(strip $(PRODUCT_MANUFACTURER_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.manufacturer_for_attestation=$(PRODUCT_MANUFACTURER_FOR_ATTESTATION)" >> $(2);\
+ fi; \
)\
$(if $(filter true,$(ZYGOTE_FORCE_64)),\
$(if $(filter vendor,$(1)),\
@@ -66,9 +78,12 @@ define generate-common-build-props
)\
echo "ro.$(1).build.date=`$(DATE_FROM_FILE)`" >> $(2);\
echo "ro.$(1).build.date.utc=`$(DATE_FROM_FILE) +%s`" >> $(2);\
- echo "ro.$(1).build.fingerprint=$(BUILD_FINGERPRINT_FROM_FILE)" >> $(2);\
- echo "ro.$(1).build.id=$(BUILD_ID)" >> $(2);\
- echo "ro.$(1).build.tags=$(BUILD_VERSION_TAGS)" >> $(2);\
+ # Allow optional assignments for ARC forward-declarations (b/249168657)
+ # TODO: Remove any tag-related inconsistencies once the goals from
+ # go/arc-android-sigprop-changes have been achieved.
+ echo "ro.$(1).build.fingerprint?=$(BUILD_FINGERPRINT_FROM_FILE)" >> $(2);\
+ echo "ro.$(1).build.id?=$(BUILD_ID)" >> $(2);\
+ echo "ro.$(1).build.tags?=$(BUILD_VERSION_TAGS)" >> $(2);\
echo "ro.$(1).build.type=$(TARGET_BUILD_VARIANT)" >> $(2);\
echo "ro.$(1).build.version.incremental=$(BUILD_NUMBER_FROM_FILE)" >> $(2);\
echo "ro.$(1).build.version.release=$(PLATFORM_VERSION_LAST_STABLE)" >> $(2);\
@@ -171,15 +186,8 @@ BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
# BUILD_FINGERPRINT is used used to uniquely identify the combined build and
# product; used by the OTA server.
ifeq (,$(strip $(BUILD_FINGERPRINT)))
- ifeq ($(strip $(HAS_BUILD_NUMBER)),false)
- BF_BUILD_NUMBER := $(BUILD_USERNAME)$$($(DATE_FROM_FILE) +%m%d%H%M)
- else
- BF_BUILD_NUMBER := $(BUILD_NUMBER_FROM_FILE)
- endif
- BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BF_BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+ BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
endif
-# unset it for safety.
-BF_BUILD_NUMBER :=
BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt
ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE) && grep " " $(BUILD_FINGERPRINT_FILE)))
@@ -565,4 +573,4 @@ ALL_INSTALLED_BUILD_PROP_FILES := \
# $1 installed file path, e.g. out/target/product/vsoc_x86_64/system/build.prop
define is-build-prop
$(if $(findstring $1,$(ALL_INSTALLED_BUILD_PROP_FILES)),Y)
-endef \ No newline at end of file
+endef
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index c8b1183e28..593b7b6aaf 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -37,16 +37,18 @@ ifneq (,$(wildcard cts/))
cts_platform_release_path := cts/tests/tests/os/assets/platform_releases.txt
cts_platform_release_string := $(shell cat $(cts_platform_release_path))
- ifeq (,$(findstring $(PLATFORM_VERSION),$(cts_platform_version_string)))
- define error_msg
- ============================================================
- Could not find version "$(PLATFORM_VERSION)" in CTS platform version file:
- $(cts_platform_version_path)
- Most likely PLATFORM_VERSION in build/core/version_defaults.mk
- has changed and a new version must be added to this CTS file.
- ============================================================
- endef
- $(error $(error_msg))
+ ifeq ($(RELEASE_PLATFORM_VERSION_CODENAME_REL),)
+ ifeq (,$(findstring $(PLATFORM_VERSION),$(cts_platform_version_string)))
+ define error_msg
+ ============================================================
+ Could not find version "$(PLATFORM_VERSION)" in CTS platform version file:
+ $(cts_platform_version_path)
+ Most likely PLATFORM_VERSION in build/core/version_defaults.mk
+ has changed and a new version must be added to this CTS file.
+ ============================================================
+ endef
+ $(error $(error_msg))
+ endif
endif
ifeq (,$(findstring $(PLATFORM_VERSION_LAST_STABLE),$(cts_platform_release_string)))
define error_msg
diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk
index 66ba8f15ce..9668b539af 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -2,40 +2,40 @@
# Currently runtime_dependencies only include the runtime libs information for cc binaries.
MODULE_INFO_JSON := $(PRODUCT_OUT)/module-info.json
+COMMA := ,
+_NEWLINE := '\n'
$(MODULE_INFO_JSON):
@echo Generating $@
$(hide) echo -ne '{\n ' > $@
- $(hide) echo -ne $(foreach m, $(sort $(ALL_MODULES)), \
- ' "$(m)": {' \
- '"class": [$(foreach w,$(sort $(ALL_MODULES.$(m).CLASS)),"$(w)", )], ' \
- '"path": [$(foreach w,$(sort $(ALL_MODULES.$(m).PATH)),"$(w)", )], ' \
- '"tags": [$(foreach w,$(sort $(ALL_MODULES.$(m).TAGS)),"$(w)", )], ' \
- '"installed": [$(foreach w,$(sort $(ALL_MODULES.$(m).INSTALLED)),"$(w)", )], ' \
- '"compatibility_suites": [$(foreach w,$(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)),"$(w)", )], ' \
- '"auto_test_config": [$(ALL_MODULES.$(m).auto_test_config)], ' \
- '"module_name": "$(ALL_MODULES.$(m).MODULE_NAME)", ' \
- '"test_config": [$(foreach w,$(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)),"$(w)", )], ' \
- '"dependencies": [$(foreach w,$(sort $(ALL_DEPS.$(m).ALL_DEPS)),"$(w)", )], ' \
- '"shared_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SHARED_LIBS)),"$(w)", )], ' \
- '"static_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).STATIC_LIBS)),"$(w)", )], ' \
- '"system_shared_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SYSTEM_SHARED_LIBS)),"$(w)", )], ' \
- '"srcs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SRCS)),"$(w)", )], ' \
- '"srcjars": [$(foreach w,$(sort $(ALL_MODULES.$(m).SRCJARS)),"$(w)", )], ' \
- '"classes_jar": [$(foreach w,$(sort $(ALL_MODULES.$(m).CLASSES_JAR)),"$(w)", )], ' \
- '"test_mainline_modules": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_MAINLINE_MODULES)),"$(w)", )], ' \
- '"is_unit_test": "$(ALL_MODULES.$(m).IS_UNIT_TEST)", ' \
- '"test_options_tags": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_OPTIONS_TAGS)),"$(w)", )], ' \
- '"data": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_DATA)),"$(w)", )], ' \
- '"runtime_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).LOCAL_RUNTIME_LIBRARIES)),"$(w)", )], ' \
- '"static_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).LOCAL_STATIC_LIBRARIES)),"$(w)", )], ' \
- '"data_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_DATA_BINS)),"$(w)", )], ' \
- '"supported_variants": [$(foreach w,$(sort $(ALL_MODULES.$(m).SUPPORTED_VARIANTS)),"$(w)", )], ' \
- '"host_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).HOST_REQUIRED_FROM_TARGET)),"$(w)", )], ' \
- '"target_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).TARGET_REQUIRED_FROM_HOST)),"$(w)", )], ' \
- '},\n' \
- ) | sed -e 's/, *\]/]/g' -e 's/, *\}/ }/g' -e '$$s/,$$//' >> $@
- $(hide) echo '}' >> $@
+ $(hide) echo -ne $(KATI_foreach_sep m,$(COMMA)$(_NEWLINE), $(sort $(ALL_MODULES)),\
+ '"$(m)": {' \
+ '"class": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).CLASS)),"$(w)")],' \
+ '"path": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).PATH)),"$(w)")],' \
+ '"tags": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TAGS)),"$(w)")],' \
+ '"installed": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).INSTALLED)),"$(w)")],' \
+ '"compatibility_suites": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)),"$(w)")],' \
+ '"auto_test_config": [$(ALL_MODULES.$(m).auto_test_config)],' \
+ '"module_name": "$(ALL_MODULES.$(m).MODULE_NAME)"$(COMMA)' \
+ '"test_config": [$(KATI_foreach_sep w,$(COMMA) ,$(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)),"$(w)")],' \
+ '"dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_DEPS.$(m).ALL_DEPS)),"$(w)")],' \
+ '"shared_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SHARED_LIBS)),"$(w)")],' \
+ '"static_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).STATIC_LIBS)),"$(w)")],' \
+ '"system_shared_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SYSTEM_SHARED_LIBS)),"$(w)")],' \
+ '"srcs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SRCS)),"$(w)")],' \
+ '"srcjars": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SRCJARS)),"$(w)")],' \
+ '"classes_jar": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).CLASSES_JAR)),"$(w)")],' \
+ '"test_mainline_modules": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TEST_MAINLINE_MODULES)),"$(w)")],' \
+ '"is_unit_test": "$(ALL_MODULES.$(m).IS_UNIT_TEST)"$(COMMA)' \
+ '"test_options_tags": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TEST_OPTIONS_TAGS)),"$(w)")],' \
+ '"data": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TEST_DATA)),"$(w)")],' \
+ '"runtime_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).LOCAL_RUNTIME_LIBRARIES)),"$(w)")],' \
+ '"static_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).LOCAL_STATIC_LIBRARIES)),"$(w)")],' \
+ '"data_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TEST_DATA_BINS)),"$(w)")],' \
+ '"supported_variants": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SUPPORTED_VARIANTS)),"$(w)")],' \
+ '"host_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).HOST_REQUIRED_FROM_TARGET)),"$(w)")],' \
+ '"target_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TARGET_REQUIRED_FROM_HOST)),"$(w)")]' \
+ '}')'\n}\n' >> $@
droidcore-unbundled: $(MODULE_INFO_JSON)
diff --git a/core/tasks/tools/package-modules.mk b/core/tasks/tools/package-modules.mk
index b15df28cf8..4ec552047a 100644
--- a/core/tasks/tools/package-modules.mk
+++ b/core/tasks/tools/package-modules.mk
@@ -106,6 +106,7 @@ $(my_package_zip) : $(my_built_modules)
$(hide) $(foreach f, $(PRIVATE_PICKUP_FILES),\
cp -RfL $(f) $(PRIVATE_STAGING_DIR) && ) true
$(hide) cd $(PRIVATE_STAGING_DIR) && zip -rqX ../$(notdir $@) *
+ rm -rf $(PRIVATE_STAGING_DIR)
my_makefile :=
my_staging_dir :=
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index c107254f0b..99d69d1221 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -52,6 +52,8 @@ PLATFORM_VERSION_LAST_STABLE := 13
# These are the current development codenames, if the build is not a final
# release build. If this is a final release build, it is simply "REL".
+# Note that this may be overridden by RELEASE_VERSION_CODENAME_REL in
+# version_util.mk.
PLATFORM_VERSION_CODENAME.UP1A := UpsideDownCake
PLATFORM_VERSION_CODENAME.VP1A := VanillaIceCream
@@ -103,7 +105,7 @@ ifndef PLATFORM_SECURITY_PATCH
# It must be of the form "YYYY-MM-DD" on production devices.
# It must match one of the Android Security Patch Level strings of the Public Security Bulletins.
# If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
- PLATFORM_SECURITY_PATCH := 2023-06-05
+ PLATFORM_SECURITY_PATCH := 2023-07-05
endif
include $(BUILD_SYSTEM)/version_util.mk
diff --git a/core/version_util.mk b/core/version_util.mk
index d3fcdc25ce..dca7482ef5 100644
--- a/core/version_util.mk
+++ b/core/version_util.mk
@@ -56,6 +56,12 @@ MAX_PLATFORM_VERSION :=
# unreleased API level targetable by this branch, not just those that are valid
# lunch targets for this branch.
+# Release config flag to override the current version to REL. Note that the
+# codename can also be locked to REL by setting it in versino_defaults.mk.
+ifneq ($(RELEASE_PLATFORM_VERSION_CODENAME_REL),)
+ PLATFORM_VERSION_CODENAME.$(TARGET_PLATFORM_VERSION) := REL
+endif
+
PLATFORM_VERSION_CODENAME := $(PLATFORM_VERSION_CODENAME.$(TARGET_PLATFORM_VERSION))
ifndef PLATFORM_VERSION_CODENAME
# PLATFORM_VERSION_CODENAME falls back to TARGET_PLATFORM_VERSION
@@ -163,17 +169,14 @@ endif
ifndef PLATFORM_VNDK_VERSION
# This is the definition of the VNDK version for the current VNDK libraries.
- # The version is only available when PLATFORM_VERSION_CODENAME == REL.
- # Otherwise, it will be set to a CODENAME version. The ABI is allowed to be
- # changed only before the Android version is released. Once
- # PLATFORM_VNDK_VERSION is set to actual version, the ABI for this version
- # will be frozon and emit build errors if any ABI for the VNDK libs are
- # changed.
- # After that the snapshot of the VNDK with this version will be generated.
- #
- # The VNDK version follows PLATFORM_SDK_VERSION.
+ # With trunk stable, VNDK will not be frozen but deprecated.
+ # This version will be removed with the VNDK deprecation.
ifeq (REL,$(PLATFORM_VERSION_CODENAME))
- PLATFORM_VNDK_VERSION := $(PLATFORM_SDK_VERSION)
+ ifdef RELEASE_PLATFORM_VNDK_VERSION
+ PLATFORM_VNDK_VERSION := $(RELEASE_PLATFORM_VNDK_VERSION)
+ else
+ PLATFORM_VNDK_VERSION := $(PLATFORM_SDK_VERSION)
+ endif
else
PLATFORM_VNDK_VERSION := $(PLATFORM_VERSION_CODENAME)
endif
diff --git a/envsetup.sh b/envsetup.sh
index f4755dd336..63837ecbe9 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -1075,6 +1075,10 @@ function cproj()
echo "can't find Android.mk"
}
+function adb() {
+ command adb "${@}"
+}
+
# simplified version of ps; output in the form
# <pid> <procname>
function qpid() {
@@ -1358,53 +1362,6 @@ function getprebuilt
get_abs_build_var ANDROID_PREBUILTS
}
-function tracedmdump()
-{
- local T=$(gettop)
- if [ ! "$T" ]; then
- echo "Couldn't locate the top of the tree. Try setting TOP."
- return
- fi
- local prebuiltdir=$(getprebuilt)
- local arch=$(gettargetarch)
- local KERNEL=$T/prebuilts/qemu-kernel/$arch/vmlinux-qemu
-
- local TRACE=$1
- if [ ! "$TRACE" ] ; then
- echo "usage: tracedmdump tracename"
- return
- fi
-
- if [ ! -r "$KERNEL" ] ; then
- echo "Error: cannot find kernel: '$KERNEL'"
- return
- fi
-
- local BASETRACE=$(basename $TRACE)
- if [ "$BASETRACE" = "$TRACE" ] ; then
- TRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE
- fi
-
- echo "post-processing traces..."
- rm -f $TRACE/qtrace.dexlist
- post_trace $TRACE
- if [ $? -ne 0 ]; then
- echo "***"
- echo "*** Error: malformed trace. Did you remember to exit the emulator?"
- echo "***"
- return
- fi
- echo "generating dexlist output..."
- /bin/ls $ANDROID_PRODUCT_OUT/system/framework/*.jar $ANDROID_PRODUCT_OUT/system/app/*.apk $ANDROID_PRODUCT_OUT/data/app/*.apk 2>/dev/null | xargs dexlist > $TRACE/qtrace.dexlist
- echo "generating dmtrace data..."
- q2dm -r $ANDROID_PRODUCT_OUT/symbols $TRACE $KERNEL $TRACE/dmtrace || return
- echo "generating html file..."
- dmtracedump -h $TRACE/dmtrace >| $TRACE/dmtrace.html || return
- echo "done, see $TRACE/dmtrace.html for details"
- echo "or run:"
- echo " traceview $TRACE/dmtrace"
-}
-
# communicate with a running device or emulator, set up necessary state,
# and run the hat command.
function runhat()
@@ -2049,6 +2006,11 @@ function source_vendorsetup() {
fi
done
done
+
+ if [[ "${PWD}" == /google/cog/* ]]; then
+ f="build/make/cogsetup.sh"
+ echo "including $f"; . "$T/$f"
+ fi
}
function showcommands() {
diff --git a/target/board/Android.mk b/target/board/Android.mk
index 21c0c10ab1..decc345ded 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -10,15 +10,29 @@ LOCAL_PATH := $(call my-dir)
# device we're building for. This file is typically packaged up
# with everything else.
#
-# If TARGET_BOARD_INFO_FILE (which can be set in BoardConfig.mk) is
-# defined, it is used, otherwise board-info.txt is looked for in
-# $(TARGET_DEVICE_DIR).
+# The following logic is used to find the contents of the info file:
+# 1. TARGET_BOARD_INFO_FILES (can be set in BoardConfig.mk) will be combined.
+# 2. TARGET_BOARD_INFO_FILE (can be set in BoardConfig.mk) will be used.
+# 3. $(TARGET_DEVICE_DIR)/board-info.txt will be used if present.
+#
+# Specifying both TARGET_BOARD_INFO_FILES and TARGET_BOARD_INFO_FILE is an
+# error.
#
INSTALLED_ANDROID_INFO_TXT_TARGET := $(PRODUCT_OUT)/android-info.txt
-board_info_txt := $(TARGET_BOARD_INFO_FILE)
-ifndef board_info_txt
-board_info_txt := $(wildcard $(TARGET_DEVICE_DIR)/board-info.txt)
+ifdef TARGET_BOARD_INFO_FILES
+ ifdef TARGET_BOARD_INFO_FILE
+ $(warning Both TARGET_BOARD_INFO_FILES and TARGET_BOARD_INFO_FILE are defined.)
+ $(warning Using $(TARGET_BOARD_INFO_FILES) rather than $(TARGET_BOARD_INFO_FILE) for android-info.txt)
+ endif
+ board_info_txt := $(call intermediates-dir-for,PACKAGING,board-info)/board-info.txt
+$(board_info_txt): $(TARGET_BOARD_INFO_FILES)
+ $(hide) cat $(TARGET_BOARD_INFO_FILES) > $@
+else ifdef TARGET_BOARD_INFO_FILE
+ board_info_txt := $(TARGET_BOARD_INFO_FILE)
+else
+ board_info_txt := $(wildcard $(TARGET_DEVICE_DIR)/board-info.txt)
endif
+
CHECK_RADIO_VERSIONS := $(HOST_OUT_EXECUTABLES)/check_radio_versions$(HOST_EXECUTABLE_SUFFIX)
$(INSTALLED_ANDROID_INFO_TXT_TARGET): $(board_info_txt) $(CHECK_RADIO_VERSIONS)
$(hide) $(CHECK_RADIO_VERSIONS) \
diff --git a/target/board/emulator_arm64/BoardConfig.mk b/target/board/emulator_arm64/BoardConfig.mk
index 963e558b6b..c16e61bf53 100644
--- a/target/board/emulator_arm64/BoardConfig.mk
+++ b/target/board/emulator_arm64/BoardConfig.mk
@@ -51,9 +51,6 @@ endif
include build/make/target/board/BoardConfigGsiCommon.mk
include build/make/target/board/BoardConfigEmuCommon.mk
-TARGET_NO_KERNEL := false
-BOARD_USES_RECOVERY_AS_BOOT := true
-
BOARD_BOOTIMAGE_PARTITION_SIZE := 0x02000000
BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index 87c16daade..6720ddbe6c 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -30,20 +30,3 @@ TARGET_CPU_ABI := armeabi-v7a
TARGET_CPU_ABI2 := armeabi
include build/make/target/board/BoardConfigGsiCommon.mk
-
-ifndef BUILDING_GSI
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-endif
diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk
index 76242c90b2..76edf6b411 100644
--- a/target/board/generic/device.mk
+++ b/target/board/generic/device.mk
@@ -14,5 +14,3 @@
# 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_64bitonly_x86_64/BoardConfig.mk b/target/board/generic_64bitonly_x86_64/BoardConfig.mk
index a240eab5ee..a129ea0fd3 100644
--- a/target/board/generic_64bitonly_x86_64/BoardConfig.mk
+++ b/target/board/generic_64bitonly_x86_64/BoardConfig.mk
@@ -28,23 +28,3 @@ TARGET_2ND_ARCH_VARIANT := x86_64
TARGET_PRELINK_MODULE := false
include build/make/target/board/BoardConfigGsiCommon.mk
-
-ifndef BUILDING_GSI
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-
-endif # !BUILDING_GSI
diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index 47fd384c26..26bede8d1f 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -19,23 +19,3 @@ TARGET_ARCH := x86
TARGET_ARCH_VARIANT := x86
include build/make/target/board/BoardConfigGsiCommon.mk
-
-ifndef BUILDING_GSI
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-# Resize to 4G to accomodate ASAN and CTS
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-endif
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index 5ad008f119..60f0cc33f1 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -14,9 +14,6 @@
# 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_VENDOR_PROPERTIES += net.eth0.startonboot=1
endif
diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk
index 36136f4b35..64da5783db 100755..100644
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -28,23 +28,3 @@ TARGET_DYNAMIC_64_32_MEDIASERVER := true
TARGET_DYNAMIC_64_32_DRMSERVER := true
include build/make/target/board/BoardConfigGsiCommon.mk
-
-ifndef BUILDING_GSI
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-
-endif # !BUILDING_GSI
diff --git a/target/board/generic_x86_64_arm64/BoardConfig.mk b/target/board/generic_x86_64_arm64/BoardConfig.mk
index f528294fc0..818ec44d2b 100755..100644
--- a/target/board/generic_x86_64_arm64/BoardConfig.mk
+++ b/target/board/generic_x86_64_arm64/BoardConfig.mk
@@ -13,7 +13,6 @@
# limitations under the License.
#
-# x86_64 emulator specific definitions
TARGET_CPU_ABI := x86_64
TARGET_ARCH := x86_64
TARGET_ARCH_VARIANT := x86_64
@@ -37,23 +36,9 @@ BUILD_BROKEN_DUP_RULES := true
TARGET_PRELINK_MODULE := false
include build/make/target/board/BoardConfigMainlineCommon.mk
-include build/make/target/board/BoardConfigEmuCommon.mk
# the settings differ from BoardConfigMainlineCommon.mk
BOARD_USES_SYSTEM_OTHER_ODEX :=
# Resize to 4G to accommodate ASAN and CTS
BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
diff --git a/target/board/generic_x86_64_arm64/device.mk b/target/board/generic_x86_64_arm64/device.mk
index 76242c90b2..76edf6b411 100755..100644
--- a/target/board/generic_x86_64_arm64/device.mk
+++ b/target/board/generic_x86_64_arm64/device.mk
@@ -14,5 +14,3 @@
# 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/BoardConfig.mk b/target/board/generic_x86_arm/BoardConfig.mk
index f6589b01e1..62bb5eb1f9 100644
--- a/target/board/generic_x86_arm/BoardConfig.mk
+++ b/target/board/generic_x86_arm/BoardConfig.mk
@@ -13,7 +13,6 @@
# limitations under the License.
#
-# x86 emulator specific definitions
TARGET_CPU_ABI := x86
TARGET_ARCH := x86
TARGET_ARCH_VARIANT := x86
@@ -30,23 +29,9 @@ BUILD_BROKEN_DUP_RULES := true
# The settings in latter makefiles overwrite those in the former.
#
include build/make/target/board/BoardConfigMainlineCommon.mk
-include build/make/target/board/BoardConfigEmuCommon.mk
# the settings differ from BoardConfigMainlineCommon.mk
BOARD_USES_SYSTEM_OTHER_ODEX :=
# Resize to 4G to accomodate ASAN and CTS
BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
diff --git a/target/board/generic_x86_arm/device.mk b/target/board/generic_x86_arm/device.mk
index 76242c90b2..76edf6b411 100644
--- a/target/board/generic_x86_arm/device.mk
+++ b/target/board/generic_x86_arm/device.mk
@@ -14,5 +14,3 @@
# 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/aosp_64bitonly_x86_64.mk b/target/product/aosp_64bitonly_x86_64.mk
index 75fd3c8f17..cf812a22d0 100644
--- a/target/product/aosp_64bitonly_x86_64.mk
+++ b/target/product/aosp_64bitonly_x86_64.mk
@@ -51,7 +51,6 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
#
diff --git a/target/product/aosp_arm.mk b/target/product/aosp_arm.mk
index 61c13169b9..d9c362eb56 100644
--- a/target/product/aosp_arm.mk
+++ b/target/product/aosp_arm.mk
@@ -50,7 +50,6 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
# All components inherited here go to vendor image
#
$(call inherit-product-if-exists, build/make/target/product/ramdisk_stub.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
#
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index 6c907db0ed..d3514a50de 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -54,7 +54,6 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
#
# All components inherited here go to vendor or vendor_boot image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/non_ab_device.mk)
diff --git a/target/product/aosp_riscv64.mk b/target/product/aosp_riscv64.mk
index 270a989620..fa503fffbd 100644
--- a/target/product/aosp_riscv64.mk
+++ b/target/product/aosp_riscv64.mk
@@ -46,7 +46,6 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_riscv64/device.mk)
#
diff --git a/target/product/aosp_x86.mk b/target/product/aosp_x86.mk
index a2f0390c22..c26a8bf45c 100644
--- a/target/product/aosp_x86.mk
+++ b/target/product/aosp_x86.mk
@@ -47,7 +47,6 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk
index 535ee3f0a7..3040dd3473 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -56,7 +56,6 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/non_ab_device.mk)
diff --git a/target/product/aosp_x86_arm.mk b/target/product/aosp_x86_arm.mk
index 39ad0d8d76..a103b1a22c 100644
--- a/target/product/aosp_x86_arm.mk
+++ b/target/product/aosp_x86_arm.mk
@@ -45,7 +45,6 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_arm/device.mk)
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 7fc33b070c..29e4ecd557 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -19,11 +19,9 @@ PRODUCT_PACKAGES += \
abx \
adbd_system_api \
am \
- android.hidl.allocator@1.0-service \
android.hidl.base-V1.0-java \
android.hidl.manager-V1.0-java \
android.hidl.memory@1.0-impl \
- android.hidl.memory@1.0-impl.vendor \
android.system.suspend-service \
android.test.base \
android.test.mock \
@@ -70,7 +68,6 @@ PRODUCT_PACKAGES += \
com.android.scheduling \
com.android.sdkext \
com.android.tethering \
- com.android.threadnetwork \
com.android.tzdata \
com.android.uwb \
com.android.virt \
@@ -89,7 +86,6 @@ PRODUCT_PACKAGES += \
dump.erofs \
dumpstate \
dumpsys \
- DynamicSystemInstallationService \
e2fsck \
ExtShared \
flags_health_check \
@@ -110,7 +106,6 @@ PRODUCT_PACKAGES += \
gatekeeperd \
gpuservice \
hid \
- hwservicemanager \
idmap2 \
idmap2d \
ime \
@@ -240,6 +235,7 @@ PRODUCT_PACKAGES += \
pm \
pppd \
preinstalled-packages-platform.xml \
+ printflags \
privapp-permissions-platform.xml \
prng_seeder \
racoon \
@@ -298,11 +294,26 @@ ifneq ($(PRODUCT_IS_ATV),true)
endif
+# Product does not support Dynamic System Update
+ifneq ($(PRODUCT_NO_DYNAMIC_SYSTEM_UPDATE),true)
+ PRODUCT_PACKAGES += \
+ DynamicSystemInstallationService \
+
+endif
+
# VINTF data for system image
PRODUCT_PACKAGES += \
system_manifest.xml \
system_compatibility_matrix.xml \
+HIDL_SUPPORT_SERVICES := \
+ hwservicemanager \
+ android.hidl.allocator@1.0-service \
+
+# Base modules when shipping api level is less than or equal to 34
+PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
+ $(HIDL_SUPPORT_SERVICES) \
+
PRODUCT_PACKAGES_ARM64 := libclang_rt.hwasan \
libclang_rt.hwasan.bootstrap \
libc_hwasan \
@@ -333,6 +344,7 @@ endif
PRODUCT_HOST_PACKAGES += \
BugReport \
adb \
+ adevice \
art-tools \
atest \
bcc \
@@ -348,7 +360,6 @@ PRODUCT_HOST_PACKAGES += \
incident_report \
ld.mc \
lpdump \
- minigzip \
mke2fs \
mkfs.erofs \
resize2fs \
@@ -381,6 +392,7 @@ PRODUCT_SYSTEM_PROPERTIES += persist.traced.enable=1
# Packages included only for eng or userdebug builds, previously debug tagged
PRODUCT_PACKAGES_DEBUG := \
adb_keys \
+ adevice_fingerprint \
arping \
dmuserd \
idlcli \
@@ -427,3 +439,6 @@ PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,\
frameworks/base/config/dirty-image-objects:system/etc/dirty-image-objects)
$(call inherit-product, $(SRC_TARGET_DIR)/product/runtime_libart.mk)
+
+# Use "image" APEXes always.
+$(call inherit-product,$(SRC_TARGET_DIR)/product/updatable_apex.mk)
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 3c4d62ea91..b6e5370a01 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -46,7 +46,8 @@ PRODUCT_HOST_PACKAGES += \
# Base modules and settings for the vendor partition.
PRODUCT_PACKAGES += \
- android.hardware.cas-service.example \
+ android.hidl.memory@1.0-impl.vendor \
+ com.android.hardware.cas \
boringssl_self_test_vendor \
dumpsys_vendor \
fs_config_files_nonsystem \
diff --git a/target/product/cfi-common.mk b/target/product/cfi-common.mk
index 5cc7ae5e94..559963cd7f 100644
--- a/target/product/cfi-common.mk
+++ b/target/product/cfi-common.mk
@@ -33,7 +33,7 @@ PRODUCT_CFI_INCLUDE_PATHS := \
hardware/qcom/wlan/wcn6740/qcwcn/wpa_supplicant_8_lib \
hardware/interfaces/keymaster \
hardware/interfaces/security \
- packages/modules/Bluetooth \
+ packages/modules/Bluetooth/system \
system/chre \
system/core/libnetutils \
system/libziparchive \
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index 1e28c80bee..2f32199686 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -38,6 +38,14 @@ endif
PRODUCT_BOOT_JARS := \
$(ART_APEX_JARS)
+# List of jars to be included in the ART boot image for testing.
+# DO NOT reorder this list. The order must match the one described above.
+# Note: We use the host variant of "core-icu4j" and "conscrypt" for testing.
+PRODUCT_TEST_ONLY_ART_BOOT_IMAGE_JARS := \
+ $(ART_APEX_JARS) \
+ platform:core-icu4j-host \
+ platform:conscrypt-host \
+
# /system and /system_ext boot jars.
PRODUCT_BOOT_JARS += \
framework-minus-apex \
@@ -60,6 +68,7 @@ PRODUCT_APEX_BOOT_JARS := \
com.android.ipsec:android.net.ipsec.ike \
com.android.media:updatable-media \
com.android.mediaprovider:framework-mediaprovider \
+ com.android.mediaprovider:framework-pdf \
com.android.ondevicepersonalization:framework-ondevicepersonalization \
com.android.os.statsd:framework-statsd \
com.android.permission:framework-permission \
@@ -106,6 +115,13 @@ PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS := \
com.android.uwb:service-uwb \
com.android.wifi:service-wifi \
+# Overrides the (apex, jar) pairs above when determining the on-device location. The format is:
+# <old_apex>:<old_jar>:<new_apex>:<new_jar>
+PRODUCT_CONFIGURED_JAR_LOCATION_OVERRIDES := \
+ platform:framework-minus-apex:platform:framework \
+ platform:core-icu4j-host:com.android.i18n:core-icu4j \
+ platform:conscrypt-host:com.android.conscrypt:conscrypt \
+
# Minimal configuration for running dex2oat (default argument values).
# PRODUCT_USES_DEFAULT_ART_CONFIG must be true to enable boot image compilation.
PRODUCT_USES_DEFAULT_ART_CONFIG := true
diff --git a/target/product/full.manifest.xml b/target/product/full.manifest.xml
new file mode 100644
index 0000000000..b8b0d37875
--- /dev/null
+++ b/target/product/full.manifest.xml
@@ -0,0 +1,2 @@
+<manifest version="1.0" type="device" target-level="7">
+</manifest>
diff --git a/target/product/full.mk b/target/product/full.mk
index 945957ff81..da04f49a19 100644
--- a/target/product/full.mk
+++ b/target/product/full.mk
@@ -20,10 +20,11 @@
# entirely appropriate to inherit from for on-device configurations.
$(call inherit-product-if-exists, build/make/target/product/ramdisk_stub.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic/device.mk)
+DEVICE_MANIFEST_FILE += build/make/target/product/full.manifest.xml
+
# Enable dynamic partition size
PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
diff --git a/target/product/full_x86.mk b/target/product/full_x86.mk
index 0f3be91764..07f6472844 100644
--- a/target/product/full_x86.mk
+++ b/target/product/full_x86.mk
@@ -23,10 +23,11 @@
# that isn't a wifi connection. This will instruct init.rc to enable the
# network connection so that you can use it with ADB
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
+DEVICE_MANIFEST_FILE += build/make/target/product/full.manifest.xml
+
ifdef NET_ETH0_STARTONBOOT
PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1
endif
diff --git a/target/product/generic.mk b/target/product/generic.mk
index fb5b727ba1..fd3b3fb0e7 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -14,9 +14,6 @@
# 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/generic_system.mk b/target/product/generic_system.mk
index 1a639ef717..dc9324cf0c 100644
--- a/target/product/generic_system.mk
+++ b/target/product/generic_system.mk
@@ -102,6 +102,11 @@ PRODUCT_PACKAGES += \
libaudiopolicyengineconfigurable \
libpolicy-subsystem
+
+ifneq ($(KEEP_VNDK),true)
+PRODUCT_PACKAGES += llndk.libraries.txt
+endif
+
# Include all zygote init scripts. "ro.zygote" will select one of them.
PRODUCT_COPY_FILES += \
system/core/rootdir/init.zygote32.rc:system/etc/init/hw/init.zygote32.rc \
@@ -126,6 +131,10 @@ PRODUCT_SYSTEM_DEVICE := generic
_base_mk_allowed_list :=
+# TODO(b/299166571) Remove this after the artifact path requirements checker picks up
+# hwservicemanager correctly.
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += $(TARGET_COPY_OUT_SYSTEM)/bin/hwservicemanager
+
_my_allowed_list := $(_base_mk_allowed_list)
# For mainline, system.img should be mounted at /, so we include ROOT here.
diff --git a/target/product/gsi/Android.bp b/target/product/gsi/Android.bp
index a8af9c4eca..45ba14331b 100644
--- a/target/product/gsi/Android.bp
+++ b/target/product/gsi/Android.bp
@@ -23,3 +23,26 @@ filegroup {
"*.txt",
],
}
+
+prebuilt_etc {
+ name: "gsi_skip_mount.cfg",
+ filename: "skip_mount.cfg",
+ src: "gsi_skip_mount.cfg",
+
+ system_ext_specific: true,
+ relative_install_path: "init/config",
+
+ required: ["gsi_skip_mount_compat_symlink"],
+}
+
+// Adds a symlink under /system/etc/init/config pointing to /system/system_ext/etc/init/config
+// because first-stage init in Android 10.0 will read the skip_mount.cfg from /system/etc/* after
+// chroot /system.
+// TODO: remove this symlink when no need to support new GSI on Android 10.
+// The actual file needs to be under /system/system_ext because it's GSI-specific and does not
+// belong to core CSI.
+install_symlink {
+ name: "gsi_skip_mount_compat_symlink",
+ installed_location: "etc/init/config",
+ symlink_target: "/system/system_ext/etc/init/config",
+}
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index 86d4622bdb..70ee78db75 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -1,5 +1,14 @@
LOCAL_PATH:= $(call my-dir)
+# VNDK will not be frozen if the PLATFORM_VNDK_VERSION is a codename or greater than 34
+ifeq ($(call math_is_number,$(PLATFORM_VNDK_VERSION)),)
+UNFROZEN_VNDK := true
+else
+ifeq ($(call math_gt,$(PLATFORM_VNDK_VERSION),34),true)
+UNFROZEN_VNDK := true
+endif
+endif
+
#####################################################################
# list of vndk libraries from the source code.
INTERNAL_VNDK_LIB_LIST := $(SOONG_VNDK_LIBRARIES_FILE)
@@ -9,10 +18,14 @@ INTERNAL_VNDK_LIB_LIST := $(SOONG_VNDK_LIBRARIES_FILE)
# TODO(b/62012285): the lib list should be stored somewhere under
# /prebuilts/vndk
ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+ifndef UNFROZEN_VNDK
LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/$(PLATFORM_VNDK_VERSION).txt
ifeq ($(wildcard $(LATEST_VNDK_LIB_LIST)),)
$(error $(LATEST_VNDK_LIB_LIST) file not found. Please copy "$(LOCAL_PATH)/current.txt" to "$(LATEST_VNDK_LIB_LIST)" and commit a CL for release branch)
endif
+else # UNFROZEN_VNDK
+LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/current.txt
+endif # UNFROZEN_VNDK
else
LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/current.txt
endif
@@ -175,8 +188,7 @@ LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
# Filter LLNDK libs moved to APEX to avoid pulling them into /system/LIB
-LOCAL_REQUIRED_MODULES := \
- $(filter-out $(LLNDK_MOVED_TO_APEX_LIBRARIES),$(LLNDK_LIBRARIES))
+LOCAL_REQUIRED_MODULES := llndk_in_system
ifneq ($(TARGET_SKIP_CURRENT_VNDK),true)
LOCAL_REQUIRED_MODULES += \
@@ -195,7 +207,10 @@ include $(BUILD_PHONY_PACKAGE)
include $(CLEAR_VARS)
_vndk_versions :=
ifeq ($(filter com.android.vndk.current.on_vendor, $(PRODUCT_PACKAGES)),)
- _vndk_versions += $(PRODUCT_EXTRA_VNDK_VERSIONS)
+ _vndk_versions += $(if $(call math_is_number,$(PLATFORM_VNDK_VERSION)),\
+ $(foreach vndk_ver,$(PRODUCT_EXTRA_VNDK_VERSIONS),\
+ $(if $(call math_lt,$(vndk_ver),$(PLATFORM_VNDK_VERSION)),$(vndk_ver))),\
+ $(PRODUCT_EXTRA_VNDK_VERSIONS))
endif
ifneq ($(BOARD_VNDK_VERSION),current)
_vndk_versions += $(BOARD_VNDK_VERSION)
@@ -210,30 +225,19 @@ include $(BUILD_PHONY_PACKAGE)
_vndk_versions :=
#####################################################################
-# skip_mount.cfg, read by init to skip mounting some partitions when GSI is used.
-
+# Define Phony module to install LLNDK modules which are installed in
+# the system image
include $(CLEAR_VARS)
-LOCAL_MODULE := gsi_skip_mount.cfg
+LOCAL_MODULE := llndk_in_system
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_STEM := skip_mount.cfg
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_SYSTEM_EXT_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := init/config
-
-# Adds a symlink under /system/etc/init/config pointing to /system/system_ext/etc/init/config
-# because first-stage init in Android 10.0 will read the skip_mount.cfg from /system/etc/* after
-# chroot /system.
-# TODO: remove this symlink when no need to support new GSI on Android 10.
-# The actual file needs to be under /system/system_ext because it's GSI-specific and does not
-# belong to core CSI.
-LOCAL_POST_INSTALL_CMD := \
- mkdir -p $(TARGET_OUT)/etc/init; \
- ln -sf /system/system_ext/etc/init/config $(TARGET_OUT)/etc/init/config
-include $(BUILD_PREBUILT)
+# Filter LLNDK libs moved to APEX to avoid pulling them into /system/LIB
+LOCAL_REQUIRED_MODULES := \
+ $(filter-out $(LLNDK_MOVED_TO_APEX_LIBRARIES),$(LLNDK_LIBRARIES))
+
+include $(BUILD_PHONY_PACKAGE)
#####################################################################
# init.gsi.rc, GSI-specific init script.
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index e39af92ae5..23eb534f45 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -28,10 +28,14 @@
BUILDING_GSI := true
-# Exclude all files under system/product and system/system_ext
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
+ system/etc/init/config \
system/product/% \
- system/system_ext/%
+ system/system_ext/% \
+ system/lib/vndk-29 \
+ system/lib/vndk-sp-29 \
+ system/lib64/vndk-29 \
+ system/lib64/vndk-sp-29
# GSI should always support up-to-date platform features.
# Keep this value at the latest API level to ensure latest build system
diff --git a/target/product/mainline_sdk.mk b/target/product/mainline_sdk.mk
index 343aed6f12..0ea72cc0bb 100644
--- a/target/product/mainline_sdk.mk
+++ b/target/product/mainline_sdk.mk
@@ -16,3 +16,5 @@
PRODUCT_NAME := mainline_sdk
PRODUCT_BRAND := Android
PRODUCT_DEVICE := mainline_sdk
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index fa7e1ad381..e4cb7ff4fb 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -14,11 +14,8 @@
# limitations under the License.
#
-# This is a simple product that uses configures the minimum amount
-# needed to build the SDK (without the emulator).
+# Don't modify this file - It's just an alias!
-$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_x86.mk)
PRODUCT_NAME := sdk
-PRODUCT_BRAND := Android
-PRODUCT_DEVICE := mainline_x86
diff --git a/target/product/sdk_arm64.mk b/target/product/sdk_arm64.mk
index 8bb38f41a1..3eb930435d 100644
--- a/target/product/sdk_arm64.mk
+++ b/target/product/sdk_arm64.mk
@@ -14,8 +14,13 @@
# limitations under the License.
#
-# Don't modify this file - It's just an alias!
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_arm64.mk)
+TARGET_SUPPORTS_32_BIT_APPS := true
+TARGET_SUPPORTS_64_BIT_APPS := true
PRODUCT_NAME := sdk_arm64
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := mainline_arm64
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_arm64.mk b/target/product/sdk_phone_arm64.mk
index 3f8161556c..c16c403c90 100644
--- a/target/product/sdk_phone_arm64.mk
+++ b/target/product/sdk_phone_arm64.mk
@@ -63,4 +63,4 @@ PRODUCT_MODEL := Android SDK built for arm64
# library name, so the check fails.
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
-
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_armv7.mk b/target/product/sdk_phone_armv7.mk
index 48a0e3be9e..293b1eab49 100644
--- a/target/product/sdk_phone_armv7.mk
+++ b/target/product/sdk_phone_armv7.mk
@@ -62,3 +62,5 @@ PRODUCT_MODEL := Android SDK built for arm
# RadioConfigLib), which makes it impossible to translate their module names to
# library name, so the check fails.
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk
index 0f8b5082a5..90cd8d5ba6 100644
--- a/target/product/sdk_phone_x86.mk
+++ b/target/product/sdk_phone_x86.mk
@@ -57,3 +57,5 @@ PRODUCT_MODEL := Android SDK built for x86
# RadioConfigLib), which makes it impossible to translate their module names to
# library name, so the check fails.
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk
index f5d9028307..b2e14a5425 100644
--- a/target/product/sdk_phone_x86_64.mk
+++ b/target/product/sdk_phone_x86_64.mk
@@ -58,3 +58,5 @@ PRODUCT_MODEL := Android SDK built for x86_64
# RadioConfigLib), which makes it impossible to translate their module names to
# library name, so the check fails.
PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_x86.mk b/target/product/sdk_x86.mk
index 13ee57d805..a6e3bcdab0 100644
--- a/target/product/sdk_x86.mk
+++ b/target/product/sdk_x86.mk
@@ -14,8 +14,13 @@
# limitations under the License.
#
-# Don't modify this file - It's just an alias!
+# This is a simple product that uses configures the minimum amount
+# needed to build the SDK (without the emulator).
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_x86.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
-PRODUCT_NAME := sdk_x86
+PRODUCT_NAME := sdk_x86_64
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := mainline_x86
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/sdk_x86_64.mk b/target/product/sdk_x86_64.mk
index 5f6553e000..af73007a35 100644
--- a/target/product/sdk_x86_64.mk
+++ b/target/product/sdk_x86_64.mk
@@ -14,8 +14,16 @@
# limitations under the License.
#
-# Don't modify this file - It's just an alias!
+# This is a simple product that uses configures the minimum amount
+# needed to build the SDK (without the emulator).
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_x86_64.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
+
+TARGET_SUPPORTS_32_BIT_APPS := true
+TARGET_SUPPORTS_64_BIT_APPS := true
PRODUCT_NAME := sdk_x86_64
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := mainline_x86_64
+
+PRODUCT_NEXT_RELEASE_HIDE_FLAGGED_API := true
diff --git a/target/product/updatable_apex.mk b/target/product/updatable_apex.mk
index c19982b274..8357fdf7fd 100644
--- a/target/product/updatable_apex.mk
+++ b/target/product/updatable_apex.mk
@@ -14,17 +14,13 @@
# limitations under the License.
#
-# Inherit this when the target needs to support updating APEXes
+# com.android.apex.cts.shim.v1_prebuilt overrides CtsShimPrebuilt
+# and CtsShimPrivPrebuilt since they are packaged inside the APEX.
+PRODUCT_PACKAGES += com.android.apex.cts.shim.v1_prebuilt
+PRODUCT_SYSTEM_PROPERTIES := ro.apex.updatable=true
-ifneq ($(OVERRIDE_TARGET_FLATTEN_APEX),true)
- # com.android.apex.cts.shim.v1_prebuilt overrides CtsShimPrebuilt
- # and CtsShimPrivPrebuilt since they are packaged inside the APEX.
- PRODUCT_PACKAGES += com.android.apex.cts.shim.v1_prebuilt
- PRODUCT_SYSTEM_PROPERTIES := ro.apex.updatable=true
- TARGET_FLATTEN_APEX := false
- # Use compressed apexes in pre-installed partitions.
- # Note: this doesn't mean that all pre-installed apexes will be compressed.
- # Whether an apex is compressed or not is controlled at apex Soong module
- # via compresible property.
- PRODUCT_COMPRESSED_APEX := true
-endif
+# Use compressed apexes in pre-installed partitions.
+# Note: this doesn't mean that all pre-installed apexes will be compressed.
+# Whether an apex is compressed or not is controlled at apex Soong module
+# via compresible property.
+PRODUCT_COMPRESSED_APEX := true
diff --git a/tools/Android.bp b/tools/Android.bp
index bea0602f59..b8ab162b76 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -82,3 +82,17 @@ python_binary_host {
}
}
}
+
+python_test_host {
+ name: "auto_gen_test_config_test",
+ main: "auto_gen_test_config_test.py",
+ srcs: [
+ "auto_gen_test_config.py",
+ "auto_gen_test_config_test.py",
+ ],
+ auto_gen_config: true,
+ test_suites: ["general-tests"],
+ test_options: {
+ unit_test: true,
+ },
+}
diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel
index 0de178b709..9ec0dcef85 100644
--- a/tools/BUILD.bazel
+++ b/tools/BUILD.bazel
@@ -1,6 +1,7 @@
py_library(
name = "event_log_tags",
srcs = ["event_log_tags.py"],
+ imports = ["."],
)
py_binary(
@@ -25,3 +26,10 @@ py_binary(
python_version = "PY3",
visibility = ["//visibility:public"],
)
+
+py_binary(
+ name = "auto_gen_test_config",
+ srcs = ["auto_gen_test_config.py"],
+ python_version = "PY3",
+ visibility = ["//visibility:public"],
+)
diff --git a/tools/aconfig/Android.bp b/tools/aconfig/Android.bp
index c3499078bf..02fc57cb74 100644
--- a/tools/aconfig/Android.bp
+++ b/tools/aconfig/Android.bp
@@ -24,14 +24,23 @@ java_library_host {
},
}
+python_library_host {
+ name: "libaconfig_python_proto",
+ srcs: ["protos/aconfig.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
+
// host binary: aconfig
-rust_protobuf_host {
+rust_protobuf {
name: "libaconfig_protos",
protos: ["protos/aconfig.proto"],
crate_name: "aconfig_protos",
source_stem: "aconfig_protos",
use_protobuf3: true,
+ host_supported: true,
}
rust_defaults {
@@ -67,7 +76,7 @@ rust_test_host {
],
}
-// integration tests: java
+// integration tests: general
aconfig_declarations {
name: "aconfig.test.flags",
@@ -91,22 +100,97 @@ aconfig_value_set {
],
}
+// integration tests: java
+
java_aconfig_library {
- name: "aconfig_test_java",
+ name: "aconfig_test_java_library",
aconfig_declarations: "aconfig.test.flags",
}
android_test {
name: "aconfig.test.java",
srcs: [
- "tests/**/*.java",
+ "tests/AconfigTest.java",
],
manifest: "tests/AndroidManifest.xml",
certificate: "platform",
static_libs: [
+ "aconfig_test_java_library",
"androidx.test.rules",
"testng",
- "aconfig_test_java",
],
test_suites: ["device-tests"],
}
+
+java_aconfig_library {
+ name: "aconfig_host_test_java_library",
+ aconfig_declarations: "aconfig.test.flags",
+ host_supported: true,
+ test: true,
+}
+
+java_test_host {
+ name: "AconfigJavaHostTest",
+ srcs: [
+ "tests/AconfigHostTest.java",
+ ],
+ static_libs: [
+ "aconfig_host_test_java_library",
+ "junit",
+ ],
+ test_suites: ["general-tests"],
+}
+
+// integration tests: C++
+
+cc_aconfig_library {
+ name: "aconfig_test_cpp_library",
+ aconfig_declarations: "aconfig.test.flags",
+}
+
+cc_test {
+ name: "aconfig.test.cpp",
+ srcs: [
+ "tests/aconfig_test.cpp",
+ ],
+ static_libs: [
+ "aconfig_test_cpp_library",
+ "libgmock",
+ ],
+ shared_libs: [
+ "server_configurable_flags",
+ ],
+}
+
+rust_aconfig_library {
+ name: "libaconfig_test_rust_library",
+ crate_name: "aconfig_test_rust_library",
+ aconfig_declarations: "aconfig.test.flags",
+}
+
+rust_test {
+ name: "aconfig.prod_mode.test.rust",
+ srcs: [
+ "tests/aconfig_prod_mode_test.rs"
+ ],
+ rustlibs: [
+ "libaconfig_test_rust_library",
+ ],
+}
+
+rust_aconfig_library {
+ name: "libaconfig_test_rust_library_with_test_mode",
+ crate_name: "aconfig_test_rust_library",
+ aconfig_declarations: "aconfig.test.flags",
+ test: true,
+}
+
+rust_test {
+ name: "aconfig.test_mode.test.rust",
+ srcs: [
+ "tests/aconfig_test_mode_test.rs"
+ ],
+ rustlibs: [
+ "libaconfig_test_rust_library_with_test_mode",
+ ],
+}
diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING
index 86124dd20d..74ac5ecd6e 100644
--- a/tools/aconfig/TEST_MAPPING
+++ b/tools/aconfig/TEST_MAPPING
@@ -10,6 +10,12 @@
"include-filter": "android.cts.flags.tests.FlagAnnotationTest"
}
]
+ },
+ {
+ // Ensure changes on aconfig auto generated library is compatible with
+ // test testing filtering logic. Breakage on this test means all tests
+ // that using the flag macros to do filtering will get affected.
+ "name": "FlagMacrosTests"
}
]
}
diff --git a/tools/aconfig/fake_device_config/Android.bp b/tools/aconfig/fake_device_config/Android.bp
new file mode 100644
index 0000000000..5f62ae94a4
--- /dev/null
+++ b/tools/aconfig/fake_device_config/Android.bp
@@ -0,0 +1,21 @@
+// Copyright (C) 2023 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.
+
+java_library {
+ name: "fake_device_config",
+ srcs: ["src/**/*.java"],
+ sdk_version: "core_platform",
+ host_supported: true,
+}
+
diff --git a/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java b/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java
new file mode 100644
index 0000000000..50b6289e4e
--- /dev/null
+++ b/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package android.provider;
+
+/*
+ * This class allows generated aconfig code to compile independently of the framework.
+ */
+public class DeviceConfig {
+ private DeviceConfig() {
+ }
+
+ public static boolean getBoolean(String ns, String name, boolean def) {
+ return false;
+ }
+}
diff --git a/tools/aconfig/printflags/Android.bp b/tools/aconfig/printflags/Android.bp
new file mode 100644
index 0000000000..da18cdc589
--- /dev/null
+++ b/tools/aconfig/printflags/Android.bp
@@ -0,0 +1,27 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+ name: "printflags.defaults",
+ edition: "2021",
+ clippy_lints: "android",
+ lints: "android",
+ srcs: ["src/main.rs"],
+ rustlibs: [
+ "libaconfig_protos",
+ "libanyhow",
+ "libprotobuf",
+ "libregex",
+ ],
+}
+
+rust_binary {
+ name: "printflags",
+ defaults: ["printflags.defaults"],
+}
+
+rust_test_host {
+ name: "printflags.test",
+ defaults: ["printflags.defaults"],
+}
diff --git a/tools/aconfig/printflags/src/main.rs b/tools/aconfig/printflags/src/main.rs
new file mode 100644
index 0000000000..88fdea9d45
--- /dev/null
+++ b/tools/aconfig/printflags/src/main.rs
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+//! `printflags` is a device binary to print feature flags.
+
+use aconfig_protos::aconfig::Flag_state as State;
+use aconfig_protos::aconfig::Parsed_flags as ProtoParsedFlags;
+use anyhow::{bail, Result};
+use regex::Regex;
+use std::collections::HashMap;
+use std::process::Command;
+use std::{fs, str};
+
+fn parse_device_config(raw: &str) -> HashMap<String, String> {
+ let mut flags = HashMap::new();
+ let regex = Regex::new(r"(?m)^([[[:alnum:]]_]+/[[[:alnum:]]_\.]+)=(true|false)$").unwrap();
+ for capture in regex.captures_iter(raw) {
+ let key = capture.get(1).unwrap().as_str().to_string();
+ let value = match capture.get(2).unwrap().as_str() {
+ "true" => format!("{:?} (device_config)", State::ENABLED),
+ "false" => format!("{:?} (device_config)", State::DISABLED),
+ _ => panic!(),
+ };
+ flags.insert(key, value);
+ }
+ flags
+}
+
+fn main() -> Result<()> {
+ // read device_config
+ let output = Command::new("/system/bin/device_config").arg("list").output()?;
+ if !output.status.success() {
+ let reason = match output.status.code() {
+ Some(code) => format!("exit code {}", code),
+ None => "terminated by signal".to_string(),
+ };
+ bail!("failed to execute device_config: {}", reason);
+ }
+ let dc_stdout = str::from_utf8(&output.stdout)?;
+ let device_config_flags = parse_device_config(dc_stdout);
+
+ // read aconfig_flags.pb files
+ let mut flags: HashMap<String, Vec<String>> = HashMap::new();
+ for partition in ["system", "system_ext", "product", "vendor"] {
+ let path = format!("/{}/etc/aconfig_flags.pb", partition);
+ let Ok(bytes) = fs::read(&path) else {
+ eprintln!("warning: failed to read {}", path);
+ continue;
+ };
+ let parsed_flags: ProtoParsedFlags = protobuf::Message::parse_from_bytes(&bytes)?;
+ for flag in parsed_flags.parsed_flag {
+ let key = format!("{}/{}.{}", flag.namespace(), flag.package(), flag.name());
+ let value = format!("{:?} + {:?} ({})", flag.permission(), flag.state(), partition);
+ flags.entry(key).or_default().push(value);
+ }
+ }
+
+ // print flags
+ for (key, mut value) in flags {
+ let (_, package_and_name) = key.split_once('/').unwrap();
+ if let Some(dc_value) = device_config_flags.get(&key) {
+ value.push(dc_value.to_string());
+ }
+ println!("{}: {}", package_and_name, value.join(", "));
+ }
+
+ Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_foo() {
+ let input = r#"
+namespace_one/com.foo.bar.flag_one=true
+namespace_one/com.foo.bar.flag_two=false
+random_noise;
+namespace_two/android.flag_one=true
+namespace_two/android.flag_two=nonsense
+"#;
+ let expected = HashMap::from([
+ (
+ "namespace_one/com.foo.bar.flag_one".to_string(),
+ "ENABLED (device_config)".to_string(),
+ ),
+ (
+ "namespace_one/com.foo.bar.flag_two".to_string(),
+ "DISABLED (device_config)".to_string(),
+ ),
+ ("namespace_two/android.flag_one".to_string(), "ENABLED (device_config)".to_string()),
+ ]);
+ let actual = parse_device_config(input);
+ assert_eq!(expected, actual);
+ }
+}
diff --git a/tools/aconfig/protos/aconfig.proto b/tools/aconfig/protos/aconfig.proto
index 4cad69ad5f..d5e286843d 100644
--- a/tools/aconfig/protos/aconfig.proto
+++ b/tools/aconfig/protos/aconfig.proto
@@ -39,6 +39,7 @@ message flag_declaration {
optional string namespace = 2;
optional string description = 3;
repeated string bug = 4;
+ optional bool is_fixed_read_only = 5;
};
message flag_declarations {
@@ -75,6 +76,7 @@ message parsed_flag {
optional flag_state state = 6;
optional flag_permission permission = 7;
repeated tracepoint trace = 8;
+ optional bool is_fixed_read_only = 9;
}
message parsed_flags {
diff --git a/tools/aconfig/src/codegen_cpp.rs b/tools/aconfig/src/codegen_cpp.rs
index a802725841..5eadf2a0e4 100644
--- a/tools/aconfig/src/codegen_cpp.rs
+++ b/tools/aconfig/src/codegen_cpp.rs
@@ -38,11 +38,11 @@ where
let cpp_namespace = package.replace('.', "::");
ensure!(codegen::is_valid_name_ident(&header));
let context = Context {
- header: header.clone(),
- cpp_namespace,
- package: package.to_string(),
+ header: &header,
+ cpp_namespace: &cpp_namespace,
+ package,
readwrite,
- for_prod: codegen_mode == CodegenMode::Production,
+ for_test: codegen_mode == CodegenMode::Test,
class_elements,
};
@@ -57,16 +57,6 @@ where
template: include_str!("../templates/cpp_source_file.template"),
dir: "",
},
- FileSpec {
- name: &format!("{}_flag_provider.h", header),
- template: match codegen_mode {
- CodegenMode::Production => {
- include_str!("../templates/cpp_prod_flag_provider.template")
- }
- CodegenMode::Test => include_str!("../templates/cpp_test_flag_provider.template"),
- },
- dir: "",
- },
];
files.iter().map(|file| generate_file(file, &context)).collect()
}
@@ -87,12 +77,12 @@ pub struct FileSpec<'a> {
}
#[derive(Serialize)]
-pub struct Context {
- pub header: String,
- pub cpp_namespace: String,
- pub package: String,
+pub struct Context<'a> {
+ pub header: &'a str,
+ pub cpp_namespace: &'a str,
+ pub package: &'a str,
pub readwrite: bool,
- pub for_prod: bool,
+ pub for_test: bool,
pub class_elements: Vec<ClassElement>,
}
@@ -101,7 +91,6 @@ pub struct ClassElement {
pub readwrite: bool,
pub default_value: String,
pub flag_name: String,
- pub uppercase_flag_name: String,
pub device_config_namespace: String,
pub device_config_flag: String,
}
@@ -115,7 +104,6 @@ fn create_class_element(package: &str, pf: &ProtoParsedFlag) -> ClassElement {
"false".to_string()
},
flag_name: pf.name().to_string(),
- uppercase_flag_name: pf.name().to_string().to_ascii_uppercase(),
device_config_namespace: pf.namespace().to_string(),
device_config_flag: codegen::create_device_config_ident(package, pf.name())
.expect("values checked at flag parse time"),
@@ -128,40 +116,30 @@ mod tests {
use std::collections::HashMap;
const EXPORTED_PROD_HEADER_EXPECTED: &str = r#"
-#ifndef com_android_aconfig_test_HEADER_H
-#define com_android_aconfig_test_HEADER_H
+#pragma once
+
+#ifdef __cplusplus
-#include <string>
#include <memory>
-#include <server_configurable_flags/get_flags.h>
-using namespace server_configurable_flags;
namespace com::android::aconfig::test {
class flag_provider_interface {
public:
-
virtual ~flag_provider_interface() = default;
virtual bool disabled_ro() = 0;
virtual bool disabled_rw() = 0;
+ virtual bool enabled_fixed_ro() = 0;
+
virtual bool enabled_ro() = 0;
virtual bool enabled_rw() = 0;
-
- virtual void override_flag(std::string const&, bool) {}
-
- virtual void reset_overrides() {}
};
extern std::unique_ptr<flag_provider_interface> provider_;
-extern std::string const DISABLED_RO;
-extern std::string const DISABLED_RW;
-extern std::string const ENABLED_RO;
-extern std::string const ENABLED_RW;
-
inline bool disabled_ro() {
return false;
}
@@ -170,6 +148,10 @@ inline bool disabled_rw() {
return provider_->disabled_rw();
}
+inline bool enabled_fixed_ro() {
+ return true;
+}
+
inline bool enabled_ro() {
return true;
}
@@ -178,28 +160,35 @@ inline bool enabled_rw() {
return provider_->enabled_rw();
}
-inline void override_flag(std::string const& name, bool val) {
- return provider_->override_flag(name, val);
}
-inline void reset_overrides() {
- return provider_->reset_overrides();
-}
+extern "C" {
+#endif // __cplusplus
-}
+bool com_android_aconfig_test_disabled_ro();
+
+bool com_android_aconfig_test_disabled_rw();
+
+bool com_android_aconfig_test_enabled_fixed_ro();
+
+bool com_android_aconfig_test_enabled_ro();
+
+bool com_android_aconfig_test_enabled_rw();
+
+#ifdef __cplusplus
+} // extern "C"
#endif
"#;
const EXPORTED_TEST_HEADER_EXPECTED: &str = r#"
-#ifndef com_android_aconfig_test_HEADER_H
-#define com_android_aconfig_test_HEADER_H
+#pragma once
+
+#ifdef __cplusplus
-#include <string>
#include <memory>
-#include <server_configurable_flags/get_flags.h>
-using namespace server_configurable_flags;
namespace com::android::aconfig::test {
+
class flag_provider_interface {
public:
@@ -207,184 +196,317 @@ public:
virtual bool disabled_ro() = 0;
+ virtual void disabled_ro(bool val) = 0;
+
virtual bool disabled_rw() = 0;
+ virtual void disabled_rw(bool val) = 0;
+
+ virtual bool enabled_fixed_ro() = 0;
+
+ virtual void enabled_fixed_ro(bool val) = 0;
+
virtual bool enabled_ro() = 0;
+ virtual void enabled_ro(bool val) = 0;
+
virtual bool enabled_rw() = 0;
- virtual void override_flag(std::string const&, bool) {}
+ virtual void enabled_rw(bool val) = 0;
- virtual void reset_overrides() {}
+ virtual void reset_flags() {}
};
extern std::unique_ptr<flag_provider_interface> provider_;
-extern std::string const DISABLED_RO;
-extern std::string const DISABLED_RW;
-extern std::string const ENABLED_RO;
-extern std::string const ENABLED_RW;
-
inline bool disabled_ro() {
return provider_->disabled_ro();
}
+inline void disabled_ro(bool val) {
+ provider_->disabled_ro(val);
+}
+
inline bool disabled_rw() {
return provider_->disabled_rw();
}
+inline void disabled_rw(bool val) {
+ provider_->disabled_rw(val);
+}
+
+inline bool enabled_fixed_ro() {
+ return provider_->enabled_fixed_ro();
+}
+
+inline void enabled_fixed_ro(bool val) {
+ provider_->enabled_fixed_ro(val);
+}
+
inline bool enabled_ro() {
return provider_->enabled_ro();
}
+inline void enabled_ro(bool val) {
+ provider_->enabled_ro(val);
+}
+
inline bool enabled_rw() {
return provider_->enabled_rw();
}
-inline void override_flag(std::string const& name, bool val) {
- return provider_->override_flag(name, val);
+inline void enabled_rw(bool val) {
+ provider_->enabled_rw(val);
}
-inline void reset_overrides() {
- return provider_->reset_overrides();
+inline void reset_flags() {
+ return provider_->reset_flags();
}
}
-#endif
-"#;
- const PROD_FLAG_PROVIDER_HEADER_EXPECTED: &str = r#"
-#ifndef com_android_aconfig_test_flag_provider_HEADER_H
-#define com_android_aconfig_test_flag_provider_HEADER_H
+extern "C" {
+#endif // __cplusplus
-#include "com_android_aconfig_test.h"
+bool com_android_aconfig_test_disabled_ro();
-namespace com::android::aconfig::test {
-class flag_provider : public flag_provider_interface {
-public:
+void set_com_android_aconfig_test_disabled_ro(bool val);
- virtual bool disabled_ro() override {
- return false;
- }
+bool com_android_aconfig_test_disabled_rw();
- virtual bool disabled_rw() override {
- return GetServerConfigurableFlag(
- "aconfig_test",
- "com.android.aconfig.test.disabled_rw",
- "false") == "true";
- }
+void set_com_android_aconfig_test_disabled_rw(bool val);
- virtual bool enabled_ro() override {
- return true;
- }
+bool com_android_aconfig_test_enabled_fixed_ro();
- virtual bool enabled_rw() override {
- return GetServerConfigurableFlag(
- "aconfig_test",
- "com.android.aconfig.test.enabled_rw",
- "true") == "true";
- }
-};
-}
+void set_com_android_aconfig_test_enabled_fixed_ro(bool val);
+
+bool com_android_aconfig_test_enabled_ro();
+
+void set_com_android_aconfig_test_enabled_ro(bool val);
+
+bool com_android_aconfig_test_enabled_rw();
+
+void set_com_android_aconfig_test_enabled_rw(bool val);
+
+void com_android_aconfig_test_reset_flags();
+
+
+#ifdef __cplusplus
+} // extern "C"
#endif
-"#;
- const TEST_FLAG_PROVIDER_HEADER_EXPECTED: &str = r#"
-#ifndef com_android_aconfig_test_flag_provider_HEADER_H
-#define com_android_aconfig_test_flag_provider_HEADER_H
-#include "com_android_aconfig_test.h"
+"#;
-#include <unordered_map>
-#include <unordered_set>
-#include <cassert>
+ const PROD_SOURCE_FILE_EXPECTED: &str = r#"
+#include "com_android_aconfig_test.h"
+#include <server_configurable_flags/get_flags.h>
namespace com::android::aconfig::test {
-class flag_provider : public flag_provider_interface {
-private:
- std::unordered_map<std::string, bool> overrides_;
- std::unordered_set<std::string> flag_names_;
-public:
+ class flag_provider : public flag_provider_interface {
+ public:
- flag_provider()
- : overrides_(),
- flag_names_() {
- flag_names_.insert(DISABLED_RO);
- flag_names_.insert(DISABLED_RW);
- flag_names_.insert(ENABLED_RO);
- flag_names_.insert(ENABLED_RW);
- }
+ virtual bool disabled_ro() override {
+ return false;
+ }
- virtual bool disabled_ro() override {
- auto it = overrides_.find(DISABLED_RO);
- if (it != overrides_.end()) {
- return it->second;
- } else {
- return false;
- }
- }
+ virtual bool disabled_rw() override {
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ "false") == "true";
+ }
- virtual bool disabled_rw() override {
- auto it = overrides_.find(DISABLED_RW);
- if (it != overrides_.end()) {
- return it->second;
- } else {
- return GetServerConfigurableFlag(
- "aconfig_test",
- "com.android.aconfig.test.disabled_rw",
- "false") == "true";
- }
- }
+ virtual bool enabled_fixed_ro() override {
+ return true;
+ }
- virtual bool enabled_ro() override {
- auto it = overrides_.find(ENABLED_RO);
- if (it != overrides_.end()) {
- return it->second;
- } else {
- return true;
- }
- }
+ virtual bool enabled_ro() override {
+ return true;
+ }
- virtual bool enabled_rw() override {
- auto it = overrides_.find(ENABLED_RW);
- if (it != overrides_.end()) {
- return it->second;
- } else {
- return GetServerConfigurableFlag(
- "aconfig_test",
- "com.android.aconfig.test.enabled_rw",
- "true") == "true";
- }
- }
+ virtual bool enabled_rw() override {
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ "true") == "true";
+ }
- virtual void override_flag(std::string const& flag, bool val) override {
- assert(flag_names_.count(flag));
- overrides_[flag] = val;
- }
+ };
- virtual void reset_overrides() override {
- overrides_.clear();
- }
-};
+ std::unique_ptr<flag_provider_interface> provider_ =
+ std::make_unique<flag_provider>();
}
-#endif
+
+bool com_android_aconfig_test_disabled_ro() {
+ return false;
+}
+
+bool com_android_aconfig_test_disabled_rw() {
+ return com::android::aconfig::test::disabled_rw();
+}
+
+bool com_android_aconfig_test_enabled_fixed_ro() {
+ return true;
+}
+
+bool com_android_aconfig_test_enabled_ro() {
+ return true;
+}
+
+bool com_android_aconfig_test_enabled_rw() {
+ return com::android::aconfig::test::enabled_rw();
+}
+
"#;
- const SOURCE_FILE_EXPECTED: &str = r#"
+ const TEST_SOURCE_FILE_EXPECTED: &str = r#"
#include "com_android_aconfig_test.h"
-#include "com_android_aconfig_test_flag_provider.h"
+#include <server_configurable_flags/get_flags.h>
+#include <unordered_map>
namespace com::android::aconfig::test {
- std::string const DISABLED_RO = "com.android.aconfig.test.disabled_ro";
- std::string const DISABLED_RW = "com.android.aconfig.test.disabled_rw";
- std::string const ENABLED_RO = "com.android.aconfig.test.enabled_ro";
- std::string const ENABLED_RW = "com.android.aconfig.test.enabled_rw";
+ class flag_provider : public flag_provider_interface {
+ private:
+ std::unordered_map<std::string, bool> overrides_;
+
+ public:
+ flag_provider()
+ : overrides_()
+ {}
+
+ virtual bool disabled_ro() override {
+ auto it = overrides_.find("disabled_ro");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return false;
+ }
+ }
+
+ virtual void disabled_ro(bool val) override {
+ overrides_["disabled_ro"] = val;
+ }
+
+ virtual bool disabled_rw() override {
+ auto it = overrides_.find("disabled_rw");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ "false") == "true";
+ }
+ }
+
+ virtual void disabled_rw(bool val) override {
+ overrides_["disabled_rw"] = val;
+ }
+
+ virtual bool enabled_fixed_ro() override {
+ auto it = overrides_.find("enabled_fixed_ro");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return true;
+ }
+ }
+
+ virtual void enabled_fixed_ro(bool val) override {
+ overrides_["enabled_fixed_ro"] = val;
+ }
+
+ virtual bool enabled_ro() override {
+ auto it = overrides_.find("enabled_ro");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return true;
+ }
+ }
+
+ virtual void enabled_ro(bool val) override {
+ overrides_["enabled_ro"] = val;
+ }
+
+ virtual bool enabled_rw() override {
+ auto it = overrides_.find("enabled_rw");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ "true") == "true";
+ }
+ }
+
+ virtual void enabled_rw(bool val) override {
+ overrides_["enabled_rw"] = val;
+ }
+
+ virtual void reset_flags() override {
+ overrides_.clear();
+ }
+ };
std::unique_ptr<flag_provider_interface> provider_ =
std::make_unique<flag_provider>();
}
+
+bool com_android_aconfig_test_disabled_ro() {
+ return com::android::aconfig::test::disabled_ro();
+}
+
+
+void set_com_android_aconfig_test_disabled_ro(bool val) {
+ com::android::aconfig::test::disabled_ro(val);
+}
+
+bool com_android_aconfig_test_disabled_rw() {
+ return com::android::aconfig::test::disabled_rw();
+}
+
+
+void set_com_android_aconfig_test_disabled_rw(bool val) {
+ com::android::aconfig::test::disabled_rw(val);
+}
+
+
+bool com_android_aconfig_test_enabled_fixed_ro() {
+ return com::android::aconfig::test::enabled_fixed_ro();
+}
+
+void set_com_android_aconfig_test_enabled_fixed_ro(bool val) {
+ com::android::aconfig::test::enabled_fixed_ro(val);
+}
+
+
+bool com_android_aconfig_test_enabled_ro() {
+ return com::android::aconfig::test::enabled_ro();
+}
+
+
+void set_com_android_aconfig_test_enabled_ro(bool val) {
+ com::android::aconfig::test::enabled_ro(val);
+}
+
+bool com_android_aconfig_test_enabled_rw() {
+ return com::android::aconfig::test::enabled_rw();
+}
+
+
+void set_com_android_aconfig_test_enabled_rw(bool val) {
+ com::android::aconfig::test::enabled_rw(val);
+}
+
+void com_android_aconfig_test_reset_flags() {
+ com::android::aconfig::test::reset_flags();
+}
+
"#;
fn test_generate_cpp_code(mode: CodegenMode) {
@@ -396,7 +518,7 @@ namespace com::android::aconfig::test {
for file in generated {
generated_files_map.insert(
String::from(file.path.to_str().unwrap()),
- String::from_utf8(file.contents.clone()).unwrap(),
+ String::from_utf8(file.contents).unwrap(),
);
}
@@ -413,28 +535,18 @@ namespace com::android::aconfig::test {
)
);
- target_file_path = String::from("com_android_aconfig_test_flag_provider.h");
+ target_file_path = String::from("com_android_aconfig_test.cc");
assert!(generated_files_map.contains_key(&target_file_path));
assert_eq!(
None,
crate::test::first_significant_code_diff(
match mode {
- CodegenMode::Production => PROD_FLAG_PROVIDER_HEADER_EXPECTED,
- CodegenMode::Test => TEST_FLAG_PROVIDER_HEADER_EXPECTED,
+ CodegenMode::Production => PROD_SOURCE_FILE_EXPECTED,
+ CodegenMode::Test => TEST_SOURCE_FILE_EXPECTED,
},
generated_files_map.get(&target_file_path).unwrap()
)
);
-
- target_file_path = String::from("com_android_aconfig_test.cc");
- assert!(generated_files_map.contains_key(&target_file_path));
- assert_eq!(
- None,
- crate::test::first_significant_code_diff(
- SOURCE_FILE_EXPECTED,
- generated_files_map.get(&target_file_path).unwrap()
- )
- );
}
#[test]
diff --git a/tools/aconfig/src/codegen_java.rs b/tools/aconfig/src/codegen_java.rs
index 8ab6ffa8f7..c4fc405a61 100644
--- a/tools/aconfig/src/codegen_java.rs
+++ b/tools/aconfig/src/codegen_java.rs
@@ -47,9 +47,13 @@ where
"FeatureFlags.java",
include_str!("../templates/FeatureFlags.java.template"),
)?;
+ template.add_template(
+ "FakeFeatureFlagsImpl.java",
+ include_str!("../templates/FakeFeatureFlagsImpl.java.template"),
+ )?;
let path: PathBuf = package.split('.').collect();
- ["Flags.java", "FeatureFlagsImpl.java", "FeatureFlags.java"]
+ ["Flags.java", "FeatureFlags.java", "FeatureFlagsImpl.java", "FakeFeatureFlagsImpl.java"]
.iter()
.map(|file| {
Ok(OutputFile {
@@ -112,29 +116,48 @@ mod tests {
use super::*;
use std::collections::HashMap;
- const EXPECTED_FEATUREFLAGS_CONTENT: &str = r#"
+ const EXPECTED_FEATUREFLAGS_COMMON_CONTENT: &str = r#"
package com.android.aconfig.test;
+ /** @hide */
public interface FeatureFlags {
+ @com.android.aconfig.annotations.AssumeFalseForR8
boolean disabledRo();
boolean disabledRw();
+ @com.android.aconfig.annotations.AssumeTrueForR8
+ boolean enabledFixedRo();
+ @com.android.aconfig.annotations.AssumeTrueForR8
boolean enabledRo();
boolean enabledRw();
- }"#;
+ }
+ "#;
const EXPECTED_FLAG_COMMON_CONTENT: &str = r#"
package com.android.aconfig.test;
+ /** @hide */
public final class Flags {
+ /** @hide */
public static final String FLAG_DISABLED_RO = "com.android.aconfig.test.disabled_ro";
+ /** @hide */
public static final String FLAG_DISABLED_RW = "com.android.aconfig.test.disabled_rw";
+ /** @hide */
+ public static final String FLAG_ENABLED_FIXED_RO = "com.android.aconfig.test.enabled_fixed_ro";
+ /** @hide */
public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro";
+ /** @hide */
public static final String FLAG_ENABLED_RW = "com.android.aconfig.test.enabled_rw";
+ @com.android.aconfig.annotations.AssumeFalseForR8
public static boolean disabledRo() {
return FEATURE_FLAGS.disabledRo();
}
public static boolean disabledRw() {
return FEATURE_FLAGS.disabledRw();
}
+ @com.android.aconfig.annotations.AssumeTrueForR8
+ public static boolean enabledFixedRo() {
+ return FEATURE_FLAGS.enabledFixedRo();
+ }
+ @com.android.aconfig.annotations.AssumeTrueForR8
public static boolean enabledRo() {
return FEATURE_FLAGS.enabledRo();
}
@@ -143,6 +166,65 @@ mod tests {
}
"#;
+ const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#"
+ package com.android.aconfig.test;
+ import java.util.HashMap;
+ import java.util.Map;
+ /** @hide */
+ public class FakeFeatureFlagsImpl implements FeatureFlags {
+ public FakeFeatureFlagsImpl() {
+ resetAll();
+ }
+ @Override
+ public boolean disabledRo() {
+ return getValue(Flags.FLAG_DISABLED_RO);
+ }
+ @Override
+ public boolean disabledRw() {
+ return getValue(Flags.FLAG_DISABLED_RW);
+ }
+ @Override
+ public boolean enabledFixedRo() {
+ return getValue(Flags.FLAG_ENABLED_FIXED_RO);
+ }
+ @Override
+ public boolean enabledRo() {
+ return getValue(Flags.FLAG_ENABLED_RO);
+ }
+ @Override
+ public boolean enabledRw() {
+ return getValue(Flags.FLAG_ENABLED_RW);
+ }
+ public void setFlag(String flagName, boolean value) {
+ if (!this.mFlagMap.containsKey(flagName)) {
+ throw new IllegalArgumentException("no such flag " + flagName);
+ }
+ this.mFlagMap.put(flagName, value);
+ }
+ public void resetAll() {
+ for (Map.Entry entry : mFlagMap.entrySet()) {
+ entry.setValue(null);
+ }
+ }
+ private boolean getValue(String flagName) {
+ Boolean value = this.mFlagMap.get(flagName);
+ if (value == null) {
+ throw new IllegalArgumentException(flagName + " is not set");
+ }
+ return value;
+ }
+ private Map<String, Boolean> mFlagMap = new HashMap<>(
+ Map.ofEntries(
+ Map.entry(Flags.FLAG_DISABLED_RO, false),
+ Map.entry(Flags.FLAG_DISABLED_RW, false),
+ Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false),
+ Map.entry(Flags.FLAG_ENABLED_RO, false),
+ Map.entry(Flags.FLAG_ENABLED_RW, false)
+ )
+ );
+ }
+ "#;
+
#[test]
fn test_generate_java_code_production() {
let parsed_flags = crate::test::parse_test_flags();
@@ -156,9 +238,11 @@ mod tests {
+ r#"
private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
}"#;
- let expected_featureflagsimpl_content = r#"
+
+ let expect_featureflagsimpl_content = r#"
package com.android.aconfig.test;
import android.provider.DeviceConfig;
+ /** @hide */
public final class FeatureFlagsImpl implements FeatureFlags {
@Override
public boolean disabledRo() {
@@ -166,30 +250,59 @@ mod tests {
}
@Override
public boolean disabledRw() {
- return DeviceConfig.getBoolean(
+ return getValue(
"aconfig_test",
"com.android.aconfig.test.disabled_rw",
false
);
}
@Override
+ public boolean enabledFixedRo() {
+ return true;
+ }
+ @Override
public boolean enabledRo() {
return true;
}
@Override
public boolean enabledRw() {
- return DeviceConfig.getBoolean(
+ return getValue(
"aconfig_test",
"com.android.aconfig.test.enabled_rw",
true
);
}
+ private boolean getValue(String nameSpace,
+ String flagName, boolean defaultValue) {
+ boolean value = defaultValue;
+ try {
+ value = DeviceConfig.getBoolean(
+ nameSpace,
+ flagName,
+ defaultValue
+ );
+ } catch (NullPointerException e) {
+ throw new RuntimeException(
+ "Cannot read value of flag " + flagName + " from DeviceConfig. " +
+ "It could be that the code using flag executed " +
+ "before SettingsProvider initialization. " +
+ "Please use fixed read-only flag by adding " +
+ "is_fixed_read_only: true in flag declaration.",
+ e
+ );
+ }
+ return value;
+ }
}
"#;
let mut file_set = HashMap::from([
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
- ("com/android/aconfig/test/FeatureFlagsImpl.java", expected_featureflagsimpl_content),
- ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_CONTENT),
+ ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
+ ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
+ (
+ "com/android/aconfig/test/FakeFeatureFlagsImpl.java",
+ EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
+ ),
]);
for file in generated_files {
@@ -199,7 +312,7 @@ mod tests {
None,
crate::test::first_significant_code_diff(
file_set.get(file_path).unwrap(),
- &String::from_utf8(file.contents.clone()).unwrap()
+ &String::from_utf8(file.contents).unwrap()
),
"File {} content is not correct",
file_path
@@ -219,75 +332,58 @@ mod tests {
CodegenMode::Test,
)
.unwrap();
+
let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string()
+ r#"
- public static void setFeatureFlagsImpl(FeatureFlags featureFlags) {
+ public static void setFeatureFlags(FeatureFlags featureFlags) {
Flags.FEATURE_FLAGS = featureFlags;
}
- public static void unsetFeatureFlagsImpl() {
+ public static void unsetFeatureFlags() {
Flags.FEATURE_FLAGS = null;
}
private static FeatureFlags FEATURE_FLAGS;
}
"#;
- let expected_featureflagsimpl_content = r#"
+ let expect_featureflagsimpl_content = r#"
package com.android.aconfig.test;
- import static java.util.stream.Collectors.toMap;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.stream.Stream;
+ /** @hide */
public final class FeatureFlagsImpl implements FeatureFlags {
@Override
public boolean disabledRo() {
- return getFlag(Flags.FLAG_DISABLED_RO);
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
}
@Override
public boolean disabledRw() {
- return getFlag(Flags.FLAG_DISABLED_RW);
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
+ }
+ @Override
+ public boolean enabledFixedRo() {
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
}
@Override
public boolean enabledRo() {
- return getFlag(Flags.FLAG_ENABLED_RO);
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
}
@Override
public boolean enabledRw() {
- return getFlag(Flags.FLAG_ENABLED_RW);
- }
- public void setFlag(String flagName, boolean value) {
- if (!this.mFlagMap.containsKey(flagName)) {
- throw new IllegalArgumentException("no such flag" + flagName);
- }
- this.mFlagMap.put(flagName, value);
- }
- public void resetAll() {
- for (Map.Entry entry : mFlagMap.entrySet()) {
- entry.setValue(null);
- }
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
}
- private boolean getFlag(String flagName) {
- Boolean value = this.mFlagMap.get(flagName);
- if (value == null) {
- throw new IllegalArgumentException(flagName + " is not set");
- }
- return value;
- }
- private HashMap<String, Boolean> mFlagMap = Stream.of(
- Flags.FLAG_DISABLED_RO,
- Flags.FLAG_DISABLED_RW,
- Flags.FLAG_ENABLED_RO,
- Flags.FLAG_ENABLED_RW
- )
- .collect(
- HashMap::new,
- (map, elem) -> map.put(elem, null),
- HashMap::putAll
- );
}
"#;
+
let mut file_set = HashMap::from([
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
- ("com/android/aconfig/test/FeatureFlagsImpl.java", expected_featureflagsimpl_content),
- ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_CONTENT),
+ ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
+ ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
+ (
+ "com/android/aconfig/test/FakeFeatureFlagsImpl.java",
+ EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
+ ),
]);
for file in generated_files {
@@ -297,7 +393,7 @@ mod tests {
None,
crate::test::first_significant_code_diff(
file_set.get(file_path).unwrap(),
- &String::from_utf8(file.contents.clone()).unwrap()
+ &String::from_utf8(file.contents).unwrap()
),
"File {} content is not correct",
file_path
diff --git a/tools/aconfig/src/codegen_rust.rs b/tools/aconfig/src/codegen_rust.rs
index f931418a7b..4e4c7dd58a 100644
--- a/tools/aconfig/src/codegen_rust.rs
+++ b/tools/aconfig/src/codegen_rust.rs
@@ -19,10 +19,14 @@ use serde::Serialize;
use tinytemplate::TinyTemplate;
use crate::codegen;
-use crate::commands::OutputFile;
+use crate::commands::{CodegenMode, OutputFile};
use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
-pub fn generate_rust_code<'a, I>(package: &str, parsed_flags_iter: I) -> Result<OutputFile>
+pub fn generate_rust_code<'a, I>(
+ package: &str,
+ parsed_flags_iter: I,
+ codegen_mode: CodegenMode,
+) -> Result<OutputFile>
where
I: Iterator<Item = &'a ProtoParsedFlag>,
{
@@ -34,7 +38,13 @@ where
modules: package.split('.').map(|s| s.to_string()).collect::<Vec<_>>(),
};
let mut template = TinyTemplate::new();
- template.add_template("rust_code_gen", include_str!("../templates/rust.template"))?;
+ template.add_template(
+ "rust_code_gen",
+ match codegen_mode {
+ CodegenMode::Production => include_str!("../templates/rust_prod.template"),
+ CodegenMode::Test => include_str!("../templates/rust_test.template"),
+ },
+ )?;
let contents = template.render("rust_code_gen", &context)?;
let path = ["src", "lib.rs"].iter().collect();
Ok(OutputFile { contents: contents.into(), path })
@@ -49,41 +59,27 @@ struct TemplateContext {
#[derive(Serialize)]
struct TemplateParsedFlag {
+ pub readwrite: bool,
+ pub default_value: String,
pub name: String,
pub device_config_namespace: String,
pub device_config_flag: String,
-
- // TinyTemplate's conditionals are limited to single <bool> expressions; list all options here
- // Invariant: exactly one of these fields will be true
- pub is_read_only_enabled: bool,
- pub is_read_only_disabled: bool,
- pub is_read_write: bool,
}
impl TemplateParsedFlag {
#[allow(clippy::nonminimal_bool)]
fn new(package: &str, pf: &ProtoParsedFlag) -> Self {
let template = TemplateParsedFlag {
+ readwrite: pf.permission() == ProtoFlagPermission::READ_WRITE,
+ default_value: match pf.state() {
+ ProtoFlagState::ENABLED => "true".to_string(),
+ ProtoFlagState::DISABLED => "false".to_string(),
+ },
name: pf.name().to_string(),
device_config_namespace: pf.namespace().to_string(),
device_config_flag: codegen::create_device_config_ident(package, pf.name())
.expect("values checked at flag parse time"),
- is_read_only_enabled: pf.permission() == ProtoFlagPermission::READ_ONLY
- && pf.state() == ProtoFlagState::ENABLED,
- is_read_only_disabled: pf.permission() == ProtoFlagPermission::READ_ONLY
- && pf.state() == ProtoFlagState::DISABLED,
- is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE,
};
- #[rustfmt::skip]
- debug_assert!(
- (template.is_read_only_enabled && !template.is_read_only_disabled && !template.is_read_write) ||
- (!template.is_read_only_enabled && template.is_read_only_disabled && !template.is_read_write) ||
- (!template.is_read_only_enabled && !template.is_read_only_disabled && template.is_read_write),
- "TemplateParsedFlag invariant failed: {} {} {}",
- template.is_read_only_enabled,
- template.is_read_only_disabled,
- template.is_read_write,
- );
template
}
}
@@ -92,48 +88,259 @@ impl TemplateParsedFlag {
mod tests {
use super::*;
- #[test]
- fn test_generate_rust_code() {
- let parsed_flags = crate::test::parse_test_flags();
- let generated =
- generate_rust_code(crate::test::TEST_PACKAGE, parsed_flags.parsed_flag.iter()).unwrap();
- assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
- let expected = r#"
-pub mod com {
-pub mod android {
-pub mod aconfig {
-pub mod test {
+ const PROD_EXPECTED: &str = r#"
+//! codegenerated rust flag lib
+
+/// flag provider
+pub struct FlagProvider;
+
+impl FlagProvider {
+ /// query flag disabled_ro
+ pub fn disabled_ro(&self) -> bool {
+ false
+ }
+
+ /// query flag disabled_rw
+ pub fn disabled_rw(&self) -> bool {
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ "false") == "true"
+ }
+
+ /// query flag enabled_fixed_ro
+ pub fn enabled_fixed_ro(&self) -> bool {
+ true
+ }
+
+ /// query flag enabled_ro
+ pub fn enabled_ro(&self) -> bool {
+ true
+ }
+
+ /// query flag enabled_rw
+ pub fn enabled_rw(&self) -> bool {
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ "true") == "true"
+ }
+}
+
+/// flag provider
+pub static PROVIDER: FlagProvider = FlagProvider;
+
+/// query flag disabled_ro
#[inline(always)]
-pub const fn r#disabled_ro() -> bool {
+pub fn disabled_ro() -> bool {
false
}
+/// query flag disabled_rw
#[inline(always)]
-pub fn r#disabled_rw() -> bool {
- flags_rust::GetServerConfigurableFlag("aconfig_test", "com.android.aconfig.test.disabled_rw", "false") == "true"
+pub fn disabled_rw() -> bool {
+ PROVIDER.disabled_rw()
}
+/// query flag enabled_fixed_ro
#[inline(always)]
-pub const fn r#enabled_ro() -> bool {
+pub fn enabled_fixed_ro() -> bool {
true
}
+/// query flag enabled_ro
+#[inline(always)]
+pub fn enabled_ro() -> bool {
+ true
+}
+
+/// query flag enabled_rw
+#[inline(always)]
+pub fn enabled_rw() -> bool {
+ PROVIDER.enabled_rw()
+}
+"#;
+
+ const TEST_EXPECTED: &str = r#"
+//! codegenerated rust flag lib
+
+use std::collections::BTreeMap;
+use std::sync::Mutex;
+
+/// flag provider
+pub struct FlagProvider {
+ overrides: BTreeMap<&'static str, bool>,
+}
+
+impl FlagProvider {
+ /// query flag disabled_ro
+ pub fn disabled_ro(&self) -> bool {
+ self.overrides.get("disabled_ro").copied().unwrap_or(
+ false
+ )
+ }
+
+ /// set flag disabled_ro
+ pub fn set_disabled_ro(&mut self, val: bool) {
+ self.overrides.insert("disabled_ro", val);
+ }
+
+ /// query flag disabled_rw
+ pub fn disabled_rw(&self) -> bool {
+ self.overrides.get("disabled_rw").copied().unwrap_or(
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ "false") == "true"
+ )
+ }
+
+ /// set flag disabled_rw
+ pub fn set_disabled_rw(&mut self, val: bool) {
+ self.overrides.insert("disabled_rw", val);
+ }
+
+ /// query flag enabled_fixed_ro
+ pub fn enabled_fixed_ro(&self) -> bool {
+ self.overrides.get("enabled_fixed_ro").copied().unwrap_or(
+ true
+ )
+ }
+
+ /// set flag enabled_fixed_ro
+ pub fn set_enabled_fixed_ro(&mut self, val: bool) {
+ self.overrides.insert("enabled_fixed_ro", val);
+ }
+
+ /// query flag enabled_ro
+ pub fn enabled_ro(&self) -> bool {
+ self.overrides.get("enabled_ro").copied().unwrap_or(
+ true
+ )
+ }
+
+ /// set flag enabled_ro
+ pub fn set_enabled_ro(&mut self, val: bool) {
+ self.overrides.insert("enabled_ro", val);
+ }
+
+ /// query flag enabled_rw
+ pub fn enabled_rw(&self) -> bool {
+ self.overrides.get("enabled_rw").copied().unwrap_or(
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ "true") == "true"
+ )
+ }
+
+ /// set flag enabled_rw
+ pub fn set_enabled_rw(&mut self, val: bool) {
+ self.overrides.insert("enabled_rw", val);
+ }
+
+ /// clear all flag overrides
+ pub fn reset_flags(&mut self) {
+ self.overrides.clear();
+ }
+}
+
+/// flag provider
+pub static PROVIDER: Mutex<FlagProvider> = Mutex::new(
+ FlagProvider {overrides: BTreeMap::new()}
+);
+
+/// query flag disabled_ro
#[inline(always)]
-pub fn r#enabled_rw() -> bool {
- flags_rust::GetServerConfigurableFlag("aconfig_test", "com.android.aconfig.test.enabled_rw", "false") == "true"
+pub fn disabled_ro() -> bool {
+ PROVIDER.lock().unwrap().disabled_ro()
}
+/// set flag disabled_ro
+#[inline(always)]
+pub fn set_disabled_ro(val: bool) {
+ PROVIDER.lock().unwrap().set_disabled_ro(val);
}
+
+/// query flag disabled_rw
+#[inline(always)]
+pub fn disabled_rw() -> bool {
+ PROVIDER.lock().unwrap().disabled_rw()
}
+
+/// set flag disabled_rw
+#[inline(always)]
+pub fn set_disabled_rw(val: bool) {
+ PROVIDER.lock().unwrap().set_disabled_rw(val);
}
+
+/// query flag enabled_fixed_ro
+#[inline(always)]
+pub fn enabled_fixed_ro() -> bool {
+ PROVIDER.lock().unwrap().enabled_fixed_ro()
+}
+
+/// set flag enabled_fixed_ro
+#[inline(always)]
+pub fn set_enabled_fixed_ro(val: bool) {
+ PROVIDER.lock().unwrap().set_enabled_fixed_ro(val);
+}
+
+/// query flag enabled_ro
+#[inline(always)]
+pub fn enabled_ro() -> bool {
+ PROVIDER.lock().unwrap().enabled_ro()
+}
+
+/// set flag enabled_ro
+#[inline(always)]
+pub fn set_enabled_ro(val: bool) {
+ PROVIDER.lock().unwrap().set_enabled_ro(val);
+}
+
+/// query flag enabled_rw
+#[inline(always)]
+pub fn enabled_rw() -> bool {
+ PROVIDER.lock().unwrap().enabled_rw()
+}
+
+/// set flag enabled_rw
+#[inline(always)]
+pub fn set_enabled_rw(val: bool) {
+ PROVIDER.lock().unwrap().set_enabled_rw(val);
+}
+
+/// clear all flag override
+pub fn reset_flags() {
+ PROVIDER.lock().unwrap().reset_flags()
}
"#;
+
+ fn test_generate_rust_code(mode: CodegenMode) {
+ let parsed_flags = crate::test::parse_test_flags();
+ let generated =
+ generate_rust_code(crate::test::TEST_PACKAGE, parsed_flags.parsed_flag.iter(), mode)
+ .unwrap();
+ assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
assert_eq!(
None,
crate::test::first_significant_code_diff(
- expected,
+ match mode {
+ CodegenMode::Production => PROD_EXPECTED,
+ CodegenMode::Test => TEST_EXPECTED,
+ },
&String::from_utf8(generated.contents).unwrap()
)
);
}
+
+ #[test]
+ fn test_generate_rust_code_for_prod() {
+ test_generate_rust_code(CodegenMode::Production);
+ }
+
+ #[test]
+ fn test_generate_rust_code_for_test() {
+ test_generate_rust_code(CodegenMode::Test);
+ }
}
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index 687f3195cf..7b051471aa 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -35,8 +35,15 @@ pub struct Input {
impl Input {
fn try_parse_flags(&mut self) -> Result<ProtoParsedFlags> {
let mut buffer = Vec::new();
- self.reader.read_to_end(&mut buffer)?;
+ self.reader
+ .read_to_end(&mut buffer)
+ .with_context(|| format!("failed to read {}", self.source))?;
crate::protos::parsed_flags::try_from_binary_proto(&buffer)
+ .with_context(|| self.error_context())
+ }
+
+ fn error_context(&self) -> String {
+ format!("failed to parse {}", self.source)
}
}
@@ -45,28 +52,36 @@ pub struct OutputFile {
pub contents: Vec<u8>,
}
-const DEFAULT_FLAG_STATE: ProtoFlagState = ProtoFlagState::DISABLED;
-const DEFAULT_FLAG_PERMISSION: ProtoFlagPermission = ProtoFlagPermission::READ_WRITE;
+pub const DEFAULT_FLAG_STATE: ProtoFlagState = ProtoFlagState::DISABLED;
+pub const DEFAULT_FLAG_PERMISSION: ProtoFlagPermission = ProtoFlagPermission::READ_WRITE;
-pub fn parse_flags(package: &str, declarations: Vec<Input>, values: Vec<Input>) -> Result<Vec<u8>> {
+pub fn parse_flags(
+ package: &str,
+ declarations: Vec<Input>,
+ values: Vec<Input>,
+ default_permission: ProtoFlagPermission,
+) -> Result<Vec<u8>> {
let mut parsed_flags = ProtoParsedFlags::new();
for mut input in declarations {
let mut contents = String::new();
- input.reader.read_to_string(&mut contents)?;
+ input
+ .reader
+ .read_to_string(&mut contents)
+ .with_context(|| format!("failed to read {}", input.source))?;
let flag_declarations = crate::protos::flag_declarations::try_from_text_proto(&contents)
- .with_context(|| format!("Failed to parse {}", input.source))?;
+ .with_context(|| input.error_context())?;
ensure!(
package == flag_declarations.package(),
- "Failed to parse {}: expected package {}, got {}",
+ "failed to parse {}: expected package {}, got {}",
input.source,
package,
flag_declarations.package()
);
for mut flag_declaration in flag_declarations.flag.into_iter() {
crate::protos::flag_declaration::verify_fields(&flag_declaration)
- .with_context(|| format!("Failed to parse {}", input.source))?;
+ .with_context(|| input.error_context())?;
// create ParsedFlag using FlagDeclaration and default values
let mut parsed_flag = ProtoParsedFlag::new();
@@ -76,11 +91,17 @@ pub fn parse_flags(package: &str, declarations: Vec<Input>, values: Vec<Input>)
parsed_flag.set_description(flag_declaration.take_description());
parsed_flag.bug.append(&mut flag_declaration.bug);
parsed_flag.set_state(DEFAULT_FLAG_STATE);
- parsed_flag.set_permission(DEFAULT_FLAG_PERMISSION);
+ let flag_permission = if flag_declaration.is_fixed_read_only() {
+ ProtoFlagPermission::READ_ONLY
+ } else {
+ default_permission
+ };
+ parsed_flag.set_permission(flag_permission);
+ parsed_flag.set_is_fixed_read_only(flag_declaration.is_fixed_read_only());
let mut tracepoint = ProtoTracepoint::new();
tracepoint.set_source(input.source.clone());
tracepoint.set_state(DEFAULT_FLAG_STATE);
- tracepoint.set_permission(DEFAULT_FLAG_PERMISSION);
+ tracepoint.set_permission(flag_permission);
parsed_flag.trace.push(tracepoint);
// verify ParsedFlag looks reasonable
@@ -101,18 +122,32 @@ pub fn parse_flags(package: &str, declarations: Vec<Input>, values: Vec<Input>)
for mut input in values {
let mut contents = String::new();
- input.reader.read_to_string(&mut contents)?;
+ input
+ .reader
+ .read_to_string(&mut contents)
+ .with_context(|| format!("failed to read {}", input.source))?;
let flag_values = crate::protos::flag_values::try_from_text_proto(&contents)
- .with_context(|| format!("Failed to parse {}", input.source))?;
+ .with_context(|| input.error_context())?;
for flag_value in flag_values.flag_value.into_iter() {
crate::protos::flag_value::verify_fields(&flag_value)
- .with_context(|| format!("Failed to parse {}", input.source))?;
+ .with_context(|| input.error_context())?;
- let Some(parsed_flag) = parsed_flags.parsed_flag.iter_mut().find(|pf| pf.package() == flag_value.package() && pf.name() == flag_value.name()) else {
+ let Some(parsed_flag) = parsed_flags
+ .parsed_flag
+ .iter_mut()
+ .find(|pf| pf.package() == flag_value.package() && pf.name() == flag_value.name())
+ else {
// (silently) skip unknown flags
continue;
};
+ ensure!(
+ !parsed_flag.is_fixed_read_only()
+ || flag_value.permission() == ProtoFlagPermission::READ_ONLY,
+ "failed to set permission of flag {}, since this flag is fixed read only flag",
+ flag_value.name()
+ );
+
parsed_flag.set_state(flag_value.state());
parsed_flag.set_permission(flag_value.permission());
let mut tracepoint = ProtoTracepoint::new();
@@ -123,6 +158,8 @@ pub fn parse_flags(package: &str, declarations: Vec<Input>, values: Vec<Input>)
}
}
+ // Create a sorted parsed_flags
+ crate::protos::parsed_flags::sort_parsed_flags(&mut parsed_flags);
crate::protos::parsed_flags::verify_fields(&parsed_flags)?;
let mut output = Vec::new();
parsed_flags.write_to_vec(&mut output)?;
@@ -151,12 +188,12 @@ pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec
generate_cpp_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
}
-pub fn create_rust_lib(mut input: Input) -> Result<OutputFile> {
+pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
let parsed_flags = input.try_parse_flags()?;
let Some(package) = find_unique_package(&parsed_flags) else {
bail!("no parsed flags, or the parsed flags use different packages");
};
- generate_rust_code(package, parsed_flags.parsed_flag.iter())
+ generate_rust_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
}
pub fn create_device_config_defaults(mut input: Input) -> Result<Vec<u8>> {
@@ -207,7 +244,7 @@ pub fn create_device_config_sysprops(mut input: Input) -> Result<Vec<u8>> {
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
pub enum DumpFormat {
Text,
- Debug,
+ Verbose,
Protobuf,
Textproto,
}
@@ -223,18 +260,27 @@ pub fn dump_parsed_flags(mut input: Vec<Input>, format: DumpFormat) -> Result<Ve
DumpFormat::Text => {
for parsed_flag in parsed_flags.parsed_flag.into_iter() {
let line = format!(
- "{}/{}: {:?} {:?}\n",
+ "{}.{}: {:?} + {:?}\n",
parsed_flag.package(),
parsed_flag.name(),
- parsed_flag.state(),
- parsed_flag.permission()
+ parsed_flag.permission(),
+ parsed_flag.state()
);
output.extend_from_slice(line.as_bytes());
}
}
- DumpFormat::Debug => {
+ DumpFormat::Verbose => {
for parsed_flag in parsed_flags.parsed_flag.into_iter() {
- let line = format!("{:#?}\n", parsed_flag);
+ let sources: Vec<_> =
+ parsed_flag.trace.iter().map(|tracepoint| tracepoint.source()).collect();
+ let line = format!(
+ "{}.{}: {:?} + {:?} ({})\n",
+ parsed_flag.package(),
+ parsed_flag.name(),
+ parsed_flag.permission(),
+ parsed_flag.state(),
+ sources.join(", ")
+ );
output.extend_from_slice(line.as_bytes());
}
}
@@ -277,6 +323,7 @@ mod tests {
assert_eq!(ProtoFlagState::ENABLED, enabled_ro.state());
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.permission());
assert_eq!(3, enabled_ro.trace.len());
+ assert!(!enabled_ro.is_fixed_read_only());
assert_eq!("tests/test.aconfig", enabled_ro.trace[0].source());
assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[0].state());
assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[0].permission());
@@ -287,8 +334,11 @@ mod tests {
assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
- assert_eq!(4, parsed_flags.parsed_flag.len());
+ assert_eq!(5, parsed_flags.parsed_flag.len());
for pf in parsed_flags.parsed_flag.iter() {
+ if pf.name() == "enabled_fixed_ro" {
+ continue;
+ }
let first = pf.trace.first().unwrap();
assert_eq!(DEFAULT_FLAG_STATE, first.state());
assert_eq!(DEFAULT_FLAG_PERMISSION, first.permission());
@@ -297,6 +347,85 @@ mod tests {
assert_eq!(pf.state(), last.state());
assert_eq!(pf.permission(), last.permission());
}
+
+ let enabled_fixed_ro =
+ parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_fixed_ro").unwrap();
+ assert!(enabled_fixed_ro.is_fixed_read_only());
+ assert_eq!(ProtoFlagState::ENABLED, enabled_fixed_ro.state());
+ assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.permission());
+ assert_eq!(2, enabled_fixed_ro.trace.len());
+ assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[0].permission());
+ assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[1].permission());
+ }
+
+ #[test]
+ fn test_parse_flags_setting_default() {
+ let first_flag = r#"
+ package: "com.first"
+ flag {
+ name: "first"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+ bug: "123"
+ }
+ "#;
+ let declaration =
+ vec![Input { source: "momery".to_string(), reader: Box::new(first_flag.as_bytes()) }];
+ let value: Vec<Input> = vec![];
+
+ let flags_bytes = crate::commands::parse_flags(
+ "com.first",
+ declaration,
+ value,
+ ProtoFlagPermission::READ_ONLY,
+ )
+ .unwrap();
+ let parsed_flags =
+ crate::protos::parsed_flags::try_from_binary_proto(&flags_bytes).unwrap();
+ assert_eq!(1, parsed_flags.parsed_flag.len());
+ let parsed_flag = parsed_flags.parsed_flag.first().unwrap();
+ assert_eq!(ProtoFlagState::DISABLED, parsed_flag.state());
+ assert_eq!(ProtoFlagPermission::READ_ONLY, parsed_flag.permission());
+ }
+
+ #[test]
+ fn test_parse_flags_override_fixed_read_only() {
+ let first_flag = r#"
+ package: "com.first"
+ flag {
+ name: "first"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+ bug: "123"
+ is_fixed_read_only: true
+ }
+ "#;
+ let declaration =
+ vec![Input { source: "memory".to_string(), reader: Box::new(first_flag.as_bytes()) }];
+
+ let first_flag_value = r#"
+ flag_value {
+ package: "com.first"
+ name: "first"
+ state: DISABLED
+ permission: READ_WRITE
+ }
+ "#;
+ let value = vec![Input {
+ source: "memory".to_string(),
+ reader: Box::new(first_flag_value.as_bytes()),
+ }];
+ let error = crate::commands::parse_flags(
+ "com.first",
+ declaration,
+ value,
+ ProtoFlagPermission::READ_WRITE,
+ )
+ .unwrap_err();
+ assert_eq!(
+ format!("{:?}", error),
+ "failed to set permission of flag first, since this flag is fixed read only flag"
+ );
}
#[test]
@@ -320,7 +449,7 @@ mod tests {
let input = parse_test_flags_as_input();
let bytes = dump_parsed_flags(vec![input], DumpFormat::Text).unwrap();
let text = std::str::from_utf8(&bytes).unwrap();
- assert!(text.contains("com.android.aconfig.test/disabled_ro: DISABLED READ_ONLY"));
+ assert!(text.contains("com.android.aconfig.test.disabled_ro: READ_ONLY + DISABLED"));
}
#[test]
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index 72feb9406f..7e44baf3c9 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -16,7 +16,7 @@
//! `aconfig` is a build time tool to manage build time configurations, such as feature flags.
-use anyhow::{anyhow, bail, ensure, Result};
+use anyhow::{anyhow, bail, Context, Result};
use clap::{builder::ArgAction, builder::EnumValueParser, Arg, ArgMatches, Command};
use core::any::Any;
use std::fs;
@@ -44,6 +44,14 @@ fn cli() -> Command {
.arg(Arg::new("package").long("package").required(true))
.arg(Arg::new("declarations").long("declarations").action(ArgAction::Append))
.arg(Arg::new("values").long("values").action(ArgAction::Append))
+ .arg(
+ Arg::new("default-permission")
+ .long("default-permission")
+ .value_parser(protos::flag_permission::parse_from_str)
+ .default_value(protos::flag_permission::to_string(
+ &commands::DEFAULT_FLAG_PERMISSION,
+ )),
+ )
.arg(Arg::new("cache").long("cache").required(true)),
)
.subcommand(
@@ -71,7 +79,13 @@ fn cli() -> Command {
.subcommand(
Command::new("create-rust-lib")
.arg(Arg::new("cache").long("cache").required(true))
- .arg(Arg::new("out").long("out").required(true)),
+ .arg(Arg::new("out").long("out").required(true))
+ .arg(
+ Arg::new("mode")
+ .long("mode")
+ .value_parser(EnumValueParser::<commands::CodegenMode>::new())
+ .default_value("production"),
+ ),
)
.subcommand(
Command::new("create-device-config-defaults")
@@ -123,26 +137,27 @@ fn open_single_file(matches: &ArgMatches, arg_name: &str) -> Result<Input> {
}
fn write_output_file_realtive_to_dir(root: &Path, output_file: &OutputFile) -> Result<()> {
- ensure!(
- root.is_dir(),
- "output directory {} does not exist or is not a directory",
- root.display()
- );
- let path = root.join(output_file.path.clone());
+ let path = root.join(&output_file.path);
let parent = path
.parent()
.ok_or(anyhow!("unable to locate parent of output file {}", path.display()))?;
- fs::create_dir_all(parent)?;
- let mut file = fs::File::create(path)?;
- file.write_all(&output_file.contents)?;
+ fs::create_dir_all(parent)
+ .with_context(|| format!("failed to create directory {}", parent.display()))?;
+ let mut file =
+ fs::File::create(&path).with_context(|| format!("failed to open {}", path.display()))?;
+ file.write_all(&output_file.contents)
+ .with_context(|| format!("failed to write to {}", path.display()))?;
Ok(())
}
fn write_output_to_file_or_stdout(path: &str, data: &[u8]) -> Result<()> {
if path == "-" {
- io::stdout().write_all(data)?;
+ io::stdout().write_all(data).context("failed to write to stdout")?;
} else {
- fs::File::create(path)?.write_all(data)?;
+ fs::File::create(path)
+ .with_context(|| format!("failed to open {}", path))?
+ .write_all(data)
+ .with_context(|| format!("failed to write to {}", path))?;
}
Ok(())
}
@@ -154,14 +169,18 @@ fn main() -> Result<()> {
let package = get_required_arg::<String>(sub_matches, "package")?;
let declarations = open_zero_or_more_files(sub_matches, "declarations")?;
let values = open_zero_or_more_files(sub_matches, "values")?;
- let output = commands::parse_flags(package, declarations, values)?;
+ let default_permission =
+ get_required_arg::<protos::ProtoFlagPermission>(sub_matches, "default-permission")?;
+ let output = commands::parse_flags(package, declarations, values, *default_permission)
+ .context("failed to create cache")?;
let path = get_required_arg::<String>(sub_matches, "cache")?;
write_output_to_file_or_stdout(path, &output)?;
}
Some(("create-java-lib", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
- let generated_files = commands::create_java_lib(cache, *mode)?;
+ let generated_files =
+ commands::create_java_lib(cache, *mode).context("failed to create java lib")?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
generated_files
.iter()
@@ -170,7 +189,8 @@ fn main() -> Result<()> {
Some(("create-cpp-lib", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
- let generated_files = commands::create_cpp_lib(cache, *mode)?;
+ let generated_files =
+ commands::create_cpp_lib(cache, *mode).context("failed to create cpp lib")?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
generated_files
.iter()
@@ -178,25 +198,30 @@ fn main() -> Result<()> {
}
Some(("create-rust-lib", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
- let generated_file = commands::create_rust_lib(cache)?;
+ let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
+ let generated_file =
+ commands::create_rust_lib(cache, *mode).context("failed to create rust lib")?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
write_output_file_realtive_to_dir(&dir, &generated_file)?;
}
Some(("create-device-config-defaults", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
- let output = commands::create_device_config_defaults(cache)?;
+ let output = commands::create_device_config_defaults(cache)
+ .context("failed to create device config defaults")?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
}
Some(("create-device-config-sysprops", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
- let output = commands::create_device_config_sysprops(cache)?;
+ let output = commands::create_device_config_sysprops(cache)
+ .context("failed to create device config sysprops")?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
}
Some(("dump", sub_matches)) => {
let input = open_zero_or_more_files(sub_matches, "cache")?;
- let format = get_required_arg::<DumpFormat>(sub_matches, "format")?;
+ let format = get_required_arg::<DumpFormat>(sub_matches, "format")
+ .context("failed to dump previously parsed flags")?;
let output = commands::dump_parsed_flags(input, *format)?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
diff --git a/tools/aconfig/src/protos.rs b/tools/aconfig/src/protos.rs
index 17019becac..d3b5b378b2 100644
--- a/tools/aconfig/src/protos.rs
+++ b/tools/aconfig/src/protos.rs
@@ -92,8 +92,7 @@ pub mod flag_declaration {
ensure!(codegen::is_valid_name_ident(pdf.name()), "bad flag declaration: bad name");
ensure!(codegen::is_valid_name_ident(pdf.namespace()), "bad flag declaration: bad name");
ensure!(!pdf.description().is_empty(), "bad flag declaration: empty description");
-
- // ProtoFlagDeclaration.bug: Vec<String>: may be empty, no checks needed
+ ensure!(pdf.bug.len() == 1, "bad flag declaration: exactly one bug required");
Ok(())
}
@@ -157,6 +156,26 @@ pub mod flag_values {
}
}
+pub mod flag_permission {
+ use super::*;
+ use anyhow::bail;
+
+ pub fn parse_from_str(permission: &str) -> Result<ProtoFlagPermission> {
+ match permission.to_ascii_lowercase().as_str() {
+ "read_write" => Ok(ProtoFlagPermission::READ_WRITE),
+ "read_only" => Ok(ProtoFlagPermission::READ_ONLY),
+ _ => bail!("Permission needs to be read_only or read_write."),
+ }
+ }
+
+ pub fn to_string(permission: &ProtoFlagPermission) -> &str {
+ match permission {
+ ProtoFlagPermission::READ_WRITE => "read_write",
+ ProtoFlagPermission::READ_ONLY => "read_only",
+ }
+ }
+}
+
pub mod tracepoint {
use super::*;
use anyhow::ensure;
@@ -195,11 +214,26 @@ pub mod parsed_flag {
for tp in pf.trace.iter() {
super::tracepoint::verify_fields(tp)?;
}
-
- // ProtoParsedFlag.bug: Vec<String>: may be empty, no checks needed
+ ensure!(pf.bug.len() == 1, "bad flag declaration: exactly one bug required");
+ if pf.is_fixed_read_only() {
+ ensure!(
+ pf.permission() == ProtoFlagPermission::READ_ONLY,
+ "bad parsed flag: flag is is_fixed_read_only but permission is not READ_ONLY"
+ );
+ for tp in pf.trace.iter() {
+ ensure!(tp.permission() == ProtoFlagPermission::READ_ONLY,
+ "bad parsed flag: flag is is_fixed_read_only but a tracepoint's permission is not READ_ONLY"
+ );
+ }
+ }
Ok(())
}
+
+ pub fn path_to_declaration(pf: &ProtoParsedFlag) -> &str {
+ debug_assert!(!pf.trace.is_empty());
+ pf.trace[0].source()
+ }
}
pub mod parsed_flags {
@@ -214,6 +248,8 @@ pub mod parsed_flags {
}
pub fn verify_fields(pf: &ProtoParsedFlags) -> Result<()> {
+ use crate::protos::parsed_flag::path_to_declaration;
+
let mut previous: Option<&ProtoParsedFlag> = None;
for parsed_flag in pf.parsed_flag.iter() {
if let Some(prev) = previous {
@@ -221,7 +257,12 @@ pub mod parsed_flags {
let b = create_sorting_key(parsed_flag);
match a.cmp(&b) {
Ordering::Less => {}
- Ordering::Equal => bail!("bad parsed flags: duplicate flag {}", a),
+ Ordering::Equal => bail!(
+ "bad parsed flags: duplicate flag {} (defined in {} and {})",
+ a,
+ path_to_declaration(prev),
+ path_to_declaration(parsed_flag)
+ ),
Ordering::Greater => {
bail!("bad parsed flags: not sorted: {} comes before {}", a, b)
}
@@ -243,6 +284,10 @@ pub mod parsed_flags {
Ok(merged)
}
+ pub fn sort_parsed_flags(pf: &mut ProtoParsedFlags) {
+ pf.parsed_flag.sort_by_key(create_sorting_key);
+ }
+
fn create_sorting_key(pf: &ProtoParsedFlag) -> String {
format!("{}.{}", pf.package(), pf.name())
}
@@ -263,12 +308,13 @@ flag {
namespace: "first_ns"
description: "This is the description of the first flag."
bug: "123"
- bug: "abc"
}
flag {
name: "second"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: "abc"
+ is_fixed_read_only: true
}
"#,
)
@@ -278,14 +324,14 @@ flag {
assert_eq!(first.name(), "first");
assert_eq!(first.namespace(), "first_ns");
assert_eq!(first.description(), "This is the description of the first flag.");
- assert_eq!(first.bug.len(), 2);
- assert_eq!(first.bug[0], "123");
- assert_eq!(first.bug[1], "abc");
+ assert_eq!(first.bug, vec!["123"]);
+ assert!(!first.is_fixed_read_only());
let second = flag_declarations.flag.iter().find(|pf| pf.name() == "second").unwrap();
assert_eq!(second.name(), "second");
assert_eq!(second.namespace(), "second_ns");
assert_eq!(second.description(), "This is the description of the second flag.");
- assert_eq!(second.bug.len(), 0);
+ assert_eq!(second.bug, vec!["abc"]);
+ assert!(second.is_fixed_read_only());
// bad input: missing package in flag declarations
let error = flag_declarations::try_from_text_proto(
@@ -360,6 +406,36 @@ flag {
)
.unwrap_err();
assert!(format!("{:?}", error).contains("bad flag declaration: bad name"));
+
+ // bad input: no bug entries in flag declaration
+ let error = flag_declarations::try_from_text_proto(
+ r#"
+package: "com.foo.bar"
+flag {
+ name: "first"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+}
+"#,
+ )
+ .unwrap_err();
+ assert!(format!("{:?}", error).contains("bad flag declaration: exactly one bug required"));
+
+ // bad input: multiple bug entries in flag declaration
+ let error = flag_declarations::try_from_text_proto(
+ r#"
+package: "com.foo.bar"
+flag {
+ name: "first"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+ bug: "123"
+ bug: "abc"
+}
+"#,
+ )
+ .unwrap_err();
+ assert!(format!("{:?}", error).contains("bad flag declaration: exactly one bug required"));
}
#[test]
@@ -466,6 +542,7 @@ parsed_flag {
name: "first"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: "SOME_BUG"
state: DISABLED
permission: READ_ONLY
trace {
@@ -479,8 +556,9 @@ parsed_flag {
name: "second"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: "SOME_BUG"
state: ENABLED
- permission: READ_WRITE
+ permission: READ_ONLY
trace {
source: "flags.declarations"
state: DISABLED
@@ -489,8 +567,9 @@ parsed_flag {
trace {
source: "flags.values"
state: ENABLED
- permission: READ_WRITE
+ permission: READ_ONLY
}
+ is_fixed_read_only: true
}
"#;
let parsed_flags = try_from_binary_proto_from_text_proto(text_proto).unwrap();
@@ -500,15 +579,17 @@ parsed_flag {
assert_eq!(second.name(), "second");
assert_eq!(second.namespace(), "second_ns");
assert_eq!(second.description(), "This is the description of the second flag.");
+ assert_eq!(second.bug, vec!["SOME_BUG"]);
assert_eq!(second.state(), ProtoFlagState::ENABLED);
- assert_eq!(second.permission(), ProtoFlagPermission::READ_WRITE);
+ assert_eq!(second.permission(), ProtoFlagPermission::READ_ONLY);
assert_eq!(2, second.trace.len());
assert_eq!(second.trace[0].source(), "flags.declarations");
assert_eq!(second.trace[0].state(), ProtoFlagState::DISABLED);
assert_eq!(second.trace[0].permission(), ProtoFlagPermission::READ_ONLY);
assert_eq!(second.trace[1].source(), "flags.values");
assert_eq!(second.trace[1].state(), ProtoFlagState::ENABLED);
- assert_eq!(second.trace[1].permission(), ProtoFlagPermission::READ_WRITE);
+ assert_eq!(second.trace[1].permission(), ProtoFlagPermission::READ_ONLY);
+ assert!(second.is_fixed_read_only());
// valid input: empty
let parsed_flags = try_from_binary_proto_from_text_proto("").unwrap();
@@ -553,6 +634,7 @@ parsed_flag {
name: "first"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: ""
state: DISABLED
permission: READ_ONLY
trace {
@@ -566,6 +648,7 @@ parsed_flag {
name: "second"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: ""
state: ENABLED
permission: READ_WRITE
trace {
@@ -588,6 +671,7 @@ parsed_flag {
name: "bbb"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: ""
state: DISABLED
permission: READ_ONLY
trace {
@@ -601,6 +685,7 @@ parsed_flag {
name: "aaa"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: ""
state: ENABLED
permission: READ_WRITE
trace {
@@ -623,6 +708,7 @@ parsed_flag {
name: "bar"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: ""
state: DISABLED
permission: READ_ONLY
trace {
@@ -636,6 +722,7 @@ parsed_flag {
name: "bar"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: ""
state: ENABLED
permission: READ_WRITE
trace {
@@ -646,7 +733,38 @@ parsed_flag {
}
"#;
let error = try_from_binary_proto_from_text_proto(text_proto).unwrap_err();
- assert_eq!(format!("{:?}", error), "bad parsed flags: duplicate flag com.foo.bar");
+ assert_eq!(format!("{:?}", error), "bad parsed flags: duplicate flag com.foo.bar (defined in flags.declarations and flags.declarations)");
+ }
+
+ #[test]
+ fn test_parsed_flag_path_to_declaration() {
+ let text_proto = r#"
+parsed_flag {
+ package: "com.foo"
+ name: "bar"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+ bug: "b/12345678"
+ state: DISABLED
+ permission: READ_ONLY
+ trace {
+ source: "flags.declarations"
+ state: DISABLED
+ permission: READ_ONLY
+ }
+ trace {
+ source: "flags.values"
+ state: ENABLED
+ permission: READ_ONLY
+ }
+}
+"#;
+ let parsed_flags = try_from_binary_proto_from_text_proto(text_proto).unwrap();
+ let parsed_flag = &parsed_flags.parsed_flag[0];
+ assert_eq!(
+ crate::protos::parsed_flag::path_to_declaration(parsed_flag),
+ "flags.declarations"
+ );
}
#[test]
@@ -657,6 +775,7 @@ parsed_flag {
name: "first"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: "a"
state: DISABLED
permission: READ_ONLY
trace {
@@ -670,6 +789,7 @@ parsed_flag {
name: "second"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: "b"
state: ENABLED
permission: READ_WRITE
trace {
@@ -687,6 +807,7 @@ parsed_flag {
name: "first"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: "a"
state: DISABLED
permission: READ_ONLY
trace {
@@ -703,6 +824,7 @@ parsed_flag {
package: "com.second"
name: "second"
namespace: "second_ns"
+ bug: "b"
description: "This is the description of the second flag."
state: ENABLED
permission: READ_WRITE
@@ -717,7 +839,7 @@ parsed_flag {
// bad cases
let error = parsed_flags::merge(vec![first.clone(), first.clone()]).unwrap_err();
- assert_eq!(format!("{:?}", error), "bad parsed flags: duplicate flag com.first.first");
+ assert_eq!(format!("{:?}", error), "bad parsed flags: duplicate flag com.first.first (defined in flags.declarations and flags.declarations)");
// valid cases
assert!(parsed_flags::merge(vec![]).unwrap().parsed_flag.is_empty());
diff --git a/tools/aconfig/src/test.rs b/tools/aconfig/src/test.rs
index 04bbe2847e..9034704283 100644
--- a/tools/aconfig/src/test.rs
+++ b/tools/aconfig/src/test.rs
@@ -41,6 +41,7 @@ parsed_flag {
state: DISABLED
permission: READ_ONLY
}
+ is_fixed_read_only: false
}
parsed_flag {
package: "com.android.aconfig.test"
@@ -55,13 +56,33 @@ parsed_flag {
state: DISABLED
permission: READ_WRITE
}
+ is_fixed_read_only: false
+}
+parsed_flag {
+ package: "com.android.aconfig.test"
+ name: "enabled_fixed_ro"
+ namespace: "aconfig_test"
+ description: "This flag is fixed READ_ONLY + ENABLED"
+ bug: ""
+ state: ENABLED
+ permission: READ_ONLY
+ trace {
+ source: "tests/test.aconfig"
+ state: DISABLED
+ permission: READ_ONLY
+ }
+ trace {
+ source: "tests/first.values"
+ state: ENABLED
+ permission: READ_ONLY
+ }
+ is_fixed_read_only: true
}
parsed_flag {
package: "com.android.aconfig.test"
name: "enabled_ro"
namespace: "aconfig_test"
description: "This flag is ENABLED + READ_ONLY"
- bug: "789"
bug: "abc"
state: ENABLED
permission: READ_ONLY
@@ -80,12 +101,14 @@ parsed_flag {
state: ENABLED
permission: READ_ONLY
}
+ is_fixed_read_only: false
}
parsed_flag {
package: "com.android.aconfig.test"
name: "enabled_rw"
namespace: "aconfig_test"
description: "This flag is ENABLED + READ_WRITE"
+ bug: ""
state: ENABLED
permission: READ_WRITE
trace {
@@ -98,6 +121,7 @@ parsed_flag {
state: ENABLED
permission: READ_WRITE
}
+ is_fixed_read_only: false
}
"#;
@@ -118,6 +142,7 @@ parsed_flag {
reader: Box::new(include_bytes!("../tests/second.values").as_slice()),
},
],
+ crate::commands::DEFAULT_FLAG_PERMISSION,
)
.unwrap();
crate::protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
diff --git a/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
new file mode 100644
index 0000000000..d2cea952f9
--- /dev/null
+++ b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
@@ -0,0 +1,47 @@
+package {package_name};
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** @hide */
+public class FakeFeatureFlagsImpl implements FeatureFlags \{
+ public FakeFeatureFlagsImpl() \{
+ resetAll();
+ }
+
+{{ for item in class_elements}}
+ @Override
+ public boolean {item.method_name}() \{
+ return getValue(Flags.FLAG_{item.flag_name_constant_suffix});
+ }
+{{ endfor}}
+ public void setFlag(String flagName, boolean value) \{
+ if (!this.mFlagMap.containsKey(flagName)) \{
+ throw new IllegalArgumentException("no such flag " + flagName);
+ }
+ this.mFlagMap.put(flagName, value);
+ }
+
+ public void resetAll() \{
+ for (Map.Entry entry : mFlagMap.entrySet()) \{
+ entry.setValue(null);
+ }
+ }
+
+ private boolean getValue(String flagName) \{
+ Boolean value = this.mFlagMap.get(flagName);
+ if (value == null) \{
+ throw new IllegalArgumentException(flagName + " is not set");
+ }
+ return value;
+ }
+
+ private Map<String, Boolean> mFlagMap = new HashMap<>(
+ Map.ofEntries(
+ {{-for item in class_elements}}
+ Map.entry(Flags.FLAG_{item.flag_name_constant_suffix}, false)
+ {{ -if not @last }},{{ endif }}
+ {{ -endfor }}
+ )
+ );
+}
diff --git a/tools/aconfig/templates/FeatureFlags.java.template b/tools/aconfig/templates/FeatureFlags.java.template
index e0f201fc88..9350d60bec 100644
--- a/tools/aconfig/templates/FeatureFlags.java.template
+++ b/tools/aconfig/templates/FeatureFlags.java.template
@@ -1,7 +1,15 @@
package {package_name};
+/** @hide */
public interface FeatureFlags \{
{{ for item in class_elements}}
+{{ -if not item.is_read_write }}
+{{ -if item.default_value }}
+ @com.android.aconfig.annotations.AssumeTrueForR8
+{{ -else }}
+ @com.android.aconfig.annotations.AssumeFalseForR8
+{{ -endif- }}
+{{ endif }}
boolean {item.method_name}();
{{ endfor }}
}
diff --git a/tools/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/templates/FeatureFlagsImpl.java.template
index 082d476de5..3913fa4ea3 100644
--- a/tools/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FeatureFlagsImpl.java.template
@@ -1,65 +1,58 @@
package {package_name};
-{{ -if is_test_mode }}
-import static java.util.stream.Collectors.toMap;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.stream.Stream;
-{{ else}}
+{{ if not is_test_mode }}
{{ if is_read_write- }}
import android.provider.DeviceConfig;
-{{ -endif- }}
{{ endif }}
+/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ for item in class_elements}}
@Override
public boolean {item.method_name}() \{
- {{ -if not is_test_mode- }}
- {{ if item.is_read_write }}
- return DeviceConfig.getBoolean(
+ {{ -if item.is_read_write }}
+ return getValue(
"{item.device_config_namespace}",
"{item.device_config_flag}",
{item.default_value}
);
- {{ -else }}
+ {{ else }}
return {item.default_value};
- {{ -endif- }}
- {{ else }}
- return getFlag(Flags.FLAG_{item.flag_name_constant_suffix});
- {{ -endif }}
+ {{ endif- }}
}
-{{ endfor- }}
-{{ if is_test_mode }}
- public void setFlag(String flagName, boolean value) \{
- if (!this.mFlagMap.containsKey(flagName)) \{
- throw new IllegalArgumentException("no such flag" + flagName);
- }
- this.mFlagMap.put(flagName, value);
- }
-
- public void resetAll() \{
- for (Map.Entry entry : mFlagMap.entrySet()) \{
- entry.setValue(null);
- }
- }
-
- private boolean getFlag(String flagName) \{
- Boolean value = this.mFlagMap.get(flagName);
- if (value == null) \{
- throw new IllegalArgumentException(flagName + " is not set");
+{{ endfor }}
+{{ if is_read_write- }}
+ private boolean getValue(String nameSpace,
+ String flagName, boolean defaultValue) \{
+ boolean value = defaultValue;
+ try \{
+ value = DeviceConfig.getBoolean(
+ nameSpace,
+ flagName,
+ defaultValue
+ );
+ } catch (NullPointerException e) \{
+ throw new RuntimeException(
+ "Cannot read value of flag " + flagName + " from DeviceConfig. " +
+ "It could be that the code using flag executed " +
+ "before SettingsProvider initialization. " +
+ "Please use fixed read-only flag by adding " +
+ "is_fixed_read_only: true in flag declaration.",
+ e
+ );
}
return value;
}
-
- private HashMap<String, Boolean> mFlagMap = Stream.of(
- {{-for item in class_elements}}
- Flags.FLAG_{item.flag_name_constant_suffix}{{ if not @last }},{{ endif }}
- {{ -endfor }}
- )
- .collect(
- HashMap::new,
- (map, elem) -> map.put(elem, null),
- HashMap::putAll
- );
-{{ -endif }}
+{{ endif- }}
}
+{{ else }}
+{#- Generate only stub if in test mode #}
+/** @hide */
+public final class FeatureFlagsImpl implements FeatureFlags \{
+{{ for item in class_elements}}
+ @Override
+ public boolean {item.method_name}() \{
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
+ }
+{{ endfor }}
+}
+{{ endif }}
diff --git a/tools/aconfig/templates/Flags.java.template b/tools/aconfig/templates/Flags.java.template
index c244b15156..39024a8f74 100644
--- a/tools/aconfig/templates/Flags.java.template
+++ b/tools/aconfig/templates/Flags.java.template
@@ -1,23 +1,32 @@
package {package_name};
+/** @hide */
public final class Flags \{
{{- for item in class_elements}}
+ /** @hide */
public static final String FLAG_{item.flag_name_constant_suffix} = "{item.device_config_flag}";
{{- endfor }}
{{ for item in class_elements}}
+{{ -if not item.is_read_write }}
+{{ -if item.default_value }}
+ @com.android.aconfig.annotations.AssumeTrueForR8
+{{ -else }}
+ @com.android.aconfig.annotations.AssumeFalseForR8
+{{ -endif- }}
+{{ endif }}
public static boolean {item.method_name}() \{
return FEATURE_FLAGS.{item.method_name}();
}
{{ endfor }}
{{ -if is_test_mode }}
- public static void setFeatureFlagsImpl(FeatureFlags featureFlags) \{
+ public static void setFeatureFlags(FeatureFlags featureFlags) \{
Flags.FEATURE_FLAGS = featureFlags;
}
- public static void unsetFeatureFlagsImpl() \{
+ public static void unsetFeatureFlags() \{
Flags.FEATURE_FLAGS = null;
}
-{{ endif}}
+{{ endif }}
private static FeatureFlags FEATURE_FLAGS{{ -if not is_test_mode }} = new FeatureFlagsImpl(){{ -endif- }};
}
diff --git a/tools/aconfig/templates/cpp_exported_header.template b/tools/aconfig/templates/cpp_exported_header.template
index e244de3d62..4d56dbc7f0 100644
--- a/tools/aconfig/templates/cpp_exported_header.template
+++ b/tools/aconfig/templates/cpp_exported_header.template
@@ -1,12 +1,9 @@
-#ifndef {header}_HEADER_H
-#define {header}_HEADER_H
+#pragma once
+
+#ifdef __cplusplus
-#include <string>
#include <memory>
-{{ if readwrite }}
-#include <server_configurable_flags/get_flags.h>
-using namespace server_configurable_flags;
-{{ endif }}
+
namespace {cpp_namespace} \{
class flag_provider_interface \{
@@ -14,35 +11,63 @@ public:
virtual ~flag_provider_interface() = default;
{{ for item in class_elements}}
virtual bool {item.flag_name}() = 0;
+
+ {{ if for_test }}
+ virtual void {item.flag_name}(bool val) = 0;
+ {{ -endif }}
{{ endfor }}
- virtual void override_flag(std::string const&, bool) \{}
- virtual void reset_overrides() \{}
+ {{ if for_test }}
+ virtual void reset_flags() \{}
+ {{ -endif }}
};
extern std::unique_ptr<flag_provider_interface> provider_;
-{{ for item in class_elements}}
-extern std::string const {item.uppercase_flag_name};{{ endfor }}
+
{{ for item in class_elements}}
inline bool {item.flag_name}() \{
- {{ if for_prod }}
+ {{ if for_test }}
+ return provider_->{item.flag_name}();
+ {{ -else- }}
{{ if not item.readwrite- }}
return {item.default_value};
{{ -else- }}
return provider_->{item.flag_name}();
{{ -endif }}
- {{ -else- }}
- return provider_->{item.flag_name}();
{{ -endif }}
}
-{{ endfor }}
-inline void override_flag(std::string const& name, bool val) \{
- return provider_->override_flag(name, val);
+
+{{ if for_test }}
+inline void {item.flag_name}(bool val) \{
+ provider_->{item.flag_name}(val);
}
+{{ -endif }}
+{{ endfor }}
-inline void reset_overrides() \{
- return provider_->reset_overrides();
+{{ if for_test }}
+inline void reset_flags() \{
+ return provider_->reset_flags();
}
+{{ -endif }}
}
+
+extern "C" \{
+#endif // __cplusplus
+
+{{ for item in class_elements }}
+bool {header}_{item.flag_name}();
+
+{{ if for_test }}
+void set_{header}_{item.flag_name}(bool val);
+{{ -endif }}
+{{ endfor - }}
+
+{{ if for_test }}
+void {header}_reset_flags();
+{{ -endif }}
+
+#ifdef __cplusplus
+} // extern "C"
#endif
+
diff --git a/tools/aconfig/templates/cpp_prod_flag_provider.template b/tools/aconfig/templates/cpp_prod_flag_provider.template
deleted file mode 100644
index c966ed4eb4..0000000000
--- a/tools/aconfig/templates/cpp_prod_flag_provider.template
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef {header}_flag_provider_HEADER_H
-#define {header}_flag_provider_HEADER_H
-#include "{header}.h"
-
-namespace {cpp_namespace} \{
-class flag_provider : public flag_provider_interface \{
-public:
- {{ for item in class_elements}}
- virtual bool {item.flag_name}() override \{
- {{ if item.readwrite- }}
- return GetServerConfigurableFlag(
- "{item.device_config_namespace}",
- "{item.device_config_flag}",
- "{item.default_value}") == "true";
- {{ -else- }}
- return {item.default_value};
- {{ -endif }}
- }
- {{ endfor }}
-};
-}
-#endif
diff --git a/tools/aconfig/templates/cpp_source_file.template b/tools/aconfig/templates/cpp_source_file.template
index 1b4f336707..c0e7343785 100644
--- a/tools/aconfig/templates/cpp_source_file.template
+++ b/tools/aconfig/templates/cpp_source_file.template
@@ -1,10 +1,101 @@
-
#include "{header}.h"
-#include "{header}_flag_provider.h"
+{{ if readwrite }}
+#include <server_configurable_flags/get_flags.h>
+{{ endif }}
+{{ if for_test }}
+#include <unordered_map>
+{{ endif }}
namespace {cpp_namespace} \{
-{{ for item in class_elements}}
-std::string const {item.uppercase_flag_name} = "{item.device_config_flag}";{{ endfor }}
+
+{{ if for_test }}
+ class flag_provider : public flag_provider_interface \{
+ private:
+ std::unordered_map<std::string, bool> overrides_;
+
+ public:
+ flag_provider()
+ : overrides_()
+ \{}
+
+ {{ for item in class_elements}}
+ virtual bool {item.flag_name}() override \{
+ auto it = overrides_.find("{item.flag_name}");
+ if (it != overrides_.end()) \{
+ return it->second;
+ } else \{
+ {{ if item.readwrite- }}
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.{item.device_config_namespace}",
+ "{item.device_config_flag}",
+ "{item.default_value}") == "true";
+ {{ -else- }}
+ return {item.default_value};
+ {{ -endif }}
+ }
+ }
+
+ virtual void {item.flag_name}(bool val) override \{
+ overrides_["{item.flag_name}"] = val;
+ }
+ {{ endfor }}
+
+ virtual void reset_flags() override \{
+ overrides_.clear();
+ }
+ };
+
+{{ -else- }}
+
+ class flag_provider : public flag_provider_interface \{
+ public:
+ {{ for item in class_elements}}
+ virtual bool {item.flag_name}() override \{
+ {{ if item.readwrite- }}
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.{item.device_config_namespace}",
+ "{item.device_config_flag}",
+ "{item.default_value}") == "true";
+ {{ -else- }}
+ return {item.default_value};
+ {{ -endif }}
+ }
+ {{ endfor }}
+ };
+
+
+{{ -endif }}
+
+
std::unique_ptr<flag_provider_interface> provider_ =
std::make_unique<flag_provider>();
+
+}
+
+
+{{ for item in class_elements}}
+bool {header}_{item.flag_name}() \{
+ {{ if for_test }}
+ return {cpp_namespace}::{item.flag_name}();
+ {{ -else- }}
+ {{ if not item.readwrite- }}
+ return {item.default_value};
+ {{ -else- }}
+ return {cpp_namespace}::{item.flag_name}();
+ {{ -endif }}
+ {{ -endif }}
}
+
+{{ if for_test }}
+void set_{header}_{item.flag_name}(bool val) \{
+ {cpp_namespace}::{item.flag_name}(val);
+}
+{{ -endif }}
+{{ endfor -}}
+
+{{ if for_test }}
+void {header}_reset_flags() \{
+ {cpp_namespace}::reset_flags();
+}
+{{ -endif }}
+
diff --git a/tools/aconfig/templates/cpp_test_flag_provider.template b/tools/aconfig/templates/cpp_test_flag_provider.template
deleted file mode 100644
index bd597e7722..0000000000
--- a/tools/aconfig/templates/cpp_test_flag_provider.template
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef {header}_flag_provider_HEADER_H
-#define {header}_flag_provider_HEADER_H
-#include "{header}.h"
-
-#include <unordered_map>
-#include <unordered_set>
-#include <cassert>
-
-namespace {cpp_namespace} \{
-class flag_provider : public flag_provider_interface \{
-private:
- std::unordered_map<std::string, bool> overrides_;
- std::unordered_set<std::string> flag_names_;
-
-public:
- flag_provider()
- : overrides_(),
- flag_names_() \{
- {{ for item in class_elements}}
- flag_names_.insert({item.uppercase_flag_name});{{ endfor }}
- }
- {{ for item in class_elements}}
- virtual bool {item.flag_name}() override \{
- auto it = overrides_.find({item.uppercase_flag_name});
- if (it != overrides_.end()) \{
- return it->second;
- } else \{
- {{ if item.readwrite- }}
- return GetServerConfigurableFlag(
- "{item.device_config_namespace}",
- "{item.device_config_flag}",
- "{item.default_value}") == "true";
- {{ -else- }}
- return {item.default_value};
- {{ -endif }}
- }
- }
- {{ endfor }}
- virtual void override_flag(std::string const& flag, bool val) override \{
- assert(flag_names_.count(flag));
- overrides_[flag] = val;
- }
-
- virtual void reset_overrides() override \{
- overrides_.clear();
- }
-};
-}
-#endif
diff --git a/tools/aconfig/templates/rust.template b/tools/aconfig/templates/rust.template
deleted file mode 100644
index 960c494942..0000000000
--- a/tools/aconfig/templates/rust.template
+++ /dev/null
@@ -1,29 +0,0 @@
-{{- for mod in modules -}}
-pub mod {mod} \{
-{{ endfor -}}
-{{- for flag in template_flags -}}
-{{- if flag.is_read_only_disabled -}}
-#[inline(always)]
-pub const fn r#{flag.name}() -> bool \{
- false
-}
-
-{{ endif -}}
-{{- if flag.is_read_only_enabled -}}
-#[inline(always)]
-pub const fn r#{flag.name}() -> bool \{
- true
-}
-
-{{ endif -}}
-{{- if flag.is_read_write -}}
-#[inline(always)]
-pub fn r#{flag.name}() -> bool \{
- flags_rust::GetServerConfigurableFlag("{flag.device_config_namespace}", "{flag.device_config_flag}", "false") == "true"
-}
-
-{{ endif -}}
-{{- endfor -}}
-{{- for mod in modules -}}
-}
-{{ endfor -}}
diff --git a/tools/aconfig/templates/rust_prod.template b/tools/aconfig/templates/rust_prod.template
new file mode 100644
index 0000000000..e22ad6faa4
--- /dev/null
+++ b/tools/aconfig/templates/rust_prod.template
@@ -0,0 +1,38 @@
+//! codegenerated rust flag lib
+
+/// flag provider
+pub struct FlagProvider;
+
+impl FlagProvider \{
+
+ {{ for flag in template_flags }}
+ /// query flag {flag.name}
+ pub fn {flag.name}(&self) -> bool \{
+ {{ if flag.readwrite -}}
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.{flag.device_config_namespace}",
+ "{flag.device_config_flag}",
+ "{flag.default_value}") == "true"
+ {{ -else- }}
+ {flag.default_value}
+ {{ -endif }}
+ }
+ {{ endfor }}
+
+}
+
+/// flag provider
+pub static PROVIDER: FlagProvider = FlagProvider;
+
+{{ for flag in template_flags }}
+/// query flag {flag.name}
+#[inline(always)]
+{{ if flag.readwrite -}}
+pub fn {flag.name}() -> bool \{
+ PROVIDER.{flag.name}()
+{{ -else- }}
+pub fn {flag.name}() -> bool \{
+ {flag.default_value}
+{{ -endif }}
+}
+{{ endfor }}
diff --git a/tools/aconfig/templates/rust_test.template b/tools/aconfig/templates/rust_test.template
new file mode 100644
index 0000000000..fd1229bf86
--- /dev/null
+++ b/tools/aconfig/templates/rust_test.template
@@ -0,0 +1,61 @@
+//! codegenerated rust flag lib
+
+use std::collections::BTreeMap;
+use std::sync::Mutex;
+
+/// flag provider
+pub struct FlagProvider \{
+ overrides: BTreeMap<&'static str, bool>,
+}
+
+impl FlagProvider \{
+ {{ for flag in template_flags }}
+ /// query flag {flag.name}
+ pub fn {flag.name}(&self) -> bool \{
+ self.overrides.get("{flag.name}").copied().unwrap_or(
+ {{ if flag.readwrite -}}
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.{flag.device_config_namespace}",
+ "{flag.device_config_flag}",
+ "{flag.default_value}") == "true"
+ {{ -else- }}
+ {flag.default_value}
+ {{ -endif }}
+ )
+ }
+
+ /// set flag {flag.name}
+ pub fn set_{flag.name}(&mut self, val: bool) \{
+ self.overrides.insert("{flag.name}", val);
+ }
+ {{ endfor }}
+
+ /// clear all flag overrides
+ pub fn reset_flags(&mut self) \{
+ self.overrides.clear();
+ }
+}
+
+/// flag provider
+pub static PROVIDER: Mutex<FlagProvider> = Mutex::new(
+ FlagProvider \{overrides: BTreeMap::new()}
+);
+
+{{ for flag in template_flags }}
+/// query flag {flag.name}
+#[inline(always)]
+pub fn {flag.name}() -> bool \{
+ PROVIDER.lock().unwrap().{flag.name}()
+}
+
+/// set flag {flag.name}
+#[inline(always)]
+pub fn set_{flag.name}(val: bool) \{
+ PROVIDER.lock().unwrap().set_{flag.name}(val);
+}
+{{ endfor }}
+
+/// clear all flag override
+pub fn reset_flags() \{
+ PROVIDER.lock().unwrap().reset_flags()
+}
diff --git a/tools/aconfig/tests/AconfigHostTest.java b/tools/aconfig/tests/AconfigHostTest.java
new file mode 100644
index 0000000000..ea71b7e52a
--- /dev/null
+++ b/tools/aconfig/tests/AconfigHostTest.java
@@ -0,0 +1,88 @@
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+
+import com.android.aconfig.test.FakeFeatureFlagsImpl;
+import com.android.aconfig.test.FeatureFlags;
+import com.android.aconfig.test.FeatureFlagsImpl;
+import com.android.aconfig.test.Flags;
+
+@RunWith(JUnit4.class)
+public final class AconfigHostTest {
+ @Test
+ public void testThrowsExceptionIfFlagNotSet() {
+ assertThrows(NullPointerException.class, () -> Flags.disabledRo());
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ assertThrows(IllegalArgumentException.class, () -> featureFlags.disabledRo());
+ }
+
+ @Test
+ public void testSetFlagInFakeFeatureFlagsImpl() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
+ assertTrue(featureFlags.enabledRw());
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, false);
+ assertFalse(featureFlags.enabledRw());
+
+ //Set Flags
+ assertThrows(NullPointerException.class, () -> Flags.enabledRw());
+ Flags.setFeatureFlags(featureFlags);
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
+ assertTrue(Flags.enabledRw());
+ Flags.unsetFeatureFlags();
+ }
+
+ @Test
+ public void testSetFlagWithRandomName() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ assertThrows(IllegalArgumentException.class,
+ () -> featureFlags.setFlag("Randome_name", true));
+ }
+
+ @Test
+ public void testResetFlagsInFakeFeatureFlagsImpl() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RO, true);
+ assertTrue(featureFlags.enabledRo());
+ featureFlags.resetAll();
+ assertThrows(IllegalArgumentException.class, () -> featureFlags.enabledRo());
+
+ // Set value after reset
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RO, false);
+ assertFalse(featureFlags.enabledRo());
+ }
+
+ @Test
+ public void testFlagsSetFeatureFlags() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
+ assertThrows(NullPointerException.class, () -> Flags.enabledRw());
+ Flags.setFeatureFlags(featureFlags);
+ assertTrue(Flags.enabledRw());
+ Flags.unsetFeatureFlags();
+ }
+
+ @Test
+ public void testFlagsUnsetFeatureFlags() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
+ assertThrows(NullPointerException.class, () -> Flags.enabledRw());
+ Flags.setFeatureFlags(featureFlags);
+ assertTrue(Flags.enabledRw());
+
+ Flags.unsetFeatureFlags();
+ assertThrows(NullPointerException.class, () -> Flags.enabledRw());
+ }
+
+ @Test
+ public void testFeatureFlagsImplNotImpl() {
+ FeatureFlags featureFlags = new FeatureFlagsImpl();
+ assertThrows(UnsupportedOperationException.class,
+ () -> featureFlags.enabledRw());
+ }
+}
diff --git a/tools/aconfig/tests/AconfigTest.java b/tools/aconfig/tests/AconfigTest.java
index 778a4c6860..958b02e29b 100644
--- a/tools/aconfig/tests/AconfigTest.java
+++ b/tools/aconfig/tests/AconfigTest.java
@@ -1,37 +1,67 @@
+import static com.android.aconfig.test.Flags.FLAG_DISABLED_RO;
+import static com.android.aconfig.test.Flags.FLAG_DISABLED_RW;
+import static com.android.aconfig.test.Flags.FLAG_ENABLED_FIXED_RO;
+import static com.android.aconfig.test.Flags.FLAG_ENABLED_RO;
+import static com.android.aconfig.test.Flags.FLAG_ENABLED_RW;
import static com.android.aconfig.test.Flags.disabledRo;
import static com.android.aconfig.test.Flags.disabledRw;
+import static com.android.aconfig.test.Flags.enabledFixedRo;
import static com.android.aconfig.test.Flags.enabledRo;
import static com.android.aconfig.test.Flags.enabledRw;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import com.android.aconfig.test.FakeFeatureFlagsImpl;
+import com.android.aconfig.test.FeatureFlags;
+
@RunWith(JUnit4.class)
public final class AconfigTest {
@Test
public void testDisabledReadOnlyFlag() {
+ assertEquals("com.android.aconfig.test.disabled_ro", FLAG_DISABLED_RO);
assertFalse(disabledRo());
}
@Test
public void testEnabledReadOnlyFlag() {
+ assertEquals("com.android.aconfig.test.disabled_rw", FLAG_DISABLED_RW);
// TODO: change to assertTrue(enabledRo()) when the build supports reading tests/*.values
// (currently all flags are assigned the default READ_ONLY + DISABLED)
assertFalse(enabledRo());
}
@Test
+ public void testEnabledFixedReadOnlyFlag() {
+ assertEquals("com.android.aconfig.test.enabled_fixed_ro", FLAG_ENABLED_FIXED_RO);
+ // TODO: change to assertTrue(enabledFixedRo()) when the build supports reading tests/*.values
+ // (currently all flags are assigned the default READ_ONLY + DISABLED)
+ assertFalse(enabledFixedRo());
+ }
+
+ @Test
public void testDisabledReadWriteFlag() {
+ assertEquals("com.android.aconfig.test.enabled_ro", FLAG_ENABLED_RO);
assertFalse(disabledRw());
}
@Test
public void testEnabledReadWriteFlag() {
+ assertEquals("com.android.aconfig.test.enabled_rw", FLAG_ENABLED_RW);
// TODO: change to assertTrue(enabledRw()) when the build supports reading tests/*.values
// (currently all flags are assigned the default READ_ONLY + DISABLED)
assertFalse(enabledRw());
}
+
+ @Test
+ public void testFakeFeatureFlagsImplImpled() {
+ FakeFeatureFlagsImpl fakeFeatureFlags = new FakeFeatureFlagsImpl();
+ fakeFeatureFlags.setFlag(FLAG_ENABLED_RW, false);
+ assertFalse(fakeFeatureFlags.enabledRw());
+ }
}
diff --git a/tools/aconfig/tests/aconfig_prod_mode_test.rs b/tools/aconfig/tests/aconfig_prod_mode_test.rs
new file mode 100644
index 0000000000..950c441c04
--- /dev/null
+++ b/tools/aconfig/tests/aconfig_prod_mode_test.rs
@@ -0,0 +1,9 @@
+#[cfg(not(feature = "cargo"))]
+#[test]
+fn test_flags() {
+ assert!(!aconfig_test_rust_library::disabled_ro());
+ assert!(!aconfig_test_rust_library::disabled_rw());
+ // TODO: Fix template to not default both disabled and enabled to false
+ assert!(!aconfig_test_rust_library::enabled_ro());
+ assert!(!aconfig_test_rust_library::enabled_rw());
+}
diff --git a/tools/aconfig/tests/aconfig_test.cpp b/tools/aconfig/tests/aconfig_test.cpp
new file mode 100644
index 0000000000..10de347918
--- /dev/null
+++ b/tools/aconfig/tests/aconfig_test.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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 "com_android_aconfig_test.h"
+#include "gtest/gtest.h"
+
+TEST(AconfigTest, TestDisabledReadOnlyFlag) {
+ ASSERT_FALSE(com_android_aconfig_test_disabled_ro());
+}
+
+TEST(AconfigTest, TestEnabledReadOnlyFlag) {
+ // TODO: change to assertTrue(enabledRo()) when the build supports reading tests/*.values
+ // (currently all flags are assigned the default READ_ONLY + DISABLED)
+ ASSERT_FALSE(com_android_aconfig_test_enabled_ro());
+}
+
+TEST(AconfigTest, TestDisabledReadWriteFlag) {
+ ASSERT_FALSE(com_android_aconfig_test_disabled_rw());
+}
+
+TEST(AconfigTest, TestEnabledReadWriteFlag) {
+ // TODO: change to assertTrue(enabledRo()) when the build supports reading tests/*.values
+ // (currently all flags are assigned the default READ_ONLY + DISABLED)
+ ASSERT_FALSE(com_android_aconfig_test_enabled_rw());
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/tools/aconfig/tests/aconfig_test_mode_test.rs b/tools/aconfig/tests/aconfig_test_mode_test.rs
new file mode 100644
index 0000000000..3f56d2c75a
--- /dev/null
+++ b/tools/aconfig/tests/aconfig_test_mode_test.rs
@@ -0,0 +1,24 @@
+#[cfg(not(feature = "cargo"))]
+#[test]
+fn test_flags() {
+ assert!(!aconfig_test_rust_library::disabled_ro());
+ assert!(!aconfig_test_rust_library::disabled_rw());
+ // TODO: Fix template to not default both disabled and enabled to false
+ assert!(!aconfig_test_rust_library::enabled_ro());
+ assert!(!aconfig_test_rust_library::enabled_rw());
+
+ aconfig_test_rust_library::set_disabled_ro(true);
+ assert!(aconfig_test_rust_library::disabled_ro());
+ aconfig_test_rust_library::set_disabled_rw(true);
+ assert!(aconfig_test_rust_library::disabled_rw());
+ aconfig_test_rust_library::set_enabled_ro(true);
+ assert!(aconfig_test_rust_library::enabled_ro());
+ aconfig_test_rust_library::set_enabled_rw(true);
+ assert!(aconfig_test_rust_library::enabled_rw());
+
+ aconfig_test_rust_library::reset_flags();
+ assert!(!aconfig_test_rust_library::disabled_ro());
+ assert!(!aconfig_test_rust_library::disabled_rw());
+ assert!(!aconfig_test_rust_library::enabled_ro());
+ assert!(!aconfig_test_rust_library::enabled_rw());
+}
diff --git a/tools/aconfig/tests/first.values b/tools/aconfig/tests/first.values
index e5244041a3..a450f7869e 100644
--- a/tools/aconfig/tests/first.values
+++ b/tools/aconfig/tests/first.values
@@ -16,3 +16,9 @@ flag_value {
state: ENABLED
permission: READ_WRITE
}
+flag_value {
+ package: "com.android.aconfig.test"
+ name: "enabled_fixed_ro"
+ state: ENABLED
+ permission: READ_ONLY
+}
diff --git a/tools/aconfig/tests/test.aconfig b/tools/aconfig/tests/test.aconfig
index a8f665223d..aaa6df585e 100644
--- a/tools/aconfig/tests/test.aconfig
+++ b/tools/aconfig/tests/test.aconfig
@@ -2,41 +2,52 @@ package: "com.android.aconfig.test"
# This flag's final value is calculated from:
# - test.aconfig: DISABLED + READ_WRITE (default)
-# - first.values: DISABLED + READ_ONLY
+# - first.values: DISABLED + READ_WRITE
+# - second.values: ENABLED + READ_ONLY
flag {
- name: "disabled_ro"
+ name: "enabled_ro"
namespace: "aconfig_test"
- description: "This flag is DISABLED + READ_ONLY"
- bug: "123"
+ description: "This flag is ENABLED + READ_ONLY"
+ bug: "abc"
}
# This flag's final value is calculated from:
# - test.aconfig: DISABLED + READ_WRITE (default)
+# - first.values: ENABLED + READ_WRITE
flag {
- name: "disabled_rw"
+ name: "enabled_rw"
namespace: "aconfig_test"
- description: "This flag is DISABLED + READ_WRITE"
- bug: "456"
+ description: "This flag is ENABLED + READ_WRITE"
+ # for bug fields, the empty string is a discouraged but valid value
+ bug: ""
}
# This flag's final value is calculated from:
# - test.aconfig: DISABLED + READ_WRITE (default)
-# - first.values: DISABLED + READ_WRITE
-# - second.values: ENABLED + READ_ONLY
+# - first.values: DISABLED + READ_ONLY
flag {
- name: "enabled_ro"
+ name: "disabled_ro"
namespace: "aconfig_test"
- description: "This flag is ENABLED + READ_ONLY"
- bug: "789"
- bug: "abc"
+ description: "This flag is DISABLED + READ_ONLY"
+ bug: "123"
}
# This flag's final value is calculated from:
# - test.aconfig: DISABLED + READ_WRITE (default)
-# - first.values: ENABLED + READ_WRITE
flag {
- name: "enabled_rw"
+ name: "disabled_rw"
namespace: "aconfig_test"
- description: "This flag is ENABLED + READ_WRITE"
- # no bug field: bug is not mandatory
+ description: "This flag is DISABLED + READ_WRITE"
+ bug: "456"
+}
+
+# This flag's final value calculated from:
+# - test.aconfig: DISABLED + READ_ONLY
+# - first.values: ENABLED + READ_ONLY
+flag {
+ name: "enabled_fixed_ro"
+ namespace: "aconfig_test"
+ description: "This flag is fixed READ_ONLY + ENABLED"
+ bug: ""
+ is_fixed_read_only: true
}
diff --git a/tools/auto_gen_test_config.py b/tools/auto_gen_test_config.py
index ce6416000b..8ee599a1ec 100755
--- a/tools/auto_gen_test_config.py
+++ b/tools/auto_gen_test_config.py
@@ -17,6 +17,8 @@
"""A tool to generate TradeFed test config file.
"""
+import argparse
+import re
import os
import shutil
import sys
@@ -42,42 +44,85 @@ def main(argv):
Returns:
0 if no error, otherwise 1.
"""
- if len(argv) != 4 and len(argv) != 6:
- sys.stderr.write(
- 'Invalid arguments. The script requires 4 arguments for file paths: '
- 'target_config android_manifest empty_config '
- 'instrumentation_test_config_template '
- 'and 2 optional arguments for extra configs: '
- '--extra-configs \'EXTRA_CONFIGS\'.\n')
- return 1
-
- target_config = argv[0]
- android_manifest = argv[1]
- empty_config = argv[2]
- instrumentation_test_config_template = argv[3]
- extra_configs = '\n'.join(argv[5].split('\\n')) if len(argv) == 6 else ''
-
- manifest = parse(android_manifest)
- instrumentation_elements = manifest.getElementsByTagName('instrumentation')
- manifest_elements = manifest.getElementsByTagName('manifest')
- if len(instrumentation_elements) != 1 or len(manifest_elements) != 1:
- # Failed to locate instrumentation or manifest element in AndroidManifest.
- # file. Empty test config file will be created.
- shutil.copyfile(empty_config, target_config)
- return 0
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "target_config",
+ help="Path to the generated output config.")
+ parser.add_argument(
+ "android_manifest",
+ help="Path to AndroidManifest.xml or output of 'aapt2 dump xmltree' with .xmltree extension.")
+ parser.add_argument(
+ "empty_config",
+ help="Path to the empty config template.")
+ parser.add_argument(
+ "instrumentation_test_config_template",
+ help="Path to the instrumentation test config template.")
+ parser.add_argument("--extra-configs", default="")
+ args = parser.parse_args(argv)
+
+ target_config = args.target_config
+ android_manifest = args.android_manifest
+ empty_config = args.empty_config
+ instrumentation_test_config_template = args.instrumentation_test_config_template
+ extra_configs = '\n'.join(args.extra_configs.split('\\n'))
module = os.path.splitext(os.path.basename(target_config))[0]
- instrumentation = instrumentation_elements[0]
- manifest = manifest_elements[0]
- if ATTRIBUTE_LABEL in instrumentation.attributes:
- label = instrumentation.attributes[ATTRIBUTE_LABEL].value
- else:
+
+ # If the AndroidManifest.xml is not available, but the APK is, this tool also
+ # accepts the output of `aapt2 dump xmltree <apk> AndroidManifest.xml` written
+ # into a file. This is a custom structured aapt2 output - not raw XML!
+ if android_manifest.endswith(".xmltree"):
label = module
- runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
- package = manifest.attributes[ATTRIBUTE_PACKAGE].value
+ with open(android_manifest, encoding="utf-8") as manifest:
+ # e.g. A: package="android.test.example.helloworld" (Raw: "android.test.example.helloworld")
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ pattern = re.compile(r"\(Raw:\s\"(.*)\"\)$")
+ curr_element = None
+ for line in manifest:
+ curr_line = line.strip()
+ if curr_line.startswith("E:"):
+ # e.g. "E: instrumentation (line=9)"
+ # ^^^^^^^^^^^^^^^
+ curr_element = curr_line.split(" ")[1]
+ if curr_element == "instrumentation":
+ if ATTRIBUTE_RUNNER in curr_line:
+ runner = re.findall(pattern, curr_line)[0]
+ if ATTRIBUTE_LABEL in curr_line:
+ label = re.findall(pattern, curr_line)[0]
+ if curr_element == "manifest":
+ if ATTRIBUTE_PACKAGE in curr_line:
+ package = re.findall(pattern, curr_line)[0]
+
+ if not (runner and label and package):
+ # Failed to locate instrumentation or manifest element in AndroidManifest.
+ # file. Empty test config file will be created.
+ shutil.copyfile(empty_config, target_config)
+ return 0
+
+ else:
+ # If the AndroidManifest.xml file is directly available, read it as an XML file.
+ manifest = parse(android_manifest)
+ instrumentation_elements = manifest.getElementsByTagName('instrumentation')
+ manifest_elements = manifest.getElementsByTagName('manifest')
+ if len(instrumentation_elements) != 1 or len(manifest_elements) != 1:
+ # Failed to locate instrumentation or manifest element in AndroidManifest.
+ # file. Empty test config file will be created.
+ shutil.copyfile(empty_config, target_config)
+ return 0
+
+ instrumentation = instrumentation_elements[0]
+ manifest = manifest_elements[0]
+ if ATTRIBUTE_LABEL in instrumentation.attributes:
+ label = instrumentation.attributes[ATTRIBUTE_LABEL].value
+ else:
+ label = module
+ runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
+ package = manifest.attributes[ATTRIBUTE_PACKAGE].value
+
test_type = ('InstrumentationTest'
- if runner.endswith('.InstrumentationTestRunner')
- else 'AndroidJUnitTest')
+ if runner.endswith('.InstrumentationTestRunner')
+ else 'AndroidJUnitTest')
with open(instrumentation_test_config_template) as template:
config = template.read()
diff --git a/tools/auto_gen_test_config_test.py b/tools/auto_gen_test_config_test.py
index 51a8583f2e..ce97723d2c 100644
--- a/tools/auto_gen_test_config_test.py
+++ b/tools/auto_gen_test_config_test.py
@@ -30,6 +30,24 @@ MANIFEST_INVALID = """<?xml version="1.0" encoding="utf-8"?>
</manifest>
"""
+XMLTREE_JUNIT_TEST = """N: android=http://schemas.android.com/apk/res/android (line=2)
+ E: manifest (line=2)
+ A: package="com.android.my.tests.x" (Raw: "com.android.my.tests.x")
+ E: instrumentation (line=9)
+ A: http://schemas.android.com/apk/res/android:label(0x01010001)="TestModule" (Raw: "TestModule")
+ A: http://schemas.android.com/apk/res/android:name(0x01010003)="androidx.test.runner.AndroidJUnitRunner" (Raw: "androidx.test.runner.AndroidJUnitRunner")
+ A: http://schemas.android.com/apk/res/android:targetPackage(0x01010021)="com.android.my.tests" (Raw: "com.android.my.tests")
+"""
+
+XMLTREE_INSTRUMENTATION_TEST = """N: android=http://schemas.android.com/apk/res/android (line=2)
+ E: manifest (line=2)
+ A: package="com.android.my.tests.x" (Raw: "com.android.my.tests.x")
+ E: instrumentation (line=9)
+ A: http://schemas.android.com/apk/res/android:label(0x01010001)="TestModule" (Raw: "TestModule")
+ A: http://schemas.android.com/apk/res/android:name(0x01010003)="android.test.InstrumentationTestRunner" (Raw: "android.test.InstrumentationTestRunner")
+ A: http://schemas.android.com/apk/res/android:targetPackage(0x01010021)="com.android.my.tests" (Raw: "com.android.my.tests")
+"""
+
MANIFEST_JUNIT_TEST = """<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.my.tests.x">
@@ -45,12 +63,12 @@ MANIFEST_INSTRUMENTATION_TEST = """<?xml version="1.0" encoding="utf-8"?>
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.android.my.tests"
- android:label="My Tests" />
+ android:label="TestModule" />
</manifest>
"""
EXPECTED_JUNIT_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2023 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.
@@ -66,19 +84,23 @@ EXPECTED_JUNIT_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
-->
<!-- This test config file is auto-generated. -->
<configuration description="Runs TestModule.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
<option name="test-file-name" value="TestModule.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.my.tests.x" />
+ {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="com.android.my.tests.x" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
</test>
</configuration>
"""
EXPECTED_INSTRUMENTATION_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- Copyright (C) 2023 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.
@@ -93,23 +115,74 @@ EXPECTED_INSTRUMENTATION_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
limitations under the License.
-->
<!-- This test config file is auto-generated. -->
-<configuration description="Runs My Tests.">
+<configuration description="Runs TestModule.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
<option name="test-file-name" value="TestModule.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.InstrumentationTest" >
- <option name="package" value="com.android.my.tests.x" />
+ {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="com.android.my.tests.x" />
<option name="runner" value="android.test.InstrumentationTestRunner" />
</test>
</configuration>
"""
-TOOLS_DIR = os.path.dirname(os.path.dirname(__file__))
-EMPTY_TEST_CONFIG = os.path.join(
- TOOLS_DIR, '..', 'core', 'empty_test_config.xml')
-INSTRUMENTATION_TEST_CONFIG_TEMPLATE = os.path.join(
- TOOLS_DIR, '..', 'core', 'instrumentation_test_config_template.xml')
+EMPTY_TEST_CONFIG_CONTENT = """<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<!-- No AndroidTest.xml was provided and the manifest does not include
+ instrumentation, hence this apk is not instrumentable.
+-->
+<configuration description="Empty Configuration" />
+"""
+
+INSTRUMENTATION_TEST_CONFIG_TEMPLATE_CONTENT = """<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs {LABEL}.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+{EXTRA_CONFIGS}
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="{MODULE}.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.{TEST_TYPE}" >
+ {EXTRA_TEST_RUNNER_CONFIGS}<option name="package" value="{PACKAGE}" />
+ <option name="runner" value="{RUNNER}" />
+ </test>
+</configuration>
+"""
class AutoGenTestConfigUnittests(unittest.TestCase):
@@ -120,6 +193,16 @@ class AutoGenTestConfigUnittests(unittest.TestCase):
self.test_dir = tempfile.mkdtemp()
self.config_file = os.path.join(self.test_dir, TEST_MODULE + '.config')
self.manifest_file = os.path.join(self.test_dir, 'AndroidManifest.xml')
+ self.xmltree_file = os.path.join(self.test_dir, TEST_MODULE + '.xmltree')
+ self.empty_test_config_file = os.path.join(self.test_dir, 'empty.config')
+ self.instrumentation_test_config_template_file = os.path.join(
+ self.test_dir, 'instrumentation.config')
+
+ with open(self.empty_test_config_file, 'w') as f:
+ f.write(EMPTY_TEST_CONFIG_CONTENT)
+
+ with open(self.instrumentation_test_config_template_file, 'w') as f:
+ f.write(INSTRUMENTATION_TEST_CONFIG_TEMPLATE_CONTENT)
def tearDown(self):
"""Cleanup the test directory."""
@@ -133,11 +216,11 @@ class AutoGenTestConfigUnittests(unittest.TestCase):
argv = [self.config_file,
self.manifest_file,
- EMPTY_TEST_CONFIG,
- INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ self.empty_test_config_file,
+ self.instrumentation_test_config_template_file]
auto_gen_test_config.main(argv)
with open(self.config_file) as config_file:
- with open(EMPTY_TEST_CONFIG) as empty_config:
+ with open(self.empty_test_config_file) as empty_config:
self.assertEqual(config_file.read(), empty_config.read())
def testCreateJUnitTestConfig(self):
@@ -148,8 +231,8 @@ class AutoGenTestConfigUnittests(unittest.TestCase):
argv = [self.config_file,
self.manifest_file,
- EMPTY_TEST_CONFIG,
- INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ self.empty_test_config_file,
+ self.instrumentation_test_config_template_file]
auto_gen_test_config.main(argv)
with open(self.config_file) as config_file:
self.assertEqual(config_file.read(), EXPECTED_JUNIT_TEST_CONFIG)
@@ -162,8 +245,37 @@ class AutoGenTestConfigUnittests(unittest.TestCase):
argv = [self.config_file,
self.manifest_file,
- EMPTY_TEST_CONFIG,
- INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ self.empty_test_config_file,
+ self.instrumentation_test_config_template_file]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ self.assertEqual(
+ config_file.read(), EXPECTED_INSTRUMENTATION_TEST_CONFIG)
+
+ def testCreateJUnitTestConfigWithXMLTree(self):
+ """Test creating test config for AndroidJUnitTest.
+ """
+ with open(self.xmltree_file, 'w') as f:
+ f.write(XMLTREE_JUNIT_TEST)
+
+ argv = [self.config_file,
+ self.xmltree_file,
+ self.empty_test_config_file,
+ self.instrumentation_test_config_template_file]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ self.assertEqual(config_file.read(), EXPECTED_JUNIT_TEST_CONFIG)
+
+ def testCreateInstrumentationTestConfigWithXMLTree(self):
+ """Test creating test config for InstrumentationTest.
+ """
+ with open(self.xmltree_file, 'w') as f:
+ f.write(XMLTREE_INSTRUMENTATION_TEST)
+
+ argv = [self.config_file,
+ self.xmltree_file,
+ self.empty_test_config_file,
+ self.instrumentation_test_config_template_file]
auto_gen_test_config.main(argv)
with open(self.config_file) as config_file:
self.assertEqual(
diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh
index c2e36dfeee..0ed9453e8d 100755
--- a/tools/buildinfo.sh
+++ b/tools/buildinfo.sh
@@ -7,9 +7,9 @@ echo "# autogenerated by buildinfo.sh"
if [ "$BOARD_USE_VBMETA_DIGTEST_IN_FINGERPRINT" = "true" ] ; then
echo "ro.build.legacy.id=$BUILD_ID"
else
- echo "ro.build.id=$BUILD_ID"
+ echo "ro.build.id?=$BUILD_ID"
fi
-echo "ro.build.display.id=$BUILD_DISPLAY_ID"
+echo "ro.build.display.id?=$BUILD_DISPLAY_ID"
echo "ro.build.version.incremental=$BUILD_NUMBER"
echo "ro.build.version.sdk=$PLATFORM_SDK_VERSION"
echo "ro.build.version.preview_sdk=$PLATFORM_PREVIEW_SDK_VERSION"
@@ -28,7 +28,9 @@ echo "ro.build.date.utc=`$DATE +%s`"
echo "ro.build.type=$TARGET_BUILD_TYPE"
echo "ro.build.user=$BUILD_USERNAME"
echo "ro.build.host=$BUILD_HOSTNAME"
-echo "ro.build.tags=$BUILD_VERSION_TAGS"
+# TODO: Remove any tag-related optional property declarations once the goals
+# from go/arc-android-sigprop-changes have been achieved.
+echo "ro.build.tags?=$BUILD_VERSION_TAGS"
echo "ro.build.flavor=$TARGET_BUILD_FLAVOR"
# These values are deprecated, use "ro.product.cpu.abilist"
@@ -49,7 +51,7 @@ echo "# ro.build.product is obsolete; use ro.product.device"
echo "ro.build.product=$TARGET_DEVICE"
echo "# Do not try to parse description or thumbprint"
-echo "ro.build.description=$PRIVATE_BUILD_DESC"
+echo "ro.build.description?=$PRIVATE_BUILD_DESC"
if [ -n "$BUILD_THUMBPRINT" ] ; then
echo "ro.build.thumbprint=$BUILD_THUMBPRINT"
fi
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index 7a2dcb76e3..bd347a1003 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -165,10 +165,10 @@ python_defaults {
"ota_utils_lib",
],
required: [
+ "apexd_host",
"brillo_update_payload",
"checkvintf",
"generate_gki_certificate",
- "minigzip",
"lz4",
"toybox",
"unpack_bootimg",
@@ -244,7 +244,6 @@ python_library_host {
"bsdiff",
"generate_gki_certificate",
"imgdiff",
- "minigzip",
"lz4",
"mkbootfs",
"signapk",
@@ -310,7 +309,6 @@ python_defaults {
"deapexer",
"generate_gki_certificate",
"imgdiff",
- "minigzip",
"lz4",
"mkbootfs",
"signapk",
@@ -347,6 +345,7 @@ python_binary_host {
},
srcs: [
"merge_ota.py",
+ "ota_signing_utils.py",
],
libs: [
"ota_metadata_proto",
@@ -496,6 +495,26 @@ python_binary_host {
}
python_binary_host {
+ name: "ota_from_raw_img",
+ srcs: [
+ "ota_from_raw_img.py",
+ "ota_signing_utils.py",
+ ],
+ main: "ota_from_raw_img.py",
+ defaults: [
+ "releasetools_binary_defaults",
+ ],
+ required: [
+ "delta_generator",
+ ],
+ libs: [
+ "ota_metadata_proto",
+ "releasetools_common",
+ "ota_utils_lib",
+ ],
+}
+
+python_binary_host {
name: "ota_package_parser",
defaults: ["releasetools_binary_defaults"],
srcs: [
@@ -593,6 +612,7 @@ python_defaults {
"sign_target_files_apks.py",
"validate_target_files.py",
"merge_ota.py",
+ "ota_signing_utils.py",
":releasetools_merge_sources",
":releasetools_merge_tests",
@@ -624,6 +644,7 @@ python_defaults {
},
},
required: [
+ "apexd_host",
"deapexer",
],
}
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 465d222a83..31f8736e46 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -517,12 +517,14 @@ def AddPvmfw(output_zip):
return img.name
-def AddCustomImages(output_zip, partition_name):
- """Adds and signs custom images in IMAGES/.
+def AddCustomImages(output_zip, partition_name, image_list):
+ """Adds and signs avb custom images as needed in IMAGES/.
Args:
output_zip: The output zip file (needs to be already open), or None to
write images to OPTIONS.input_tmp/.
+ partition_name: The custom image partition name.
+ image_list: The image list of the custom image partition.
Uses the image under IMAGES/ if it already exists. Otherwise looks for the
image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
@@ -531,19 +533,20 @@ def AddCustomImages(output_zip, partition_name):
AssertionError: If image can't be found.
"""
+ builder = None
key_path = OPTIONS.info_dict.get("avb_{}_key_path".format(partition_name))
- algorithm = OPTIONS.info_dict.get("avb_{}_algorithm".format(partition_name))
- extra_args = OPTIONS.info_dict.get(
- "avb_{}_add_hashtree_footer_args".format(partition_name))
- partition_size = OPTIONS.info_dict.get(
- "avb_{}_partition_size".format(partition_name))
-
- builder = verity_utils.CreateCustomImageBuilder(
- OPTIONS.info_dict, partition_name, partition_size,
- key_path, algorithm, extra_args)
-
- for img_name in OPTIONS.info_dict.get(
- "avb_{}_image_list".format(partition_name)).split():
+ if key_path is not None:
+ algorithm = OPTIONS.info_dict.get("avb_{}_algorithm".format(partition_name))
+ extra_args = OPTIONS.info_dict.get(
+ "avb_{}_add_hashtree_footer_args".format(partition_name))
+ partition_size = OPTIONS.info_dict.get(
+ "avb_{}_partition_size".format(partition_name))
+
+ builder = verity_utils.CreateCustomImageBuilder(
+ OPTIONS.info_dict, partition_name, partition_size,
+ key_path, algorithm, extra_args)
+
+ for img_name in image_list:
custom_image = OutputFile(
output_zip, OPTIONS.input_tmp, "IMAGES", img_name)
if os.path.exists(custom_image.name):
@@ -684,34 +687,6 @@ def AddVBMeta(output_zip, partitions, name, needed_partitions):
return img.name
-def AddPartitionTable(output_zip):
- """Create a partition table image and store it in output_zip."""
-
- img = OutputFile(
- output_zip, OPTIONS.input_tmp, "IMAGES", "partition-table.img")
- bpt = OutputFile(
- output_zip, OPTIONS.input_tmp, "META", "partition-table.bpt")
-
- # use BPTTOOL from environ, or "bpttool" if empty or not set.
- bpttool = os.getenv("BPTTOOL") or "bpttool"
- cmd = [bpttool, "make_table", "--output_json", bpt.name,
- "--output_gpt", img.name]
- input_files_str = OPTIONS.info_dict["board_bpt_input_files"]
- input_files = input_files_str.split()
- for i in input_files:
- cmd.extend(["--input", i])
- disk_size = OPTIONS.info_dict.get("board_bpt_disk_size")
- if disk_size:
- cmd.extend(["--disk_size", disk_size])
- args = OPTIONS.info_dict.get("board_bpt_make_table_args")
- if args:
- cmd.extend(shlex.split(args))
- common.RunAndCheckOutput(cmd)
-
- img.Write()
- bpt.Write()
-
-
def AddCache(output_zip):
"""Create an empty cache image and store it in output_zip."""
@@ -1087,10 +1062,6 @@ def AddImagesToTargetFiles(filename):
banner("cache")
AddCache(output_zip)
- if OPTIONS.info_dict.get("board_bpt_enable") == "true":
- banner("partition-table")
- AddPartitionTable(output_zip)
-
add_partition("dtbo",
OPTIONS.info_dict.get("has_dtbo") == "true", AddDtbo, [])
add_partition("pvmfw",
@@ -1098,18 +1069,29 @@ def AddImagesToTargetFiles(filename):
# Custom images.
custom_partitions = OPTIONS.info_dict.get(
- "avb_custom_images_partition_list", "").strip().split()
+ "custom_images_partition_list", "").strip().split()
for partition_name in custom_partitions:
partition_name = partition_name.strip()
banner("custom images for " + partition_name)
- partitions[partition_name] = AddCustomImages(output_zip, partition_name)
+ image_list = OPTIONS.info_dict.get(
+ "{}_image_list".format(partition_name)).split()
+ partitions[partition_name] = AddCustomImages(output_zip, partition_name, image_list)
+
+ avb_custom_partitions = OPTIONS.info_dict.get(
+ "avb_custom_images_partition_list", "").strip().split()
+ for partition_name in avb_custom_partitions:
+ partition_name = partition_name.strip()
+ banner("avb custom images for " + partition_name)
+ image_list = OPTIONS.info_dict.get(
+ "avb_{}_image_list".format(partition_name)).split()
+ partitions[partition_name] = AddCustomImages(output_zip, partition_name, image_list)
if OPTIONS.info_dict.get("avb_enable") == "true":
# vbmeta_partitions includes the partitions that should be included into
# top-level vbmeta.img, which are the ones that are not included in any
# chained VBMeta image plus the chained VBMeta images themselves.
- # Currently custom_partitions are all chained to VBMeta image.
- vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(custom_partitions)
+ # Currently avb_custom_partitions are all chained to VBMeta image.
+ vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(avb_custom_partitions)
vbmeta_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip()
if vbmeta_system:
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 11bd78428c..5e4130c764 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# Copyright (C) 2011 The Android Open Source Project
#
@@ -22,9 +22,9 @@ Usage: build_image input_directory properties_file output_image \\
target_output_directory
"""
-from __future__ import print_function
import datetime
+import argparse
import glob
import logging
import os
@@ -34,6 +34,7 @@ import shlex
import shutil
import sys
import uuid
+import tempfile
import common
import verity_utils
@@ -683,7 +684,9 @@ def ImagePropFromGlobalDict(glob_dict, mount_point):
d = {}
TryParseFingerprint(glob_dict)
- d["timestamp"] = FIXED_FILE_TIMESTAMP
+ # Set fixed timestamp for building the OTA package.
+ if "use_fixed_timestamp" in glob_dict:
+ d["timestamp"] = FIXED_FILE_TIMESTAMP
if "build.prop" in glob_dict:
timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc")
if timestamp:
@@ -917,27 +920,69 @@ def BuildVBMeta(in_dir, glob_dict, output_path):
common.BuildVBMeta(output_path, partitions, name, vbmeta_partitions)
-def main(argv):
- args = common.ParseOptions(argv, __doc__)
+def BuildImageOrVBMeta(input_directory, target_out, glob_dict, image_properties, out_file):
+ try:
+ if "vbmeta" in os.path.basename(out_file):
+ OPTIONS.info_dict = glob_dict
+ BuildVBMeta(input_directory, glob_dict, out_file)
+ else:
+ BuildImage(input_directory, image_properties, out_file, target_out)
+ except:
+ logger.error("Failed to build %s from %s", out_file, input_directory)
+ raise
- if len(args) != 4:
- print(__doc__)
- sys.exit(1)
- common.InitLogging()
+def CopyInputDirectory(src, dst, filter_file):
+ with open(filter_file, 'r') as f:
+ for line in f:
+ line = line.strip()
+ if not line:
+ return
+ if line != os.path.normpath(line):
+ sys.exit(f"{line}: not normalized")
+ if line.startswith("../") or line.startswith('/'):
+ sys.exit(f"{line}: escapes staging directory by starting with ../ or /")
+ full_src = os.path.join(src, line)
+ full_dst = os.path.join(dst, line)
+ if os.path.isdir(full_src):
+ os.makedirs(full_dst, exist_ok=True)
+ else:
+ os.makedirs(os.path.dirname(full_dst), exist_ok=True)
+ os.link(full_src, full_dst, follow_symlinks=False)
+
- in_dir = args[0]
- glob_dict_file = args[1]
- out_file = args[2]
- target_out = args[3]
+def main(argv):
+ parser = argparse.ArgumentParser(
+ description="Builds output_image from the given input_directory and properties_file, and "
+ "writes the image to target_output_directory.")
+ parser.add_argument("--input-directory-filter-file",
+ help="the path to a file that contains a list of all files in the input_directory. If this "
+ "option is provided, all files under the input_directory that are not listed in this file will "
+ "be deleted before building the image. This is to work around the fact that building a module "
+ "will install in by default, so there could be files in the input_directory that are not "
+ "actually supposed to be part of the partition. The paths in this file must be relative to "
+ "input_directory.")
+ parser.add_argument("input_directory",
+ help="the staging directory to be converted to an image file")
+ parser.add_argument("properties_file",
+ help="a file containing the 'global dictionary' of properties that affect how the image is "
+ "built")
+ parser.add_argument("out_file",
+ help="the output file to write")
+ parser.add_argument("target_out",
+ help="the path to $(TARGET_OUT). Certain tools will use this to look through multiple staging "
+ "directories for fs config files.")
+ args = parser.parse_args()
+
+ common.InitLogging()
- glob_dict = LoadGlobalDict(glob_dict_file)
+ glob_dict = LoadGlobalDict(args.properties_file)
if "mount_point" in glob_dict:
# The caller knows the mount point and provides a dictionary needed by
# BuildImage().
image_properties = glob_dict
else:
- image_filename = os.path.basename(out_file)
+ image_filename = os.path.basename(args.out_file)
mount_point = ""
if image_filename == "system.img":
mount_point = "system"
@@ -972,15 +1017,12 @@ def main(argv):
if "vbmeta" != mount_point:
image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
- try:
- if "vbmeta" in os.path.basename(out_file):
- OPTIONS.info_dict = glob_dict
- BuildVBMeta(in_dir, glob_dict, out_file)
- else:
- BuildImage(in_dir, image_properties, out_file, target_out)
- except:
- logger.error("Failed to build %s from %s", out_file, in_dir)
- raise
+ if args.input_directory_filter_file and not os.environ.get("BUILD_BROKEN_INCORRECT_PARTITION_IMAGES"):
+ with tempfile.TemporaryDirectory(dir=os.path.dirname(args.input_directory)) as new_input_directory:
+ CopyInputDirectory(args.input_directory, new_input_directory, args.input_directory_filter_file)
+ BuildImageOrVBMeta(new_input_directory, args.target_out, glob_dict, image_properties, args.out_file)
+ else:
+ BuildImageOrVBMeta(args.input_directory, args.target_out, glob_dict, image_properties, args.out_file)
if __name__ == '__main__':
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 091121f2fe..c5a3fe777f 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -20,7 +20,6 @@ import copy
import datetime
import errno
import fnmatch
-from genericpath import isdir
import getopt
import getpass
import gzip
@@ -34,12 +33,13 @@ import re
import shlex
import shutil
import subprocess
-import sys
import stat
+import sys
import tempfile
import threading
import time
import zipfile
+from genericpath import isdir
from hashlib import sha1, sha256
import images
@@ -96,7 +96,6 @@ class Options(object):
self.cache_size = None
self.stash_threshold = 0.8
self.logfile = None
- self.host_tools = {}
self.sepolicy_name = 'sepolicy.apex'
@@ -113,13 +112,18 @@ SPECIAL_CERT_STRINGS = ("PRESIGNED", "EXTERNAL")
# descriptor into vbmeta.img. When adding a new entry here, the
# AVB_FOOTER_ARGS_BY_PARTITION in sign_target_files_apks need to be updated
# accordingly.
-AVB_PARTITIONS = ('boot', 'init_boot', 'dtbo', 'odm', 'product', 'pvmfw', 'recovery',
- 'system', 'system_ext', 'vendor', 'vendor_boot', 'vendor_kernel_boot',
- 'vendor_dlkm', 'odm_dlkm', 'system_dlkm')
+AVB_PARTITIONS = ('boot', 'init_boot', 'dtbo', 'odm', 'product', 'pvmfw',
+ 'recovery', 'system', 'system_ext', 'vendor', 'vendor_boot',
+ 'vendor_kernel_boot', 'vendor_dlkm', 'odm_dlkm',
+ 'system_dlkm')
# Chained VBMeta partitions.
AVB_VBMETA_PARTITIONS = ('vbmeta_system', 'vbmeta_vendor')
+# avbtool arguments name
+AVB_ARG_NAME_INCLUDE_DESC_FROM_IMG = '--include_descriptors_from_image'
+AVB_ARG_NAME_CHAIN_PARTITION = '--chain_partition'
+
# Partitions that should have their care_map added to META/care_map.pb
PARTITIONS_WITH_CARE_MAP = [
'system',
@@ -195,7 +199,7 @@ def InitLogging():
'': {
'handlers': ['default'],
'propagate': True,
- 'level': 'INFO',
+ 'level': 'WARNING',
}
}
}
@@ -225,23 +229,15 @@ def InitLogging():
logging.config.dictConfig(config)
-def SetHostToolLocation(tool_name, location):
- OPTIONS.host_tools[tool_name] = location
-
-
def FindHostToolPath(tool_name):
"""Finds the path to the host tool.
Args:
tool_name: name of the tool to find
Returns:
- path to the tool if found under either one of the host_tools map or under
- the same directory as this binary is located at. If not found, tool_name
- is returned.
+ path to the tool if found under the same directory as this binary is located at. If not found,
+ tool_name is returned.
"""
- if tool_name in OPTIONS.host_tools:
- return OPTIONS.host_tools[tool_name]
-
my_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
tool_path = os.path.join(my_dir, tool_name)
if os.path.exists(tool_path):
@@ -459,6 +455,15 @@ class BuildInfo(object):
return system_prop and system_prop.GetProp("ro.build.version.release") == "11"
@property
+ def is_release_key(self):
+ system_prop = self.info_dict.get("build.prop")
+ return system_prop and system_prop.GetProp("ro.build.tags") == "release-key"
+
+ @property
+ def vabc_compression_param(self):
+ return self.get("virtual_ab_compression_method", "")
+
+ @property
def vendor_api_level(self):
vendor_prop = self.info_dict.get("vendor.build.prop")
if not vendor_prop:
@@ -985,7 +990,7 @@ class PartitionBuildProps(object):
each of the variables.
ramdisk_format: If name is "boot", the format of ramdisk inside the
boot image. Otherwise, its value is ignored.
- Use lz4 to decompress by default. If its value is gzip, use minigzip.
+ Use lz4 to decompress by default. If its value is gzip, use gzip.
"""
def __init__(self, input_file, name, placeholder_values=None):
@@ -1429,7 +1434,7 @@ def ResolveAVBSigningPathArgs(split_args):
if os.path.exists(new_path):
return new_path
raise ExternalError(
- "Failed to find {}".format(new_path))
+ "Failed to find {}".format(path))
if not split_args:
return split_args
@@ -1467,7 +1472,7 @@ def GetAvbPartitionArg(partition, image, info_dict=None):
# Check if chain partition is used.
key_path = info_dict.get("avb_" + partition + "_key_path")
if not key_path:
- return ["--include_descriptors_from_image", image]
+ return [AVB_ARG_NAME_INCLUDE_DESC_FROM_IMG, image]
# For a non-A/B device, we don't chain /recovery nor include its descriptor
# into vbmeta.img. The recovery image will be configured on an independent
@@ -1479,7 +1484,7 @@ def GetAvbPartitionArg(partition, image, info_dict=None):
# Otherwise chain the partition into vbmeta.
chained_partition_arg = GetAvbChainedPartitionArg(partition, info_dict)
- return ["--chain_partition", chained_partition_arg]
+ return [AVB_ARG_NAME_CHAIN_PARTITION, chained_partition_arg]
def GetAvbChainedPartitionArg(partition, info_dict, key=None):
@@ -1598,7 +1603,7 @@ def BuildVBMeta(image_path, partitions, name, needed_partitions):
# same location when running this script (we have the input target_files
# zip only). For such cases, we additionally scan other locations (e.g.
# IMAGES/, RADIO/, etc) before bailing out.
- if arg == '--include_descriptors_from_image':
+ if arg == AVB_ARG_NAME_INCLUDE_DESC_FROM_IMG:
chained_image = split_args[index + 1]
if os.path.exists(chained_image):
continue
@@ -1638,9 +1643,9 @@ def _MakeRamdisk(sourcedir, fs_config_file=None,
p2 = Run(["lz4", "-l", "-12", "--favor-decSpeed"], stdin=p1.stdout,
stdout=ramdisk_img.file.fileno())
elif ramdisk_format == RamdiskFormat.GZ:
- p2 = Run(["minigzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
+ p2 = Run(["gzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
else:
- raise ValueError("Only support lz4 or minigzip ramdisk format.")
+ raise ValueError("Only support lz4 or gzip ramdisk format.")
p2.wait()
p1.wait()
@@ -2120,20 +2125,33 @@ def UnzipSingleFile(input_zip: zipfile.ZipFile, info: zipfile.ZipInfo, dirname:
# According to https://stackoverflow.com/questions/434641/how-do-i-set-permissions-attributes-on-a-file-in-a-zip-file-using-pythons-zip/6297838#6297838
# higher bits of |external_attr| are unix file permission and types
unix_filetype = info.external_attr >> 16
+ file_perm = unix_filetype & 0o777
def CheckMask(a, mask):
return (a & mask) == mask
def IsSymlink(a):
return CheckMask(a, stat.S_IFLNK)
+
+ def IsDir(a):
+ return CheckMask(a, stat.S_IFDIR)
# python3.11 zipfile implementation doesn't handle symlink correctly
if not IsSymlink(unix_filetype):
- return input_zip.extract(info, dirname)
+ target = input_zip.extract(info, dirname)
+ # We want to ensure that the file is at least read/writable by owner and readable by all users
+ if IsDir(unix_filetype):
+ os.chmod(target, file_perm | 0o755)
+ else:
+ os.chmod(target, file_perm | 0o644)
+ return target
if dirname is None:
dirname = os.getcwd()
target = os.path.join(dirname, info.filename)
os.makedirs(os.path.dirname(target), exist_ok=True)
+ if os.path.exists(target):
+ os.unlink(target)
os.symlink(input_zip.read(info).decode(), target)
+ return target
def UnzipToDir(filename, dirname, patterns=None):
@@ -2425,8 +2443,9 @@ def GetMinSdkVersion(apk_name):
apk_name, proc.returncode, stdoutdata, stderrdata))
for line in stdoutdata.split("\n"):
- # Looking for lines such as sdkVersion:'23' or sdkVersion:'M'.
- m = re.match(r'sdkVersion:\'([^\']*)\'', line)
+ # Due to ag/24161708, looking for lines such as minSdkVersion:'23',minSdkVersion:'M'
+ # or sdkVersion:'23', sdkVersion:'M'.
+ m = re.match(r'(?:minSdkVersion|sdkVersion):\'([^\']*)\'', line)
if m:
return m.group(1)
raise ExternalError("No minSdkVersion returned by aapt2")
@@ -4075,7 +4094,7 @@ def GetBootImageBuildProp(boot_img, ramdisk_format=RamdiskFormat.LZ4):
Get build.prop from ramdisk within the boot image
Args:
- boot_img: the boot image file. Ramdisk must be compressed with lz4 or minigzip format.
+ boot_img: the boot image file. Ramdisk must be compressed with lz4 or gzip format.
Return:
An extracted file that stores properties in the boot image.
@@ -4094,11 +4113,11 @@ def GetBootImageBuildProp(boot_img, ramdisk_format=RamdiskFormat.LZ4):
elif ramdisk_format == RamdiskFormat.GZ:
with open(ramdisk, 'rb') as input_stream:
with open(uncompressed_ramdisk, 'wb') as output_stream:
- p2 = Run(['minigzip', '-d'], stdin=input_stream.fileno(),
+ p2 = Run(['gzip', '-d'], stdin=input_stream.fileno(),
stdout=output_stream.fileno())
p2.wait()
else:
- logger.error('Only support lz4 or minigzip ramdisk format.')
+ logger.error('Only support lz4 or gzip ramdisk format.')
return None
abs_uncompressed_ramdisk = os.path.abspath(uncompressed_ramdisk)
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index fa53ad2fa7..a3e3681c73 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -64,7 +64,8 @@ OPTIONS.super_device_list = None
OPTIONS.retrofit_dap = None
OPTIONS.build_super = None
OPTIONS.sparse_userimages = None
-OPTIONS.use_fastboot_info = False
+OPTIONS.use_fastboot_info = True
+OPTIONS.build_super_image = None
def LoadOptions(input_file):
"""Loads information from input_file to OPTIONS.
@@ -174,7 +175,13 @@ def RebuildAndWriteSuperImages(input_file, output_file):
input_tmp = common.UnzipTemp(input_file)
super_file = common.MakeTempFile('super_', '.img')
- BuildSuperImage(input_tmp, super_file)
+
+ # Allow overriding the BUILD_SUPER_IMAGE binary
+ if OPTIONS.build_super_image:
+ command = [OPTIONS.build_super_image, input_tmp, super_file]
+ common.RunAndCheckOutput(command)
+ else:
+ BuildSuperImage(input_tmp, super_file)
logger.info('Writing super.img to archive...')
with zipfile.ZipFile(
@@ -231,6 +238,8 @@ def main(argv):
OPTIONS.bootable_only = True
elif o == '--additional':
OPTIONS.additional_entries.append(a)
+ elif o == '--build_super_image':
+ OPTIONS.build_super_image = a
else:
return False
return True
@@ -240,6 +249,7 @@ def main(argv):
extra_long_opts=[
'additional=',
'bootable_zip',
+ 'build_super_image=',
],
extra_option_handler=option_handler)
if len(args) != 2:
diff --git a/tools/releasetools/merge/merge_meta.py b/tools/releasetools/merge/merge_meta.py
index b61f039051..198c973456 100644
--- a/tools/releasetools/merge/merge_meta.py
+++ b/tools/releasetools/merge/merge_meta.py
@@ -53,8 +53,6 @@ PARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"')
MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
-
-
def MergeUpdateEngineConfig(input_metadir1, input_metadir2, merged_meta_dir):
UPDATE_ENGINE_CONFIG_NAME = "update_engine_config.txt"
config1_path = os.path.join(
@@ -74,7 +72,7 @@ def MergeUpdateEngineConfig(input_metadir1, input_metadir2, merged_meta_dir):
merged_meta_dir, UPDATE_ENGINE_CONFIG_NAME))
-def MergeMetaFiles(temp_dir, merged_dir):
+def MergeMetaFiles(temp_dir, merged_dir, framework_partitions):
"""Merges various files in META/*."""
framework_meta_dir = os.path.join(temp_dir, 'framework_meta', 'META')
@@ -114,7 +112,8 @@ def MergeMetaFiles(temp_dir, merged_dir):
MergeAbPartitions(
framework_meta_dir=framework_meta_dir,
vendor_meta_dir=vendor_meta_dir,
- merged_meta_dir=merged_meta_dir)
+ merged_meta_dir=merged_meta_dir,
+ framework_partitions=framework_partitions)
UpdateCareMapImageSizeProps(images_dir=os.path.join(merged_dir, 'IMAGES'))
for file_name in ('apkcerts.txt', 'apexkeys.txt'):
@@ -124,10 +123,10 @@ def MergeMetaFiles(temp_dir, merged_dir):
merged_meta_dir=merged_meta_dir,
file_name=file_name)
- MergeUpdateEngineConfig(
- framework_meta_dir,
- vendor_meta_dir, merged_meta_dir,
- )
+ if OPTIONS.merged_misc_info.get('ab_update') == 'true':
+ MergeUpdateEngineConfig(
+ framework_meta_dir,
+ vendor_meta_dir, merged_meta_dir)
# Write the now-finalized OPTIONS.merged_misc_info.
merge_utils.WriteSortedData(
@@ -135,13 +134,22 @@ def MergeMetaFiles(temp_dir, merged_dir):
path=os.path.join(merged_meta_dir, 'misc_info.txt'))
-def MergeAbPartitions(framework_meta_dir, vendor_meta_dir, merged_meta_dir):
+def MergeAbPartitions(framework_meta_dir, vendor_meta_dir, merged_meta_dir,
+ framework_partitions):
"""Merges META/ab_partitions.txt.
The output contains the union of the partition names.
"""
with open(os.path.join(framework_meta_dir, 'ab_partitions.txt')) as f:
- framework_ab_partitions = f.read().splitlines()
+ # Filter out some partitions here to support the case that the
+ # ab_partitions.txt of framework-target-files has non-framework partitions.
+ # This case happens when we use a complete merged target files package as
+ # the framework-target-files.
+ framework_ab_partitions = [
+ partition
+ for partition in f.read().splitlines()
+ if partition in framework_partitions
+ ]
with open(os.path.join(vendor_meta_dir, 'ab_partitions.txt')) as f:
vendor_ab_partitions = f.read().splitlines()
diff --git a/tools/releasetools/merge/merge_target_files.py b/tools/releasetools/merge/merge_target_files.py
index d8f7b15a51..a0d3a1c67a 100755
--- a/tools/releasetools/merge/merge_target_files.py
+++ b/tools/releasetools/merge/merge_target_files.py
@@ -209,7 +209,9 @@ def create_merged_package(temp_dir):
# After this function completes successfully, all the files we need to create
# the output target files package are in place.
merge_meta.MergeMetaFiles(
- temp_dir=temp_dir, merged_dir=output_target_files_temp_dir)
+ temp_dir=temp_dir,
+ merged_dir=output_target_files_temp_dir,
+ framework_partitions=OPTIONS.framework_partition_set)
merge_dexopt.MergeDexopt(
temp_dir=temp_dir, output_target_files_dir=output_target_files_temp_dir)
diff --git a/tools/releasetools/merge/merge_utils.py b/tools/releasetools/merge/merge_utils.py
index b5683a854a..d446fc020d 100644
--- a/tools/releasetools/merge/merge_utils.py
+++ b/tools/releasetools/merge/merge_utils.py
@@ -217,7 +217,7 @@ def ItemListToPartitionSet(item_list):
# Partitions that are grabbed from the framework partial build by default.
_FRAMEWORK_PARTITIONS = {
- 'system', 'product', 'system_ext', 'system_other', 'root', 'system_dlkm',
+ 'system', 'product', 'system_ext', 'system_other', 'root',
'vbmeta_system', 'pvmfw'
}
diff --git a/tools/releasetools/merge_ota.py b/tools/releasetools/merge_ota.py
index 441312cf25..24d9ea9cf0 100644
--- a/tools/releasetools/merge_ota.py
+++ b/tools/releasetools/merge_ota.py
@@ -14,7 +14,6 @@
import argparse
import logging
-import shlex
import struct
import sys
import update_payload
@@ -31,6 +30,7 @@ from update_payload import Payload
from payload_signer import PayloadSigner
from ota_utils import PayloadGenerator, METADATA_PROTO_NAME, FinalizeMetadata
+from ota_signing_utils import AddSigningArgumentParse
logger = logging.getLogger(__name__)
@@ -126,7 +126,7 @@ def MergeManifests(payloads: List[Payload]) -> DeltaArchiveManifest:
ExtendPartitionUpdates(output_manifest.partitions, manifest.partitions)
try:
MergeDynamicPartitionMetadata(
- output_manifest.dynamic_partition_metadata, manifest.dynamic_partition_metadata)
+ output_manifest.dynamic_partition_metadata, manifest.dynamic_partition_metadata)
except DuplicatePartitionError:
logger.error(
"OTA %s has duplicate partition with some of the previous OTAs", payload.name)
@@ -190,6 +190,7 @@ def CheckDuplicatePartitions(payloads: List[Payload]):
f"OTA {partition_to_ota[part].name} and {payload.name} have duplicating partition {part}")
partition_to_ota[part] = payload
+
def ApexInfo(file_paths):
if len(file_paths) > 1:
logger.info("More than one target file specified, will ignore "
@@ -201,33 +202,19 @@ def ApexInfo(file_paths):
return apex_info_bytes
return None
-def ParseSignerArgs(args):
- if args is None:
- return None
- return shlex.split(args)
def main(argv):
parser = argparse.ArgumentParser(description='Merge multiple partial OTAs')
parser.add_argument('packages', type=str, nargs='+',
help='Paths to OTA packages to merge')
- parser.add_argument('--package_key', type=str,
- help='Paths to private key for signing payload')
- parser.add_argument('--search_path', type=str,
- help='Search path for framework/signapk.jar')
- parser.add_argument('--payload_signer', type=str,
- help='Path to custom payload signer')
- parser.add_argument('--payload_signer_args', type=ParseSignerArgs,
- help='Arguments for payload signer if necessary')
- parser.add_argument('--payload_signer_maximum_signature_size', type=str,
- help='Maximum signature size (in bytes) that would be '
- 'generated by the given payload signer')
parser.add_argument('--output', type=str,
help='Paths to output merged ota', required=True)
parser.add_argument('--metadata_ota', type=str,
help='Output zip will use build metadata from this OTA package, if unspecified, use the last OTA package in merge list')
- parser.add_argument('--private_key_suffix', type=str,
- help='Suffix to be appended to package_key path', default=".pk8")
- parser.add_argument('-v', action="store_true", help="Enable verbose logging", dest="verbose")
+ parser.add_argument('-v', action="store_true",
+ help="Enable verbose logging", dest="verbose")
+ AddSigningArgumentParse(parser)
+
parser.epilog = ('This tool can also be used to resign a regular OTA. For a single regular OTA, '
'apex_info.pb will be written to output. When merging multiple OTAs, '
'apex_info.pb will not be written.')
@@ -301,8 +288,6 @@ def main(argv):
return 0
-
-
if __name__ == '__main__':
logging.basicConfig()
sys.exit(main(sys.argv))
diff --git a/tools/releasetools/ota_from_raw_img.py b/tools/releasetools/ota_from_raw_img.py
new file mode 100644
index 0000000000..0c1c05acde
--- /dev/null
+++ b/tools/releasetools/ota_from_raw_img.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2008 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.
+
+"""
+Given a series of .img files, produces an OTA package that installs thoese images
+"""
+
+import sys
+import os
+import argparse
+import subprocess
+import tempfile
+import logging
+import zipfile
+
+import common
+from payload_signer import PayloadSigner
+from ota_utils import PayloadGenerator
+from ota_signing_utils import AddSigningArgumentParse
+
+
+logger = logging.getLogger(__name__)
+
+
+def ResolveBinaryPath(filename, search_path):
+ if not search_path:
+ return filename
+ if not os.path.exists(search_path):
+ return filename
+ path = os.path.join(search_path, "bin", filename)
+ if os.path.exists(path):
+ return path
+ path = os.path.join(search_path, filename)
+ if os.path.exists(path):
+ return path
+ return path
+
+
+def main(argv):
+ parser = argparse.ArgumentParser(
+ prog=argv[0], description="Given a series of .img files, produces a full OTA package that installs thoese images")
+ parser.add_argument("images", nargs="+", type=str,
+ help="List of images to generate OTA")
+ parser.add_argument("--partition_names", nargs='+', type=str,
+ help="Partition names to install the images, default to basename of the image(no file name extension)")
+ parser.add_argument('--output', type=str,
+ help='Paths to output merged ota', required=True)
+ parser.add_argument('--max_timestamp', type=int,
+ help='Maximum build timestamp allowed to install this OTA')
+ parser.add_argument("-v", action="store_true",
+ help="Enable verbose logging", dest="verbose")
+ AddSigningArgumentParse(parser)
+
+ args = parser.parse_args(argv[1:])
+ if args.verbose:
+ logger.setLevel(logging.INFO)
+ logger.info(args)
+ if not args.partition_names:
+ args.partition_names = [os.path.os.path.splitext(os.path.basename(path))[
+ 0] for path in args.images]
+ with tempfile.NamedTemporaryFile() as unsigned_payload, tempfile.NamedTemporaryFile() as dynamic_partition_info_file:
+ dynamic_partition_info_file.writelines(
+ [b"virtual_ab=true\n", b"super_partition_groups=\n"])
+ dynamic_partition_info_file.flush()
+ cmd = [ResolveBinaryPath("delta_generator", args.search_path)]
+ cmd.append("--partition_names=" + ",".join(args.partition_names))
+ cmd.append("--dynamic_partition_info_file=" +
+ dynamic_partition_info_file.name)
+ cmd.append("--new_partitions=" + ",".join(args.images))
+ cmd.append("--out_file=" + unsigned_payload.name)
+ cmd.append("--is_partial_update")
+ if args.max_timestamp:
+ cmd.append("--max_timestamp=" + str(args.max_timestamp))
+ cmd.append("--partition_timestamps=boot:" + str(args.max_timestamp))
+ logger.info("Running %s", cmd)
+
+ subprocess.check_call(cmd)
+ generator = PayloadGenerator()
+ generator.payload_file = unsigned_payload.name
+ logger.info("Payload size: %d", os.path.getsize(generator.payload_file))
+
+ # Get signing keys
+ key_passwords = common.GetKeyPasswords([args.package_key])
+
+ if args.package_key:
+ logger.info("Signing payload...")
+ # TODO: remove OPTIONS when no longer used as fallback in payload_signer
+ common.OPTIONS.payload_signer_args = None
+ common.OPTIONS.payload_signer_maximum_signature_size = None
+ signer = PayloadSigner(args.package_key, args.private_key_suffix,
+ key_passwords[args.package_key],
+ payload_signer=args.payload_signer,
+ payload_signer_args=args.payload_signer_args,
+ payload_signer_maximum_signature_size=args.payload_signer_maximum_signature_size)
+ generator.payload_file = unsigned_payload.name
+ generator.Sign(signer)
+
+ logger.info("Payload size: %d", os.path.getsize(generator.payload_file))
+
+ logger.info("Writing to %s", args.output)
+ with zipfile.ZipFile(args.output, "w") as zfp:
+ generator.WriteToZip(zfp)
+
+
+if __name__ == "__main__":
+ logging.basicConfig()
+ main(sys.argv)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index f3e6f1e3d1..d4420c9943 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -147,7 +147,7 @@ Non-A/B OTA specific options
A/B OTA specific options
--disable_fec_computation
- Disable the on device FEC data computation for incremental updates.
+ Disable the on device FEC data computation for incremental updates. OTA will be larger but installation will be faster.
--include_secondary
Additionally include the payload for secondary slot images (default:
@@ -224,7 +224,7 @@ A/B OTA specific options
wait time in recovery.
--enable_vabc_xor
- Enable the VABC xor feature. Will reduce space requirements for OTA
+ Enable the VABC xor feature. Will reduce space requirements for OTA, but OTA installation will be slower.
--force_minor_version
Override the update_engine minor version for delta generation.
@@ -233,7 +233,10 @@ A/B OTA specific options
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.
+ Whether to enable to zucchini feature. Will generate smaller OTA but uses more memory, OTA generation will take longer.
+
+ --enable_puffdiff
+ Whether to enable to puffdiff feature. Will generate smaller OTA but uses more memory, OTA generation will take longer.
--enable_lz4diff
Whether to enable lz4diff feature. Will generate smaller OTA for EROFS but
@@ -244,7 +247,9 @@ A/B OTA specific options
older SPL.
--vabc_compression_param
- Compression algorithm to be used for VABC. Available options: gz, brotli, none
+ Compression algorithm to be used for VABC. Available options: gz, lz4, zstd, brotli, none.
+ Compression level can be specified by appending ",$LEVEL" to option.
+ e.g. --vabc_compression_param=gz,9 specifies level 9 compression with gz algorithm
--security_patch_level
Override the security patch level in target files
@@ -269,7 +274,7 @@ import zipfile
import care_map_pb2
import common
import ota_utils
-from ota_utils import (UNZIP_PATTERN, FinalizeMetadata, GetPackageMetadata,
+from ota_utils import (VABC_COMPRESSION_PARAM_SUPPORT, FinalizeMetadata, GetPackageMetadata,
PayloadGenerator, SECURITY_PATCH_LEVEL_PROP_NAME, ExtractTargetFiles, CopyTargetFilesDir)
from common import DoesInputFileContain, IsSparseImage
import target_files_diff
@@ -320,6 +325,7 @@ OPTIONS.enable_vabc_xor = True
OPTIONS.force_minor_version = None
OPTIONS.compressor_types = None
OPTIONS.enable_zucchini = True
+OPTIONS.enable_puffdiff = None
OPTIONS.enable_lz4diff = False
OPTIONS.vabc_compression_param = None
OPTIONS.security_patch_level = None
@@ -456,48 +462,51 @@ def GetTargetFilesZipForSecondaryImages(input_file, skip_postinstall=False):
target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
target_zip = zipfile.ZipFile(target_file, 'w', allowZip64=True)
- with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
- infolist = input_zip.infolist()
+ fileslist = []
+ for (root, dirs, files) in os.walk(input_file):
+ root = root.lstrip(input_file).lstrip("/")
+ fileslist.extend([os.path.join(root, d) for d in dirs])
+ fileslist.extend([os.path.join(root, d) for d in files])
- input_tmp = common.UnzipTemp(input_file, UNZIP_PATTERN)
- for info in infolist:
- unzipped_file = os.path.join(input_tmp, *info.filename.split('/'))
- if info.filename == 'IMAGES/system_other.img':
+ input_tmp = input_file
+ for filename in fileslist:
+ unzipped_file = os.path.join(input_tmp, *filename.split('/'))
+ if filename == 'IMAGES/system_other.img':
common.ZipWrite(target_zip, unzipped_file, arcname='IMAGES/system.img')
# Primary images and friends need to be skipped explicitly.
- elif info.filename in ('IMAGES/system.img',
- 'IMAGES/system.map'):
+ elif filename in ('IMAGES/system.img',
+ 'IMAGES/system.map'):
pass
# Copy images that are not in SECONDARY_PAYLOAD_SKIPPED_IMAGES.
- elif info.filename.startswith(('IMAGES/', 'RADIO/')):
- image_name = os.path.basename(info.filename)
+ elif filename.startswith(('IMAGES/', 'RADIO/')):
+ image_name = os.path.basename(filename)
if image_name not in ['{}.img'.format(partition) for partition in
SECONDARY_PAYLOAD_SKIPPED_IMAGES]:
- common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+ common.ZipWrite(target_zip, unzipped_file, arcname=filename)
# Skip copying the postinstall config if requested.
- elif skip_postinstall and info.filename == POSTINSTALL_CONFIG:
+ elif skip_postinstall and filename == POSTINSTALL_CONFIG:
pass
- elif info.filename.startswith('META/'):
+ elif filename.startswith('META/'):
# Remove the unnecessary partitions for secondary images from the
# ab_partitions file.
- if info.filename == AB_PARTITIONS:
+ if filename == AB_PARTITIONS:
with open(unzipped_file) as f:
partition_list = f.read().splitlines()
partition_list = [partition for partition in partition_list if partition
and partition not in SECONDARY_PAYLOAD_SKIPPED_IMAGES]
- common.ZipWriteStr(target_zip, info.filename,
+ common.ZipWriteStr(target_zip, filename,
'\n'.join(partition_list))
# Remove the unnecessary partitions from the dynamic partitions list.
- elif (info.filename == 'META/misc_info.txt' or
- info.filename == DYNAMIC_PARTITION_INFO):
+ elif (filename == 'META/misc_info.txt' or
+ filename == DYNAMIC_PARTITION_INFO):
modified_info = GetInfoForSecondaryImages(unzipped_file)
- common.ZipWriteStr(target_zip, info.filename, modified_info)
+ common.ZipWriteStr(target_zip, filename, modified_info)
else:
- common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+ common.ZipWrite(target_zip, unzipped_file, arcname=filename)
common.ZipClose(target_zip)
@@ -719,47 +728,33 @@ def GetTargetFilesZipForRetrofitDynamicPartitions(input_file,
return input_file
-def GetTargetFilesZipForCustomImagesUpdates(input_file, custom_images):
+def GetTargetFilesZipForCustomImagesUpdates(input_file, custom_images: dict):
"""Returns a target-files.zip for custom partitions update.
This function modifies ab_partitions list with the desired custom partitions
and puts the custom images into the target target-files.zip.
Args:
- input_file: The input target-files.zip filename.
+ input_file: The input target-files extracted directory
custom_images: A map of custom partitions and custom images.
Returns:
- The filename of a target-files.zip which has renamed the custom images in
- the IMAGES/ to their partition names.
+ The extracted dir of a target-files.zip which has renamed the custom images
+ in the IMAGES/ to their partition names.
"""
+ for custom_image in custom_images.values():
+ if not os.path.exists(os.path.join(input_file, "IMAGES", custom_image)):
+ raise ValueError("Specified custom image {} not found in target files {}, available images are {}",
+ custom_image, input_file, os.listdir(os.path.join(input_file, "IMAGES")))
- # First pass: use zip2zip to copy the target files contents, excluding
- # the "custom" images that will be replaced.
- target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
- cmd = ['zip2zip', '-i', input_file, '-o', target_file]
-
- images = {}
for custom_partition, custom_image in custom_images.items():
default_custom_image = '{}.img'.format(custom_partition)
if default_custom_image != custom_image:
- src = 'IMAGES/' + custom_image
- dst = 'IMAGES/' + default_custom_image
- cmd.extend(['-x', dst])
- images[dst] = src
-
- common.RunAndCheckOutput(cmd)
-
- # Second pass: write {custom_image}.img as {custom_partition}.img.
- with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
- with zipfile.ZipFile(target_file, 'a', allowZip64=True) as output_zip:
- for dst, src in images.items():
- data = input_zip.read(src)
- logger.info("Update custom partition '%s'", dst)
- common.ZipWriteStr(output_zip, dst, data)
- output_zip.close()
+ src = os.path.join(input_file, 'IMAGES', custom_image)
+ dst = os.path.join(input_file, 'IMAGES', default_custom_image)
+ os.rename(src, dst)
- return target_file
+ return input_file
def GeneratePartitionTimestampFlags(partition_state):
@@ -836,6 +831,10 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
"""Generates an Android OTA package that has A/B update payload."""
# If input target_files are directories, create a copy so that we can modify
# them directly
+ target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
+ if OPTIONS.disable_vabc and target_info.is_release_key:
+ raise ValueError("Disabling VABC on release-key builds is not supported.")
+
target_file = ExtractOrCopyTargetFiles(target_file)
if source_file is not None:
source_file = ExtractOrCopyTargetFiles(source_file)
@@ -863,6 +862,10 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
if not source_info.is_vabc or not target_info.is_vabc:
logger.info("Either source or target does not support VABC, disabling.")
OPTIONS.disable_vabc = True
+ if source_info.vabc_compression_param != target_info.vabc_compression_param:
+ logger.info("Source build and target build use different compression methods {} vs {}, default to source builds parameter {}".format(
+ source_info.vabc_compression_param, target_info.vabc_compression_param, source_info.vabc_compression_param))
+ OPTIONS.vabc_compression_param = source_info.vabc_compression_param
# Virtual AB Compression was introduced in Androd S.
# Later, we backported VABC to Android R. But verity support was not
@@ -875,8 +878,23 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
else:
assert "ab_partitions" in OPTIONS.info_dict, \
"META/ab_partitions.txt is required for ab_update."
- target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
source_info = None
+ if target_info.vabc_compression_param:
+ minimum_api_level_required = VABC_COMPRESSION_PARAM_SUPPORT[
+ target_info.vabc_compression_param]
+ if target_info.vendor_api_level < minimum_api_level_required:
+ logger.warning(
+ "This full OTA is configured to use VABC compression algorithm"
+ " {}, which is supported since"
+ " Android API level {}, but device is "
+ "launched with {} . If this full OTA is"
+ " served to a device running old build, OTA might fail due to "
+ "unsupported compression parameter. For safety, gz is used because "
+ "it's supported since day 1.".format(
+ target_info.vabc_compression_param,
+ minimum_api_level_required,
+ target_info.vendor_api_level))
+ OPTIONS.vabc_compression_param = "gz"
if OPTIONS.partial == []:
logger.info(
@@ -994,6 +1012,9 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
additional_args += ["--enable_zucchini=" +
str(OPTIONS.enable_zucchini).lower()]
+ if OPTIONS.enable_puffdiff is not None:
+ additional_args += ["--enable_puffdiff=" +
+ str(OPTIONS.enable_puffdiff).lower()]
if not ota_utils.IsLz4diffCompatible(source_file, target_file):
logger.warning(
@@ -1193,11 +1214,20 @@ def main(argv):
elif o == "--enable_zucchini":
assert a.lower() in ["true", "false"]
OPTIONS.enable_zucchini = a.lower() != "false"
+ elif o == "--enable_puffdiff":
+ assert a.lower() in ["true", "false"]
+ OPTIONS.enable_puffdiff = a.lower() != "false"
elif o == "--enable_lz4diff":
assert a.lower() in ["true", "false"]
OPTIONS.enable_lz4diff = a.lower() != "false"
elif o == "--vabc_compression_param":
+ words = a.split(",")
+ assert len(words) >= 1 and len(words) <= 2
OPTIONS.vabc_compression_param = a.lower()
+ if len(words) == 2:
+ if not words[1].isdigit():
+ raise ValueError("Cannot parse value %r for option $COMPRESSION_LEVEL - only "
+ "integers are allowed." % words[1])
elif o == "--security_patch_level":
OPTIONS.security_patch_level = a
elif o in ("--max_threads"):
@@ -1254,6 +1284,7 @@ def main(argv):
"force_minor_version=",
"compressor_types=",
"enable_zucchini=",
+ "enable_puffdiff=",
"enable_lz4diff=",
"vabc_compression_param=",
"security_patch_level=",
diff --git a/tools/releasetools/ota_signing_utils.py b/tools/releasetools/ota_signing_utils.py
new file mode 100644
index 0000000000..60c8c94f91
--- /dev/null
+++ b/tools/releasetools/ota_signing_utils.py
@@ -0,0 +1,38 @@
+# Copyright (C) 2022 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.
+
+import argparse
+import shlex
+
+
+def ParseSignerArgs(args):
+ if args is None:
+ return None
+ return shlex.split(args)
+
+
+def AddSigningArgumentParse(parser: argparse.ArgumentParser):
+ parser.add_argument('--package_key', type=str,
+ help='Paths to private key for signing payload')
+ parser.add_argument('--search_path', '--path', type=str,
+ help='Search path for framework/signapk.jar')
+ parser.add_argument('--payload_signer', type=str,
+ help='Path to custom payload signer')
+ parser.add_argument('--payload_signer_args', type=ParseSignerArgs,
+ help='Arguments for payload signer if necessary')
+ parser.add_argument('--payload_signer_maximum_signature_size', type=str,
+ help='Maximum signature size (in bytes) that would be '
+ 'generated by the given payload signer')
+ parser.add_argument('--private_key_suffix', type=str,
+ help='Suffix to be appended to package_key path', default=".pk8")
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 68c6887f87..5c702233a0 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -51,6 +51,19 @@ SECURITY_PATCH_LEVEL_PROP_NAME = "ro.build.version.security_patch"
TARGET_FILES_IMAGES_SUBDIR = ["IMAGES", "PREBUILT_IMAGES", "RADIO"]
+# Key is the compression algorithm, value is minimum API level required to
+# use this compression algorithm for VABC OTA on device.
+VABC_COMPRESSION_PARAM_SUPPORT = {
+ "gz": 31,
+ "brotli": 31,
+ "none": 31,
+ # lz4 support is added in Android U
+ "lz4": 34,
+ # zstd support is added in Android V
+ "zstd": 35,
+}
+
+
def FinalizeMetadata(metadata, input_file, output_file, needed_property_files=None, package_key=None, pw=None):
"""Finalizes the metadata and signs an A/B OTA package.
@@ -727,6 +740,7 @@ def ExtractTargetFiles(path: str):
logger.info("target files %s is already extracted", path)
return path
extracted_dir = common.MakeTempDir("target_files")
+ logger.info(f"Extracting target files {path} to {extracted_dir}")
common.UnzipToDir(path, extracted_dir, UNZIP_PATTERN + [""])
for subdir in TARGET_FILES_IMAGES_SUBDIR:
image_dir = os.path.join(extracted_dir, subdir)
@@ -741,12 +755,10 @@ def ExtractTargetFiles(path: str):
def LocatePartitionPath(target_files_dir: str, partition: str, allow_empty):
- path = os.path.join(target_files_dir, "RADIO", partition + ".img")
- if os.path.exists(path):
- return path
- path = os.path.join(target_files_dir, "IMAGES", partition + ".img")
- if os.path.exists(path):
- return path
+ for subdir in TARGET_FILES_IMAGES_SUBDIR:
+ path = os.path.join(target_files_dir, subdir, partition + ".img")
+ if os.path.exists(path):
+ return path
if allow_empty:
return ""
raise common.ExternalError(
@@ -759,12 +771,10 @@ def GetPartitionImages(target_files_dir: str, ab_partitions, allow_empty=True):
def LocatePartitionMap(target_files_dir: str, partition: str):
- path = os.path.join(target_files_dir, "RADIO", partition + ".map")
- if os.path.exists(path):
- return path
- path = os.path.join(target_files_dir, "IMAGES", partition + ".map")
- if os.path.exists(path):
- return path
+ for subdir in TARGET_FILES_IMAGES_SUBDIR:
+ path = os.path.join(target_files_dir, subdir, partition + ".map")
+ if os.path.exists(path):
+ return path
return ""
@@ -850,7 +860,7 @@ class PayloadGenerator(object):
cmd.extend(["--dynamic_partition_info_file", dynamic_partition_info])
apex_info = os.path.join(
- target_dir, "META", "apex_info.pb")
+ target_dir, "META", "apex_info.pb")
if os.path.exists(apex_info):
cmd.extend(["--apex_info_file", apex_info])
@@ -883,30 +893,7 @@ class PayloadGenerator(object):
"""
assert isinstance(payload_signer, PayloadSigner)
- # 1. Generate hashes of the payload and metadata files.
- payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- cmd = ["brillo_update_payload", "hash",
- "--unsigned_payload", self.payload_file,
- "--signature_size", str(payload_signer.maximum_signature_size),
- "--metadata_hash_file", metadata_sig_file,
- "--payload_hash_file", payload_sig_file]
- self._Run(cmd)
-
- # 2. Sign the hashes.
- signed_payload_sig_file = payload_signer.SignHashFile(payload_sig_file)
- signed_metadata_sig_file = payload_signer.SignHashFile(metadata_sig_file)
-
- # 3. Insert the signatures back into the payload file.
- signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
- suffix=".bin")
- cmd = ["brillo_update_payload", "sign",
- "--unsigned_payload", self.payload_file,
- "--payload", signed_payload_file,
- "--signature_size", str(payload_signer.maximum_signature_size),
- "--metadata_signature_file", signed_metadata_sig_file,
- "--payload_signature_file", signed_payload_sig_file]
- self._Run(cmd)
+ signed_payload_file = payload_signer.SignPayload(self.payload_file)
self.payload_file = signed_payload_file
@@ -920,9 +907,9 @@ class PayloadGenerator(object):
# 4. Dump the signed payload properties.
properties_file = common.MakeTempFile(prefix="payload-properties-",
suffix=".txt")
- cmd = ["brillo_update_payload", "properties",
- "--payload", self.payload_file,
- "--properties_file", properties_file]
+ cmd = ["delta_generator",
+ "--in_file=" + self.payload_file,
+ "--properties_file=" + properties_file]
self._Run(cmd)
if self.secondary:
@@ -1070,7 +1057,7 @@ def CopyTargetFilesDir(input_dir):
if common.IsSparseImage(src):
return common.UnsparseImage(src, dst)
else:
- return os.link(src, dst)
+ return os.symlink(os.path.realpath(src), dst)
for subdir in TARGET_FILES_IMAGES_SUBDIR:
if not os.path.exists(os.path.join(input_dir, subdir)):
diff --git a/tools/releasetools/payload_signer.py b/tools/releasetools/payload_signer.py
index 9933aefeb8..bbd2896508 100644
--- a/tools/releasetools/payload_signer.py
+++ b/tools/releasetools/payload_signer.py
@@ -95,11 +95,11 @@ class PayloadSigner(object):
# 1. Generate hashes of the payload and metadata files.
payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- cmd = ["brillo_update_payload", "hash",
- "--unsigned_payload", unsigned_payload,
- "--signature_size", str(self.maximum_signature_size),
- "--metadata_hash_file", metadata_sig_file,
- "--payload_hash_file", payload_sig_file]
+ cmd = ["delta_generator",
+ "--in_file=" + unsigned_payload,
+ "--signature_size=" + str(self.maximum_signature_size),
+ "--out_metadata_hash_file=" + metadata_sig_file,
+ "--out_hash_file=" + payload_sig_file]
self._Run(cmd)
# 2. Sign the hashes.
@@ -109,16 +109,15 @@ class PayloadSigner(object):
# 3. Insert the signatures back into the payload file.
signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
suffix=".bin")
- cmd = ["brillo_update_payload", "sign",
- "--unsigned_payload", unsigned_payload,
- "--payload", signed_payload_file,
- "--signature_size", str(self.maximum_signature_size),
- "--metadata_signature_file", signed_metadata_sig_file,
- "--payload_signature_file", signed_payload_sig_file]
+ cmd = ["delta_generator",
+ "--in_file=" + unsigned_payload,
+ "--out_file=" + signed_payload_file,
+ "--signature_size=" + str(self.maximum_signature_size),
+ "--metadata_signature_file=" + signed_metadata_sig_file,
+ "--payload_signature_file=" + signed_payload_sig_file]
self._Run(cmd)
return signed_payload_file
-
def SignHashFile(self, in_file):
"""Signs the given input file. Returns the output filename."""
out_file = common.MakeTempFile(prefix="signed-", suffix=".bin")
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 8291448249..2b45825ae5 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -1234,11 +1234,11 @@ def BuildVendorPartitions(output_zip_path):
vendor_misc_info["no_recovery"] = "true" # recovery
vendor_misc_info["avb_enable"] = "false" # vbmeta
- vendor_misc_info["board_bpt_enable"] = "false" # partition-table
vendor_misc_info["has_dtbo"] = "false" # dtbo
vendor_misc_info["has_pvmfw"] = "false" # pvmfw
- vendor_misc_info["avb_custom_images_partition_list"] = "" # custom images
+ vendor_misc_info["avb_custom_images_partition_list"] = "" # avb custom images
vendor_misc_info["avb_building_vbmeta_image"] = "false" # skip building vbmeta
+ vendor_misc_info["custom_images_partition_list"] = "" # custom images
vendor_misc_info["use_dynamic_partitions"] = "false" # super_empty
vendor_misc_info["build_super_partition"] = "false" # super split
vendor_misc_info["avb_vbmeta_system"] = "" # skip building vbmeta_system
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 86fb480d0d..2bd4f36bd9 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -15,14 +15,13 @@
#
import copy
-import json
import os
import subprocess
import tempfile
-import time
import unittest
import zipfile
from hashlib import sha1
+from typing import BinaryIO
import common
import test_utils
@@ -36,14 +35,24 @@ MiB = 1024 * KiB
GiB = 1024 * MiB
-def get_2gb_string():
+def get_2gb_file():
size = int(2 * GiB + 1)
block_size = 4 * KiB
step_size = 4 * MiB
- # Generate a long string with holes, e.g. 'xyz\x00abc\x00...'.
+ tmpfile = tempfile.NamedTemporaryFile()
+ tmpfile.truncate(size)
for _ in range(0, size, step_size):
- yield os.urandom(block_size)
- yield b'\0' * (step_size - block_size)
+ tmpfile.write(os.urandom(block_size))
+ tmpfile.seek(step_size - block_size, os.SEEK_CUR)
+ return tmpfile
+
+
+def hash_file(filename):
+ sha1_hash = sha1()
+ with open(filename, "rb") as fp:
+ for data in iter(lambda: fp.read(4*MiB), b''):
+ sha1_hash.update(data)
+ return sha1_hash
class BuildInfoTest(test_utils.ReleaseToolsTestCase):
@@ -222,17 +231,17 @@ class BuildInfoTest(test_utils.ReleaseToolsTestCase):
info_dict = copy.deepcopy(self.TEST_INFO_FINGERPRINT_DICT)
build_info = common.BuildInfo(info_dict)
self.assertEqual(
- 'product-brand/product-name/product-device:version-release/build-id/'
- 'version-incremental:build-type/build-tags', build_info.fingerprint)
+ 'product-brand/product-name/product-device:version-release/build-id/'
+ 'version-incremental:build-type/build-tags', build_info.fingerprint)
build_props = info_dict['build.prop'].build_props
del build_props['ro.build.id']
build_props['ro.build.legacy.id'] = 'legacy-build-id'
build_info = common.BuildInfo(info_dict, use_legacy_id=True)
self.assertEqual(
- 'product-brand/product-name/product-device:version-release/'
- 'legacy-build-id/version-incremental:build-type/build-tags',
- build_info.fingerprint)
+ 'product-brand/product-name/product-device:version-release/'
+ 'legacy-build-id/version-incremental:build-type/build-tags',
+ build_info.fingerprint)
self.assertRaises(common.ExternalError, common.BuildInfo, info_dict, None,
False)
@@ -241,9 +250,9 @@ class BuildInfoTest(test_utils.ReleaseToolsTestCase):
info_dict['vbmeta_digest'] = 'abcde12345'
build_info = common.BuildInfo(info_dict, use_legacy_id=False)
self.assertEqual(
- 'product-brand/product-name/product-device:version-release/'
- 'legacy-build-id.abcde123/version-incremental:build-type/build-tags',
- build_info.fingerprint)
+ 'product-brand/product-name/product-device:version-release/'
+ 'legacy-build-id.abcde123/version-incremental:build-type/build-tags',
+ build_info.fingerprint)
def test___getitem__(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
@@ -376,7 +385,7 @@ class BuildInfoTest(test_utils.ReleaseToolsTestCase):
info_dict['build.prop'].build_props[
'ro.product.property_source_order'] = 'bad-source'
with self.assertRaisesRegexp(common.ExternalError,
- 'Invalid ro.product.property_source_order'):
+ 'Invalid ro.product.property_source_order'):
info = common.BuildInfo(info_dict, None)
info.GetBuildProp('ro.product.device')
@@ -429,6 +438,13 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
self.assertIsNone(zip_file.testzip())
def _test_ZipWrite(self, contents, extra_zipwrite_args=None):
+ with tempfile.NamedTemporaryFile() as test_file:
+ test_file_name = test_file.name
+ for data in contents:
+ test_file.write(bytes(data))
+ return self._test_ZipWriteFile(test_file_name, extra_zipwrite_args)
+
+ def _test_ZipWriteFile(self, test_file_name, extra_zipwrite_args=None):
extra_zipwrite_args = dict(extra_zipwrite_args or {})
test_file = tempfile.NamedTemporaryFile(delete=False)
@@ -441,17 +457,12 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
arcname = extra_zipwrite_args.get("arcname", test_file_name)
if arcname[0] == "/":
arcname = arcname[1:]
+ sha1_hash = hash_file(test_file_name)
zip_file.close()
zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
try:
- sha1_hash = sha1()
- for data in contents:
- sha1_hash.update(bytes(data))
- test_file.write(bytes(data))
- test_file.close()
-
expected_mode = extra_zipwrite_args.get("perms", 0o644)
expected_compress_type = extra_zipwrite_args.get("compress_type",
zipfile.ZIP_STORED)
@@ -467,7 +478,6 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
test_file_name, expected_stat, expected_mode,
expected_compress_type)
finally:
- os.remove(test_file_name)
os.remove(zip_file_name)
def _test_ZipWriteStr(self, zinfo_or_arcname, contents, extra_args=None):
@@ -502,14 +512,13 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
finally:
os.remove(zip_file_name)
- def _test_ZipWriteStr_large_file(self, large, small, extra_args=None):
+ def _test_ZipWriteStr_large_file(self, large_file: BinaryIO, small, extra_args=None):
extra_args = dict(extra_args or {})
zip_file = tempfile.NamedTemporaryFile(delete=False)
zip_file_name = zip_file.name
- test_file = tempfile.NamedTemporaryFile(delete=False)
- test_file_name = test_file.name
+ test_file_name = large_file.name
arcname_large = test_file_name
arcname_small = "bar"
@@ -522,11 +531,7 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
try:
- sha1_hash = sha1()
- for data in large:
- sha1_hash.update(data)
- test_file.write(data)
- test_file.close()
+ sha1_hash = hash_file(test_file_name)
# Arbitrary timestamp, just to make sure common.ZipWrite() restores
# the timestamp after writing.
@@ -551,7 +556,6 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
expected_compress_type=expected_compress_type)
finally:
os.remove(zip_file_name)
- os.remove(test_file_name)
def _test_reset_ZIP64_LIMIT(self, func, *args):
default_limit = (1 << 31) - 1
@@ -577,10 +581,10 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
})
def test_ZipWrite_large_file(self):
- file_contents = get_2gb_string()
- self._test_ZipWrite(file_contents, {
- "compress_type": zipfile.ZIP_DEFLATED,
- })
+ with get_2gb_file() as tmpfile:
+ self._test_ZipWriteFile(tmpfile.name, {
+ "compress_type": zipfile.ZIP_DEFLATED,
+ })
def test_ZipWrite_resets_ZIP64_LIMIT(self):
self._test_reset_ZIP64_LIMIT(self._test_ZipWrite, "")
@@ -627,11 +631,11 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
# zipfile.writestr() doesn't work when the str size is over 2GiB even with
# the workaround. We will only test the case of writing a string into a
# large archive.
- long_string = get_2gb_string()
short_string = os.urandom(1024)
- self._test_ZipWriteStr_large_file(long_string, short_string, {
- "compress_type": zipfile.ZIP_DEFLATED,
- })
+ with get_2gb_file() as large_file:
+ self._test_ZipWriteStr_large_file(large_file, short_string, {
+ "compress_type": zipfile.ZIP_DEFLATED,
+ })
def test_ZipWriteStr_resets_ZIP64_LIMIT(self):
self._test_reset_ZIP64_LIMIT(self._test_ZipWriteStr, 'foo', b'')
@@ -821,9 +825,9 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
)
APKCERTS_CERTMAP1 = {
- 'RecoveryLocalizer.apk' : 'certs/devkey',
- 'Settings.apk' : 'build/make/target/product/security/platform',
- 'TV.apk' : 'PRESIGNED',
+ 'RecoveryLocalizer.apk': 'certs/devkey',
+ 'Settings.apk': 'build/make/target/product/security/platform',
+ 'TV.apk': 'PRESIGNED',
}
APKCERTS_TXT2 = (
@@ -838,10 +842,10 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
)
APKCERTS_CERTMAP2 = {
- 'Compressed1.apk' : 'certs/compressed1',
- 'Compressed2a.apk' : 'certs/compressed2',
- 'Compressed2b.apk' : 'certs/compressed2',
- 'Compressed3.apk' : 'certs/compressed3',
+ 'Compressed1.apk': 'certs/compressed1',
+ 'Compressed2a.apk': 'certs/compressed2',
+ 'Compressed2b.apk': 'certs/compressed2',
+ 'Compressed3.apk': 'certs/compressed3',
}
APKCERTS_TXT3 = (
@@ -850,7 +854,7 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
)
APKCERTS_CERTMAP3 = {
- 'Compressed4.apk' : 'certs/compressed4',
+ 'Compressed4.apk': 'certs/compressed4',
}
# Test parsing with no optional fields, both optional fields, and only the
@@ -867,9 +871,9 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
)
APKCERTS_CERTMAP4 = {
- 'RecoveryLocalizer.apk' : 'certs/devkey',
- 'Settings.apk' : 'build/make/target/product/security/platform',
- 'TV.apk' : 'PRESIGNED',
+ 'RecoveryLocalizer.apk': 'certs/devkey',
+ 'Settings.apk': 'build/make/target/product/security/platform',
+ 'TV.apk': 'PRESIGNED',
}
def setUp(self):
@@ -973,7 +977,7 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
extracted_from_privkey = common.ExtractAvbPublicKey('avbtool', privkey)
extracted_from_pubkey = common.ExtractAvbPublicKey('avbtool', pubkey)
with open(extracted_from_privkey, 'rb') as privkey_fp, \
- open(extracted_from_pubkey, 'rb') as pubkey_fp:
+ open(extracted_from_pubkey, 'rb') as pubkey_fp:
self.assertEqual(privkey_fp.read(), pubkey_fp.read())
def test_ParseCertificate(self):
@@ -1237,7 +1241,8 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
self.assertEqual(
'1-5 9-10',
sparse_image.file_map['//system/file1'].extra['text_str'])
- self.assertTrue(sparse_image.file_map['//system/file2'].extra['incomplete'])
+ self.assertTrue(
+ sparse_image.file_map['//system/file2'].extra['incomplete'])
self.assertTrue(
sparse_image.file_map['/system/app/file3'].extra['incomplete'])
@@ -1345,7 +1350,7 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
'recovery_api_version': 3,
'fstab_version': 2,
'system_root_image': 'true',
- 'no_recovery' : 'true',
+ 'no_recovery': 'true',
'recovery_as_boot': 'true',
}
@@ -1580,7 +1585,8 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
info_dict = {}
cmd = common.GetAvbPartitionArg('system', '/path/to/system.img', info_dict)
self.assertEqual(
- ['--include_descriptors_from_image', '/path/to/system.img'], cmd)
+ [common.AVB_ARG_NAME_INCLUDE_DESC_FROM_IMG, '/path/to/system.img'],
+ cmd)
@test_utils.SkipIfExternalToolsUnavailable()
def test_AppendVBMetaArgsForPartition_vendorAsChainedPartition(self):
@@ -1593,7 +1599,7 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
}
cmd = common.GetAvbPartitionArg('vendor', '/path/to/vendor.img', info_dict)
self.assertEqual(2, len(cmd))
- self.assertEqual('--chain_partition', cmd[0])
+ self.assertEqual(common.AVB_ARG_NAME_CHAIN_PARTITION, cmd[0])
chained_partition_args = cmd[1].split(':')
self.assertEqual(3, len(chained_partition_args))
self.assertEqual('vendor', chained_partition_args[0])
@@ -1626,7 +1632,7 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
cmd = common.GetAvbPartitionArg(
'recovery', '/path/to/recovery.img', info_dict)
self.assertEqual(2, len(cmd))
- self.assertEqual('--chain_partition', cmd[0])
+ self.assertEqual(common.AVB_ARG_NAME_CHAIN_PARTITION, cmd[0])
chained_partition_args = cmd[1].split(':')
self.assertEqual(3, len(chained_partition_args))
self.assertEqual('recovery', chained_partition_args[0])
@@ -1667,6 +1673,7 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
self.assertRaises(common.ExternalError, common._GenerateGkiCertificate,
test_file.name, 'generic_kernel')
+
class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
"""Checks the format of install-recovery.sh.
@@ -1676,7 +1683,7 @@ class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
def setUp(self):
self._tempdir = common.MakeTempDir()
# Create a fake dict that contains the fstab info for boot&recovery.
- self._info = {"fstab" : {}}
+ self._info = {"fstab": {}}
fake_fstab = [
"/dev/soc.0/by-name/boot /boot emmc defaults defaults",
"/dev/soc.0/by-name/recovery /recovery emmc defaults defaults"]
@@ -2023,11 +2030,11 @@ class PartitionBuildPropsTest(test_utils.ReleaseToolsTestCase):
input_zip, 'odm', placeholder_values)
self.assertEqual({
- 'ro.odm.build.date.utc': '1578430045',
- 'ro.odm.build.fingerprint':
- 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
- 'ro.product.odm.device': 'coral',
- 'ro.product.odm.name': 'product1',
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ 'ro.product.odm.name': 'product1',
}, partition_props.build_props)
with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
@@ -2210,8 +2217,8 @@ class PartitionBuildPropsTest(test_utils.ReleaseToolsTestCase):
copied_props = copy.deepcopy(partition_props)
self.assertEqual({
- 'ro.odm.build.date.utc': '1578430045',
- 'ro.odm.build.fingerprint':
- 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
- 'ro.product.odm.device': 'coral',
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
}, copied_props.build_props)
diff --git a/tools/sbom/Android.bp b/tools/sbom/Android.bp
index 4837dde51d..519251e1c7 100644
--- a/tools/sbom/Android.bp
+++ b/tools/sbom/Android.bp
@@ -53,5 +53,27 @@ python_test_host {
libs: [
"sbom_lib",
],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+ test_suites: ["general-tests"],
+}
+
+python_test_host {
+ name: "sbom_data_test",
+ main: "sbom_data_test.py",
+ srcs: [
+ "sbom_data_test.py",
+ ],
+ libs: [
+ "sbom_lib",
+ ],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
test_suites: ["general-tests"],
}
diff --git a/tools/sbom/sbom_data.py b/tools/sbom/sbom_data.py
index ea38e364dc..71f8660d67 100644
--- a/tools/sbom/sbom_data.py
+++ b/tools/sbom/sbom_data.py
@@ -133,7 +133,7 @@ class Document:
checksums = []
for file in self.files:
if file.id in package.file_ids:
- checksums.append(file.checksum)
+ checksums.append(file.checksum.split(': ')[1])
checksums.sort()
h = hashlib.sha1()
h.update(''.join(checksums).encode(encoding='utf-8'))
diff --git a/tools/sbom/sbom_data_test.py b/tools/sbom/sbom_data_test.py
new file mode 100644
index 0000000000..69bc9d2d29
--- /dev/null
+++ b/tools/sbom/sbom_data_test.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 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.
+
+import hashlib
+import unittest
+import sbom_data
+
+BUILD_FINGER_PRINT = 'build_finger_print'
+SUPPLIER_GOOGLE = 'Organization: Google'
+SUPPLIER_UPSTREAM = 'Organization: upstream'
+
+SPDXID_PREBUILT_PACKAGE1 = 'SPDXRef-PREBUILT-package1'
+SPDXID_SOURCE_PACKAGE1 = 'SPDXRef-SOURCE-package1'
+SPDXID_UPSTREAM_PACKAGE1 = 'SPDXRef-UPSTREAM-package1'
+
+SPDXID_FILE1 = 'SPDXRef-file1'
+SPDXID_FILE2 = 'SPDXRef-file2'
+SPDXID_FILE3 = 'SPDXRef-file3'
+SPDXID_FILE4 = 'SPDXRef-file4'
+
+
+class SBOMDataTest(unittest.TestCase):
+
+ def setUp(self):
+ # SBOM of a product
+ self.sbom_doc = sbom_data.Document(name='test doc',
+ namespace='http://www.google.com/sbom/spdx/android',
+ creators=[SUPPLIER_GOOGLE],
+ created='2023-03-31T22:17:58Z',
+ describes=sbom_data.SPDXID_PRODUCT)
+ self.sbom_doc.add_external_ref(
+ sbom_data.DocumentExternalReference(id='DocumentRef-external_doc_ref',
+ uri='external_doc_uri',
+ checksum='SHA1: 1234567890'))
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=sbom_data.SPDXID_PRODUCT,
+ name=sbom_data.PACKAGE_NAME_PRODUCT,
+ download_location=sbom_data.VALUE_NONE,
+ supplier=SUPPLIER_GOOGLE,
+ version=BUILD_FINGER_PRINT,
+ files_analyzed=True,
+ verification_code='',
+ file_ids=[SPDXID_FILE1, SPDXID_FILE2, SPDXID_FILE3, SPDXID_FILE4]))
+
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=sbom_data.SPDXID_PLATFORM,
+ name=sbom_data.PACKAGE_NAME_PLATFORM,
+ download_location=sbom_data.VALUE_NONE,
+ supplier=SUPPLIER_GOOGLE,
+ version=BUILD_FINGER_PRINT,
+ ))
+
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE1,
+ name='Prebuilt package1',
+ download_location=sbom_data.VALUE_NONE,
+ supplier=SUPPLIER_GOOGLE,
+ version=BUILD_FINGER_PRINT,
+ ))
+
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=SPDXID_SOURCE_PACKAGE1,
+ name='Source package1',
+ download_location=sbom_data.VALUE_NONE,
+ supplier=SUPPLIER_GOOGLE,
+ version=BUILD_FINGER_PRINT,
+ external_refs=[sbom_data.PackageExternalRef(
+ category=sbom_data.PackageExternalRefCategory.SECURITY,
+ type=sbom_data.PackageExternalRefType.cpe22Type,
+ locator='cpe:/a:jsoncpp_project:jsoncpp:1.9.4')]
+ ))
+
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=SPDXID_UPSTREAM_PACKAGE1,
+ name='Upstream package1',
+ supplier=SUPPLIER_UPSTREAM,
+ version='1.1',
+ ))
+
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_SOURCE_PACKAGE1,
+ relationship=sbom_data.RelationshipType.VARIANT_OF,
+ id2=SPDXID_UPSTREAM_PACKAGE1))
+
+ self.sbom_doc.files.append(
+ sbom_data.File(id=SPDXID_FILE1, name='/bin/file1',
+ checksum='SHA1: 356a192b7913b04c54574d18c28d46e6395428ab')) # sha1 hash of 1
+ self.sbom_doc.files.append(
+ sbom_data.File(id=SPDXID_FILE2, name='/bin/file2',
+ checksum='SHA1: da4b9237bacccdf19c0760cab7aec4a8359010b0')) # sha1 hash of 2
+ self.sbom_doc.files.append(
+ sbom_data.File(id=SPDXID_FILE3, name='/bin/file3',
+ checksum='SHA1: 77de68daecd823babbb58edb1c8e14d7106e83bb')) # sha1 hash of 3
+ self.sbom_doc.files.append(
+ sbom_data.File(id=SPDXID_FILE4, name='file4.a',
+ checksum='SHA1: 1b6453892473a467d07372d45eb05abc2031647a')) # sha1 of 4
+
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE1,
+ relationship=sbom_data.RelationshipType.GENERATED_FROM,
+ id2=sbom_data.SPDXID_PLATFORM))
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE2,
+ relationship=sbom_data.RelationshipType.GENERATED_FROM,
+ id2=SPDXID_PREBUILT_PACKAGE1))
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE3,
+ relationship=sbom_data.RelationshipType.GENERATED_FROM,
+ id2=SPDXID_SOURCE_PACKAGE1
+ ))
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE1,
+ relationship=sbom_data.RelationshipType.STATIC_LINK,
+ id2=SPDXID_FILE4
+ ))
+
+ def test_package_verification_code(self):
+ checksums = []
+ for file in self.sbom_doc.files:
+ checksums.append(file.checksum.split(': ')[1])
+ checksums.sort()
+ h = hashlib.sha1()
+ h.update(''.join(checksums).encode(encoding='utf-8'))
+ expected_package_verification_code = h.hexdigest()
+
+ self.sbom_doc.generate_packages_verification_code()
+ self.assertEqual(expected_package_verification_code, self.sbom_doc.packages[0].verification_code)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/tools/zipalign/Android.bp b/tools/zipalign/Android.bp
index 0e1d58ed74..8be7e25f22 100644
--- a/tools/zipalign/Android.bp
+++ b/tools/zipalign/Android.bp
@@ -70,6 +70,7 @@ cc_test_host {
"libgmock",
],
data: [
+ "tests/data/apkWithUncompressedSharedLibs.zip",
"tests/data/archiveWithOneDirectoryEntry.zip",
"tests/data/diffOrders.zip",
"tests/data/holes.zip",
diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp
index 23840e3945..f32f90b130 100644
--- a/tools/zipalign/ZipAlign.cpp
+++ b/tools/zipalign/ZipAlign.cpp
@@ -17,6 +17,7 @@
#include "ZipFile.h"
#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
#include <unistd.h>
@@ -36,17 +37,14 @@ static bool isDirectory(ZipEntry* entry) {
}
static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
- ZipEntry* pEntry) {
-
- static const int kPageAlignment = 4096;
-
+ ZipEntry* pEntry, int pageSize) {
if (!pageAlignSharedLibs) {
return defaultAlignment;
}
const char* ext = strrchr(pEntry->getFileName(), '.');
if (ext && strcmp(ext, ".so") == 0) {
- return kPageAlignment;
+ return pageSize;
}
return defaultAlignment;
@@ -56,7 +54,7 @@ static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
* Copy all entries from "pZin" to "pZout", aligning as needed.
*/
static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfli,
- bool pageAlignSharedLibs)
+ bool pageAlignSharedLibs, int pageSize)
{
int numEntries = pZin->getNumEntries();
ZipEntry* pEntry;
@@ -84,7 +82,8 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfl
status = pZout->add(pZin, pEntry, padding, &pNewEntry);
}
} else {
- const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
+ const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry,
+ pageSize);
//printf("--- %s: orig at %ld(+%d) len=%ld, adding pad=%d\n",
// pEntry->getFileName(), (long) pEntry->getFileOffset(),
@@ -107,7 +106,7 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfl
* output file exists and "force" wasn't specified.
*/
int process(const char* inFileName, const char* outFileName,
- int alignment, bool force, bool zopfli, bool pageAlignSharedLibs)
+ int alignment, bool force, bool zopfli, bool pageAlignSharedLibs, int pageSize)
{
ZipFile zin, zout;
@@ -127,7 +126,7 @@ int process(const char* inFileName, const char* outFileName,
}
if (zin.open(inFileName, ZipFile::kOpenReadOnly) != OK) {
- fprintf(stderr, "Unable to open '%s' as zip archive\n", inFileName);
+ fprintf(stderr, "Unable to open '%s' as zip archive: %s\n", inFileName, strerror(errno));
return 1;
}
if (zout.open(outFileName,
@@ -138,7 +137,8 @@ int process(const char* inFileName, const char* outFileName,
return 1;
}
- int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs);
+ int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs,
+ pageSize);
if (result != 0) {
printf("zipalign: failed rewriting '%s' to '%s'\n",
inFileName, outFileName);
@@ -150,7 +150,7 @@ int process(const char* inFileName, const char* outFileName,
* Verify the alignment of a zip archive.
*/
int verify(const char* fileName, int alignment, bool verbose,
- bool pageAlignSharedLibs)
+ bool pageAlignSharedLibs, int pageSize)
{
ZipFile zipFile;
bool foundBad = false;
@@ -181,7 +181,8 @@ int verify(const char* fileName, int alignment, bool verbose,
continue;
} else {
off_t offset = pEntry->getFileOffset();
- const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
+ const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry,
+ pageSize);
if ((offset % alignTo) != 0) {
if (verbose) {
printf("%8jd %s (BAD - %jd)\n",
diff --git a/tools/zipalign/ZipAlignMain.cpp b/tools/zipalign/ZipAlignMain.cpp
index 53fc8d4f62..2f24403a1a 100644
--- a/tools/zipalign/ZipAlignMain.cpp
+++ b/tools/zipalign/ZipAlignMain.cpp
@@ -34,15 +34,18 @@ void usage(void)
fprintf(stderr, "Zip alignment utility\n");
fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
fprintf(stderr,
- "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
- " zipalign -c [-p] [-v] <align> infile.zip\n\n" );
+ "Usage: zipalign [-f] [-p] [-P <pagesize_kb>] [-v] [-z] <align> infile.zip outfile.zip\n"
+ " zipalign -c [-p] [-P <pagesize_kb>] [-v] <align> infile.zip\n\n" );
fprintf(stderr,
" <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
fprintf(stderr, " -c: check alignment only (does not modify file)\n");
fprintf(stderr, " -f: overwrite existing outfile.zip\n");
- fprintf(stderr, " -p: page-align uncompressed .so files\n");
+ fprintf(stderr, " -p: 4kb page-align uncompressed .so files\n");
fprintf(stderr, " -v: verbose output\n");
fprintf(stderr, " -z: recompress using Zopfli\n");
+ fprintf(stderr, " -P <pagesize_kb>: Align uncompressed .so files to the specified\n");
+ fprintf(stderr, " page size. Valid values for <pagesize_kb> are 4, 16\n");
+ fprintf(stderr, " and 64. '-P' cannot be used in combination with '-p'.\n");
}
@@ -57,12 +60,16 @@ int main(int argc, char* const argv[])
bool verbose = false;
bool zopfli = false;
bool pageAlignSharedLibs = false;
+ int pageSize = 4096;
+ bool legacyPageAlignmentFlag = false; // -p
+ bool pageAlignmentFlag = false; // -P <pagesize_kb>
int result = 1;
int alignment;
char* endp;
int opt;
- while ((opt = getopt(argc, argv, "fcpvz")) != -1) {
+
+ while ((opt = getopt(argc, argv, "fcpvzP:")) != -1) {
switch (opt) {
case 'c':
check = true;
@@ -77,7 +84,29 @@ int main(int argc, char* const argv[])
zopfli = true;
break;
case 'p':
+ legacyPageAlignmentFlag = true;
pageAlignSharedLibs = true;
+ pageSize = 4096;
+ break;
+ case 'P':
+ pageAlignmentFlag = true;
+ pageAlignSharedLibs = true;
+
+ if (!optarg) {
+ fprintf(stderr, "ERROR: -P requires an argument\n");
+ wantUsage = true;
+ goto bail;
+ }
+
+ pageSize = atoi(optarg);
+ if (pageSize != 4 && pageSize != 16 && pageSize != 64) {
+ fprintf(stderr, "ERROR: Invalid argument for -P: %s\n", optarg);
+ wantUsage = true;
+ goto bail;
+ }
+
+ pageSize *= 1024; // Convert from kB to bytes.
+
break;
default:
fprintf(stderr, "ERROR: unknown flag -%c\n", opt);
@@ -86,6 +115,13 @@ int main(int argc, char* const argv[])
}
}
+ if (legacyPageAlignmentFlag && pageAlignmentFlag) {
+ fprintf(stderr, "ERROR: Invalid options: '-P <pagesize_kb>' and '-p'"
+ "cannot be used in combination.\n");
+ wantUsage = true;
+ goto bail;
+ }
+
if (!((check && (argc - optind) == 2) || (!check && (argc - optind) == 3))) {
wantUsage = true;
goto bail;
@@ -100,14 +136,15 @@ int main(int argc, char* const argv[])
if (check) {
/* check existing archive for correct alignment */
- result = verify(argv[optind + 1], alignment, verbose, pageAlignSharedLibs);
+ result = verify(argv[optind + 1], alignment, verbose, pageAlignSharedLibs, pageSize);
} else {
/* create the new archive */
- result = process(argv[optind + 1], argv[optind + 2], alignment, force, zopfli, pageAlignSharedLibs);
+ result = process(argv[optind + 1], argv[optind + 2], alignment, force, zopfli,
+ pageAlignSharedLibs, pageSize);
/* trust, but verify */
if (result == 0) {
- result = verify(argv[optind + 2], alignment, verbose, pageAlignSharedLibs);
+ result = verify(argv[optind + 2], alignment, verbose, pageAlignSharedLibs, pageSize);
}
}
diff --git a/tools/zipalign/ZipEntry.cpp b/tools/zipalign/ZipEntry.cpp
index 689999ee18..0355e56238 100644
--- a/tools/zipalign/ZipEntry.cpp
+++ b/tools/zipalign/ZipEntry.cpp
@@ -18,6 +18,8 @@
// Access to entries in a Zip archive.
//
+#define _POSIX_THREAD_SAFE_FUNCTIONS // For mingw localtime_r().
+
#define LOG_TAG "zip"
#include "ZipEntry.h"
@@ -354,31 +356,29 @@ time_t ZipEntry::getModWhen(void) const
*/
void ZipEntry::setModWhen(time_t when)
{
-#if !defined(_WIN32)
- struct tm tmResult;
-#endif
- time_t even;
- uint16_t zdate, ztime;
-
- struct tm* ptm;
-
/* round up to an even number of seconds */
- even = (when & 1) ? (when + 1) : when;
+ time_t even = (when & 1) ? (when + 1) : when;
/* expand */
-#if !defined(_WIN32)
- ptm = localtime_r(&even, &tmResult);
-#else
- ptm = localtime(&even);
-#endif
-
- int year;
- year = ptm->tm_year;
- if (year < 80)
- year = 80;
-
- zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday;
- ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
+ struct tm tmResult;
+ struct tm* ptm = localtime_r(&even, &tmResult);
+
+ // The earliest valid time for ZIP file entries is 1980-01-01. See:
+ // https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html.
+ // Set any time before 1980 to 1980-01-01.
+ if (ptm->tm_year < 80) {
+ ptm->tm_year = 80;
+ ptm->tm_mon = 0;
+ ptm->tm_mday = 1;
+ ptm->tm_hour = 0;
+ ptm->tm_min = 0;
+ ptm->tm_sec = 0;
+ }
+
+ uint16_t zdate = static_cast<uint16_t>(
+ (ptm->tm_year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday);
+ uint16_t ztime = static_cast<uint16_t>(
+ ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1);
mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime;
mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate;
diff --git a/tools/zipalign/include/ZipAlign.h b/tools/zipalign/include/ZipAlign.h
index ab3608682c..85dda1400a 100644
--- a/tools/zipalign/include/ZipAlign.h
+++ b/tools/zipalign/include/ZipAlign.h
@@ -25,24 +25,28 @@ namespace android {
* - force : Overwrite output if it exists, fail otherwise.
* - zopfli : Recompress compressed entries with more efficient algorithm.
* Copy compressed entries as-is, and unaligned, otherwise.
- * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ * - pageAlignSharedLibs: Align .so files to @pageSize and other files to
* alignTo, or all files to alignTo if false..
+ * - pageSize: Specifies the page size of the target device. This is used
+ * to correctly page-align shared libraries.
*
* Returns 0 on success.
*/
int process(const char* input, const char* output, int alignTo, bool force,
- bool zopfli, bool pageAlignSharedLibs);
+ bool zopfli, bool pageAlignSharedLibs, int pageSize);
/*
* Verify the alignment of a zip archive.
* - alignTo: Alignment (in bytes) for uncompressed entries.
- * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ * - pageAlignSharedLibs: Align .so files to @pageSize and other files to
* alignTo, or all files to alignTo if false..
+ * - pageSize: Specifies the page size of the target device. This is used
+ * to correctly page-align shared libraries.
*
* Returns 0 on success.
*/
int verify(const char* fileName, int alignTo, bool verbose,
- bool pageAlignSharedLibs);
+ bool pageAlignSharedLibs, int pageSize);
} // namespace android
diff --git a/tools/zipalign/tests/data/apkWithUncompressedSharedLibs.zip b/tools/zipalign/tests/data/apkWithUncompressedSharedLibs.zip
new file mode 100644
index 0000000000..930e3b5010
--- /dev/null
+++ b/tools/zipalign/tests/data/apkWithUncompressedSharedLibs.zip
Binary files differ
diff --git a/tools/zipalign/tests/src/align_test.cpp b/tools/zipalign/tests/src/align_test.cpp
index a8433fad47..07ad7ccda2 100644
--- a/tools/zipalign/tests/src/align_test.cpp
+++ b/tools/zipalign/tests/src/align_test.cpp
@@ -48,11 +48,12 @@ static std::string GetTempPath(const std::string& filename) {
TEST(Align, Unaligned) {
const std::string src = GetTestPath("unaligned.zip");
const std::string dst = GetTempPath("unaligned_out.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, false, pageSize);
ASSERT_EQ(0, processed);
- int verified = verify(dst.c_str(), 4, true, false);
+ int verified = verify(dst.c_str(), 4, true, false, pageSize);
ASSERT_EQ(0, verified);
}
@@ -60,18 +61,19 @@ TEST(Align, DoubleAligment) {
const std::string src = GetTestPath("unaligned.zip");
const std::string tmp = GetTempPath("da_aligned.zip");
const std::string dst = GetTempPath("da_d_aligner.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), tmp.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), tmp.c_str(), 4, true, false, false, pageSize);
ASSERT_EQ(0, processed);
- int verified = verify(tmp.c_str(), 4, true, false);
+ int verified = verify(tmp.c_str(), 4, true, false, pageSize);
ASSERT_EQ(0, verified);
// Align the result of the previous run. Essentially double aligning.
- processed = process(tmp.c_str(), dst.c_str(), 4, true, false, 4096);
+ processed = process(tmp.c_str(), dst.c_str(), 4, true, false, false, pageSize);
ASSERT_EQ(0, processed);
- verified = verify(dst.c_str(), 4, true, false);
+ verified = verify(dst.c_str(), 4, true, false, pageSize);
ASSERT_EQ(0, verified);
// Nothing should have changed between tmp and dst.
@@ -90,11 +92,12 @@ TEST(Align, DoubleAligment) {
TEST(Align, Holes) {
const std::string src = GetTestPath("holes.zip");
const std::string dst = GetTempPath("holes_out.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
ASSERT_EQ(0, processed);
- int verified = verify(dst.c_str(), 4, false, true);
+ int verified = verify(dst.c_str(), 4, false, true, pageSize);
ASSERT_EQ(0, verified);
}
@@ -102,28 +105,85 @@ TEST(Align, Holes) {
TEST(Align, DifferenteOrders) {
const std::string src = GetTestPath("diffOrders.zip");
const std::string dst = GetTempPath("diffOrders_out.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
ASSERT_EQ(0, processed);
- int verified = verify(dst.c_str(), 4, false, true);
+ int verified = verify(dst.c_str(), 4, false, true, pageSize);
ASSERT_EQ(0, verified);
}
TEST(Align, DirectoryEntryDoNotRequireAlignment) {
const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip");
- int verified = verify(src.c_str(), 4, false, true);
+ int pageSize = 4096;
+ int verified = verify(src.c_str(), 4, false, true, pageSize);
ASSERT_EQ(0, verified);
}
TEST(Align, DirectoryEntry) {
const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip");
const std::string dst = GetTempPath("archiveWithOneDirectoryEntry_out.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
ASSERT_EQ(0, processed);
ASSERT_EQ(true, sameContent(src, dst));
- int verified = verify(dst.c_str(), 4, false, true);
+ int verified = verify(dst.c_str(), 4, false, true, pageSize);
+ ASSERT_EQ(0, verified);
+}
+
+class UncompressedSharedLibsTest : public ::testing::Test {
+ protected:
+ static void SetUpTestSuite() {
+ src = GetTestPath("apkWithUncompressedSharedLibs.zip");
+ dst = GetTempPath("apkWithUncompressedSharedLibs_out.zip");
+ }
+
+ static std::string src;
+ static std::string dst;
+};
+
+std::string UncompressedSharedLibsTest::src;
+std::string UncompressedSharedLibsTest::dst;
+
+TEST_F(UncompressedSharedLibsTest, Unaligned) {
+ int pageSize = 4096;
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, false, pageSize);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, true, pageSize);
+ ASSERT_NE(0, verified); // .so's not page-aligned
+}
+
+TEST_F(UncompressedSharedLibsTest, AlignedPageSize4kB) {
+ int pageSize = 4096;
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, true, pageSize);
+ ASSERT_EQ(0, verified);
+}
+
+TEST_F(UncompressedSharedLibsTest, AlignedPageSize16kB) {
+ int pageSize = 16384;
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, true, pageSize);
+ ASSERT_EQ(0, verified);
+}
+
+TEST_F(UncompressedSharedLibsTest, AlignedPageSize64kB) {
+ int pageSize = 65536;
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, true, pageSize);
ASSERT_EQ(0, verified);
}