Merge changes from topic "vintf_matrix_sepolicy"
* changes:
core/config.mk: Add PLATFORM_SEPOLICY_COMPAT_VERSIONS
Move PLATFORM_SEPOLICY_VERSION from system/sepolicy/Android.mk
diff --git a/core/Makefile b/core/Makefile
index c9e64f8..d150ec3 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -406,6 +406,9 @@
$(hide) echo ro.vendor.build.date=`$(DATE_FROM_FILE)`>>$@
$(hide) echo ro.vendor.build.date.utc=`$(DATE_FROM_FILE) +%s`>>$@
$(hide) echo ro.vendor.build.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
+ $(hide) echo ro.vendor.product.cpu.abilist="$(TARGET_CPU_ABI_LIST)">>$@
+ $(hide) echo ro.vendor.product.cpu.abilist32="$(TARGET_CPU_ABI_LIST_32_BIT)">>$@
+ $(hide) echo ro.vendor.product.cpu.abilist64="$(TARGET_CPU_ABI_LIST_64_BIT)">>$@
$(hide) TARGET_DEVICE="$(TARGET_DEVICE)" \
PRODUCT_NAME="$(TARGET_PRODUCT)" \
PRODUCT_BRAND="$(PRODUCT_BRAND)" \
@@ -2374,18 +2377,18 @@
system/extras/verity/build_verity_metadata.py \
system/extras/ext4_utils/mke2fs.conf \
external/avb/test/data/testkey_rsa4096.pem \
- $(shell find system/update_engine/scripts -name \*.pyc -prune -o -type f -print | sort) \
- $(shell find build/target/product/security -type f -name \*.x509.pem -o -name \*.pk8 -o \
- -name verity_key | sort) \
- $(shell find device $(wildcard vendor) -type f -name \*.pk8 -o -name verifiedboot\* -o \
- -name \*.x509.pem -o -name oem\*.prop | sort)
+ $(sort $(shell find system/update_engine/scripts -name \*.pyc -prune -o -type f -print)) \
+ $(sort $(shell find build/target/product/security -type f -name \*.x509.pem -o -name \*.pk8 -o \
+ -name verity_key)) \
+ $(sort $(shell find device $(wildcard vendor) -type f -name \*.pk8 -o -name verifiedboot\* -o \
+ -name \*.x509.pem -o -name oem\*.prop))
OTATOOLS_RELEASETOOLS := \
- $(shell find build/make/tools/releasetools -name \*.pyc -prune -o -type f | sort)
+ $(sort $(shell find build/make/tools/releasetools -name \*.pyc -prune -o -type f))
ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT))
OTATOOLS_DEPS += \
- $(shell find external/vboot_reference/tests/devkeys -type f | sort)
+ $(sort $(shell find external/vboot_reference/tests/devkeys -type f))
endif
$(BUILT_OTATOOLS_PACKAGE): $(OTATOOLS) $(OTATOOLS_DEPS) $(OTATOOLS_RELEASETOOLS) | $(ACP)
diff --git a/core/aux_config.mk b/core/aux_config.mk
index bdae86a..6a5cd63 100644
--- a/core/aux_config.mk
+++ b/core/aux_config.mk
@@ -154,7 +154,7 @@
config_roots := $(wildcard device vendor)
all_configs :=
ifdef config_roots
-all_configs := $(shell find $(config_roots) -maxdepth 4 -name '*$(variant_sfx)' -o -name '*$(os_sfx)' | sort)
+all_configs := $(sort $(shell find $(config_roots) -maxdepth 4 -name '*$(variant_sfx)' -o -name '*$(os_sfx)'))
endif
all_os_configs := $(filter %$(os_sfx),$(all_configs))
all_variant_configs := $(filter %$(variant_sfx),$(all_configs))
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 3ff3bd3..bbcf202 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -654,6 +654,9 @@
ALL_MODULES.$(my_register_name).TARGET_REQUIRED := \
$(strip $(ALL_MODULES.$(my_register_name).TARGET_REQUIRED)\
$(LOCAL_TARGET_REQUIRED_MODULES))
+ALL_MODULES.$(my_register_name).HOST_REQUIRED := \
+ $(strip $(ALL_MODULES.$(my_register_name).HOST_REQUIRED)\
+ $(LOCAL_HOST_REQUIRED_MODULES))
ALL_MODULES.$(my_register_name).EVENT_LOG_TAGS := \
$(ALL_MODULES.$(my_register_name).EVENT_LOG_TAGS) $(event_log_tags)
ALL_MODULES.$(my_register_name).MAKEFILE := \
diff --git a/core/clang/versions.mk b/core/clang/versions.mk
index f3a206a..1e41f92 100644
--- a/core/clang/versions.mk
+++ b/core/clang/versions.mk
@@ -1,4 +1,4 @@
## Clang/LLVM release versions.
-LLVM_PREBUILTS_VERSION ?= clang-4393122
+LLVM_PREBUILTS_VERSION ?= clang-4579689
LLVM_PREBUILTS_BASE ?= prebuilts/clang/host
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 7d3fa75..c3694ab2 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -98,6 +98,7 @@
LOCAL_GTEST:=true
LOCAL_HAL_STATIC_LIBRARIES:=
LOCAL_HEADER_LIBRARIES:=
+LOCAL_HOST_REQUIRED_MODULES:=
LOCAL_INIT_RC:=
LOCAL_INSTALLED_MODULE:=
LOCAL_INSTALLED_MODULE_STEM:=
@@ -435,6 +436,13 @@
LOCAL_WHOLE_STATIC_LIBRARIES_32:=
LOCAL_WHOLE_STATIC_LIBRARIES_64:=
+# Robolectric variables
+LOCAL_INSTRUMENT_SOURCE_DIRS :=
+LOCAL_ROBOTEST_FAILURE_FATAL :=
+LOCAL_ROBOTEST_FILES :=
+LOCAL_ROBOTEST_TIMEOUT :=
+LOCAL_TEST_PACKAGE :=
+
# Aux specific variables
LOCAL_AUX_ARCH :=
LOCAL_AUX_CPU :=
diff --git a/core/config.mk b/core/config.mk
index a32e9f2..e9b5d4c 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -837,12 +837,6 @@
DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
endif
-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.)
-
BUILD_NUMBER_FROM_FILE := $$(cat $(OUT_DIR)/build_number.txt)
BUILD_DATETIME_FROM_FILE := $$(cat $(OUT_DIR)/build_date.txt)
@@ -959,8 +953,8 @@
$(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/android_system.jar)))) \
$(TARGET_AVAILABLE_SDK_VERSIONS)
-# We don't have prebuilt test_current SDK yet.
-TARGET_AVAILABLE_SDK_VERSIONS := test_current $(TARGET_AVAILABLE_SDK_VERSIONS)
+# We don't have prebuilt test_current and core_current SDK yet.
+TARGET_AVAILABLE_SDK_VERSIONS := test_current core_current $(TARGET_AVAILABLE_SDK_VERSIONS)
TARGET_SDK_VERSIONS_WITHOUT_JAVA_18_SUPPORT := $(call numbers_less_than,24,$(TARGET_AVAILABLE_SDK_VERSIONS))
TARGET_SDK_VERSIONS_WITHOUT_JAVA_19_SUPPORT := $(call numbers_less_than,27,$(TARGET_AVAILABLE_SDK_VERSIONS))
diff --git a/core/dpi_specific_apk.mk b/core/dpi_specific_apk.mk
index e29cde7..f32daf5 100644
--- a/core/dpi_specific_apk.mk
+++ b/core/dpi_specific_apk.mk
@@ -18,7 +18,7 @@
$(built_dpi_apk): PRIVATE_ASSET_DIR := $(LOCAL_ASSET_DIR)
$(built_dpi_apk): PRIVATE_AAPT_INCLUDES := $(all_library_res_package_exports)
$(built_dpi_apk): PRIVATE_RESOURCE_LIST := $(all_res_assets)
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
+ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
else
$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(DEFAULT_APP_TARGET_SDK)
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index 176a01d..25b591c 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -71,19 +71,16 @@
else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),test_current)
LOCAL_JAVA_LIBRARIES := android_test_stubs_current $(LOCAL_JAVA_LIBRARIES)
$(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, android_test_stubs_current)
+ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),core_current)
+ LOCAL_JAVA_LIBRARIES := core.current.stubs $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, core.current.stubs)
else
- ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
- ifeq (,$(TARGET_BUILD_APPS))
- LOCAL_JAVA_LIBRARIES := system_sdk_v$(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION)) $(LOCAL_JAVA_LIBRARIES)
- $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, system_sdk_v$(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION)))
- else
- LOCAL_JAVA_LIBRARIES := sdk_v$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES)
- $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, sdk_v$(LOCAL_SDK_VERSION))
- endif
- else
- LOCAL_JAVA_LIBRARIES := sdk_v$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES)
- $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, sdk_v$(LOCAL_SDK_VERSION))
- endif
+ # core_<ver> is subset of <ver>. Instead of defining a prebuilt lib for core_<ver>,
+ # use the stub for <ver> when building for apps.
+ _version := $(patsubst core_%,%,$(LOCAL_SDK_VERSION))
+ LOCAL_JAVA_LIBRARIES := sdk_v$(_version) $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, sdk_v$(_version))
+ _version :=
endif
else
LOCAL_JAVA_LIBRARIES := core-oj core-libart ext framework $(LOCAL_JAVA_LIBRARIES)
diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk
index 1ff9b91..7bae696 100644
--- a/core/host_dalvik_java_library.mk
+++ b/core/host_dalvik_java_library.mk
@@ -193,7 +193,7 @@
endif # !LOCAL_IS_STATIC_JAVA_LIBRARY
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
+ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
my_default_app_target_sdk := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
my_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
else
diff --git a/core/java.mk b/core/java.mk
index 6f5dce4..5945fae 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -125,7 +125,7 @@
else
ifneq (,$(LOCAL_SDK_VERSION))
# Set target-api for LOCAL_SDK_VERSIONs other than current.
- ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
+ ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
renderscript_target_api := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
endif
endif # LOCAL_SDK_VERSION is set
@@ -150,7 +150,7 @@
renderscript_flags += $(LOCAL_RENDERSCRIPT_FLAGS)
# prepend the RenderScript system include path
-ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current test_current,$(LOCAL_SDK_VERSION))),)
+ifneq ($(filter-out current system_current test_current core_current,$(LOCAL_SDK_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current test_current,$(LOCAL_SDK_VERSION))),)
# if a numeric LOCAL_SDK_VERSION, or current LOCAL_SDK_VERSION with TARGET_BUILD_APPS
LOCAL_RENDERSCRIPT_INCLUDES := \
$(HISTORICAL_SDK_VERSIONS_ROOT)/renderscript/clang-include \
@@ -266,7 +266,7 @@
aidl_preprocess_import :=
ifdef LOCAL_SDK_VERSION
-ifneq ($(filter current system_current test_current, $(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS)),)
+ifneq ($(filter current system_current test_current core_current, $(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS)),)
# LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS
aidl_preprocess_import := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl
else
@@ -610,7 +610,7 @@
my_proguard_sdk_raise :=
ifdef LOCAL_SDK_VERSION
ifdef TARGET_BUILD_APPS
-ifeq (,$(filter current system_current test_current, $(LOCAL_SDK_VERSION)))
+ifeq (,$(filter current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
my_proguard_sdk_raise := $(call java-lib-header-files, sdk_vcurrent)
endif
else
@@ -806,7 +806,7 @@
endif # full_classes_jar is defined
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
+ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
my_default_app_target_sdk := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
my_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
else
diff --git a/core/java_common.mk b/core/java_common.mk
index ac8b0d2..3a5c5c6 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -258,17 +258,15 @@
full_java_bootclasspath_libs := $(call java-lib-header-files,android_system_stubs_current)
else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),test_current)
full_java_bootclasspath_libs := $(call java-lib-header-files,android_test_stubs_current)
+ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),core_current)
+ full_java_bootclasspath_libs := $(call java-lib-header-files,core.current.stubs)
else
- ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
- ifeq (,$(TARGET_BUILD_APPS))
- full_java_bootclasspath_libs := $(call java-lib-header-files,system_sdk_v$(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION)))
- else
- full_java_bootclasspath_libs := $(call java-lib-header-files,sdk_v$(LOCAL_SDK_VERSION))
- endif
- else
- full_java_bootclasspath_libs := $(call java-lib-header-files,sdk_v$(LOCAL_SDK_VERSION))
- endif
- endif # current, system_current, system_${VER} or test_current
+ # core_<ver> is subset of <ver>. Instead of defining a prebuilt lib for core_<ver>,
+ # use the stub for <ver> when building for apps.
+ _version := $(patsubst core_%,%,$(LOCAL_SDK_VERSION))
+ full_java_bootclasspath_libs := $(call java-lib-header-files,sdk_v$(_version))
+ _version :=
+ endif # current, system_current, system_${VER}, test_current or core_current
endif # LOCAL_SDK_VERSION
ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
@@ -460,19 +458,23 @@
ifeq ($(LOCAL_SDK_VERSION),system_current)
my_link_type := java:system
my_warn_types := java:platform
-my_allowed_types := java:sdk java:system
+my_allowed_types := java:sdk java:system java:core
else ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
my_link_type := java:system
my_warn_types := java:platform
-my_allowed_types := java:sdk java:system
+my_allowed_types := java:sdk java:system java:core
+else ifeq ($(LOCAL_SDK_VERSION),core_current)
+my_link_type := java:core
+my_warn_types :=
+my_allowed_types := java:core
else ifneq ($(LOCAL_SDK_VERSION),)
my_link_type := java:sdk
my_warn_types := java:system java:platform
-my_allowed_types := java:sdk
+my_allowed_types := java:sdk java:core
else
my_link_type := java:platform
my_warn_types :=
-my_allowed_types := java:sdk java:system java:platform
+my_allowed_types := java:sdk java:system java:platform java:core
endif
ifdef LOCAL_AAPT2_ONLY
diff --git a/core/main.mk b/core/main.mk
index 38e9bd1..4d43295 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -610,6 +610,31 @@
endef
$(call add-all-host-to-target-required-modules-deps)
+# Sets up dependencies such that whenever a target module is installed,
+# any host modules listed in $(ALL_MODULES.$(m).HOST_REQUIRED) will also be installed
+define add-all-target-to-host-required-modules-deps
+$(foreach m,$(ALL_MODULES), \
+ $(eval req_mods := $(ALL_MODULES.$(m).HOST_REQUIRED))\
+ $(if $(req_mods), \
+ $(eval req_files := )\
+ $(foreach req_mod,$(req_mods), \
+ $(eval req_file := $(filter $(HOST_OUT)/%, $(call module-installed-files,$(req_mod)))) \
+ $(if $(strip $(req_file)),\
+ ,\
+ $(error $(m).LOCAL_HOST_REQUIRED_MODULES : illegal value $(req_mod) : not a host module. If you want to specify target modules to be required to be installed along with your target module, add those module names to LOCAL_REQUIRED_MODULES instead)\
+ )\
+ $(eval req_files := $(req_files)$(space)$(req_file))\
+ )\
+ $(eval req_files := $(strip $(req_files)))\
+ $(eval mod_files := $(filter $(TARGET_OUT_ROOT)/%, $(call module-installed-files,$(m))))\
+ $(eval mod_files := $(filter-out $(req_files),$(mod_files)))\
+ $(if $(mod_files),\
+ $(eval $(call add-required-deps, $(mod_files),$(req_files))) \
+ )\
+ )\
+)
+endef
+$(call add-all-target-to-host-required-modules-deps)
t_m :=
h_m :=
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 4890966..d7944bb 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -394,7 +394,7 @@
else
ifneq (,$(LOCAL_SDK_VERSION))
# Set target-api for LOCAL_SDK_VERSIONs other than current.
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
+ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
renderscript_target_api := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
endif
endif # LOCAL_SDK_VERSION is set
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index ea7fd03..cb1d401 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -546,6 +546,8 @@
my_link_type := java:system
else ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
my_link_type := java:system
+else ifeq ($(LOCAL_SDK_VERSION),core_current)
+my_link_type := java:core
else ifneq ($(LOCAL_SDK_VERSION),)
my_link_type := java:sdk
else
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index 65aabff..c553c4c 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -78,15 +78,15 @@
ifeq ($(LOCAL_SDK_VERSION),system_current)
my_link_type := java:system
my_warn_types := java:platform
-my_allowed_types := java:sdk java:system
+my_allowed_types := java:sdk java:system java:core
else ifneq ($(LOCAL_SDK_VERSION),)
my_link_type := java:sdk
my_warn_types := java:system java:platform
-my_allowed_types := java:sdk
+my_allowed_types := java:sdk java:core
else
my_link_type := java:platform
my_warn_types :=
-my_allowed_types := java:sdk java:system java:platform
+my_allowed_types := java:sdk java:system java:platform java:core
endif
my_link_deps :=
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index 5c2d768..f3ed376 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -90,19 +90,23 @@
ifeq ($(LOCAL_SDK_VERSION),system_current)
my_link_type := java:system
my_warn_types := java:platform
-my_allowed_types := java:sdk java:system
+my_allowed_types := java:sdk java:system java:core
else ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
my_link_type := java:system
my_warn_types := java:platform
-my_allowed_types := java:sdk java:system
+my_allowed_types := java:sdk java:system java:core
+else ifeq ($(LOCAL_SDK_VERSION),core_current)
+my_link_type := java:core
+my_warn_types :=
+my_allowed_types := java:core
else ifneq ($(LOCAL_SDK_VERSION),)
my_link_type := java:sdk
my_warn_types := java:system java:platform
-my_allowed_types := java:sdk
+my_allowed_types := java:sdk java:core
else
my_link_type := java:platform
my_warn_types :=
-my_allowed_types := java:sdk java:system java:platform
+my_allowed_types := java:sdk java:system java:platform java:core
endif
my_link_deps :=
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index aa1f0fa..c1478f1 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -156,7 +156,7 @@
else
ifneq (,$(LOCAL_SDK_VERSION))
# Set target-api for LOCAL_SDK_VERSIONs other than current.
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
+ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
renderscript_target_api := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
endif
endif # LOCAL_SDK_VERSION is set
diff --git a/target/board/Android.mk b/target/board/Android.mk
index 9b2620c..7fe45eb 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -52,65 +52,3 @@
include $(BUILD_PREBUILT)
BUILT_VENDOR_MANIFEST := $(LOCAL_BUILT_MODULE)
endif
-
-# VNDK Version in device compatibility matrix and framework manifest
-ifeq ($(BOARD_VNDK_VERSION),current)
-VINTF_VNDK_VERSION := $(PLATFORM_VNDK_VERSION)
-else
-VINTF_VNDK_VERSION := $(BOARD_VNDK_VERSION)
-endif
-
-# Device Compatibility Matrix
-ifdef DEVICE_MATRIX_FILE
-include $(CLEAR_VARS)
-LOCAL_MODULE := device_compatibility_matrix.xml
-LOCAL_MODULE_STEM := compatibility_matrix.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/vintf
-
-GEN := $(local-generated-sources-dir)/compatibility_matrix.xml
-
-$(GEN): PRIVATE_VINTF_VNDK_VERSION := $(VINTF_VNDK_VERSION)
-$(GEN): $(DEVICE_MATRIX_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
- REQUIRED_VNDK_VERSION=$(PRIVATE_VINTF_VNDK_VERSION) \
- BOARD_SYSTEMSDK_VERSIONS="$(BOARD_SYSTEMSDK_VERSIONS)" \
- $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $< -o $@
-
-LOCAL_PREBUILT_MODULE_FILE := $(GEN)
-include $(BUILD_PREBUILT)
-BUILT_VENDOR_MATRIX := $(LOCAL_BUILT_MODULE)
-endif
-
-# Framework Manifest
-include $(CLEAR_VARS)
-LOCAL_MODULE := framework_manifest.xml
-LOCAL_MODULE_STEM := manifest.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
-
-GEN := $(local-generated-sources-dir)/manifest.xml
-
-$(GEN): PRIVATE_FLAGS :=
-
-ifeq ($(PRODUCT_ENFORCE_VINTF_MANIFEST),true)
-ifdef BUILT_VENDOR_MATRIX
-$(GEN): $(BUILT_VENDOR_MATRIX)
-$(GEN): PRIVATE_FLAGS += -c "$(BUILT_VENDOR_MATRIX)"
-endif
-endif
-
-$(GEN): PRIVATE_VINTF_VNDK_VERSION := $(VINTF_VNDK_VERSION)
-$(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) \
- PROVIDED_VNDK_VERSIONS="$(PRIVATE_VINTF_VNDK_VERSION) $(PRODUCT_EXTRA_VNDK_VERSIONS)" \
- PLATFORM_SYSTEMSDK_VERSIONS="$(PLATFORM_SYSTEMSDK_VERSIONS)" \
- $(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)
-BUILT_SYSTEM_MANIFEST := $(LOCAL_BUILT_MODULE)
-
-VINTF_VNDK_VERSION :=
diff --git a/target/product/core.mk b/target/product/core.mk
index cab8d97..bbc2b75 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -56,6 +56,7 @@
StorageManager \
Telecom \
TeleService \
+ Traceur \
VpnDialogs \
vr \
MmsService
diff --git a/target/product/core_64_bit_only.mk b/target/product/core_64_bit_only.mk
new file mode 100644
index 0000000..72d30f5
--- /dev/null
+++ b/target/product/core_64_bit_only.mk
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2014 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.
+#
+
+# Inherit from this product for devices that support only 64-bit apps using:
+# $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)
+# The inheritance for this must come before the inheritance chain that leads
+# to core_minimal.mk.
+
+# Copy the 64-bit zygote startup script
+PRODUCT_COPY_FILES += system/core/rootdir/init.zygote64.rc:root/init.zygote64.rc
+
+# Set the zygote property to select the 64-bit script.
+# This line must be parsed before the one in core_minimal.mk
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote64
+
+TARGET_SUPPORTS_32_BIT_APPS := false
+TARGET_SUPPORTS_64_BIT_APPS := true
diff --git a/tools/releasetools/check_ota_package_signature.py b/tools/releasetools/check_ota_package_signature.py
index b5e9d8b..3cac90a 100755
--- a/tools/releasetools/check_ota_package_signature.py
+++ b/tools/releasetools/check_ota_package_signature.py
@@ -154,22 +154,18 @@
print('Verifying A/B OTA payload signatures...')
# Dump pubkey from the certificate.
- pubkey = common.MakeTempFile(prefix="key-", suffix=".key")
- cmd = ['openssl', 'x509', '-pubkey', '-noout', '-in', cert, '-out', pubkey]
- proc = common.Run(cmd, stdout=subprocess.PIPE)
- stdoutdata, _ = proc.communicate()
- assert proc.returncode == 0, \
- 'Failed to dump public key from certificate: %s\n%s' % (cert, stdoutdata)
+ pubkey = common.MakeTempFile(prefix="key-", suffix=".pem")
+ with open(pubkey, 'wb') as pubkey_fp:
+ pubkey_fp.write(common.ExtractPublicKey(cert))
- package_dir = tempfile.mkdtemp(prefix='package-')
- common.OPTIONS.tempfiles.append(package_dir)
+ package_dir = common.MakeTempDir(prefix='package-')
# Signature verification with delta_generator.
payload_file = package_zip.extract('payload.bin', package_dir)
cmd = ['delta_generator',
'--in_file=' + payload_file,
'--public_key=' + pubkey]
- proc = common.Run(cmd, stdout=subprocess.PIPE)
+ proc = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdoutdata, _ = proc.communicate()
assert proc.returncode == 0, \
'Failed to verify payload with delta_generator: %s\n%s' % (package,
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index d0ee6ae..16600ed 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -25,6 +25,7 @@
import re
import shlex
import shutil
+import string
import subprocess
import sys
import tempfile
@@ -34,6 +35,7 @@
from hashlib import sha1, sha256
import blockimgdiff
+import sparse_img
class Options(object):
def __init__(self):
@@ -124,6 +126,11 @@
return subprocess.Popen(args, **kwargs)
+def RoundUpTo4K(value):
+ rounded_up = value + 4095
+ return rounded_up - (rounded_up % 4096)
+
+
def CloseInheritedPipes():
""" Gmake in MAC OS has file descriptor (PIPE) leak. We close those fds
before doing other work."""
@@ -618,6 +625,56 @@
return tmp, zipfile.ZipFile(filename, "r")
+def GetSparseImage(which, tmpdir, input_zip):
+ """Returns a SparseImage object suitable for passing to BlockImageDiff.
+
+ This function loads the specified sparse image from the given path, and
+ performs additional processing for OTA purpose. For example, it always adds
+ block 0 to clobbered blocks list. It also detects files that cannot be
+ reconstructed from the block list, for whom we should avoid applying imgdiff.
+
+ Args:
+ which: The partition name, which must be "system" or "vendor".
+ tmpdir: The directory that contains the prebuilt image and block map file.
+ input_zip: The target-files ZIP archive.
+
+ Returns:
+ A SparseImage object, with file_map info loaded.
+ """
+ assert which in ("system", "vendor")
+
+ path = os.path.join(tmpdir, "IMAGES", which + ".img")
+ mappath = os.path.join(tmpdir, "IMAGES", which + ".map")
+
+ # The image and map files must have been created prior to calling
+ # ota_from_target_files.py (since LMP).
+ assert os.path.exists(path) and os.path.exists(mappath)
+
+ # In ext4 filesystems, block 0 might be changed even being mounted R/O. We add
+ # it to clobbered_blocks so that it will be written to the target
+ # unconditionally. Note that they are still part of care_map. (Bug: 20939131)
+ clobbered_blocks = "0"
+
+ image = sparse_img.SparseImage(path, mappath, clobbered_blocks)
+
+ # block.map may contain less blocks, because mke2fs may skip allocating blocks
+ # if they contain all zeros. We can't reconstruct such a file from its block
+ # list. Tag such entries accordingly. (Bug: 65213616)
+ for entry in image.file_map:
+ # "/system/framework/am.jar" => "SYSTEM/framework/am.jar".
+ arcname = string.replace(entry, which, which.upper(), 1)[1:]
+ # Skip artificial names, such as "__ZERO", "__NONZERO-1".
+ if arcname not in input_zip.namelist():
+ continue
+
+ info = input_zip.getinfo(arcname)
+ ranges = image.file_map[entry]
+ if RoundUpTo4K(info.file_size) > ranges.size() * 4096:
+ ranges.extra['incomplete'] = True
+
+ return image
+
+
def GetKeyPasswords(keylist):
"""Given a list of keys, prompt the user to enter passwords for
those which require them. Return a {key: password} dict. password
@@ -1747,6 +1804,31 @@
cert = "".join(cert).decode('base64')
return cert
+
+def ExtractPublicKey(cert):
+ """Extracts the public key (PEM-encoded) from the given certificate file.
+
+ Args:
+ cert: The certificate filename.
+
+ Returns:
+ The public key string.
+
+ Raises:
+ AssertionError: On non-zero return from 'openssl'.
+ """
+ # The behavior with '-out' is different between openssl 1.1 and openssl 1.0.
+ # While openssl 1.1 writes the key into the given filename followed by '-out',
+ # openssl 1.0 (both of 1.0.1 and 1.0.2) doesn't. So we collect the output from
+ # stdout instead.
+ cmd = ['openssl', 'x509', '-pubkey', '-noout', '-in', cert]
+ proc = Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ pubkey, stderrdata = proc.communicate()
+ assert proc.returncode == 0, \
+ 'Failed to dump public key from certificate: %s\n%s' % (cert, stderrdata)
+ return pubkey
+
+
def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img,
info_dict=None):
"""Generate a binary patch that creates the recovery image starting
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 95b7303..cd497b2 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -92,6 +92,24 @@
first, so that any changes made to the system partition are done
using the new recovery (new kernel, etc.).
+ --include_secondary
+ Additionally include the payload for secondary slot images (default:
+ False). Only meaningful when generating A/B OTAs.
+
+ By default, an A/B OTA package doesn't contain the images for the
+ secondary slot (e.g. system_other.img). Specifying this flag allows
+ generating a separate payload that will install secondary slot images.
+
+ Such a package needs to be applied in a two-stage manner, with a reboot
+ in-between. During the first stage, the updater applies the primary
+ payload only. Upon finishing, it reboots the device into the newly updated
+ slot. It then continues to install the secondary payload to the inactive
+ slot, but without switching the active slot at the end (needs the matching
+ support in update_engine, i.e. SWITCH_SLOT_ON_REBOOT flag).
+
+ Due to the special install procedure, the secondary payload will be always
+ generated as a full payload.
+
--block
Generate a block-based OTA for non-A/B device. We have deprecated the
support for file-based OTA since O. Block-based OTA will be used by
@@ -140,7 +158,6 @@
import common
import edify_generator
-import sparse_img
if sys.hexversion < 0x02070000:
print("Python 2.7 or newer is required.", file=sys.stderr)
@@ -160,6 +177,7 @@
if OPTIONS.worker_threads == 0:
OPTIONS.worker_threads = 1
OPTIONS.two_step = False
+OPTIONS.include_secondary = False
OPTIONS.no_signing = False
OPTIONS.block_based = True
OPTIONS.updater_binary = None
@@ -360,6 +378,133 @@
return out_file
+class Payload(object):
+ """Manages the creation and the signing of an A/B OTA Payload."""
+
+ PAYLOAD_BIN = 'payload.bin'
+ PAYLOAD_PROPERTIES_TXT = 'payload_properties.txt'
+ SECONDARY_PAYLOAD_BIN = 'secondary/payload.bin'
+ SECONDARY_PAYLOAD_PROPERTIES_TXT = 'secondary/payload_properties.txt'
+
+ def __init__(self):
+ # The place where the output from the subprocess should go.
+ self._log_file = sys.stdout if OPTIONS.verbose else subprocess.PIPE
+ self.payload_file = None
+ self.payload_properties = None
+
+ def Generate(self, target_file, source_file=None, additional_args=None):
+ """Generates a payload from the given target-files zip(s).
+
+ Args:
+ target_file: The filename of the target build target-files zip.
+ source_file: The filename of the source build target-files zip; or None if
+ generating a full OTA.
+ additional_args: A list of additional args that should be passed to
+ brillo_update_payload script; or None.
+ """
+ if additional_args is None:
+ additional_args = []
+
+ payload_file = common.MakeTempFile(prefix="payload-", suffix=".bin")
+ cmd = ["brillo_update_payload", "generate",
+ "--payload", payload_file,
+ "--target_image", target_file]
+ if source_file is not None:
+ cmd.extend(["--source_image", source_file])
+ cmd.extend(additional_args)
+ p = common.Run(cmd, stdout=self._log_file, stderr=subprocess.STDOUT)
+ stdoutdata, _ = p.communicate()
+ assert p.returncode == 0, \
+ "brillo_update_payload generate failed: {}".format(stdoutdata)
+
+ self.payload_file = payload_file
+ self.payload_properties = None
+
+ def Sign(self, payload_signer):
+ """Generates and signs the hashes of the payload and metadata.
+
+ Args:
+ payload_signer: A PayloadSigner() instance that serves the signing work.
+
+ Raises:
+ AssertionError: On any failure when calling brillo_update_payload script.
+ """
+ assert isinstance(payload_signer, PayloadSigner)
+
+ # 1. Generate hashes of the payload and metadata files.
+ payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
+ metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
+ cmd = ["brillo_update_payload", "hash",
+ "--unsigned_payload", self.payload_file,
+ "--signature_size", "256",
+ "--metadata_hash_file", metadata_sig_file,
+ "--payload_hash_file", payload_sig_file]
+ p1 = common.Run(cmd, stdout=self._log_file, stderr=subprocess.STDOUT)
+ p1.communicate()
+ assert p1.returncode == 0, "brillo_update_payload hash failed"
+
+ # 2. Sign the hashes.
+ signed_payload_sig_file = payload_signer.Sign(payload_sig_file)
+ signed_metadata_sig_file = payload_signer.Sign(metadata_sig_file)
+
+ # 3. Insert the signatures back into the payload file.
+ signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
+ suffix=".bin")
+ cmd = ["brillo_update_payload", "sign",
+ "--unsigned_payload", self.payload_file,
+ "--payload", signed_payload_file,
+ "--signature_size", "256",
+ "--metadata_signature_file", signed_metadata_sig_file,
+ "--payload_signature_file", signed_payload_sig_file]
+ p1 = common.Run(cmd, stdout=self._log_file, stderr=subprocess.STDOUT)
+ p1.communicate()
+ assert p1.returncode == 0, "brillo_update_payload sign failed"
+
+ # 4. Dump the signed payload properties.
+ properties_file = common.MakeTempFile(prefix="payload-properties-",
+ suffix=".txt")
+ cmd = ["brillo_update_payload", "properties",
+ "--payload", signed_payload_file,
+ "--properties_file", properties_file]
+ p1 = common.Run(cmd, stdout=self._log_file, stderr=subprocess.STDOUT)
+ p1.communicate()
+ assert p1.returncode == 0, "brillo_update_payload properties failed"
+
+ if OPTIONS.wipe_user_data:
+ with open(properties_file, "a") as f:
+ f.write("POWERWASH=1\n")
+
+ self.payload_file = signed_payload_file
+ self.payload_properties = properties_file
+
+ def WriteToZip(self, output_zip, secondary=False):
+ """Writes the payload to the given zip.
+
+ Args:
+ output_zip: The output ZipFile instance.
+ secondary: Whether the payload should be packed as secondary payload
+ (default: False).
+ """
+ assert self.payload_file is not None
+ assert self.payload_properties is not None
+
+ if secondary:
+ payload_arcname = Payload.SECONDARY_PAYLOAD_BIN
+ payload_properties_arcname = Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT
+ else:
+ payload_arcname = Payload.PAYLOAD_BIN
+ payload_properties_arcname = Payload.PAYLOAD_PROPERTIES_TXT
+
+ # Add the signed payload file and properties into the zip. In order to
+ # support streaming, we pack them as ZIP_STORED. So these entries can be
+ # read directly with the offset and length pairs.
+ common.ZipWrite(output_zip, self.payload_file, arcname=payload_arcname,
+ compress_type=zipfile.ZIP_STORED)
+ common.ZipWrite(output_zip, self.payload_properties,
+ arcname=payload_properties_arcname,
+ compress_type=zipfile.ZIP_STORED)
+
+
def SignOutput(temp_zip_name, output_zip_name):
pw = OPTIONS.key_passwords[OPTIONS.package_key]
@@ -452,31 +597,6 @@
source_info.GetBuildProp("ro.build.thumbprint"))
-def GetImage(which, tmpdir):
- """Returns an image object suitable for passing to BlockImageDiff.
-
- 'which' partition must be "system" or "vendor". A prebuilt image and file
- map must already exist in tmpdir.
- """
-
- assert which in ("system", "vendor")
-
- path = os.path.join(tmpdir, "IMAGES", which + ".img")
- mappath = os.path.join(tmpdir, "IMAGES", which + ".map")
-
- # The image and map files must have been created prior to calling
- # ota_from_target_files.py (since LMP).
- assert os.path.exists(path) and os.path.exists(mappath)
-
- # Bug: http://b/20939131
- # In ext4 filesystems, block 0 might be changed even being mounted
- # R/O. We add it to clobbered_blocks so that it will be written to the
- # target unconditionally. Note that they are still part of care_map.
- clobbered_blocks = "0"
-
- return sparse_img.SparseImage(path, mappath, clobbered_blocks)
-
-
def AddCompatibilityArchiveIfTrebleEnabled(target_zip, output_zip, target_info,
source_info=None):
"""Adds compatibility info into the output zip if it's Treble-enabled target.
@@ -662,7 +782,7 @@
# has the effect of writing new data from the package to the entire
# partition, but lets us reuse the updater code that writes incrementals to
# do it.
- system_tgt = GetImage("system", OPTIONS.input_tmp)
+ system_tgt = common.GetSparseImage("system", OPTIONS.input_tmp, input_zip)
system_tgt.ResetFileMap()
system_diff = common.BlockDifference("system", system_tgt, src=None)
system_diff.WriteScript(script, output_zip)
@@ -673,7 +793,7 @@
if HasVendorPartition(input_zip):
script.ShowProgress(0.1, 0)
- vendor_tgt = GetImage("vendor", OPTIONS.input_tmp)
+ vendor_tgt = common.GetSparseImage("vendor", OPTIONS.input_tmp, input_zip)
vendor_tgt.ResetFileMap()
vendor_diff = common.BlockDifference("vendor", vendor_tgt)
vendor_diff.WriteScript(script, output_zip)
@@ -778,6 +898,10 @@
'post-build' : target_info.fingerprint,
'post-build-incremental' : target_info.GetBuildProp(
'ro.build.version.incremental'),
+ 'post-sdk-level' : target_info.GetBuildProp(
+ 'ro.build.version.sdk'),
+ 'post-security-patch-level' : target_info.GetBuildProp(
+ 'ro.build.version.security_patch'),
}
if target_info.is_ab:
@@ -846,8 +970,8 @@
target_recovery = common.GetBootableImage(
"/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY")
- system_src = GetImage("system", OPTIONS.source_tmp)
- system_tgt = GetImage("system", OPTIONS.target_tmp)
+ system_src = common.GetSparseImage("system", OPTIONS.source_tmp, source_zip)
+ system_tgt = common.GetSparseImage("system", OPTIONS.target_tmp, target_zip)
blockimgdiff_version = max(
int(i) for i in target_info.get("blockimgdiff_versions", "1").split(","))
@@ -872,8 +996,8 @@
if HasVendorPartition(target_zip):
if not HasVendorPartition(source_zip):
raise RuntimeError("can't generate incremental that adds /vendor")
- vendor_src = GetImage("vendor", OPTIONS.source_tmp)
- vendor_tgt = GetImage("vendor", OPTIONS.target_tmp)
+ vendor_src = common.GetSparseImage("vendor", OPTIONS.source_tmp, source_zip)
+ vendor_tgt = common.GetSparseImage("vendor", OPTIONS.target_tmp, target_zip)
# Check first block of vendor partition for remount R/W only if
# disk type is ext4
@@ -919,7 +1043,7 @@
if OPTIONS.two_step:
if not source_info.get("multistage_support"):
assert False, "two-step packages not supported by this build"
- fs = OPTIONS.source_info_dict["fstab"]["/misc"]
+ fs = source_info["fstab"]["/misc"]
assert fs.fs_type.upper() == "EMMC", \
"two-step packages only supported on devices with EMMC /misc partitions"
bcb_dev = {"bcb_dev" : fs.device}
@@ -1049,7 +1173,6 @@
if OPTIONS.wipe_user_data:
script.Print("Erasing user data...")
script.FormatPartition("/data")
- metadata["ota-wipe"] = "yes"
if OPTIONS.two_step:
script.AppendExtra("""
@@ -1069,6 +1192,47 @@
WriteMetadata(metadata, output_zip)
+def GetTargetFilesZipForSecondaryImages(input_file):
+ """Returns a target-files.zip file for generating secondary payload.
+
+ Although the original target-files.zip already contains secondary slot
+ images (i.e. IMAGES/system_other.img), we need to rename the files to the
+ ones without _other suffix. Note that we cannot instead modify the names in
+ META/ab_partitions.txt, because there are no matching partitions on device.
+
+ For the partitions that don't have secondary images, the ones for primary
+ slot will be used. This is to ensure that we always have valid boot, vbmeta,
+ bootloader images in the inactive slot.
+
+ Args:
+ input_file: The input target-files.zip file.
+
+ Returns:
+ The filename of the target-files.zip for generating secondary payload.
+ """
+ target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
+ target_zip = zipfile.ZipFile(target_file, 'w', allowZip64=True)
+
+ input_tmp, input_zip = common.UnzipTemp(input_file, UNZIP_PATTERN)
+ for info in input_zip.infolist():
+ unzipped_file = os.path.join(input_tmp, *info.filename.split('/'))
+ if info.filename == 'IMAGES/system_other.img':
+ common.ZipWrite(target_zip, unzipped_file, arcname='IMAGES/system.img')
+
+ # Primary images and friends need to be skipped explicitly.
+ elif info.filename in ('IMAGES/system.img',
+ 'IMAGES/system.map'):
+ pass
+
+ elif info.filename.startswith(('META/', 'IMAGES/')):
+ common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+
+ common.ZipClose(input_zip)
+ common.ZipClose(target_zip)
+
+ return target_file
+
+
def WriteABOTAPackageWithBrilloScript(target_file, output_file,
source_file=None):
"""Generate an Android OTA package that has A/B update payload."""
@@ -1123,12 +1287,6 @@
value += ' ' * (expected_length - len(value))
return value
- # The place where the output from the subprocess should go.
- log_file = sys.stdout if OPTIONS.verbose else subprocess.PIPE
-
- # Get the PayloadSigner to be used in step 3.
- payload_signer = PayloadSigner()
-
# Stage the output zip package for package signing.
temp_zip_file = tempfile.NamedTemporaryFile()
output_zip = zipfile.ZipFile(temp_zip_file, "w",
@@ -1144,73 +1302,27 @@
# Metadata to comply with Android OTA package format.
metadata = GetPackageMetadata(target_info, source_info)
- # 1. Generate payload.
- payload_file = common.MakeTempFile(prefix="payload-", suffix=".bin")
- cmd = ["brillo_update_payload", "generate",
- "--payload", payload_file,
- "--target_image", target_file]
- if source_file is not None:
- cmd.extend(["--source_image", source_file])
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "brillo_update_payload generate failed"
+ # Generate payload.
+ payload = Payload()
+ payload.Generate(target_file, source_file)
- # 2. Generate hashes of the payload and metadata files.
- payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- cmd = ["brillo_update_payload", "hash",
- "--unsigned_payload", payload_file,
- "--signature_size", "256",
- "--metadata_hash_file", metadata_sig_file,
- "--payload_hash_file", payload_sig_file]
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "brillo_update_payload hash failed"
+ # Sign the payload.
+ payload_signer = PayloadSigner()
+ payload.Sign(payload_signer)
- # 3. Sign the hashes and insert them back into the payload file.
- # 3a. Sign the payload hash.
- signed_payload_sig_file = payload_signer.Sign(payload_sig_file)
+ # Write the payload into output zip.
+ payload.WriteToZip(output_zip)
- # 3b. Sign the metadata hash.
- signed_metadata_sig_file = payload_signer.Sign(metadata_sig_file)
-
- # 3c. Insert the signatures back into the payload file.
- signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
- suffix=".bin")
- cmd = ["brillo_update_payload", "sign",
- "--unsigned_payload", payload_file,
- "--payload", signed_payload_file,
- "--signature_size", "256",
- "--metadata_signature_file", signed_metadata_sig_file,
- "--payload_signature_file", signed_payload_sig_file]
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "brillo_update_payload sign failed"
-
- # 4. Dump the signed payload properties.
- properties_file = common.MakeTempFile(prefix="payload-properties-",
- suffix=".txt")
- cmd = ["brillo_update_payload", "properties",
- "--payload", signed_payload_file,
- "--properties_file", properties_file]
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "brillo_update_payload properties failed"
-
- if OPTIONS.wipe_user_data:
- with open(properties_file, "a") as f:
- f.write("POWERWASH=1\n")
- metadata["ota-wipe"] = "yes"
-
- # Add the signed payload file and properties into the zip. In order to
- # support streaming, we pack payload.bin, payload_properties.txt and
- # care_map.txt as ZIP_STORED. So these entries can be read directly with
- # the offset and length pairs.
- common.ZipWrite(output_zip, signed_payload_file, arcname="payload.bin",
- compress_type=zipfile.ZIP_STORED)
- common.ZipWrite(output_zip, properties_file,
- arcname="payload_properties.txt",
- compress_type=zipfile.ZIP_STORED)
+ # Generate and include the secondary payload that installs secondary images
+ # (e.g. system_other.img).
+ if OPTIONS.include_secondary:
+ # We always include a full payload for the secondary slot, even when
+ # building an incremental OTA. See the comments for "--include_secondary".
+ secondary_target_file = GetTargetFilesZipForSecondaryImages(target_file)
+ secondary_payload = Payload()
+ secondary_payload.Generate(secondary_target_file)
+ secondary_payload.Sign(payload_signer)
+ secondary_payload.WriteToZip(output_zip, secondary=True)
# If dm-verity is supported for the device, copy contents of care_map
# into A/B OTA package.
@@ -1221,6 +1333,8 @@
namelist = target_zip.namelist()
if care_map_path in namelist:
care_map_data = target_zip.read(care_map_path)
+ # In order to support streaming, care_map.txt needs to be packed as
+ # ZIP_STORED.
common.ZipWriteStr(output_zip, "care_map.txt", care_map_data,
compress_type=zipfile.ZIP_STORED)
else:
@@ -1308,6 +1422,8 @@
"integers are allowed." % (a, o))
elif o in ("-2", "--two_step"):
OPTIONS.two_step = True
+ elif o == "--include_secondary":
+ OPTIONS.include_secondary = True
elif o == "--no_signing":
OPTIONS.no_signing = True
elif o == "--verify":
@@ -1347,6 +1463,7 @@
"extra_script=",
"worker_threads=",
"two_step",
+ "include_secondary",
"no_signing",
"block",
"binary=",
diff --git a/tools/releasetools/rangelib.py b/tools/releasetools/rangelib.py
index 87380a5..8af61c3 100644
--- a/tools/releasetools/rangelib.py
+++ b/tools/releasetools/rangelib.py
@@ -25,6 +25,7 @@
def __init__(self, data=None):
self.monotonic = False
+ self._extra = {}
if isinstance(data, str):
self._parse_internal(data)
elif data:
@@ -56,6 +57,10 @@
def __repr__(self):
return '<RangeSet("' + self.to_string() + '")>'
+ @property
+ def extra(self):
+ return self._extra
+
@classmethod
def parse(cls, text):
"""Parse a text string consisting of a space-separated list of
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 7a1126c..1f9a3ca 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -538,10 +538,7 @@
" as payload verification key.\n\n")
print("Using %s for payload verification." % (mapped_keys[0],))
- cmd = common.Run(
- ["openssl", "x509", "-pubkey", "-noout", "-in", mapped_keys[0]],
- stdout=subprocess.PIPE)
- pubkey, _ = cmd.communicate()
+ pubkey = common.ExtractPublicKey(mapped_keys[0])
common.ZipWriteStr(
output_tf_zip,
"SYSTEM/etc/update_engine/update-payload-key.pub.pem",
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 8fb4600..6da286c 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -21,8 +21,10 @@
from hashlib import sha1
import common
+import test_utils
import validate_target_files
+
KiB = 1024
MiB = 1024 * KiB
GiB = 1024 * MiB
@@ -474,6 +476,18 @@
with zipfile.ZipFile(target_files, 'r') as input_zip:
self.assertRaises(ValueError, common.ReadApkCerts, input_zip)
+ def test_ExtractPublicKey(self):
+ testdata_dir = test_utils.get_testdata_dir()
+ cert = os.path.join(testdata_dir, 'testkey.x509.pem')
+ pubkey = os.path.join(testdata_dir, 'testkey.pubkey.pem')
+ with open(pubkey, 'rb') as pubkey_fp:
+ self.assertEqual(pubkey_fp.read(), common.ExtractPublicKey(cert))
+
+ def test_ExtractPublicKey_invalidInput(self):
+ testdata_dir = test_utils.get_testdata_dir()
+ wrong_input = os.path.join(testdata_dir, 'testkey.pk8')
+ self.assertRaises(AssertionError, common.ExtractPublicKey, wrong_input)
+
class InstallRecoveryScriptFormatTest(unittest.TestCase):
"""Checks the format of install-recovery.sh.
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index fa6655b..6edf80c 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -15,20 +15,44 @@
#
import copy
+import os
import os.path
import unittest
+import zipfile
import common
+import test_utils
from ota_from_target_files import (
- _LoadOemDicts, BuildInfo, GetPackageMetadata, PayloadSigner,
+ _LoadOemDicts, BuildInfo, GetPackageMetadata,
+ GetTargetFilesZipForSecondaryImages, Payload, PayloadSigner,
WriteFingerprintAssertion)
-def get_testdata_dir():
- """Returns the testdata dir, in relative to the script dir."""
- # The script dir is the one we want, which could be different from pwd.
- current_dir = os.path.dirname(os.path.realpath(__file__))
- return os.path.join(current_dir, 'testdata')
+def construct_target_files(secondary=False):
+ """Returns a target-files.zip file for generating OTA packages."""
+ target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
+ with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ # META/update_engine_config.txt
+ target_files_zip.writestr(
+ 'META/update_engine_config.txt',
+ "PAYLOAD_MAJOR_VERSION=2\nPAYLOAD_MINOR_VERSION=4\n")
+
+ # META/ab_partitions.txt
+ ab_partitions = ['boot', 'system', 'vendor']
+ target_files_zip.writestr(
+ 'META/ab_partitions.txt',
+ '\n'.join(ab_partitions))
+
+ # Create dummy images for each of them.
+ for partition in ab_partitions:
+ target_files_zip.writestr('IMAGES/' + partition + '.img',
+ os.urandom(len(partition)))
+
+ if secondary:
+ target_files_zip.writestr('IMAGES/system_other.img',
+ os.urandom(len("system_other")))
+
+ return target_files
class MockScriptWriter(object):
@@ -318,6 +342,8 @@
'ro.product.device' : 'product-device',
'ro.build.fingerprint' : 'build-fingerprint-target',
'ro.build.version.incremental' : 'build-version-incremental-target',
+ 'ro.build.version.sdk' : '27',
+ 'ro.build.version.security_patch' : '2017-12-01',
'ro.build.date.utc' : '1500000000',
},
}
@@ -327,6 +353,8 @@
'ro.product.device' : 'product-device',
'ro.build.fingerprint' : 'build-fingerprint-source',
'ro.build.version.incremental' : 'build-version-incremental-source',
+ 'ro.build.version.sdk' : '25',
+ 'ro.build.version.security_patch' : '2016-12-01',
'ro.build.date.utc' : '1400000000',
},
}
@@ -349,6 +377,8 @@
'ota-required-cache' : '0',
'post-build' : 'build-fingerprint-target',
'post-build-incremental' : 'build-version-incremental-target',
+ 'post-sdk-level' : '27',
+ 'post-security-patch-level' : '2017-12-01',
'post-timestamp' : '1500000000',
'pre-device' : 'product-device',
},
@@ -367,6 +397,8 @@
'ota-required-cache' : '0',
'post-build' : 'build-fingerprint-target',
'post-build-incremental' : 'build-version-incremental-target',
+ 'post-sdk-level' : '27',
+ 'post-security-patch-level' : '2017-12-01',
'post-timestamp' : '1500000000',
'pre-device' : 'product-device',
'pre-build' : 'build-fingerprint-source',
@@ -382,6 +414,8 @@
'ota-type' : 'BLOCK',
'post-build' : 'build-fingerprint-target',
'post-build-incremental' : 'build-version-incremental-target',
+ 'post-sdk-level' : '27',
+ 'post-security-patch-level' : '2017-12-01',
'post-timestamp' : '1500000000',
'pre-device' : 'product-device',
},
@@ -397,6 +431,8 @@
'ota-type' : 'BLOCK',
'post-build' : 'build-fingerprint-target',
'post-build-incremental' : 'build-version-incremental-target',
+ 'post-sdk-level' : '27',
+ 'post-security-patch-level' : '2017-12-01',
'post-timestamp' : '1500000000',
'pre-device' : 'product-device',
'pre-build' : 'build-fingerprint-source',
@@ -414,6 +450,8 @@
'ota-wipe' : 'yes',
'post-build' : 'build-fingerprint-target',
'post-build-incremental' : 'build-version-incremental-target',
+ 'post-sdk-level' : '27',
+ 'post-security-patch-level' : '2017-12-01',
'post-timestamp' : '1500000000',
'pre-device' : 'product-device',
},
@@ -457,6 +495,8 @@
'ota-wipe' : 'yes',
'post-build' : 'build-fingerprint-target',
'post-build-incremental' : 'build-version-incremental-target',
+ 'post-sdk-level' : '27',
+ 'post-security-patch-level' : '2017-12-01',
'pre-device' : 'product-device',
'pre-build' : 'build-fingerprint-source',
'pre-build-incremental' : 'build-version-incremental-source',
@@ -479,6 +519,8 @@
'ota-type' : 'BLOCK',
'post-build' : 'build-fingerprint-target',
'post-build-incremental' : 'build-version-incremental-target',
+ 'post-sdk-level' : '27',
+ 'post-security-patch-level' : '2017-12-01',
'post-timestamp' : '1500000001',
'pre-device' : 'product-device',
'pre-build' : 'build-fingerprint-source',
@@ -486,6 +528,21 @@
},
metadata)
+ def test_GetTargetFilesZipForSecondaryImages(self):
+ input_file = construct_target_files(secondary=True)
+ target_file = GetTargetFilesZipForSecondaryImages(input_file)
+
+ with zipfile.ZipFile(target_file) as verify_zip:
+ namelist = verify_zip.namelist()
+
+ self.assertIn('META/ab_partitions.txt', namelist)
+ self.assertIn('IMAGES/boot.img', namelist)
+ self.assertIn('IMAGES/system.img', namelist)
+ self.assertIn('IMAGES/vendor.img', namelist)
+
+ self.assertNotIn('IMAGES/system_other.img', namelist)
+ self.assertNotIn('IMAGES/system.map', namelist)
+
class PayloadSignerTest(unittest.TestCase):
@@ -493,7 +550,7 @@
SIGNED_SIGFILE = 'signed-sigfile.bin'
def setUp(self):
- self.testdata_dir = get_testdata_dir()
+ self.testdata_dir = test_utils.get_testdata_dir()
self.assertTrue(os.path.exists(self.testdata_dir))
common.OPTIONS.payload_signer = None
@@ -564,3 +621,159 @@
verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE)
self._assertFilesEqual(verify_file, signed_file)
+
+
+class PayloadTest(unittest.TestCase):
+
+ def setUp(self):
+ self.testdata_dir = test_utils.get_testdata_dir()
+ self.assertTrue(os.path.exists(self.testdata_dir))
+
+ common.OPTIONS.wipe_user_data = False
+ common.OPTIONS.payload_signer = None
+ common.OPTIONS.payload_signer_args = None
+ common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey')
+ common.OPTIONS.key_passwords = {
+ common.OPTIONS.package_key : None,
+ }
+
+ def tearDown(self):
+ common.Cleanup()
+
+ @staticmethod
+ def _create_payload_full(secondary=False):
+ target_file = construct_target_files(secondary)
+ payload = Payload()
+ payload.Generate(target_file)
+ return payload
+
+ @staticmethod
+ def _create_payload_incremental():
+ target_file = construct_target_files()
+ source_file = construct_target_files()
+ payload = Payload()
+ payload.Generate(target_file, source_file)
+ return payload
+
+ def test_Generate_full(self):
+ payload = self._create_payload_full()
+ self.assertTrue(os.path.exists(payload.payload_file))
+
+ def test_Generate_incremental(self):
+ payload = self._create_payload_incremental()
+ self.assertTrue(os.path.exists(payload.payload_file))
+
+ def test_Generate_additionalArgs(self):
+ target_file = construct_target_files()
+ source_file = construct_target_files()
+ payload = Payload()
+ # This should work the same as calling payload.Generate(target_file,
+ # source_file).
+ payload.Generate(
+ target_file, additional_args=["--source_image", source_file])
+ self.assertTrue(os.path.exists(payload.payload_file))
+
+ def test_Generate_invalidInput(self):
+ target_file = construct_target_files()
+ common.ZipDelete(target_file, 'IMAGES/vendor.img')
+ payload = Payload()
+ self.assertRaises(AssertionError, payload.Generate, target_file)
+
+ def test_Sign_full(self):
+ payload = self._create_payload_full()
+ payload.Sign(PayloadSigner())
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip)
+
+ import check_ota_package_signature
+ check_ota_package_signature.VerifyAbOtaPayload(
+ os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+ output_file)
+
+ def test_Sign_incremental(self):
+ payload = self._create_payload_incremental()
+ payload.Sign(PayloadSigner())
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip)
+
+ import check_ota_package_signature
+ check_ota_package_signature.VerifyAbOtaPayload(
+ os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+ output_file)
+
+ def test_Sign_withDataWipe(self):
+ common.OPTIONS.wipe_user_data = True
+ payload = self._create_payload_full()
+ payload.Sign(PayloadSigner())
+
+ with open(payload.payload_properties) as properties_fp:
+ self.assertIn("POWERWASH=1", properties_fp.read())
+
+ def test_Sign_badSigner(self):
+ """Tests that signing failure can be captured."""
+ payload = self._create_payload_full()
+ payload_signer = PayloadSigner()
+ payload_signer.signer_args.append('bad-option')
+ self.assertRaises(AssertionError, payload.Sign, payload_signer)
+
+ def test_WriteToZip(self):
+ payload = self._create_payload_full()
+ payload.Sign(PayloadSigner())
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip)
+
+ with zipfile.ZipFile(output_file) as verify_zip:
+ # First make sure we have the essential entries.
+ namelist = verify_zip.namelist()
+ self.assertIn(Payload.PAYLOAD_BIN, namelist)
+ self.assertIn(Payload.PAYLOAD_PROPERTIES_TXT, namelist)
+
+ # Then assert these entries are stored.
+ for entry_info in verify_zip.infolist():
+ if entry_info.filename not in (Payload.PAYLOAD_BIN,
+ Payload.PAYLOAD_PROPERTIES_TXT):
+ continue
+ self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
+
+ def test_WriteToZip_unsignedPayload(self):
+ """Unsigned payloads should not be allowed to be written to zip."""
+ payload = self._create_payload_full()
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ self.assertRaises(AssertionError, payload.WriteToZip, output_zip)
+
+ # Also test with incremental payload.
+ payload = self._create_payload_incremental()
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ self.assertRaises(AssertionError, payload.WriteToZip, output_zip)
+
+ def test_WriteToZip_secondary(self):
+ payload = self._create_payload_full(secondary=True)
+ payload.Sign(PayloadSigner())
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip, secondary=True)
+
+ with zipfile.ZipFile(output_file) as verify_zip:
+ # First make sure we have the essential entries.
+ namelist = verify_zip.namelist()
+ self.assertIn(Payload.SECONDARY_PAYLOAD_BIN, namelist)
+ self.assertIn(Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT, namelist)
+
+ # Then assert these entries are stored.
+ for entry_info in verify_zip.infolist():
+ if entry_info.filename not in (
+ Payload.SECONDARY_PAYLOAD_BIN,
+ Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT):
+ continue
+ self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
diff --git a/tools/releasetools/test_utils.py b/tools/releasetools/test_utils.py
new file mode 100644
index 0000000..ec53731
--- /dev/null
+++ b/tools/releasetools/test_utils.py
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2018 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.
+#
+
+"""
+Utils for running unittests.
+"""
+
+import os.path
+
+
+def get_testdata_dir():
+ """Returns the testdata dir, in relative to the script dir."""
+ # The script dir is the one we want, which could be different from pwd.
+ current_dir = os.path.dirname(os.path.realpath(__file__))
+ return os.path.join(current_dir, 'testdata')
diff --git a/tools/releasetools/testdata/testkey.pubkey.pem b/tools/releasetools/testdata/testkey.pubkey.pem
new file mode 100644
index 0000000..418ae60
--- /dev/null
+++ b/tools/releasetools/testdata/testkey.pubkey.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvjvyO2LwWgmQNyq7z+xK
+04eg0t3AL4y2NhpAAOzVnFyCArFcFjLTGQDDvkbZP6N12O6+dwJoPLntnm9A+VnP
+IFFRHg0HUWSbHM+Qk8Jgv2/2AVkAUj5J1r9t4X+2WI0eRzJP15Zjn68pQKGmcyci
+ry0gbvmYvXL2ZUmTm56DmEfCUCRIY2IGJ/CcMnFeItVU0LxKsV5Mlt5BO0Vv/CV4
+EaiOLwyCnoZuUhYto7dHlO/47v/H9zhkJC54OA1dkD38EPgO5GnfhGFSNXQRmJDT
+XrFgd6O+QO4yUNX8lYP10MzimUpItZa05t68NADqwYl3T7nWzvuC9r4IqZDyPf21
+TQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index b590392..1b3eb73 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -29,35 +29,17 @@
import sys
import common
-import sparse_img
-
-
-def _GetImage(which, tmpdir):
- assert which in ('system', 'vendor')
-
- path = os.path.join(tmpdir, 'IMAGES', which + '.img')
- mappath = os.path.join(tmpdir, 'IMAGES', which + '.map')
-
- # Map file must exist (allowed to be empty).
- assert os.path.exists(path) and os.path.exists(mappath)
-
- clobbered_blocks = '0'
- return sparse_img.SparseImage(path, mappath, clobbered_blocks)
def _ReadFile(file_name, unpacked_name, round_up=False):
"""Constructs and returns a File object. Rounds up its size if needed."""
- def RoundUpTo4K(value):
- rounded_up = value + 4095
- return rounded_up - (rounded_up % 4096)
-
assert os.path.exists(unpacked_name)
with open(unpacked_name, 'r') as f:
file_data = f.read()
file_size = len(file_data)
if round_up:
- file_size_rounded_up = RoundUpTo4K(file_size)
+ file_size_rounded_up = common.RoundUpTo4K(file_size)
file_data += '\0' * (file_size_rounded_up - file_size)
return common.File(file_name, file_data)
@@ -79,33 +61,28 @@
def CheckAllFiles(which):
logging.info('Checking %s image.', which)
- image = _GetImage(which, input_tmp)
+ image = common.GetSparseImage(which, input_tmp, input_zip)
prefix = '/' + which
for entry in image.file_map:
+ # Skip entries like '__NONZERO-0'.
if not entry.startswith(prefix):
continue
# Read the blocks that the file resides. Note that it will contain the
# bytes past the file length, which is expected to be padded with '\0's.
ranges = image.file_map[entry]
+
+ incomplete = ranges.extra.get('incomplete', False)
+ if incomplete:
+ logging.warning('Skipping %s that has incomplete block list', entry)
+ continue
+
blocks_sha1 = image.RangeSha1(ranges)
# The filename under unpacked directory, such as SYSTEM/bin/sh.
unpacked_name = os.path.join(
input_tmp, which.upper(), entry[(len(prefix) + 1):])
unpacked_file = _ReadFile(entry, unpacked_name, True)
- file_size = unpacked_file.size
-
- # block.map may contain less blocks, because mke2fs may skip allocating
- # blocks if they contain all zeros. We can't reconstruct such a file from
- # its block list. (Bug: 65213616)
- if file_size > ranges.size() * 4096:
- logging.warning(
- 'Skipping %s that has less blocks: file size %d-byte,'
- ' ranges %s (%d-byte)', entry, file_size, ranges,
- ranges.size() * 4096)
- continue
-
file_sha1 = unpacked_file.sha1
assert blocks_sha1 == file_sha1, \
'file: %s, range: %s, blocks_sha1: %s, file_sha1: %s' % (