Merge "Remove zlib_fingerprint support."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1a84e8f..7e23ee0 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -450,6 +450,12 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/vndk)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/vndk-sp)
+# Remove old dex output directories
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/with-local/)
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/no-local/)
+$(call add-clean-step, rm -rf $(HOST_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/with-local/)
+$(call add-clean-step, rm -rf $(HOST_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/no-local/)
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/core/Makefile b/core/Makefile
index cfb8656..a3fbe33 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -841,7 +841,8 @@
tools_notice_file_txt := $(HOST_OUT_INTERMEDIATES)/NOTICE.txt
tools_notice_file_html := $(HOST_OUT_INTERMEDIATES)/NOTICE.html
-ifeq ($(PRODUCT_FULL_TREBLE),true)
+# TODO(b/69865032): Make PRODUCT_NOTICE_SPLIT the default behavior.
+ifeq ($(PRODUCT_NOTICE_SPLIT),true)
target_notice_file_html_or_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml
target_notice_file_html_or_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml.gz
installed_notice_html_or_xml_gz := $(TARGET_OUT)/etc/NOTICE.xml.gz
@@ -1043,7 +1044,6 @@
$(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_fs_type=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "system_extfs_inode_count=$(BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_JOURNAL_SIZE),$(hide) echo "system_journal_size=$(BOARD_SYSTEMIMAGE_JOURNAL_SIZE)" >> $(1))
-$(if $(BOARD_HAS_EXT4_RESERVED_BLOCKS),$(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_squashfs_compressor=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "system_squashfs_block_size=$(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
@@ -1456,9 +1456,6 @@
du -sm $(TARGET_OUT) 1>&2;\
if [ "$(INTERNAL_USERIMAGES_EXT_VARIANT)" == "ext4" ]; then \
maxsize=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE); \
- if [ "$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" == "true" ]; then \
- maxsize=$$((maxsize - 4096 * 4096)); \
- fi; \
echo "The max is $$(( maxsize / 1048576 )) MB." 1>&2 ;\
else \
echo "The max is $$(( $(BOARD_SYSTEMIMAGE_PARTITION_SIZE) / 1048576 )) MB." 1>&2 ;\
@@ -2174,6 +2171,7 @@
$(HOST_OUT_EXECUTABLES)/simg2img \
$(HOST_OUT_EXECUTABLES)/e2fsck \
$(HOST_OUT_EXECUTABLES)/build_verity_tree \
+ $(HOST_OUT_EXECUTABLES)/generate_verity_key \
$(HOST_OUT_EXECUTABLES)/verity_signer \
$(HOST_OUT_EXECUTABLES)/verity_verifier \
$(HOST_OUT_EXECUTABLES)/append2simg \
@@ -2199,6 +2197,7 @@
$(HOST_LIBRARY_PATH)/liblog$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libcutils$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libselinux$(HOST_SHLIB_SUFFIX) \
+ $(HOST_LIBRARY_PATH)/libcrypto_utils$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libcrypto-host$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libext2fs-host$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libext2_blkid-host$(HOST_SHLIB_SUFFIX) \
@@ -2478,9 +2477,6 @@
ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE
$(hide) echo "recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
-ifdef BOARD_HAS_EXT4_RESERVED_BLOCKS
- $(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(zip_root)/META/misc_info.txt
-endif
ifdef TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS
@# TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS can be empty to indicate that nothing but defaults should be used.
$(hide) echo "recovery_mount_options=$(TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)" >> $(zip_root)/META/misc_info.txt
diff --git a/core/autogen_test_config.mk b/core/autogen_test_config.mk
new file mode 100644
index 0000000..9f3a2a6
--- /dev/null
+++ b/core/autogen_test_config.mk
@@ -0,0 +1,60 @@
+#
+# 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.
+#
+
+# This build rule allows TradeFed test config file to be created based on
+# following inputs:
+# is_native: If the test is a native test.
+# LOCAL_MANIFEST_FILE: Name of the AndroidManifest file for the test. If it's
+# not set, default value `AndroidManifest.xml` will be used.
+# Output:
+# autogen_test_config_file: Path to the test config file generated.
+
+autogen_test_config_file := $(dir $(LOCAL_BUILT_MODULE))$(LOCAL_MODULE).config
+ifeq (true,$(is_native))
+# Auto generating test config file for native test
+$(autogen_test_config_file) : $(NATIVE_TEST_CONFIG_TEMPLATE)
+ @echo "Auto generating test config $(notdir $@)"
+ $(hide) sed 's&{MODULE}&$(PRIVATE_MODULE)&g' $^ > $@
+my_auto_generate_config := true
+else
+# Auto generating test config file for instrumentation test
+ifeq ($(strip $(LOCAL_MANIFEST_FILE)),)
+ LOCAL_MANIFEST_FILE := AndroidManifest.xml
+endif
+ifdef LOCAL_FULL_MANIFEST_FILE
+ my_android_manifest := $(LOCAL_FULL_MANIFEST_FILE)
+else
+ my_android_manifest := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE)
+endif
+ifneq (,$(wildcard $(my_android_manifest)))
+$(autogen_test_config_file) : $(my_android_manifest) $(EMPTY_TEST_CONFIG) $(INSTRUMENTATION_TEST_CONFIG_TEMPLATE)
+ @echo "Auto generating test config $(notdir $@)"
+ @rm -f $@
+ $(hide) $(AUTOGEN_TEST_CONFIG_SCRIPT) $@ $^
+my_auto_generate_config := true
+endif # ifeq (,$(wildcard $(my_android_manifest)))
+endif # ifneq (true,$(is_native))
+
+ifeq (true,$(my_auto_generate_config))
+ LOCAL_INTERMEDIATE_TARGETS += $(autogen_test_config_file)
+ $(LOCAL_BUILT_MODULE): $(autogen_test_config_file)
+ ALL_MODULES.$(my_register_name).auto_test_config := true
+else
+ autogen_test_config_file :=
+endif
+
+my_android_manifest :=
+my_auto_generate_config :=
diff --git a/core/base_rules.mk b/core/base_rules.mk
index dc3a78b..9234abe 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -510,7 +510,6 @@
endif
ifdef is_native
arch_dir := /$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
- is_native :=
endif
# The module itself.
@@ -531,13 +530,35 @@
$(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
$(s):$(dir)/$(n)))))
+test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml)
+ifeq (,$(test_config))
+ ifneq (true,$(is_native))
+ is_instrumentation_test := true
+ ifeq (true, $(LOCAL_IS_HOST_MODULE))
+ is_instrumentation_test := false
+ endif
+ endif
+ # CTS modules can be used for test data, so test config files must be
+ # explicitly created using AndroidTest.xml
+ ifeq (,$(filter cts, $(LOCAL_COMPATIBILITY_SUITE)))
+ ifeq (true, $(filter true,$(is_native) $(is_instrumentation_test)))
+ include $(BUILD_SYSTEM)/autogen_test_config.mk
+ test_config := $(autogen_test_config_file)
+ autogen_test_config_file :=
+ endif
+ endif
+endif
-ifneq (,$(wildcard $(LOCAL_PATH)/AndroidTest.xml))
+is_instrumentation_test :=
+
+ifneq (,$(test_config))
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
- $(LOCAL_PATH)/AndroidTest.xml:$(dir)/$(LOCAL_MODULE).config)))
+ $(test_config):$(dir)/$(LOCAL_MODULE).config)))
endif
+test_config :=
+
ifneq (,$(wildcard $(LOCAL_PATH)/DynamicConfig.xml))
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
@@ -552,6 +573,9 @@
endif
endif # $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files
+arch_dir :=
+is_native :=
+
ifneq ($(my_test_data_file_pairs),)
$(foreach pair, $(my_test_data_file_pairs), \
$(eval parts := $(subst :,$(space),$(pair))) \
diff --git a/core/binary.mk b/core/binary.mk
index cc6df60..6920373 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -88,7 +88,7 @@
endif
# Make sure we've built the NDK.
- my_additional_dependencies += $(SOONG_OUT_DIR)/ndk.timestamp
+ my_additional_dependencies += $(SOONG_OUT_DIR)/ndk_base.timestamp
# mips32r6 is not supported by the NDK. No released NDK contains these
# libraries, but the r10 in prebuilts/ndk had a local hack to add them :(
diff --git a/core/config.mk b/core/config.mk
index d317bd0..43eaf01 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -156,8 +156,15 @@
BUILD_HOST_DALVIK_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_java_library.mk
BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_static_java_library.mk
-BUILD_HOST_TEST_CONFIG:= $(BUILD_SYSTEM)/host_test_config.mk
-BUILD_TARGET_TEST_CONFIG:= $(BUILD_SYSTEM)/target_test_config.mk
+BUILD_HOST_TEST_CONFIG := $(BUILD_SYSTEM)/host_test_config.mk
+BUILD_TARGET_TEST_CONFIG := $(BUILD_SYSTEM)/target_test_config.mk
+
+INSTRUMENTATION_TEST_CONFIG_TEMPLATE := $(BUILD_SYSTEM)/instrumentation_test_config_template.xml
+NATIVE_TEST_CONFIG_TEMPLATE := $(BUILD_SYSTEM)/native_test_config_template.xml
+EMPTY_TEST_CONFIG := $(BUILD_SYSTEM)/empty_test_config.xml
+
+# Tool to generate TradeFed test config file automatically.
+AUTOGEN_TEST_CONFIG_SCRIPT := build/make/tools/auto_gen_test_config.py
# ###############################################################
# Parse out any modifier targets.
@@ -713,14 +720,8 @@
TARGET_OPENJDK9 := true
endif
-# Path to tools.jar, or empty if USE_OPENJDK9 is unset
-HOST_JDK_TOOLS_JAR :=
-# TODO: Remove HOST_JDK_TOOLS_JAR and all references to it once OpenJDK 8
-# toolchains are no longer supported (i.e. when USE_OPENJDK9 is enforced).
-# http://b/38418220
-ifndef USE_OPENJDK9
-HOST_JDK_TOOLS_JAR := $(ANDROID_JAVA_TOOLCHAIN)/../lib/tools.jar
-endif # ifndef USE_OPENJDK9
+# Path to tools.jar
+HOST_JDK_TOOLS_JAR := $(ANDROID_JAVA8_HOME)/lib/tools.jar
# It's called md5 on Mac OS and md5sum on Linux
ifeq ($(HOST_OS),darwin)
@@ -748,15 +749,25 @@
PRODUCT_FULL_TREBLE := true
endif
+# TODO(b/69865032): Make PRODUCT_NOTICE_SPLIT the default behavior and remove
+# references to it here and below.
+ifdef PRODUCT_NOTICE_SPLIT_OVERRIDE
+ $(error PRODUCT_NOTICE_SPLIT_OVERRIDE cannot be set.)
+endif
+
requirements := \
PRODUCT_TREBLE_LINKER_NAMESPACES \
PRODUCT_SEPOLICY_SPLIT \
PRODUCT_ENFORCE_VINTF_MANIFEST \
+ PRODUCT_NOTICE_SPLIT
# If it is overriden, then the requirement override is taken, otherwise it's
# PRODUCT_FULL_TREBLE
$(foreach req,$(requirements),$(eval \
$(req) := $(if $($(req)_OVERRIDE),$($(req)_OVERRIDE),$(PRODUCT_FULL_TREBLE))))
+# If the requirement is false for any reason, then it's not PRODUCT_FULL_TREBLE
+$(foreach req,$(requirements),$(eval \
+ PRODUCT_FULL_TREBLE := $(if $(filter false,$($(req))),false,$(PRODUCT_FULL_TREBLE))))
PRODUCT_FULL_TREBLE_OVERRIDE ?=
$(foreach req,$(requirements),$(eval $(req)_OVERRIDE ?=))
@@ -769,6 +780,28 @@
requirements :=
+# If PRODUCT_USE_VNDK is true and BOARD_VNDK_VERSION is not defined yet,
+# BOARD_VNDK_VERSION will be set to "current" as default.
+# PRODUCT_USE_VNDK will be true in Android-P or later launching devices.
+PRODUCT_USE_VNDK := false
+ifneq ($(PRODUCT_USE_VNDK_OVERRIDE),)
+ PRODUCT_USE_VNDK := $(PRODUCT_USE_VNDK_OVERRIDE)
+else ifeq ($(PRODUCT_SHIPPING_API_LEVEL),)
+ # No shipping level defined
+else ifeq ($(call math_gt_or_eq,27,$(PRODUCT_SHIPPING_API_LEVEL)),)
+ PRODUCT_USE_VNDK := $(PRODUCT_FULL_TREBLE)
+endif
+
+ifeq ($(PRODUCT_USE_VNDK),true)
+ ifndef BOARD_VNDK_VERSION
+ BOARD_VNDK_VERSION := current
+ endif
+endif
+
+$(KATI_obsolete_var PRODUCT_USE_VNDK_OVERRIDE,Use PRODUCT_USE_VNDK instead)
+.KATI_READONLY := \
+ PRODUCT_USE_VNDK
+
ifdef PRODUCT_SHIPPING_API_LEVEL
ifneq ($(call math_gt_or_eq,$(PRODUCT_SHIPPING_API_LEVEL),27),)
ifneq ($(TARGET_USES_MKE2FS),true)
@@ -784,7 +817,12 @@
DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
endif
-FRAMEWORK_MANIFEST_FILE := system/libhidl/manifest.xml
+FRAMEWORK_MANIFEST_INPUT_FILES := system/libhidl/manifest.xml
+ifdef DEVICE_FRAMEWORK_MANIFEST_FILE
+ FRAMEWORK_MANIFEST_INPUT_FILES += $(DEVICE_FRAMEWORK_MANIFEST_FILE)
+endif
+$(.KATI_obsolete_var DEVICE_FRAMEWORK_MANIFEST_FILE,No one should ever need to use this.)
+
FRAMEWORK_COMPATIBILITY_MATRIX_FILES := $(wildcard hardware/interfaces/compatibility_matrix.*.xml)
BUILD_NUMBER_FROM_FILE := $$(cat $(OUT_DIR)/build_number.txt)
diff --git a/core/definitions.mk b/core/definitions.mk
index 405f7c6..a20bf44 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2415,15 +2415,15 @@
define transform-classes-d8.jar-to-dex
@echo "target Dex: $(PRIVATE_MODULE)"
@mkdir -p $(dir $@)
-$(hide) rm -rf $(dir $@)classes*.dex $(dir $@)*.class $(dir $@)d8_input
-$(hide) unzip -qq -d $(dir $@)d8_input $< "*.class"
+$(hide) rm -f $(dir $@)classes*.dex $(dir $@)d8_input.jar
+$(hide) $(ZIP2ZIP) -j -i $< -o $(dir $@)d8_input.jar "**/*.class"
$(hide) $(DX_COMMAND) \
--output $(dir $@) \
--min-api $(PRIVATE_MIN_SDK_VERSION) \
- $(subst --no-locals, --release, \
- $(filter-out --core-library --multi-dex,$(PRIVATE_DX_FLAGS))) \
- $$(find $(dir $@)d8_input -name *.class | sort)
-$(hide) rm -fr $(dir $@)d8_input
+ $(subst --main-dex-list=, --main-dex-list , \
+ $(filter-out --core-library --multi-dex --minimal-main-dex,$(PRIVATE_DX_FLAGS))) \
+ $(dir $@)d8_input.jar
+$(hide) rm -f $(dir $@)d8_input.jar
endef
# Create a mostly-empty .jar file that we'll add to later.
diff --git a/core/empty_test_config.xml b/core/empty_test_config.xml
new file mode 100644
index 0000000..7c9daff
--- /dev/null
+++ b/core/empty_test_config.xml
@@ -0,0 +1,19 @@
+<?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" />
diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk
index 4b12bfe..1ff9b91 100644
--- a/core/host_dalvik_java_library.mk
+++ b/core/host_dalvik_java_library.mk
@@ -176,7 +176,7 @@
else # !LOCAL_IS_STATIC_JAVA_LIBRARY
$(built_dex): PRIVATE_INTERMEDIATES_DIR := $(intermediates.COMMON)
$(built_dex): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
-$(built_dex): $(full_classes_desugar_jar) $(DX)
+$(built_dex): $(full_classes_desugar_jar) $(DX) $(ZIP2ZIP)
ifneq ($(USE_D8_DESUGAR),true)
$(transform-classes.jar-to-dex)
else
diff --git a/core/instrumentation_test_config_template.xml b/core/instrumentation_test_config_template.xml
new file mode 100644
index 0000000..a0badab
--- /dev/null
+++ b/core/instrumentation_test_config_template.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs {LABEL}.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="{MODULE}.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.{TEST_TYPE}" >
+ <option name="package" value="{PACKAGE}" />
+ <option name="runner" value="{RUNNER}" />
+ </test>
+</configuration>
diff --git a/core/java.mk b/core/java.mk
index 08e4035..3e0123b 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -59,15 +59,6 @@
intermediates := $(call local-intermediates-dir)
intermediates.COMMON := $(call local-intermediates-dir,COMMON)
-# Choose leaf name for the compiled jar file.
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-full_classes_compiled_jar_leaf := classes-no-debug-var.jar
-built_dex_intermediate_leaf := no-local
-else
-full_classes_compiled_jar_leaf := classes-full-debug.jar
-built_dex_intermediate_leaf := with-local
-endif
-
ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)
LOCAL_PROGUARD_ENABLED :=
endif
@@ -75,14 +66,13 @@
full_classes_turbine_jar := $(intermediates.COMMON)/classes-turbine.jar
full_classes_header_jarjar := $(intermediates.COMMON)/classes-header-jarjar.jar
full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
-full_classes_compiled_jar := $(intermediates.COMMON)/$(full_classes_compiled_jar_leaf)
+full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar
full_classes_processed_jar := $(intermediates.COMMON)/classes-processed.jar
full_classes_desugar_jar := $(intermediates.COMMON)/classes-desugar.jar
-jarjar_leaf := classes-jarjar.jar
-full_classes_jarjar_jar := $(intermediates.COMMON)/$(jarjar_leaf)
+full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
full_classes_proguard_jar := $(intermediates.COMMON)/classes-proguard.jar
full_classes_combined_jar := $(intermediates.COMMON)/classes-combined.jar
-built_dex_intermediate := $(intermediates.COMMON)/$(built_dex_intermediate_leaf)/classes.dex
+built_dex_intermediate := $(intermediates.COMMON)/dex/classes.dex
full_classes_stubs_jar := $(intermediates.COMMON)/stubs.jar
java_source_list_file := $(intermediates.COMMON)/java-source-list
@@ -751,15 +741,6 @@
ifneq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
$(built_dex_intermediate): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
-# If you instrument class files that have local variable debug information in
-# them emma does not correctly maintain the local variable table.
-# This will cause an error when you try to convert the class files for Android.
-# The workaround here is to build different dex file here based on emma switch
-# then later copy into classes.dex. When emma is on, dx is run with --no-locals
-# option to remove local variable information
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-$(built_dex_intermediate): PRIVATE_DX_FLAGS += --no-locals
-endif
my_r8 :=
ifdef LOCAL_PROGUARD_ENABLED
@@ -777,7 +758,7 @@
endif # LOCAL_PROGUARD_ENABLED
ifndef my_r8
-$(built_dex_intermediate): $(full_classes_proguard_jar) $(DX)
+$(built_dex_intermediate): $(full_classes_proguard_jar) $(DX) $(ZIP2ZIP)
ifneq ($(USE_D8_DESUGAR),true)
$(transform-classes.jar-to-dex)
else
diff --git a/core/java_common.mk b/core/java_common.mk
index aac5982..cfc9d7f 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -36,6 +36,27 @@
LOCAL_JAVACFLAGS += -source $(LOCAL_JAVA_LANGUAGE_VERSION) -target $(LOCAL_JAVA_LANGUAGE_VERSION)
###########################################################
+
+# OpenJDK versions up to 8 shipped with bootstrap and tools jars
+# (rt.jar, jce.jar, tools.jar etc.). These are no longer part of
+# OpenJDK 9, but we still make them available for host tools that
+# are targeting older versions.
+USE_HOST_BOOTSTRAP_JARS := true
+ifeq (,$(filter $(LOCAL_JAVA_LANGUAGE_VERSION), 1.6 1.7 1.8))
+USE_HOST_BOOTSTRAP_JARS := false
+endif
+
+###########################################################
+
+# Drop HOST_JDK_TOOLS_JAR from classpath when targeting versions > 9 (which don't have it).
+# TODO: Remove HOST_JDK_TOOLS_JAR and all references to it once host
+# bootstrap jars are no longer supported (ie. when USE_HOST_BOOTSTRAP_JARS
+# is always false). http://b/38418220
+ifneq ($(USE_HOST_BOOTSTRAP_JARS),true)
+LOCAL_CLASSPATH := $(filter-out $(HOST_JDK_TOOLS_JAR),$(LOCAL_CLASSPATH))
+endif
+
+###########################################################
## .proto files: Compile proto files to .java
###########################################################
ifeq ($(strip $(LOCAL_PROTOC_OPTIMIZE_TYPE)),)
@@ -290,7 +311,23 @@
full_shared_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),true)
full_shared_java_header_libs := $(call java-lib-header-files,$(LOCAL_JAVA_LIBRARIES),true)
else # !USE_CORE_LIB_BOOTCLASSPATH
-
+ # Give host-side tools a version of OpenJDK's standard libraries
+ # close to what they're targeting. As of Dec 2017, AOSP is only
+ # bundling OpenJDK 8 and 9, so nothing < 8 is available.
+ #
+ # When building with OpenJDK 8, the following should have no
+ # effect since those jars would be available by default.
+ #
+ # When building with OpenJDK 9 but targeting a version < 1.8,
+ # putting them on the bootclasspath means that:
+ # a) code can't (accidentally) refer to OpenJDK 9 specific APIs
+ # b) references to existing APIs are not reinterpreted in an
+ # OpenJDK 9-specific way, eg. calls to subclasses of
+ # java.nio.Buffer as in http://b/70862583
+ ifeq ($(USE_HOST_BOOTSTRAP_JARS),true)
+ full_java_bootclasspath_libs += $(ANDROID_JAVA8_HOME)/jre/lib/jce.jar
+ full_java_bootclasspath_libs += $(ANDROID_JAVA8_HOME)/jre/lib/rt.jar
+ endif
full_shared_java_libs := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,\
$(addsuffix $(COMMON_JAVA_PACKAGE_SUFFIX),$(LOCAL_JAVA_LIBRARIES)))
full_shared_java_header_libs := $(full_shared_java_libs)
diff --git a/core/main.mk b/core/main.mk
index 621d309..fe178da 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -126,6 +126,8 @@
$(error ADDITIONAL_BUILD_PROPERTIES must not be set before here: $(ADDITIONAL_BUILD_PROPERTIES))
endif
+ADDITIONAL_BUILD_PROPERTIES :=
+
#
# -----------------------------------------------------------------
# Add the product-defined properties to the build properties.
@@ -198,6 +200,11 @@
ADDITIONAL_BUILD_PROPERTIES += ro.treble.enabled=${PRODUCT_FULL_TREBLE}
+$(KATI_obsolete_var PRODUCT_FULL_TREBLE,\
+ Code should be written to work regardless of a device being Treble or \
+ variables like PRODUCT_SEPOLICY_SPLIT should be used until that is \
+ possible.)
+
# -----------------------------------------------------------------
###
### In this section we set up the things that are different
diff --git a/core/native_test_config_template.xml b/core/native_test_config_template.xml
new file mode 100644
index 0000000..a960529
--- /dev/null
+++ b/core/native_test_config_template.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs {MODULE}.">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="{MODULE}" />
+ </test>
+</configuration>
diff --git a/core/soong_config.mk b/core/soong_config.mk
index eb19a8c..bbad4c8 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -118,11 +118,12 @@
$(call add_json_str, Override_rs_driver, $(OVERRIDE_RS_DRIVER))
$(call add_json_bool, Treble_linker_namespaces, $(filter true,$(PRODUCT_TREBLE_LINKER_NAMESPACES)))
-$(call add_json_bool, Sepolicy_split, $(filter true,$(PRODUCT_SEPOLICY_SPLIT)))
$(call add_json_bool, Enforce_vintf_manifest, $(filter true,$(PRODUCT_ENFORCE_VINTF_MANIFEST)))
$(call add_json_bool, Uml, $(filter true,$(TARGET_USER_MODE_LINUX)))
$(call add_json_str, VendorPath, $(TARGET_COPY_OUT_VENDOR))
+$(call add_json_str, OdmPath, $(TARGET_COPY_OUT_ODM))
+$(call add_json_str, OemPath, $(TARGET_COPY_OUT_OEM))
$(call add_json_bool, MinimizeJavaDebugInfo, $(filter true,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO)))
$(call add_json_bool, UseGoma, $(filter-out false,$(USE_GOMA)))
diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk
index f6d688c..b45526f 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -12,6 +12,7 @@
'"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)], ' \
'},\n' \
) | sed -e 's/, *\]/]/g' -e 's/, *\}/ }/g' -e '$$s/,$$//' >> $@
$(hide) echo '}' >> $@
diff --git a/core/tasks/vndk.mk b/core/tasks/vndk.mk
index 962fae1..fd7a696 100644
--- a/core/tasks/vndk.mk
+++ b/core/tasks/vndk.mk
@@ -17,6 +17,9 @@
# BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
ifeq ($(BOARD_VNDK_VERSION),current)
+# PLATFORM_VNDK_VERSION must be set.
+ifneq (,$(PLATFORM_VNDK_VERSION))
+
# Returns arch-specific libclang_rt.ubsan* library name.
# Because VNDK_CORE_LIBRARIES includes all arch variants for libclang_rt.ubsan*
# libs, the arch-specific libs are selected separately.
@@ -46,6 +49,22 @@
)
endef
+# Returns paths of notice files under $(TARGET_OUT_NOTICE_FILES)
+#
+# Args:
+# $(1): list of lib names (e.g., libfoo.vendor)
+# $(2): vndk lib type, one of 'vndk' or 'vndk-sp'
+define paths-of-notice-files
+$(strip \
+ $(eval lib_dir := lib$(if $(TARGET_IS_64BIT),64,)) \
+ $(eval vndk_dir := $(2)-$(PLATFORM_VNDK_VERSION)) \
+ $(foreach lib,$(1), \
+ $(eval notice_file_name := $(patsubst %.vendor,%.so.txt,$(lib))) \
+ $(TARGET_OUT_NOTICE_FILES)/src/system/$(lib_dir)/$(vndk_dir)/$(notice_file_name) \
+ ) \
+)
+endef
+
# If in the future libclang_rt.ubsan* is removed from the VNDK-core list,
# need to update the related logic in this file.
ifeq (,$(filter libclang_rt.ubsan%,$(VNDK_CORE_LIBRARIES)))
@@ -101,9 +120,21 @@
$(hide) $(foreach lib,$^,echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
+#######################################
+# module_paths.txt
+module_paths.txt := $(vndk_snapshot_configs_out)/module_paths.txt
+$(module_paths.txt): $(vndk_snapshot_libs)
+ @echo 'Generating: $@'
+ @rm -f $@
+ @mkdir -p $(dir $@)
+ $(hide) echo -n > $@
+ $(hide) $(foreach lib,$^,echo $(patsubst %.vendor,%,$(lib)).so $(ALL_MODULES.$(lib).PATH) >> $@;)
+
+
vndk_snapshot_configs := \
$(vndkcore.libraries.txt) \
- $(vndkprivate.libraries.txt)
+ $(vndkprivate.libraries.txt) \
+ $(module_paths.txt)
#######################################
# vndk_snapshot_zip
@@ -125,6 +156,11 @@
$(call paths-of-intermediates,$(vndk_prebuilt_txts),ETC) \
$(vndk_snapshot_configs)
+$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_OUT := $(vndk_snapshot_arch)/NOTICE_FILES
+$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_INTERMEDIATES := \
+ $(call paths-of-notice-files,$(vndk_core_libs),vndk) \
+ $(call paths-of-notice-files,$(vndk_sp_libs),vndk-sp)
+
# TODO(b/69834489): Package additional arch variants
# ifdef TARGET_2ND_ARCH
# vndk_snapshot_arch_2ND := $(vndk_snapshot_out)/arch-$(TARGET_2ND_ARCH)-$(TARGET_2ND_ARCH_VARIANT)
@@ -165,6 +201,8 @@
$(PRIVATE_VNDK_SP_OUT),$(PRIVATE_VNDK_SP_INTERMEDIATES))
$(call private-copy-vndk-intermediates, \
$(PRIVATE_CONFIGS_OUT),$(PRIVATE_CONFIGS_INTERMEDIATES))
+ $(call private-copy-vndk-intermediates, \
+ $(PRIVATE_NOTICE_FILES_OUT),$(PRIVATE_NOTICE_FILES_INTERMEDIATES))
# TODO(b/69834489): Package additional arch variants
# ifdef TARGET_2ND_ARCH
# $(call private-copy-vndk-intermediates, \
@@ -182,6 +220,7 @@
# clear global vars
clang-ubsan-vndk-core :=
paths-of-intermediates :=
+paths-of-notice-files :=
vndk_core_libs :=
vndk_sp_libs :=
vndk_snapshot_libs :=
@@ -197,6 +236,15 @@
# vndk_snapshot_arch_2ND :=
# endif
+else # PLATFORM_VNDK_VERSION is NOT set
+
+.PHONY: vndk
+vndk:
+ $(call echo-error,$(current_makefile),CANNOT generate VNDK snapshot. PLATFORM_VNDK_VERSION must be set.)
+ exit 1
+
+endif # PLATFORM_VNDK_VERSION
+
else # BOARD_VNDK_VERSION is NOT set to 'current'
.PHONY: vndk
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 32d9003..f6bc76b 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -187,17 +187,18 @@
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 "current". The ABI is allowed to be changed
- # only if PLATFORM_VNDK_VERSION == current. 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.
+ # 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 version follows PLATFORM_SDK_VERSION.
+ # The VNDK version follows PLATFORM_SDK_VERSION.
ifeq (REL,$(PLATFORM_VERSION_CODENAME))
PLATFORM_VNDK_VERSION := $(PLATFORM_SDK_VERSION)
else
- PLATFORM_VNDK_VERSION := current
+ PLATFORM_VNDK_VERSION := $(PLATFORM_VERSION_CODENAME)
endif
endif
diff --git a/target/board/Android.mk b/target/board/Android.mk
index fc32cd9..f4d6b93 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -89,8 +89,11 @@
endif
endif
-$(GEN): $(FRAMEWORK_MANIFEST_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
- BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $< -o $@ $(PRIVATE_FLAGS)
+$(GEN): PRIVATE_FRAMEWORK_MANIFEST_INPUT_FILES := $(FRAMEWORK_MANIFEST_INPUT_FILES)
+$(GEN): $(FRAMEWORK_MANIFEST_INPUT_FILES) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+ BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) $(HOST_OUT_EXECUTABLES)/assemble_vintf \
+ -i $(call normalize-path-list,$(PRIVATE_FRAMEWORK_MANIFEST_INPUT_FILES)) \
+ -o $@ $(PRIVATE_FLAGS)
LOCAL_PREBUILT_MODULE_FILE := $(GEN)
include $(BUILD_PREBUILT)
diff --git a/target/product/treble_common.mk b/target/product/treble_common.mk
index 2377188..c385352 100644
--- a/target/product/treble_common.mk
+++ b/target/product/treble_common.mk
@@ -81,3 +81,13 @@
$(error BOARD_AVB_ENABLE cannot be set for Treble GSI)
endif
BOARD_BUILD_DISABLED_VBMETAIMAGE := true
+
+#GSI support for the devices that disable VNDK enforcing
+PRODUCT_COPY_FILES += \
+ system/core/rootdir/etc/ld.config.txt:system/etc/ld.config.noenforce.txt \
+ build/make/target/product/vndk/init.gsi.rc:system/etc/init/init.gsi.rc \
+ build/make/target/product/vndk/init.noenforce.rc:system/etc/init/gsi/init.noenforce.rc
+
+#Set current VNDK version for GSI
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+ ro.gsi.vndk.version=$(PLATFORM_VNDK_VERSION)
diff --git a/target/product/vndk/init.gsi.rc b/target/product/vndk/init.gsi.rc
new file mode 100644
index 0000000..3e6b1fb
--- /dev/null
+++ b/target/product/vndk/init.gsi.rc
@@ -0,0 +1,2 @@
+# If ro.vndk.version is not defined, import init.noenforce.rc
+import /system/etc/init/gsi/init.${ro.vndk.version:-noenforce}.rc
diff --git a/target/product/vndk/init.noenforce.rc b/target/product/vndk/init.noenforce.rc
new file mode 100644
index 0000000..6cf1df7
--- /dev/null
+++ b/target/product/vndk/init.noenforce.rc
@@ -0,0 +1,5 @@
+on early-init
+ # If ro.vndk.version is not set, use ld.config.nonenforce.txt
+ export LD_CONFIG_FILE /system/etc/ld.config.noenforce.txt
+ # To use current VNDK libs, set ro.vndk.version to system vndk version
+ setprop ro.vndk.version ${ro.gsi.vndk.version}
diff --git a/tools/auto_gen_test_config.py b/tools/auto_gen_test_config.py
new file mode 100755
index 0000000..da4443c
--- /dev/null
+++ b/tools/auto_gen_test_config.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""A tool to generate TradeFed test config file.
+"""
+
+import os
+import shutil
+import sys
+from xml.dom.minidom import parse
+
+ATTRIBUTE_LABEL = 'android:label'
+ATTRIBUTE_RUNNER = 'android:name'
+ATTRIBUTE_PACKAGE = 'package'
+
+PLACEHOLDER_LABEL = '{LABEL}'
+PLACEHOLDER_MODULE = '{MODULE}'
+PLACEHOLDER_PACKAGE = '{PACKAGE}'
+PLACEHOLDER_RUNNER = '{RUNNER}'
+PLACEHOLDER_TEST_TYPE = '{TEST_TYPE}'
+
+
+def main(argv):
+ """Entry point of auto_gen_test_config.
+
+ Args:
+ argv: A list of arguments.
+ Returns:
+ 0 if no error, otherwise 1.
+ """
+ if len(argv) != 4:
+ sys.stderr.write(
+ 'Invalid arguements. The script requires 4 arguments for file paths: '
+ 'target_config android_manifest empty_config '
+ 'instrumentation_test_config_template.\n')
+ return 1
+ target_config = argv[0]
+ android_manifest = argv[1]
+ empty_config = argv[2]
+ instrumentation_test_config_template = argv[3]
+
+ 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
+
+ module = os.path.splitext(os.path.basename(target_config))[0]
+ instrumentation = instrumentation_elements[0]
+ manifest = manifest_elements[0]
+ if instrumentation.attributes.has_key(ATTRIBUTE_LABEL):
+ label = instrumentation.attributes[ATTRIBUTE_LABEL].value
+ else:
+ label = module
+ runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
+ package = manifest.attributes[ATTRIBUTE_PACKAGE].value
+ test_type = ('AndroidJUnitTest' if runner.endswith('.AndroidJUnitRunner')
+ else 'InstrumentationTest')
+
+ with open(instrumentation_test_config_template) as template:
+ config = template.read()
+ config = config.replace(PLACEHOLDER_LABEL, label)
+ config = config.replace(PLACEHOLDER_MODULE, module)
+ config = config.replace(PLACEHOLDER_PACKAGE, package)
+ config = config.replace(PLACEHOLDER_TEST_TYPE, test_type)
+ config = config.replace(PLACEHOLDER_RUNNER, runner)
+ with open(target_config, 'w') as config_file:
+ config_file.write(config)
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/tools/auto_gen_test_config_test.py b/tools/auto_gen_test_config_test.py
new file mode 100644
index 0000000..e70eff8
--- /dev/null
+++ b/tools/auto_gen_test_config_test.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+
+"""Unittests for auto_gen_test_config."""
+
+import os
+import shutil
+import tempfile
+import unittest
+
+import auto_gen_test_config
+
+TEST_MODULE = 'TestModule'
+
+MANIFEST_INVALID = """<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+</manifest>
+"""
+
+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">
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.my.tests" />
+</manifest>
+"""
+
+MANIFEST_INSTRUMENTATION_TEST = """<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.my.tests.x">
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.my.tests"
+ android:label="My Tests" />
+</manifest>
+"""
+
+EXPECTED_JUNIT_TEST_CONFIG = """<?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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs TestModule.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <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" />
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
+"""
+
+EXPECTED_INSTRUMENTATION_TEST_CONFIG = """<?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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs My Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <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" />
+ <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')
+
+
+class AutoGenTestConfigUnittests(unittest.TestCase):
+ """Unittests for auto_gen_test_config."""
+
+ def setUp(self):
+ """Setup directory for test."""
+ 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')
+
+ def tearDown(self):
+ """Cleanup the test directory."""
+ shutil.rmtree(self.test_dir, ignore_errors=True)
+
+ def testInvalidManifest(self):
+ """An empty test config should be generated if AndroidManifest is invalid.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_INVALID)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ with open(EMPTY_TEST_CONFIG) as empty_config:
+ self.assertEqual(config_file.read(), empty_config.read())
+
+ def testCreateJUnitTestConfig(self):
+ """Test creating test config for AndroidJUnitTest.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_JUNIT_TEST)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ self.assertEqual(config_file.read(), EXPECTED_JUNIT_TEST_CONFIG)
+
+ def testCreateInstrumentationTestConfig(self):
+ """Test creating test config for AndroidJUnitTest.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_INSTRUMENTATION_TEST)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ self.assertEqual(
+ config_file.read(), EXPECTED_INSTRUMENTATION_TEST_CONFIG)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index e4e4138..2a92d86 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -376,6 +376,40 @@
return None
return base_fs_file
+
+def CheckHeadroom(ext4fs_output, prop_dict):
+ """Checks if there's enough headroom space available.
+
+ Headroom is the reserved space on system image (via PRODUCT_SYSTEM_HEADROOM),
+ which is useful for devices with low disk space that have system image
+ variation between builds. The 'partition_headroom' in prop_dict is the size
+ in bytes, while the numbers in 'ext4fs_output' are for 4K-blocks.
+
+ Args:
+ ext4fs_output: The output string from mke2fs command.
+ prop_dict: The property dict.
+
+ Returns:
+ The check result.
+ """
+ ext4fs_stats = re.compile(
+ r'Created filesystem with .* (?P<used_blocks>[0-9]+)/'
+ r'(?P<total_blocks>[0-9]+) blocks')
+ m = ext4fs_stats.match(ext4fs_output.strip().split('\n')[-1])
+ used_blocks = int(m.groupdict().get('used_blocks'))
+ total_blocks = int(m.groupdict().get('total_blocks'))
+ headroom_blocks = int(prop_dict.get('partition_headroom')) / BLOCK_SIZE
+ adjusted_blocks = total_blocks - headroom_blocks
+ if used_blocks > adjusted_blocks:
+ mount_point = prop_dict.get("mount_point")
+ print("Error: Not enough room on %s (total: %d blocks, used: %d blocks, "
+ "headroom: %d blocks, available: %d blocks)" % (
+ mount_point, total_blocks, used_blocks, headroom_blocks,
+ adjusted_blocks))
+ return False
+ return True
+
+
def BuildImage(in_dir, prop_dict, out_file, target_out=None):
"""Build an image to out_file from in_dir with property prop_dict.
@@ -542,9 +576,7 @@
shutil.rmtree(staging_system, ignore_errors=True)
shutil.copytree(origin_in, staging_system, symlinks=True)
- has_reserved_blocks = prop_dict.get("has_ext4_reserved_blocks") == "true"
ext4fs_output = None
-
try:
if fs_type.startswith("ext4"):
(ext4fs_output, exit_code) = RunCommand(build_command)
@@ -562,37 +594,10 @@
print("Error: '%s' failed with exit code %d" % (build_command, exit_code))
return False
- # Bug: 21522719, 22023465
- # There are some reserved blocks on ext4 FS (lesser of 4096 blocks and 2%).
- # We need to deduct those blocks from the available space, since they are
- # not writable even with root privilege. It only affects devices using
- # file-based OTA and a kernel version of 3.10 or greater (currently just
- # sprout).
- # Separately, check if there's enough headroom space available. This is useful for
- # devices with low disk space that have system image variation between builds.
- if (has_reserved_blocks or "partition_headroom" in prop_dict) and fs_type.startswith("ext4"):
+ # Check if there's enough headroom space available for ext4 image.
+ if "partition_headroom" in prop_dict and fs_type.startswith("ext4"):
assert ext4fs_output is not None
- ext4fs_stats = re.compile(
- r'Created filesystem with .* (?P<used_blocks>[0-9]+)/'
- r'(?P<total_blocks>[0-9]+) blocks')
- m = ext4fs_stats.match(ext4fs_output.strip().split('\n')[-1])
- used_blocks = int(m.groupdict().get('used_blocks'))
- total_blocks = int(m.groupdict().get('total_blocks'))
- reserved_blocks = 0
- headroom_blocks = 0
- adjusted_blocks = total_blocks
- if has_reserved_blocks:
- reserved_blocks = min(4096, int(total_blocks * 0.02))
- adjusted_blocks -= reserved_blocks
- if "partition_headroom" in prop_dict:
- headroom_blocks = int(prop_dict.get('partition_headroom')) / BLOCK_SIZE
- adjusted_blocks -= headroom_blocks
- if used_blocks > adjusted_blocks:
- mount_point = prop_dict.get("mount_point")
- print("Error: Not enough room on %s (total: %d blocks, used: %d blocks, "
- "reserved: %d blocks, headroom: %d blocks, available: %d blocks)" % (
- mount_point, total_blocks, used_blocks, reserved_blocks,
- headroom_blocks, adjusted_blocks))
+ if not CheckHeadroom(ext4fs_output, prop_dict):
return False
if not fs_spans_partition:
@@ -698,7 +703,6 @@
copy_prop("system_root_image", "system_root_image")
copy_prop("ramdisk_dir", "ramdisk_dir")
copy_prop("ramdisk_fs_config", "ramdisk_fs_config")
- copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
copy_prop("system_squashfs_compressor", "squashfs_compressor")
copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
copy_prop("system_squashfs_block_size", "squashfs_block_size")
@@ -718,7 +722,6 @@
copy_prop("system_size", "partition_size")
copy_prop("system_journal_size", "journal_size")
copy_prop("system_verity_block_device", "verity_block_device")
- copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
copy_prop("system_squashfs_compressor", "squashfs_compressor")
copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
copy_prop("system_squashfs_block_size", "squashfs_block_size")
@@ -744,7 +747,6 @@
copy_prop("vendor_size", "partition_size")
copy_prop("vendor_journal_size", "journal_size")
copy_prop("vendor_verity_block_device", "verity_block_device")
- copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
copy_prop("vendor_squashfs_compressor", "squashfs_compressor")
copy_prop("vendor_squashfs_compressor_opt", "squashfs_compressor_opt")
copy_prop("vendor_squashfs_block_size", "squashfs_block_size")
@@ -755,7 +757,6 @@
copy_prop("fs_type", "fs_type")
copy_prop("oem_size", "partition_size")
copy_prop("oem_journal_size", "journal_size")
- copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
copy_prop("oem_extfs_inode_count", "extfs_inode_count")
d["partition_name"] = mount_point
return d
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 829b8db..12e757d 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1431,11 +1431,9 @@
self.disable_imgdiff = disable_imgdiff
if version is None:
- version = 1
- if OPTIONS.info_dict:
- version = max(
- int(i) for i in
- OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
+ version = max(
+ int(i) for i in
+ OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
assert version >= 3
self.version = version
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 60e2e5c..d5ac922 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -409,10 +409,10 @@
# in the target build.
script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict)
- recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options")
oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
oem_dicts = None
if oem_props:
+ recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options")
oem_dicts = _LoadOemDicts(script, recovery_mount_options)
target_fp = CalculateFingerprint(oem_props, oem_dicts and oem_dicts[0],
@@ -503,8 +503,6 @@
if HasVendorPartition(input_zip):
system_progress -= 0.1
- recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options")
-
script.ShowProgress(system_progress, 0)
# Full OTA is done as an "incremental" against an empty source image. This
@@ -632,12 +630,12 @@
source_version, OPTIONS.target_info_dict,
fstab=OPTIONS.source_info_dict["fstab"])
- recovery_mount_options = OPTIONS.source_info_dict.get(
- "recovery_mount_options")
source_oem_props = OPTIONS.source_info_dict.get("oem_fingerprint_properties")
target_oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties")
oem_dicts = None
- if source_oem_props and target_oem_props:
+ if source_oem_props or target_oem_props:
+ recovery_mount_options = OPTIONS.source_info_dict.get(
+ "recovery_mount_options")
oem_dicts = _LoadOemDicts(script, recovery_mount_options)
metadata = {
@@ -684,11 +682,10 @@
system_src = GetImage("system", OPTIONS.source_tmp)
system_tgt = GetImage("system", OPTIONS.target_tmp)
- blockimgdiff_version = 1
- if OPTIONS.info_dict:
- blockimgdiff_version = max(
- int(i) for i in
- OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
+ blockimgdiff_version = max(
+ int(i) for i in
+ OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
+ assert blockimgdiff_version >= 3
# Check the first block of the source system partition for remount R/W only
# if the filesystem is ext4.
@@ -786,32 +783,20 @@
device_specific.IncrementalOTA_VerifyBegin()
- # When blockimgdiff version is less than 3 (non-resumable block-based OTA),
- # patching on a device that's already on the target build will damage the
- # system. Because operations like move don't check the block state, they
- # always apply the changes unconditionally.
- if blockimgdiff_version <= 2:
- if source_oem_props is None:
- script.AssertSomeFingerprint(source_fp)
- else:
- script.AssertSomeThumbprint(
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
-
- else: # blockimgdiff_version > 2
- if source_oem_props is None and target_oem_props is None:
- script.AssertSomeFingerprint(source_fp, target_fp)
- elif source_oem_props is not None and target_oem_props is not None:
- script.AssertSomeThumbprint(
- GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict),
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
- elif source_oem_props is None and target_oem_props is not None:
- script.AssertFingerprintOrThumbprint(
- source_fp,
- GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict))
- else:
- script.AssertFingerprintOrThumbprint(
- target_fp,
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
+ if source_oem_props is None and target_oem_props is None:
+ script.AssertSomeFingerprint(source_fp, target_fp)
+ elif source_oem_props is not None and target_oem_props is not None:
+ script.AssertSomeThumbprint(
+ GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict),
+ GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
+ elif source_oem_props is None and target_oem_props is not None:
+ script.AssertFingerprintOrThumbprint(
+ source_fp,
+ GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict))
+ else:
+ script.AssertFingerprintOrThumbprint(
+ target_fp,
+ GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
# Check the required cache size (i.e. stashed blocks).
size = []
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index f559b29..7bfc04b 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -278,7 +278,7 @@
if stat.S_ISLNK(info.external_attr >> 16):
new_data = data
else:
- new_data = RewriteProps(data, misc_info)
+ new_data = RewriteProps(data)
common.ZipWriteStr(output_tf_zip, out_info, new_data)
elif info.filename.endswith("mac_permissions.xml"):
@@ -385,8 +385,14 @@
def EditTags(tags):
- """Given a string containing comma-separated tags, apply the edits
- specified in OPTIONS.tag_changes and return the updated string."""
+ """Applies the edits to the tag string as specified in OPTIONS.tag_changes.
+
+ Args:
+ tags: The input string that contains comma-separated tags.
+
+ Returns:
+ The updated tags (comma-separated and sorted).
+ """
tags = set(tags.split(","))
for ch in OPTIONS.tag_changes:
if ch[0] == "-":
@@ -396,20 +402,27 @@
return ",".join(sorted(tags))
-def RewriteProps(data, misc_info):
+def RewriteProps(data):
+ """Rewrites the system properties in the given string.
+
+ Each property is expected in 'key=value' format. The properties that contain
+ build tags (i.e. test-keys, dev-keys) will be updated accordingly by calling
+ EditTags().
+
+ Args:
+ data: Input string, separated by newlines.
+
+ Returns:
+ The string with modified properties.
+ """
output = []
for line in data.split("\n"):
line = line.strip()
original_line = line
if line and line[0] != '#' and "=" in line:
key, value = line.split("=", 1)
- if (key in ("ro.build.fingerprint", "ro.vendor.build.fingerprint")
- and misc_info.get("oem_fingerprint_properties") is None):
- pieces = value.split("/")
- pieces[-1] = EditTags(pieces[-1])
- value = "/".join(pieces)
- elif (key in ("ro.build.thumbprint", "ro.vendor.build.thumbprint")
- and misc_info.get("oem_fingerprint_properties") is not None):
+ if key in ("ro.build.fingerprint", "ro.build.thumbprint",
+ "ro.vendor.build.fingerprint", "ro.vendor.build.thumbprint"):
pieces = value.split("/")
pieces[-1] = EditTags(pieces[-1])
value = "/".join(pieces)
diff --git a/tools/releasetools/test_build_image.py b/tools/releasetools/test_build_image.py
new file mode 100644
index 0000000..6566a5a
--- /dev/null
+++ b/tools/releasetools/test_build_image.py
@@ -0,0 +1,65 @@
+#
+# 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.
+#
+
+import shutil
+import tempfile
+import unittest
+
+from build_image import CheckHeadroom, RunCommand
+
+
+class BuildImageTest(unittest.TestCase):
+
+ def test_CheckHeadroom_SizeUnderLimit(self):
+ ext4fs_output = ("Created filesystem with 2777/129024 inodes and "
+ "508140/516099 blocks")
+ prop_dict = {
+ 'partition_headroom' : '4194304',
+ 'mount_point' : 'system',
+ }
+ self.assertTrue(CheckHeadroom(ext4fs_output, prop_dict))
+
+ def test_CheckHeadroom_InsufficientHeadroom(self):
+ ext4fs_output = ("Created filesystem with 2777/129024 inodes and "
+ "515099/516099 blocks")
+ prop_dict = {
+ 'partition_headroom' : '4100096',
+ 'mount_point' : 'system',
+ }
+ self.assertFalse(CheckHeadroom(ext4fs_output, prop_dict))
+
+ def test_CheckHeadroom_WithMke2fsOutput(self):
+ """Tests the result parsing from actual call to mke2fs."""
+ input_dir = tempfile.mkdtemp()
+ output_image = tempfile.NamedTemporaryFile(suffix='.img')
+ command = ['mkuserimg_mke2fs.sh', input_dir, output_image.name, 'ext4',
+ '/system', '409600', '-j', '0']
+ ext4fs_output, exit_code = RunCommand(command)
+ self.assertEqual(0, exit_code)
+
+ prop_dict = {
+ 'partition_headroom' : '40960',
+ 'mount_point' : 'system',
+ }
+ self.assertTrue(CheckHeadroom(ext4fs_output, prop_dict))
+
+ prop_dict = {
+ 'partition_headroom' : '413696',
+ 'mount_point' : 'system',
+ }
+ self.assertFalse(CheckHeadroom(ext4fs_output, prop_dict))
+
+ shutil.rmtree(input_dir)
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
new file mode 100644
index 0000000..90afdc7
--- /dev/null
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -0,0 +1,67 @@
+#
+# 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.
+#
+
+from __future__ import print_function
+
+import unittest
+
+from sign_target_files_apks import EditTags, RewriteProps
+
+
+class SignTargetFilesApksTest(unittest.TestCase):
+
+ def test_EditTags(self):
+ self.assertEqual(EditTags('dev-keys'), ('release-keys'))
+ self.assertEqual(EditTags('test-keys'), ('release-keys'))
+
+ # Multiple tags.
+ self.assertEqual(EditTags('abc,dev-keys,xyz'), ('abc,release-keys,xyz'))
+
+ # Tags are sorted.
+ self.assertEqual(EditTags('xyz,abc,dev-keys,xyz'), ('abc,release-keys,xyz'))
+
+ def test_RewriteProps(self):
+ props = (
+ ('', '\n'),
+ ('ro.build.fingerprint=foo/bar/dev-keys',
+ 'ro.build.fingerprint=foo/bar/release-keys\n'),
+ ('ro.build.thumbprint=foo/bar/dev-keys',
+ 'ro.build.thumbprint=foo/bar/release-keys\n'),
+ ('ro.vendor.build.fingerprint=foo/bar/dev-keys',
+ 'ro.vendor.build.fingerprint=foo/bar/release-keys\n'),
+ ('ro.vendor.build.thumbprint=foo/bar/dev-keys',
+ 'ro.vendor.build.thumbprint=foo/bar/release-keys\n'),
+ ('# comment line 1', '# comment line 1\n'),
+ ('ro.bootimage.build.fingerprint=foo/bar/dev-keys',
+ 'ro.bootimage.build.fingerprint=foo/bar/release-keys\n'),
+ ('ro.build.description='
+ 'sailfish-user 8.0.0 OPR6.170623.012 4283428 dev-keys',
+ 'ro.build.description='
+ 'sailfish-user 8.0.0 OPR6.170623.012 4283428 release-keys\n'),
+ ('ro.build.tags=dev-keys', 'ro.build.tags=release-keys\n'),
+ ('# comment line 2', '# comment line 2\n'),
+ ('ro.build.display.id=OPR6.170623.012 dev-keys',
+ 'ro.build.display.id=OPR6.170623.012\n'),
+ ('# comment line 3', '# comment line 3\n'),
+ )
+
+ # Assert the case for each individual line.
+ for input, output in props:
+ self.assertEqual(RewriteProps(input), output)
+
+ # Concatenate all the input lines.
+ self.assertEqual(RewriteProps('\n'.join([prop[0] for prop in props])),
+ ''.join([prop[1] for prop in props]))