+
+
+
+由于编译时间较长,建议把[.github/workflows/actions_recovery.yml](.github/workflows/actions_recovery.yml)末尾上传处的`${{ secrets.GITHUB_TOKEN }}`改成自己的[Personal Access Token](https://github.com/settings/tokens)
+
+注意保护自己的Personal Access Token,将它放入仓库[Settings](../../settings)里的[Secrets](../../settings/secrets)里后用`${{ secrets.YOUR_TOKEN_NAME }}`来替换`${{ secrets.GITHUB_TOKEN }}`
+
+比如我的secret名字叫做work.则使用`${{ secrets.work }}`
+
+## 配置
+
+配置文件是[config.json](config.json)
+
+| 名称 | 类型 | 描述 |
+| ------------------ | ------- | ------------------------------------------------------------ |
+| `twrp_url` | String | Recovery Manifest地址 |
+| `twrp_branch` | String | Recovery Manifest分支 |
+| `git_username` | String | 您使用Git的用户名 |
+| `git_email` | String | 您使用Git的邮箱(Github可使用`Github ID+Github用户名@users.noreply.github.com`) |
+| `use_own_dt` | Boolean | 指示是否使用个人设备树(此项为`true`后以下三项起效) |
+| `dt_url` | String | 您使用的设备树的地址(格式:`USER/REPO`) |
+| `dt_branch` | String | 您使用的设备树的分支 |
+| `dt_remote` | String | 您使用设备树的存储库(如`github/gitlab`) |
+| `dt_path` | String | 指示设备树本地保存位置(示例`device/huawei/kiwi`) |
+| `device_code` | String | 您将要编译机型的机型代号 |
+| `fix_product` | Boolean | 指示是否修复无法找到设备的问题 |
+| `fix_branch` | String | 指示修复以上问题所使用的分支 |
+| `fix_misscom` | Boolean | 指示是否修复缺少`device/qcom/common`的问题 |
+| `fix_busybox` | Boolean | 指示是否修复缺少`busybox`的问题 |
+
+## 开始
+
+Fork此仓库后,点击右上角Star就会开始
+
+## 编译结果
+可以在[Release](../../releases)下载
diff --git a/build/core/android-7.1/product_config.mk b/build/core/android-7.1/product_config.mk
new file mode 100644
index 0000000..d76ed0c
--- /dev/null
+++ b/build/core/android-7.1/product_config.mk
@@ -0,0 +1,413 @@
+#
+# 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.
+#
+
+# ---------------------------------------------------------------
+# Generic functions
+# TODO: Move these to definitions.make once we're able to include
+# definitions.make before config.make.
+
+###########################################################
+## Return non-empty if $(1) is a C identifier; i.e., if it
+## matches /^[a-zA-Z_][a-zA-Z0-9_]*$/. We do this by first
+## making sure that it isn't empty and doesn't start with
+## a digit, then by removing each valid character. If the
+## final result is empty, then it was a valid C identifier.
+##
+## $(1): word to check
+###########################################################
+
+_ici_digits := 0 1 2 3 4 5 6 7 8 9
+_ici_alphaunderscore := \
+ a b c d e f g h i j k l m n o p q r s t u v w x y z \
+ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _
+define is-c-identifier
+$(strip \
+ $(if $(1), \
+ $(if $(filter $(addsuffix %,$(_ici_digits)),$(1)), \
+ , \
+ $(eval w := $(1)) \
+ $(foreach c,$(_ici_digits) $(_ici_alphaunderscore), \
+ $(eval w := $(subst $(c),,$(w))) \
+ ) \
+ $(if $(w),,TRUE) \
+ $(eval w :=) \
+ ) \
+ ) \
+ )
+endef
+
+# TODO: push this into the combo files; unfortunately, we don't even
+# know HOST_OS at this point.
+trysed := $(shell echo a | sed -E -e 's/a/b/' 2>/dev/null)
+ifeq ($(trysed),b)
+ SED_EXTENDED := sed -E
+else
+ trysed := $(shell echo c | sed -r -e 's/c/d/' 2>/dev/null)
+ ifeq ($(trysed),d)
+ SED_EXTENDED := sed -r
+ else
+ $(error Unknown sed version)
+ endif
+endif
+
+###########################################################
+## List all of the files in a subdirectory in a format
+## suitable for PRODUCT_COPY_FILES and
+## PRODUCT_SDK_ADDON_COPY_FILES
+##
+## $(1): Glob to match file name
+## $(2): Source directory
+## $(3): Target base directory
+###########################################################
+
+define find-copy-subdir-files
+$(sort $(shell find $(2) -name "$(1)" -type f | $(SED_EXTENDED) "s:($(2)/?(.*)):\\1\\:$(3)/\\2:" | sed "s://:/:g"))
+endef
+
+# ---------------------------------------------------------------
+
+# These are the valid values of TARGET_BUILD_VARIANT. Also, if anything else is passed
+# as the variant in the PRODUCT-$TARGET_BUILD_PRODUCT-$TARGET_BUILD_VARIANT form,
+# it will be treated as a goal, and the eng variant will be used.
+INTERNAL_VALID_VARIANTS := user userdebug eng
+
+# ---------------------------------------------------------------
+# Provide "PRODUCT--" targets, which lets you build
+# a particular configuration without needing to set up the environment.
+#
+product_goals := $(strip $(filter PRODUCT-%,$(MAKECMDGOALS)))
+ifdef product_goals
+ # Scrape the product and build names out of the goal,
+ # which should be of the form PRODUCT--.
+ #
+ ifneq ($(words $(product_goals)),1)
+ $(error Only one PRODUCT-* goal may be specified; saw "$(product_goals)")
+ endif
+ goal_name := $(product_goals)
+ product_goals := $(patsubst PRODUCT-%,%,$(product_goals))
+ product_goals := $(subst -, ,$(product_goals))
+ ifneq ($(words $(product_goals)),2)
+ $(error Bad PRODUCT-* goal "$(goal_name)")
+ endif
+
+ # The product they want
+ TARGET_PRODUCT := $(word 1,$(product_goals))
+
+ # The variant they want
+ TARGET_BUILD_VARIANT := $(word 2,$(product_goals))
+
+ ifeq ($(TARGET_BUILD_VARIANT),tests)
+ $(error "tests" has been deprecated as a build variant. Use it as a build goal instead.)
+ endif
+
+ # The build server wants to do make PRODUCT-dream-installclean
+ # which really means TARGET_PRODUCT=dream make installclean.
+ ifneq ($(filter-out $(INTERNAL_VALID_VARIANTS),$(TARGET_BUILD_VARIANT)),)
+ MAKECMDGOALS := $(MAKECMDGOALS) $(TARGET_BUILD_VARIANT)
+ TARGET_BUILD_VARIANT := userdebug
+ default_goal_substitution :=
+ else
+ default_goal_substitution := $(DEFAULT_GOAL)
+ endif
+
+ # Replace the PRODUCT-* goal with the build goal that it refers to.
+ # Note that this will ensure that it appears in the same relative
+ # position, in case it matters.
+ #
+ # Note that modifying this will not affect the goals that make will
+ # attempt to build, but it's important because we inspect this value
+ # in certain situations (like for "make sdk").
+ #
+ MAKECMDGOALS := $(patsubst $(goal_name),$(default_goal_substitution),$(MAKECMDGOALS))
+
+ # Define a rule for the PRODUCT-* goal, and make it depend on the
+ # patched-up command-line goals as well as any other goals that we
+ # want to force.
+ #
+.PHONY: $(goal_name)
+$(goal_name): $(MAKECMDGOALS)
+endif
+# else: Use the value set in the environment or buildspec.mk.
+
+# ---------------------------------------------------------------
+# Provide "APP-" targets, which lets you build
+# an unbundled app.
+#
+unbundled_goals := $(strip $(filter APP-%,$(MAKECMDGOALS)))
+ifdef unbundled_goals
+ ifneq ($(words $(unbundled_goals)),1)
+ $(error Only one APP-* goal may be specified; saw "$(unbundled_goals)")
+ endif
+ TARGET_BUILD_APPS := $(strip $(subst -, ,$(patsubst APP-%,%,$(unbundled_goals))))
+ ifneq ($(filter $(DEFAULT_GOAL),$(MAKECMDGOALS)),)
+ MAKECMDGOALS := $(patsubst $(unbundled_goals),,$(MAKECMDGOALS))
+ else
+ MAKECMDGOALS := $(patsubst $(unbundled_goals),$(DEFAULT_GOAL),$(MAKECMDGOALS))
+ endif
+
+.PHONY: $(unbundled_goals)
+$(unbundled_goals): $(MAKECMDGOALS)
+endif # unbundled_goals
+
+# Default to building dalvikvm on hosts that support it...
+ifeq ($(HOST_OS),linux)
+# ... or if the if the option is already set
+ifeq ($(WITH_HOST_DALVIK),)
+ WITH_HOST_DALVIK := true
+endif
+endif
+
+# ---------------------------------------------------------------
+# Include the product definitions.
+# We need to do this to translate TARGET_PRODUCT into its
+# underlying TARGET_DEVICE before we start defining any rules.
+#
+include $(BUILD_SYSTEM)/node_fns.mk
+include $(BUILD_SYSTEM)/product.mk
+include $(BUILD_SYSTEM)/device.mk
+
+ifneq ($(strip $(TARGET_BUILD_APPS)),)
+# An unbundled app build needs only the core product makefiles.
+all_product_configs := $(call get-product-makefiles,\
+ $(SRC_TARGET_DIR)/product/AndroidProducts.mk)
+else
+# Read in all of the product definitions specified by the AndroidProducts.mk
+# files in the tree.
+all_product_configs := $(get-all-product-makefiles)
+endif
+
+# Find the product config makefile for the current product.
+# all_product_configs consists items like:
+# :
+# or just in case the product name is the
+# same as the base filename of the product config makefile.
+current_product_makefile :=
+all_product_makefiles :=
+$(foreach f, $(all_product_configs),\
+ $(eval _cpm_words := $(subst :,$(space),$(f)))\
+ $(eval _cpm_word1 := $(word 1,$(_cpm_words)))\
+ $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
+ $(if $(_cpm_word2),\
+ $(eval all_product_makefiles += $(_cpm_word2))\
+ $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
+ $(eval current_product_makefile += $(_cpm_word2)),),\
+ $(eval all_product_makefiles += $(f))\
+ $(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\
+ $(eval current_product_makefile += $(f)),)))
+_cpm_words :=
+_cpm_word1 :=
+_cpm_word2 :=
+current_product_makefile := $(strip $(current_product_makefile))
+all_product_makefiles := $(strip $(all_product_makefiles))
+
+load_all_product_makefiles :=
+ifneq (,$(filter product-graph, $(MAKECMDGOALS)))
+ifeq ($(ANDROID_PRODUCT_GRAPH),--all)
+load_all_product_makefiles := true
+endif
+endif
+ifneq (,$(filter dump-products,$(MAKECMDGOALS)))
+ifeq ($(ANDROID_DUMP_PRODUCTS),all)
+load_all_product_makefiles := true
+endif
+endif
+
+ifeq ($(load_all_product_makefiles),true)
+# Import all product makefiles.
+$(call import-products, $(all_product_makefiles))
+else
+$(call import-products, $(current_product_makefile))
+endif # Import all or just the current product makefile
+
+# Sanity check
+$(check-all-products)
+
+ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
+$(dump-products)
+$(error done)
+endif
+
+# Convert a short name like "sooner" into the path to the product
+# file defining that product.
+#
+current_product_makefile :=
+all_product_makefiles :=
+all_product_configs :=
+
+
+#############################################################################
+
+# A list of module names of BOOTCLASSPATH (jar files)
+PRODUCT_BOOT_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BOOT_JARS))
+PRODUCT_SYSTEM_SERVER_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_JARS))
+
+# Find the device that this product maps to.
+TARGET_DEVICE := device_code
+
+# Figure out which resoure configuration options to use for this
+# product.
+PRODUCT_LOCALES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOCALES))
+# TODO: also keep track of things like "port", "land" in product files.
+
+# If CUSTOM_LOCALES contains any locales not already included
+# in PRODUCT_LOCALES, add them to PRODUCT_LOCALES.
+extra_locales := $(filter-out $(PRODUCT_LOCALES),$(CUSTOM_LOCALES))
+ifneq (,$(extra_locales))
+ ifneq ($(CALLED_FROM_SETUP),true)
+ # Don't spam stdout, because envsetup.sh may be scraping values from it.
+ $(info Adding CUSTOM_LOCALES [$(extra_locales)] to PRODUCT_LOCALES [$(PRODUCT_LOCALES)])
+ endif
+ PRODUCT_LOCALES += $(extra_locales)
+ extra_locales :=
+endif
+
+# Add PRODUCT_LOCALES to PRODUCT_AAPT_CONFIG
+PRODUCT_AAPT_CONFIG := $(strip $(PRODUCT_LOCALES) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_CONFIG))
+PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREF_CONFIG))
+PRODUCT_AAPT_PREBUILT_DPI := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREBUILT_DPI))
+
+# Keep a copy of the space-separated config
+PRODUCT_AAPT_CONFIG_SP := $(PRODUCT_AAPT_CONFIG)
+
+# Convert spaces to commas.
+PRODUCT_AAPT_CONFIG := \
+ $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
+
+# product-scoped aapt flags
+PRODUCT_AAPT_FLAGS :=
+PRODUCT_AAPT2_CFLAGS :=
+ifneq ($(filter en_XA ar_XB,$(PRODUCT_LOCALES)),)
+ # Force generating resources for pseudo-locales.
+ PRODUCT_AAPT2_CFLAGS += --pseudo-localize
+ PRODUCT_AAPT_FLAGS += --pseudo-localize
+endif
+
+PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))
+
+PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MODEL))
+ifndef PRODUCT_MODEL
+ PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_NAME))
+endif
+
+PRODUCT_MANUFACTURER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))
+ifndef PRODUCT_MANUFACTURER
+ PRODUCT_MANUFACTURER := unknown
+endif
+
+ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS),)
+ TARGET_AAPT_CHARACTERISTICS := default
+else
+ TARGET_AAPT_CHARACTERISTICS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS))
+endif
+
+PRODUCT_DEFAULT_WIFI_CHANNELS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))
+
+PRODUCT_DEFAULT_DEV_CERTIFICATE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_DEV_CERTIFICATE))
+ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
+ifneq (1,$(words $(PRODUCT_DEFAULT_DEV_CERTIFICATE)))
+ $(error PRODUCT_DEFAULT_DEV_CERTIFICATE='$(PRODUCT_DEFAULT_DEV_CERTIFICATE)', \
+ only 1 certificate is allowed.)
+endif
+endif
+
+# A list of words like :[:].
+# The file at the source path should be copied to the destination path
+# when building this product. is relative to
+# $(PRODUCT_OUT), so it should look like, e.g., "system/etc/file.xml".
+# The rules for these copy steps are defined in build/core/Makefile.
+# The optional : is used to indicate the owner of a vendor file.
+PRODUCT_COPY_FILES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COPY_FILES))
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+PRODUCT_PROPERTY_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES))
+
+PRODUCT_SHIPPING_API_LEVEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SHIPPING_API_LEVEL))
+ifdef PRODUCT_SHIPPING_API_LEVEL
+ADDITIONAL_BUILD_PROPERTIES += \
+ ro.product.first_api_level=$(PRODUCT_SHIPPING_API_LEVEL)
+endif
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to default.prop
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
+
+PRODUCT_BUILD_PROP_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BUILD_PROP_OVERRIDES))
+
+# Should we use the default resources or add any product specific overlays
+PRODUCT_PACKAGE_OVERLAYS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGE_OVERLAYS))
+DEVICE_PACKAGE_OVERLAYS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).DEVICE_PACKAGE_OVERLAYS))
+
+# The list of product-specific kernel header dirs
+PRODUCT_VENDOR_KERNEL_HEADERS := \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_KERNEL_HEADERS)
+
+# Add the product-defined properties to the build properties.
+ADDITIONAL_BUILD_PROPERTIES := \
+ $(ADDITIONAL_BUILD_PROPERTIES) \
+ $(PRODUCT_PROPERTY_OVERRIDES)
+
+# The OTA key(s) specified by the product config, if any. The names
+# of these keys are stored in the target-files zip so that post-build
+# signing tools can substitute them for the test key embedded by
+# default.
+PRODUCT_OTA_PUBLIC_KEYS := $(sort \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTA_PUBLIC_KEYS))
+
+PRODUCT_EXTRA_RECOVERY_KEYS := $(sort \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_EXTRA_RECOVERY_KEYS))
+
+PRODUCT_DEX_PREOPT_DEFAULT_FLAGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
+PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
+# Resolve and setup per-module dex-preopt configs.
+PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_pdpmc_modules :=
+$(foreach c,$(PRODUCT_DEX_PREOPT_MODULE_CONFIGS),\
+ $(eval m := $(firstword $(subst =,$(space),$(c))))\
+ $(if $(filter $(_pdpmc_modules),$(m)),,\
+ $(eval _pdpmc_modules += $(m))\
+ $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+ $(eval cf := $(subst $(_PDPMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+ $(eval DEXPREOPT.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_pdpmc_modules :=
+
+# Resolve and setup per-module sanitizer configs.
+PRODUCT_SANITIZER_MODULE_CONFIGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SANITIZER_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_psmc_modules :=
+$(foreach c,$(PRODUCT_SANITIZER_MODULE_CONFIGS),\
+ $(eval m := $(firstword $(subst =,$(space),$(c))))\
+ $(if $(filter $(_psmc_modules),$(m)),,\
+ $(eval _psmc_modules += $(m))\
+ $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+ $(eval cf := $(subst $(_PSMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+ $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_psmc_modules :=
diff --git a/build/core/android-8.1/product_config.mk b/build/core/android-8.1/product_config.mk
new file mode 100644
index 0000000..395ecbe
--- /dev/null
+++ b/build/core/android-8.1/product_config.mk
@@ -0,0 +1,461 @@
+#
+# 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.
+#
+
+# ---------------------------------------------------------------
+# Generic functions
+# TODO: Move these to definitions.make once we're able to include
+# definitions.make before config.make.
+
+###########################################################
+## Return non-empty if $(1) is a C identifier; i.e., if it
+## matches /^[a-zA-Z_][a-zA-Z0-9_]*$/. We do this by first
+## making sure that it isn't empty and doesn't start with
+## a digit, then by removing each valid character. If the
+## final result is empty, then it was a valid C identifier.
+##
+## $(1): word to check
+###########################################################
+
+_ici_digits := 0 1 2 3 4 5 6 7 8 9
+_ici_alphaunderscore := \
+ a b c d e f g h i j k l m n o p q r s t u v w x y z \
+ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _
+define is-c-identifier
+$(strip \
+ $(if $(1), \
+ $(if $(filter $(addsuffix %,$(_ici_digits)),$(1)), \
+ , \
+ $(eval w := $(1)) \
+ $(foreach c,$(_ici_digits) $(_ici_alphaunderscore), \
+ $(eval w := $(subst $(c),,$(w))) \
+ ) \
+ $(if $(w),,TRUE) \
+ $(eval w :=) \
+ ) \
+ ) \
+ )
+endef
+
+# TODO: push this into the combo files; unfortunately, we don't even
+# know HOST_OS at this point.
+trysed := $(shell echo a | sed -E -e 's/a/b/' 2>/dev/null)
+ifeq ($(trysed),b)
+ SED_EXTENDED := sed -E
+else
+ trysed := $(shell echo c | sed -r -e 's/c/d/' 2>/dev/null)
+ ifeq ($(trysed),d)
+ SED_EXTENDED := sed -r
+ else
+ $(error Unknown sed version)
+ endif
+endif
+
+###########################################################
+## List all of the files in a subdirectory in a format
+## suitable for PRODUCT_COPY_FILES and
+## PRODUCT_SDK_ADDON_COPY_FILES
+##
+## $(1): Glob to match file name
+## $(2): Source directory
+## $(3): Target base directory
+###########################################################
+
+define find-copy-subdir-files
+$(sort $(shell find $(2) -name "$(1)" -type f | $(SED_EXTENDED) "s:($(2)/?(.*)):\\1\\:$(3)/\\2:" | sed "s://:/:g"))
+endef
+
+# ---------------------------------------------------------------
+
+# These are the valid values of TARGET_BUILD_VARIANT. Also, if anything else is passed
+# as the variant in the PRODUCT-$TARGET_BUILD_PRODUCT-$TARGET_BUILD_VARIANT form,
+# it will be treated as a goal, and the eng variant will be used.
+INTERNAL_VALID_VARIANTS := user userdebug eng
+
+# ---------------------------------------------------------------
+# Provide "PRODUCT--" targets, which lets you build
+# a particular configuration without needing to set up the environment.
+#
+ifndef KATI
+product_goals := $(strip $(filter PRODUCT-%,$(MAKECMDGOALS)))
+ifdef product_goals
+ # Scrape the product and build names out of the goal,
+ # which should be of the form PRODUCT--.
+ #
+ ifneq ($(words $(product_goals)),1)
+ $(error Only one PRODUCT-* goal may be specified; saw "$(product_goals)")
+ endif
+ goal_name := $(product_goals)
+ product_goals := $(patsubst PRODUCT-%,%,$(product_goals))
+ product_goals := $(subst -, ,$(product_goals))
+ ifneq ($(words $(product_goals)),2)
+ $(error Bad PRODUCT-* goal "$(goal_name)")
+ endif
+
+ # The product they want
+ TARGET_PRODUCT := $(word 1,$(product_goals))
+
+ # The variant they want
+ TARGET_BUILD_VARIANT := $(word 2,$(product_goals))
+
+ ifeq ($(TARGET_BUILD_VARIANT),tests)
+ $(error "tests" has been deprecated as a build variant. Use it as a build goal instead.)
+ endif
+
+ # The build server wants to do make PRODUCT-dream-sdk
+ # which really means TARGET_PRODUCT=dream make sdk.
+ ifneq ($(filter-out $(INTERNAL_VALID_VARIANTS),$(TARGET_BUILD_VARIANT)),)
+ override MAKECMDGOALS := $(MAKECMDGOALS) $(TARGET_BUILD_VARIANT)
+ TARGET_BUILD_VARIANT := userdebug
+ default_goal_substitution :=
+ else
+ default_goal_substitution := droid
+ endif
+
+ # Replace the PRODUCT-* goal with the build goal that it refers to.
+ # Note that this will ensure that it appears in the same relative
+ # position, in case it matters.
+ override MAKECMDGOALS := $(patsubst $(goal_name),$(default_goal_substitution),$(MAKECMDGOALS))
+endif
+endif # !KATI
+# else: Use the value set in the environment or buildspec.mk.
+
+# ---------------------------------------------------------------
+# Provide "APP-" targets, which lets you build
+# an unbundled app.
+#
+ifndef KATI
+unbundled_goals := $(strip $(filter APP-%,$(MAKECMDGOALS)))
+ifdef unbundled_goals
+ ifneq ($(words $(unbundled_goals)),1)
+ $(error Only one APP-* goal may be specified; saw "$(unbundled_goals)")
+ endif
+ TARGET_BUILD_APPS := $(strip $(subst -, ,$(patsubst APP-%,%,$(unbundled_goals))))
+ ifneq ($(filter droid,$(MAKECMDGOALS)),)
+ override MAKECMDGOALS := $(patsubst $(unbundled_goals),,$(MAKECMDGOALS))
+ else
+ override MAKECMDGOALS := $(patsubst $(unbundled_goals),droid,$(MAKECMDGOALS))
+ endif
+endif # unbundled_goals
+endif
+
+# Default to building dalvikvm on hosts that support it...
+ifeq ($(HOST_OS),linux)
+# ... or if the if the option is already set
+ifeq ($(WITH_HOST_DALVIK),)
+ WITH_HOST_DALVIK := true
+endif
+endif
+
+# ---------------------------------------------------------------
+# Include the product definitions.
+# We need to do this to translate TARGET_PRODUCT into its
+# underlying TARGET_DEVICE before we start defining any rules.
+#
+include $(BUILD_SYSTEM)/node_fns.mk
+include $(BUILD_SYSTEM)/product.mk
+include $(BUILD_SYSTEM)/device.mk
+
+ifneq ($(strip $(TARGET_BUILD_APPS)),)
+# An unbundled app build needs only the core product makefiles.
+all_product_configs := $(call get-product-makefiles,\
+ $(SRC_TARGET_DIR)/product/AndroidProducts.mk)
+else
+# Read in all of the product definitions specified by the AndroidProducts.mk
+# files in the tree.
+all_product_configs := $(get-all-product-makefiles)
+endif
+
+all_named_products :=
+
+# Find the product config makefile for the current product.
+# all_product_configs consists items like:
+# :
+# or just in case the product name is the
+# same as the base filename of the product config makefile.
+current_product_makefile :=
+all_product_makefiles :=
+$(foreach f, $(all_product_configs),\
+ $(eval _cpm_words := $(subst :,$(space),$(f)))\
+ $(eval _cpm_word1 := $(word 1,$(_cpm_words)))\
+ $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
+ $(if $(_cpm_word2),\
+ $(eval all_product_makefiles += $(_cpm_word2))\
+ $(eval all_named_products += $(_cpm_word1))\
+ $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
+ $(eval current_product_makefile += $(_cpm_word2)),),\
+ $(eval all_product_makefiles += $(f))\
+ $(eval all_named_products += $(basename $(notdir $(f))))\
+ $(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\
+ $(eval current_product_makefile += $(f)),)))
+_cpm_words :=
+_cpm_word1 :=
+_cpm_word2 :=
+current_product_makefile := $(strip $(current_product_makefile))
+all_product_makefiles := $(strip $(all_product_makefiles))
+
+load_all_product_makefiles :=
+ifneq (,$(filter product-graph, $(MAKECMDGOALS)))
+ifeq ($(ANDROID_PRODUCT_GRAPH),--all)
+load_all_product_makefiles := true
+endif
+endif
+ifneq (,$(filter dump-products,$(MAKECMDGOALS)))
+ifeq ($(ANDROID_DUMP_PRODUCTS),all)
+load_all_product_makefiles := true
+endif
+endif
+
+ifeq ($(load_all_product_makefiles),true)
+# Import all product makefiles.
+$(call import-products, $(all_product_makefiles))
+else
+$(call import-products, $(current_product_makefile))
+endif # Import all or just the current product makefile
+
+# Sanity check
+$(check-all-products)
+
+ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
+$(dump-products)
+$(error done)
+endif
+
+# Convert a short name like "sooner" into the path to the product
+# file defining that product.
+#
+current_product_makefile :=
+all_product_makefiles :=
+all_product_configs :=
+
+
+#############################################################################
+
+# A list of module names of BOOTCLASSPATH (jar files)
+PRODUCT_BOOT_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BOOT_JARS))
+PRODUCT_SYSTEM_SERVER_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_JARS))
+PRODUCT_SYSTEM_SERVER_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_APPS))
+PRODUCT_DEXPREOPT_SPEED_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEXPREOPT_SPEED_APPS))
+
+# All of the apps that we force preopt, this overrides WITH_DEXPREOPT.
+PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK))
+
+# Find the device that this product maps to.
+TARGET_DEVICE := device_code
+
+# Figure out which resoure configuration options to use for this
+# product.
+PRODUCT_LOCALES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOCALES))
+# TODO: also keep track of things like "port", "land" in product files.
+
+# If CUSTOM_LOCALES contains any locales not already included
+# in PRODUCT_LOCALES, add them to PRODUCT_LOCALES.
+extra_locales := $(filter-out $(PRODUCT_LOCALES),$(CUSTOM_LOCALES))
+ifneq (,$(extra_locales))
+ ifneq ($(CALLED_FROM_SETUP),true)
+ # Don't spam stdout, because envsetup.sh may be scraping values from it.
+ $(info Adding CUSTOM_LOCALES [$(extra_locales)] to PRODUCT_LOCALES [$(PRODUCT_LOCALES)])
+ endif
+ PRODUCT_LOCALES += $(extra_locales)
+ extra_locales :=
+endif
+
+# Add PRODUCT_LOCALES to PRODUCT_AAPT_CONFIG
+PRODUCT_AAPT_CONFIG := $(strip $(PRODUCT_LOCALES) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_CONFIG))
+PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREF_CONFIG))
+PRODUCT_AAPT_PREBUILT_DPI := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREBUILT_DPI))
+
+# Keep a copy of the space-separated config
+PRODUCT_AAPT_CONFIG_SP := $(PRODUCT_AAPT_CONFIG)
+
+# Convert spaces to commas.
+PRODUCT_AAPT_CONFIG := \
+ $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
+
+# product-scoped aapt flags
+PRODUCT_AAPT_FLAGS :=
+PRODUCT_AAPT2_CFLAGS :=
+ifneq ($(filter en_XA ar_XB,$(PRODUCT_LOCALES)),)
+ # Force generating resources for pseudo-locales.
+ PRODUCT_AAPT2_CFLAGS += --pseudo-localize
+ PRODUCT_AAPT_FLAGS += --pseudo-localize
+endif
+
+PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))
+
+PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MODEL))
+ifndef PRODUCT_MODEL
+ PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_NAME))
+endif
+
+PRODUCT_MANUFACTURER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))
+ifndef PRODUCT_MANUFACTURER
+ PRODUCT_MANUFACTURER := unknown
+endif
+
+ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS),)
+ TARGET_AAPT_CHARACTERISTICS := default
+else
+ TARGET_AAPT_CHARACTERISTICS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS))
+endif
+
+PRODUCT_DEFAULT_WIFI_CHANNELS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))
+
+PRODUCT_DEFAULT_DEV_CERTIFICATE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_DEV_CERTIFICATE))
+ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
+ifneq (1,$(words $(PRODUCT_DEFAULT_DEV_CERTIFICATE)))
+ $(error PRODUCT_DEFAULT_DEV_CERTIFICATE='$(PRODUCT_DEFAULT_DEV_CERTIFICATE)', \
+ only 1 certificate is allowed.)
+endif
+endif
+
+# A list of words like :[:].
+# The file at the source path should be copied to the destination path
+# when building this product. is relative to
+# $(PRODUCT_OUT), so it should look like, e.g., "system/etc/file.xml".
+# The rules for these copy steps are defined in build/core/Makefile.
+# The optional : is used to indicate the owner of a vendor file.
+PRODUCT_COPY_FILES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COPY_FILES))
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+PRODUCT_PROPERTY_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES))
+.KATI_READONLY := PRODUCT_PROPERTY_OVERRIDES
+
+PRODUCT_SHIPPING_API_LEVEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SHIPPING_API_LEVEL))
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to default.prop
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
+.KATI_READONLY := PRODUCT_DEFAULT_PROPERTY_OVERRIDES
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for overriding properties in build.prop
+PRODUCT_BUILD_PROP_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BUILD_PROP_OVERRIDES))
+.KATI_READONLY := PRODUCT_BUILD_PROP_OVERRIDES
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to default.prop of system partition
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_DEFAULT_PROPERTIES))
+.KATI_READONLY := PRODUCT_SYSTEM_DEFAULT_PROPERTIES
+
+# Should we use the default resources or add any product specific overlays
+PRODUCT_PACKAGE_OVERLAYS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGE_OVERLAYS))
+DEVICE_PACKAGE_OVERLAYS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).DEVICE_PACKAGE_OVERLAYS))
+
+# The list of product-specific kernel header dirs
+PRODUCT_VENDOR_KERNEL_HEADERS := \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_KERNEL_HEADERS)
+
+# The OTA key(s) specified by the product config, if any. The names
+# of these keys are stored in the target-files zip so that post-build
+# signing tools can substitute them for the test key embedded by
+# default.
+PRODUCT_OTA_PUBLIC_KEYS := $(sort \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTA_PUBLIC_KEYS))
+
+PRODUCT_EXTRA_RECOVERY_KEYS := $(sort \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_EXTRA_RECOVERY_KEYS))
+
+PRODUCT_DEX_PREOPT_DEFAULT_FLAGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
+PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
+PRODUCT_DEX_PREOPT_PROFILE_DIR := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_PROFILE_DIR))
+
+# Boot image options.
+PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE))
+PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION))
+
+PRODUCT_SYSTEM_SERVER_COMPILER_FILTER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
+PRODUCT_SYSTEM_SERVER_DEBUG_INFO := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_DEBUG_INFO))
+
+# Resolve and setup per-module dex-preopt configs.
+PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_pdpmc_modules :=
+$(foreach c,$(PRODUCT_DEX_PREOPT_MODULE_CONFIGS),\
+ $(eval m := $(firstword $(subst =,$(space),$(c))))\
+ $(if $(filter $(_pdpmc_modules),$(m)),,\
+ $(eval _pdpmc_modules += $(m))\
+ $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+ $(eval cf := $(subst $(_PDPMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+ $(eval DEXPREOPT.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_pdpmc_modules :=
+
+# Resolve and setup per-module sanitizer configs.
+PRODUCT_SANITIZER_MODULE_CONFIGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SANITIZER_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_psmc_modules :=
+$(foreach c,$(PRODUCT_SANITIZER_MODULE_CONFIGS),\
+ $(eval m := $(firstword $(subst =,$(space),$(c))))\
+ $(if $(filter $(_psmc_modules),$(m)),,\
+ $(eval _psmc_modules += $(m))\
+ $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+ $(eval cf := $(subst $(_PSMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+ $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_psmc_modules :=
+
+# Whether the product wants to ship libartd. For rules and meaning, see art/Android.mk.
+PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD))
+
+# Make this art variable visible to soong_config.mk.
+PRODUCT_ART_USE_READ_BARRIER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ART_USE_READ_BARRIER))
+
+# Whether the product is an Android Things variant.
+PRODUCT_IOT := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_IOT))
+
+# Resource overlay list which must be excluded from enforcing RRO.
+PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS))
+
+# Package list to apply enforcing RRO.
+PRODUCT_ENFORCE_RRO_TARGETS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_RRO_TARGETS))
+
+# Add reserved headroom to a system image.
+PRODUCT_SYSTEM_HEADROOM := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_HEADROOM))
+
+# Whether to save disk space by minimizing java debug info
+PRODUCT_MINIMIZE_JAVA_DEBUG_INFO := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MINIMIZE_JAVA_DEBUG_INFO))
+
+# Whether any paths are excluded from sanitization when SANITIZE_TARGET=integer_overflow
+PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS))
diff --git a/build/core/android-9.0/product_config.mk b/build/core/android-9.0/product_config.mk
new file mode 100644
index 0000000..515ce2f
--- /dev/null
+++ b/build/core/android-9.0/product_config.mk
@@ -0,0 +1,501 @@
+#
+# 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.
+#
+
+# ---------------------------------------------------------------
+# Generic functions
+# TODO: Move these to definitions.make once we're able to include
+# definitions.make before config.make.
+
+###########################################################
+## Return non-empty if $(1) is a C identifier; i.e., if it
+## matches /^[a-zA-Z_][a-zA-Z0-9_]*$/. We do this by first
+## making sure that it isn't empty and doesn't start with
+## a digit, then by removing each valid character. If the
+## final result is empty, then it was a valid C identifier.
+##
+## $(1): word to check
+###########################################################
+
+_ici_digits := 0 1 2 3 4 5 6 7 8 9
+_ici_alphaunderscore := \
+ a b c d e f g h i j k l m n o p q r s t u v w x y z \
+ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _
+define is-c-identifier
+$(strip \
+ $(if $(1), \
+ $(if $(filter $(addsuffix %,$(_ici_digits)),$(1)), \
+ , \
+ $(eval w := $(1)) \
+ $(foreach c,$(_ici_digits) $(_ici_alphaunderscore), \
+ $(eval w := $(subst $(c),,$(w))) \
+ ) \
+ $(if $(w),,TRUE) \
+ $(eval w :=) \
+ ) \
+ ) \
+ )
+endef
+
+# TODO: push this into the combo files; unfortunately, we don't even
+# know HOST_OS at this point.
+trysed := $(shell echo a | sed -E -e 's/a/b/' 2>/dev/null)
+ifeq ($(trysed),b)
+ SED_EXTENDED := sed -E
+else
+ trysed := $(shell echo c | sed -r -e 's/c/d/' 2>/dev/null)
+ ifeq ($(trysed),d)
+ SED_EXTENDED := sed -r
+ else
+ $(error Unknown sed version)
+ endif
+endif
+
+###########################################################
+## List all of the files in a subdirectory in a format
+## suitable for PRODUCT_COPY_FILES and
+## PRODUCT_SDK_ADDON_COPY_FILES
+##
+## $(1): Glob to match file name
+## $(2): Source directory
+## $(3): Target base directory
+###########################################################
+
+define find-copy-subdir-files
+$(sort $(shell find $(2) -name "$(1)" -type f | $(SED_EXTENDED) "s:($(2)/?(.*)):\\1\\:$(3)/\\2:" | sed "s://:/:g"))
+endef
+
+# ---------------------------------------------------------------
+
+# These are the valid values of TARGET_BUILD_VARIANT. Also, if anything else is passed
+# as the variant in the PRODUCT-$TARGET_BUILD_PRODUCT-$TARGET_BUILD_VARIANT form,
+# it will be treated as a goal, and the eng variant will be used.
+INTERNAL_VALID_VARIANTS := user userdebug eng
+
+# ---------------------------------------------------------------
+# Provide "PRODUCT--" targets, which lets you build
+# a particular configuration without needing to set up the environment.
+#
+ifeq ($(CALLED_FROM_SETUP),true)
+product_goals := $(strip $(filter PRODUCT-%,$(MAKECMDGOALS)))
+ifdef product_goals
+ # Scrape the product and build names out of the goal,
+ # which should be of the form PRODUCT--.
+ #
+ ifneq ($(words $(product_goals)),1)
+ $(error Only one PRODUCT-* goal may be specified; saw "$(product_goals)")
+ endif
+ goal_name := $(product_goals)
+ product_goals := $(patsubst PRODUCT-%,%,$(product_goals))
+ product_goals := $(subst -, ,$(product_goals))
+ ifneq ($(words $(product_goals)),2)
+ $(error Bad PRODUCT-* goal "$(goal_name)")
+ endif
+
+ # The product they want
+ TARGET_PRODUCT := $(word 1,$(product_goals))
+
+ # The variant they want
+ TARGET_BUILD_VARIANT := $(word 2,$(product_goals))
+
+ ifeq ($(TARGET_BUILD_VARIANT),tests)
+ $(error "tests" has been deprecated as a build variant. Use it as a build goal instead.)
+ endif
+
+ # The build server wants to do make PRODUCT-dream-sdk
+ # which really means TARGET_PRODUCT=dream make sdk.
+ ifneq ($(filter-out $(INTERNAL_VALID_VARIANTS),$(TARGET_BUILD_VARIANT)),)
+ override MAKECMDGOALS := $(MAKECMDGOALS) $(TARGET_BUILD_VARIANT)
+ TARGET_BUILD_VARIANT := userdebug
+ default_goal_substitution :=
+ else
+ default_goal_substitution := droid
+ endif
+
+ # Replace the PRODUCT-* goal with the build goal that it refers to.
+ # Note that this will ensure that it appears in the same relative
+ # position, in case it matters.
+ override MAKECMDGOALS := $(patsubst $(goal_name),$(default_goal_substitution),$(MAKECMDGOALS))
+endif
+endif # CALLED_FROM_SETUP
+# else: Use the value set in the environment or buildspec.mk.
+
+# ---------------------------------------------------------------
+# Provide "APP-" targets, which lets you build
+# an unbundled app.
+#
+ifeq ($(CALLED_FROM_SETUP),true)
+unbundled_goals := $(strip $(filter APP-%,$(MAKECMDGOALS)))
+ifdef unbundled_goals
+ ifneq ($(words $(unbundled_goals)),1)
+ $(error Only one APP-* goal may be specified; saw "$(unbundled_goals)")
+ endif
+ TARGET_BUILD_APPS := $(strip $(subst -, ,$(patsubst APP-%,%,$(unbundled_goals))))
+ ifneq ($(filter droid,$(MAKECMDGOALS)),)
+ override MAKECMDGOALS := $(patsubst $(unbundled_goals),,$(MAKECMDGOALS))
+ else
+ override MAKECMDGOALS := $(patsubst $(unbundled_goals),droid,$(MAKECMDGOALS))
+ endif
+endif # unbundled_goals
+endif
+
+# Now that we've parsed APP-* and PRODUCT-*, mark these as readonly
+TARGET_BUILD_APPS ?=
+.KATI_READONLY := \
+ TARGET_PRODUCT \
+ TARGET_BUILD_VARIANT \
+ TARGET_BUILD_APPS
+
+# Default to building dalvikvm on hosts that support it...
+ifeq ($(HOST_OS),linux)
+# ... or if the if the option is already set
+ifeq ($(WITH_HOST_DALVIK),)
+ WITH_HOST_DALVIK := true
+endif
+endif
+
+# ---------------------------------------------------------------
+# Include the product definitions.
+# We need to do this to translate TARGET_PRODUCT into its
+# underlying TARGET_DEVICE before we start defining any rules.
+#
+include $(BUILD_SYSTEM)/node_fns.mk
+include $(BUILD_SYSTEM)/product.mk
+include $(BUILD_SYSTEM)/device.mk
+
+ifneq ($(strip $(TARGET_BUILD_APPS)),)
+# An unbundled app build needs only the core product makefiles.
+all_product_configs := $(call get-product-makefiles,\
+ $(SRC_TARGET_DIR)/product/AndroidProducts.mk)
+else
+# Read in all of the product definitions specified by the AndroidProducts.mk
+# files in the tree.
+all_product_configs := $(get-all-product-makefiles)
+endif
+
+all_named_products :=
+
+# Find the product config makefile for the current product.
+# all_product_configs consists items like:
+# :
+# or just in case the product name is the
+# same as the base filename of the product config makefile.
+current_product_makefile :=
+all_product_makefiles :=
+$(foreach f, $(all_product_configs),\
+ $(eval _cpm_words := $(subst :,$(space),$(f)))\
+ $(eval _cpm_word1 := $(word 1,$(_cpm_words)))\
+ $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
+ $(if $(_cpm_word2),\
+ $(eval all_product_makefiles += $(_cpm_word2))\
+ $(eval all_named_products += $(_cpm_word1))\
+ $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
+ $(eval current_product_makefile += $(_cpm_word2)),),\
+ $(eval all_product_makefiles += $(f))\
+ $(eval all_named_products += $(basename $(notdir $(f))))\
+ $(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\
+ $(eval current_product_makefile += $(f)),)))
+_cpm_words :=
+_cpm_word1 :=
+_cpm_word2 :=
+current_product_makefile := $(strip $(current_product_makefile))
+all_product_makefiles := $(strip $(all_product_makefiles))
+
+load_all_product_makefiles :=
+ifneq (,$(filter product-graph, $(MAKECMDGOALS)))
+ifeq ($(ANDROID_PRODUCT_GRAPH),--all)
+load_all_product_makefiles := true
+endif
+endif
+ifneq (,$(filter dump-products,$(MAKECMDGOALS)))
+ifeq ($(ANDROID_DUMP_PRODUCTS),all)
+load_all_product_makefiles := true
+endif
+endif
+
+ifeq ($(load_all_product_makefiles),true)
+# Import all product makefiles.
+$(call import-products, $(all_product_makefiles))
+else
+$(call import-products, $(current_product_makefile))
+endif # Import all or just the current product makefile
+
+# Sanity check
+$(check-all-products)
+
+ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
+$(dump-products)
+$(error done)
+endif
+
+# Convert a short name like "sooner" into the path to the product
+# file defining that product.
+#
+current_product_makefile :=
+all_product_makefiles :=
+all_product_configs :=
+
+
+#############################################################################
+
+# A list of module names of BOOTCLASSPATH (jar files)
+PRODUCT_BOOT_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BOOT_JARS))
+PRODUCT_SYSTEM_SERVER_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_JARS))
+PRODUCT_SYSTEM_SERVER_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_APPS))
+PRODUCT_DEXPREOPT_SPEED_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEXPREOPT_SPEED_APPS))
+PRODUCT_LOADED_BY_PRIVILEGED_MODULES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
+
+# All of the apps that we force preopt, this overrides WITH_DEXPREOPT.
+PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK))
+
+# Find the device that this product maps to.
+TARGET_DEVICE := device_code
+
+# Figure out which resoure configuration options to use for this
+# product.
+PRODUCT_LOCALES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOCALES))
+# TODO: also keep track of things like "port", "land" in product files.
+
+# If CUSTOM_LOCALES contains any locales not already included
+# in PRODUCT_LOCALES, add them to PRODUCT_LOCALES.
+extra_locales := $(filter-out $(PRODUCT_LOCALES),$(CUSTOM_LOCALES))
+ifneq (,$(extra_locales))
+ ifneq ($(CALLED_FROM_SETUP),true)
+ # Don't spam stdout, because envsetup.sh may be scraping values from it.
+ $(info Adding CUSTOM_LOCALES [$(extra_locales)] to PRODUCT_LOCALES [$(PRODUCT_LOCALES)])
+ endif
+ PRODUCT_LOCALES += $(extra_locales)
+ extra_locales :=
+endif
+
+# Add PRODUCT_LOCALES to PRODUCT_AAPT_CONFIG
+PRODUCT_AAPT_CONFIG := $(strip $(PRODUCT_LOCALES) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_CONFIG))
+PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREF_CONFIG))
+PRODUCT_AAPT_PREBUILT_DPI := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREBUILT_DPI))
+
+# Keep a copy of the space-separated config
+PRODUCT_AAPT_CONFIG_SP := $(PRODUCT_AAPT_CONFIG)
+
+# Convert spaces to commas.
+PRODUCT_AAPT_CONFIG := \
+ $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
+
+PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))
+
+PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MODEL))
+ifndef PRODUCT_MODEL
+ PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_NAME))
+endif
+
+PRODUCT_MANUFACTURER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))
+ifndef PRODUCT_MANUFACTURER
+ PRODUCT_MANUFACTURER := unknown
+endif
+
+ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS),)
+ TARGET_AAPT_CHARACTERISTICS := default
+else
+ TARGET_AAPT_CHARACTERISTICS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS))
+endif
+
+PRODUCT_DEFAULT_WIFI_CHANNELS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))
+
+PRODUCT_DEFAULT_DEV_CERTIFICATE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_DEV_CERTIFICATE))
+ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
+ifneq (1,$(words $(PRODUCT_DEFAULT_DEV_CERTIFICATE)))
+ $(error PRODUCT_DEFAULT_DEV_CERTIFICATE='$(PRODUCT_DEFAULT_DEV_CERTIFICATE)', \
+ only 1 certificate is allowed.)
+endif
+endif
+
+# A list of words like :[:].
+# The file at the source path should be copied to the destination path
+# when building this product. is relative to
+# $(PRODUCT_OUT), so it should look like, e.g., "system/etc/file.xml".
+# The rules for these copy steps are defined in build/make/core/Makefile.
+# The optional : is used to indicate the owner of a vendor file.
+PRODUCT_COPY_FILES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COPY_FILES))
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+PRODUCT_PROPERTY_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES))
+.KATI_READONLY := PRODUCT_PROPERTY_OVERRIDES
+
+PRODUCT_SHIPPING_API_LEVEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SHIPPING_API_LEVEL))
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to default.prop
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
+.KATI_READONLY := PRODUCT_DEFAULT_PROPERTY_OVERRIDES
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to default.prop of system partition
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_DEFAULT_PROPERTIES))
+.KATI_READONLY := PRODUCT_SYSTEM_DEFAULT_PROPERTIES
+
+# A list of property assignments, like "key = value", with zero or more
+# whitespace characters on either side of the '='.
+# used for adding properties to build.prop of product partition
+PRODUCT_PRODUCT_PROPERTIES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_PROPERTIES))
+.KATI_READONLY := PRODUCT_PRODUCT_PROPERTIES
+
+# used for overriding properties in build.prop
+PRODUCT_BUILD_PROP_OVERRIDES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BUILD_PROP_OVERRIDES))
+.KATI_READONLY := PRODUCT_BUILD_PROP_OVERRIDES
+
+# Should we use the default resources or add any product specific overlays
+PRODUCT_PACKAGE_OVERLAYS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGE_OVERLAYS))
+DEVICE_PACKAGE_OVERLAYS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).DEVICE_PACKAGE_OVERLAYS))
+
+# The list of product-specific kernel header dirs
+PRODUCT_VENDOR_KERNEL_HEADERS := \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_KERNEL_HEADERS)
+
+# The OTA key(s) specified by the product config, if any. The names
+# of these keys are stored in the target-files zip so that post-build
+# signing tools can substitute them for the test key embedded by
+# default.
+PRODUCT_OTA_PUBLIC_KEYS := $(sort \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTA_PUBLIC_KEYS))
+
+PRODUCT_EXTRA_RECOVERY_KEYS := $(sort \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_EXTRA_RECOVERY_KEYS))
+
+PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER))
+PRODUCT_DEX_PREOPT_DEFAULT_FLAGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
+PRODUCT_DEX_PREOPT_GENERATE_DM_FILES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_GENERATE_DM_FILES))
+PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
+PRODUCT_DEX_PREOPT_PROFILE_DIR := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_PROFILE_DIR))
+
+# Boot image options.
+PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE))
+PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION))
+
+PRODUCT_SYSTEM_SERVER_COMPILER_FILTER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
+PRODUCT_SYSTEM_SERVER_DEBUG_INFO := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_DEBUG_INFO))
+PRODUCT_OTHER_JAVA_DEBUG_INFO := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTHER_JAVA_DEBUG_INFO))
+
+# Resolve and setup per-module dex-preopt configs.
+PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_pdpmc_modules :=
+$(foreach c,$(PRODUCT_DEX_PREOPT_MODULE_CONFIGS),\
+ $(eval m := $(firstword $(subst =,$(space),$(c))))\
+ $(if $(filter $(_pdpmc_modules),$(m)),,\
+ $(eval _pdpmc_modules += $(m))\
+ $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+ $(eval cf := $(subst $(_PDPMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+ $(eval DEXPREOPT.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_pdpmc_modules :=
+
+# Resolve and setup per-module sanitizer configs.
+PRODUCT_SANITIZER_MODULE_CONFIGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SANITIZER_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_psmc_modules :=
+$(foreach c,$(PRODUCT_SANITIZER_MODULE_CONFIGS),\
+ $(eval m := $(firstword $(subst =,$(space),$(c))))\
+ $(if $(filter $(_psmc_modules),$(m)),,\
+ $(eval _psmc_modules += $(m))\
+ $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+ $(eval cf := $(subst $(_PSMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+ $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_psmc_modules :=
+
+# Whether the product wants to ship libartd. For rules and meaning, see art/Android.mk.
+PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD))
+
+# Make this art variable visible to soong_config.mk.
+PRODUCT_ART_USE_READ_BARRIER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ART_USE_READ_BARRIER))
+
+# Whether the product is an Android Things variant.
+PRODUCT_IOT := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_IOT))
+
+# Resource overlay list which must be excluded from enforcing RRO.
+PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS))
+
+# Package list to apply enforcing RRO.
+PRODUCT_ENFORCE_RRO_TARGETS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_RRO_TARGETS))
+
+# Add reserved headroom to a system image.
+PRODUCT_SYSTEM_HEADROOM := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_HEADROOM))
+
+# Whether to save disk space by minimizing java debug info
+PRODUCT_MINIMIZE_JAVA_DEBUG_INFO := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MINIMIZE_JAVA_DEBUG_INFO))
+
+# Whether any paths are excluded from sanitization when SANITIZE_TARGET=integer_overflow
+PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS))
+
+# ADB keys for debuggable builds
+PRODUCT_ADB_KEYS :=
+ifneq ($(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
+ PRODUCT_ADB_KEYS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ADB_KEYS))
+endif
+ifneq ($(filter-out 0 1,$(words $(PRODUCT_ADB_KEYS))),)
+ $(error Only one file may be in PRODUCT_ADB_KEYS: $(PRODUCT_ADB_KEYS))
+endif
+.KATI_READONLY := PRODUCT_ADB_KEYS
+
+# Whether any paths are excluded from sanitization when SANITIZE_TARGET=cfi
+PRODUCT_CFI_EXCLUDE_PATHS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CFI_EXCLUDE_PATHS))
+
+# Whether any paths should have CFI enabled for components
+PRODUCT_CFI_INCLUDE_PATHS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CFI_INCLUDE_PATHS))
+
+# which Soong namespaces to export to Make
+PRODUCT_SOONG_NAMESPACES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SOONG_NAMESPACES))
+
+# A flag to override PRODUCT_COMPATIBLE_PROPERTY
+PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE))
+
+# Whether the whitelist of actionable compatible properties should be disabled or not
+PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE))
diff --git a/config.json b/config.json
new file mode 100644
index 0000000..ba869fc
--- /dev/null
+++ b/config.json
@@ -0,0 +1,16 @@
+{
+ "twrp_url": "https://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni",
+ "twrp_branch": "twrp-9.0",
+ "git_username": "Pinkdoge",
+ "git_email": "42758990+Pinkdoge@users.noreply.github.com",
+ "use_own_dt": true,
+ "dt_url": "pinkdoge/twrp_device_huawei_kiwi",
+ "dt_branch": "android-9.0",
+ "dt_remote": "github",
+ "dt_path": "device/huawei/kiwi",
+ "device_code": "kiwi",
+ "fix_product": true,
+ "fix_misscom": true,
+ "fix_busybox": false,
+ "fix_branch": "android-9.0"
+}
diff --git a/demo.jpg b/demo.jpg
new file mode 100755
index 0000000000000000000000000000000000000000..549d510fdf50ce82df04057365890b2b1d80dffa
GIT binary patch
literal 254093
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