diff options
85 files changed, 2819 insertions, 736 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk index e83f2e7..46e652b 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -200,6 +200,12 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DMService.apk) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/SprintDM.apk) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/omadm) +# GCC 4.8 +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/*.o) + # KLP I mean KitKat now API 19. $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) @@ -223,8 +229,22 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*) +# L development +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*) + +# L development +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*) + # Add ro.product.cpu.abilist{32,64} to build.prop. $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) + +# Unset TARGET_PREFER_32_BIT_APPS for 64 bit targets. +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) # Adding dalvik.vm.dex2oat-flags to eng builds $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) diff --git a/core/Makefile b/core/Makefile index 55391dd..83a9684 100644 --- a/core/Makefile +++ b/core/Makefile @@ -22,7 +22,7 @@ endif # src:dest pair is the first one to match the same dest" #$(1): the src:dest pair define check-product-copy-files -$(if $(filter %.apk, $(1)),$(error \ +$(if $(filter %.apk, $(call word-colon, 2, $(1))),$(error \ Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!)) endef # filter out the duplicate <source file>:<dest file> pairs. @@ -109,7 +109,7 @@ BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS))) build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER) $(BUILD_VERSION_TAGS) $(INSTALLED_BUILD_PROP_TARGET): PRIVATE_BUILD_DESC := $(build_desc) -# The string used to uniquely identify this build; used by the OTA server. +# The string used to uniquely identify the combined build and product; used by the OTA server. ifeq (,$(strip $(BUILD_FINGERPRINT))) BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS) endif @@ -117,6 +117,15 @@ ifneq ($(words $(BUILD_FINGERPRINT)),1) $(error BUILD_FINGERPRINT cannot contain spaces: "$(BUILD_FINGERPRINT)") endif +# The string used to uniquely identify the system build; used by the OTA server. +# This purposefully excludes any product-specific variables. +ifeq (,$(strip $(BUILD_THUMBPRINT))) + BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS) +endif +ifneq ($(words $(BUILD_THUMBPRINT)),1) + $(error BUILD_THUMBPRINT cannot contain spaces: "$(BUILD_THUMBPRINT)") +endif + # Display parameters shown under Settings -> About Phone ifeq ($(TARGET_BUILD_VARIANT),user) # User builds should show: @@ -165,10 +174,17 @@ system_prop_file := $(TARGET_SYSTEM_PROP) else system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop) endif - $(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) @echo Target buildinfo: $@ @mkdir -p $(dir $@) + $(hide) echo > $@ +ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES),) + $(hide) echo "#" >> $@; \ + echo "# PRODUCT_OEM_PROPERTIES" >> $@; \ + echo "#" >> $@; + $(hide) $(foreach prop,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES), \ + echo "import /oem/oem.prop $(prop)" >> $@;) +endif $(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \ TARGET_DEVICE="$(TARGET_DEVICE)" \ PRODUCT_NAME="$(TARGET_PRODUCT)" \ @@ -185,9 +201,11 @@ $(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $( PLATFORM_VERSION="$(PLATFORM_VERSION)" \ PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \ PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \ + PLATFORM_VERSION_ALL_CODENAMES="$(PLATFORM_VERSION_ALL_CODENAMES)" \ BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \ TARGET_BOOTLOADER_BOARD_NAME="$(TARGET_BOOTLOADER_BOARD_NAME)" \ BUILD_FINGERPRINT="$(BUILD_FINGERPRINT)" \ + BUILD_THUMBPRINT="$(BUILD_THUMBPRINT)" \ TARGET_BOARD_PLATFORM="$(TARGET_BOARD_PLATFORM)" \ TARGET_CPU_ABI_LIST="$(TARGET_CPU_ABI_LIST)" \ TARGET_CPU_ABI_LIST_32_BIT="$(TARGET_CPU_ABI_LIST_32_BIT)" \ @@ -195,7 +213,7 @@ $(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $( TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \ TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \ TARGET_AAPT_CHARACTERISTICS="$(TARGET_AAPT_CHARACTERISTICS)" \ - bash $(BUILDINFO_SH) > $@ + bash $(BUILDINFO_SH) >> $@ $(hide) $(foreach file,$(system_prop_file), \ if [ -f "$(file)" ]; then \ echo "#" >> $@; \ @@ -211,7 +229,7 @@ $(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $( echo "#" >> $@; ) $(hide) $(foreach line,$(ADDITIONAL_BUILD_PROPERTIES), \ echo "$(line)" >> $@;) - $(hide) build/tools/post_process_props.py $@ + $(hide) build/tools/post_process_props.py $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_PROPERTY_BLACKLIST) build_desc := @@ -622,6 +640,10 @@ INTERNAL_USERIMAGES_DEPS := $(MKYAFFS2) endif INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS))) +ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)) +INTERNAL_USERIMAGES_DEPS += $(BUILD_VERITY_TREE) $(APPEND2SIMG) $(VERITY_SIGNER) +endif + SELINUX_FC := $(TARGET_ROOT_OUT)/file_contexts INTERNAL_USERIMAGES_DEPS += $(SELINUX_FC) @@ -635,9 +657,15 @@ $(if $(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "cache_fs_type=$(BOARD_CA $(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),$(hide) echo "cache_size=$(BOARD_CACHEIMAGE_PARTITION_SIZE)" >> $(1)) $(if $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_fs_type=$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) $(if $(BOARD_VENDORIMAGE_PARTITION_SIZE),$(hide) echo "vendor_size=$(BOARD_VENDORIMAGE_PARTITION_SIZE)" >> $(1)) +$(if $(BOARD_OEMIMAGE_PARTITION_SIZE),$(hide) echo "oem_size=$(BOARD_OEMIMAGE_PARTITION_SIZE)" >> $(1)) $(if $(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG),$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(1)) $(if $(mkyaffs2_extra_flags),$(hide) echo "mkyaffs2_extra_flags=$(mkyaffs2_extra_flags)" >> $(1)) $(hide) echo "selinux_fc=$(SELINUX_FC)" >> $(1) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY), $(hide) echo "verity=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)" >> $(1)) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_PARTITION)" >> $(1)) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)" >> $(1)) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(VERITY_SIGNER)" >> $(1)) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_mountpoint=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_MOUNTPOINT)" >> $(1)) $(if $(2),$(hide) $(foreach kv,$(2),echo "$(kv)" >> $(1);)) endef @@ -656,6 +684,23 @@ recovery_build_prop := $(INSTALLED_BUILD_PROP_TARGET) recovery_binary := $(call intermediates-dir-for,EXECUTABLES,recovery)/recovery recovery_resources_common := $(call include-path-for, recovery)/res +ifneq (,$(filter xxxhdpi,$(PRODUCT_AAPT_CONFIG_SP))) +recovery_resources_common := $(recovery_resources_common)-xxxhdpi +else ifneq (,$(filter xxhdpi,$(PRODUCT_AAPT_CONFIG_SP))) +recovery_resources_common := $(recovery_resources_common)-xxhdpi +else ifneq (,$(filter xhdpi,$(PRODUCT_AAPT_CONFIG_SP))) +recovery_resources_common := $(recovery_resources_common)-xhdpi +else ifneq (,$(filter hdpi,$(PRODUCT_AAPT_CONFIG_SP))) +recovery_resources_common := $(recovery_resources_common)-hdpi +else ifneq (,$(filter mdpi,$(PRODUCT_AAPT_CONFIG_SP))) +recovery_resources_common := $(recovery_resources_common)-mdpi +else +# xhdpi is closest in size to the single set of resources we had +# before, so make that the default if PRODUCT_AAPT_CONFIG doesn't +# specify a dpi we have. +recovery_resources_common := $(recovery_resources_common)-xhdpi +endif + # Select the 18x32 font on high-density devices; and the 12x22 font on # other devices. Note that the font selected here can be overridden # for a particular device by putting a font.png in its private @@ -740,7 +785,9 @@ $(INSTALLED_RECOVERYIMAGE_TARGET): $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) \ $(hide) cp -f $(recovery_initrc) $(TARGET_RECOVERY_ROOT_OUT)/ $(hide) -cp $(TARGET_ROOT_OUT)/init.recovery.*.rc $(TARGET_RECOVERY_ROOT_OUT)/ $(hide) cp -f $(recovery_binary) $(TARGET_RECOVERY_ROOT_OUT)/sbin/ - $(hide) cp -rf $(recovery_resources_common) $(TARGET_RECOVERY_ROOT_OUT)/ + $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/res + $(hide) rm -rf $(TARGET_RECOVERY_ROOT_OUT)/res/* + $(hide) cp -rf $(recovery_resources_common)/* $(TARGET_RECOVERY_ROOT_OUT)/res $(hide) cp -f $(recovery_font) $(TARGET_RECOVERY_ROOT_OUT)/res/images/font.png $(hide) $(foreach item,$(recovery_resources_private), \ cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/) @@ -822,7 +869,8 @@ BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img define build-systemimage-target @echo "Target system fs image: $(1)" @mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt - $(call generate-userimage-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt, skip_fsck=true) + $(call generate-userimage-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt, \ + skip_fsck=true) $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ ./build/tools/releasetools/build_image.py \ $(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) @@ -1111,7 +1159,9 @@ DISTTOOLS := $(HOST_OUT_EXECUTABLES)/minigzip \ $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \ $(HOST_OUT_EXECUTABLES)/make_ext4fs \ $(HOST_OUT_EXECUTABLES)/simg2img \ - $(HOST_OUT_EXECUTABLES)/e2fsck + $(HOST_OUT_EXECUTABLES)/e2fsck \ + $(HOST_OUT_EXECUTABLES)/xdelta3 \ + $(HOST_OUT_EXECUTABLES)/syspatch_host OTATOOLS := $(DISTTOOLS) \ $(HOST_OUT_EXECUTABLES)/aapt @@ -1267,7 +1317,12 @@ endif $(hide) echo "use_set_metadata=1" >> $(zip_root)/META/misc_info.txt $(hide) echo "multistage_support=1" >> $(zip_root)/META/misc_info.txt $(hide) echo "update_rename_support=1" >> $(zip_root)/META/misc_info.txt +ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES),) + # OTA scripts are only interested in fingerprint related properties + $(hide) echo "oem_fingerprint_properties=$(filter ro.product.brand ro.product.name ro.product.device, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES))" >> $(zip_root)/META/misc_info.txt +endif $(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt) + $(hide) ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root) @# Zip everything up, preserving symlinks $(hide) (cd $(zip_root) && zip -qry ../$(notdir $@) .) @# Run fs_config on all the system, boot ramdisk, and recovery ramdisk files in the zip, and save the output @@ -1305,8 +1360,10 @@ $(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(DISTTOOLS) @echo "Package OTA: $@" $(hide) MKBOOTIMG=$(BOARD_CUSTOM_MKBOOTIMG) \ ./build/tools/releasetools/ota_from_target_files -v \ + --block \ -p $(HOST_OUT) \ -k $(KEY_CERT_PAIR) \ + $(if $(OEM_OTA_CONFIG), -o $(OEM_OTA_CONFIG)) \ $(BUILT_TARGET_FILES_PACKAGE) $@ .PHONY: otapackage @@ -1323,18 +1380,10 @@ name := $(name)-img-$(FILE_NAME_TAG) INTERNAL_UPDATE_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip -ifeq ($(TARGET_RELEASETOOLS_EXTENSIONS),) -# default to common dir for device vendor -$(INTERNAL_UPDATE_PACKAGE_TARGET): extensions := $(TARGET_DEVICE_DIR)/../common -else -$(INTERNAL_UPDATE_PACKAGE_TARGET): extensions := $(TARGET_RELEASETOOLS_EXTENSIONS) -endif - $(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(DISTTOOLS) @echo "Package: $@" $(hide) MKBOOTIMG=$(BOARD_CUSTOM_MKBOOTIMG) \ ./build/tools/releasetools/img_from_target_files -v \ - -s $(extensions) \ -p $(HOST_OUT) \ $(BUILT_TARGET_FILES_PACKAGE) $@ @@ -1390,7 +1439,7 @@ EMMA_META_ZIP := $(PRODUCT_OUT)/emma_meta.zip # the dependency will be set up later in build/core/main.mk. $(EMMA_META_ZIP) : @echo "Collecting Emma coverage meta files." - $(hide) find $(TARGET_COMMON_OUT_ROOT) -name "coverage.em" | \ + $(hide) find $(TARGET_COMMON_OUT_ROOT) $(HOST_COMMON_OUT_ROOT) -name "coverage.em" | \ zip -@ -q $@ endif # EMMA_INSTRUMENT=true @@ -1406,7 +1455,8 @@ $(PROGUARD_DICT_ZIP) : @echo "Packaging Proguard obfuscation dictionary files." $(hide) dict_files=`find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary`; \ if [ -n "$$dict_files" ]; then \ - zip -q $@ $$dict_files; \ + unobfuscated_jars=$${dict_files//proguard_dictionary/classes.jar}; \ + zip -q $@ $$dict_files $$unobfuscated_jars; \ else \ touch $(dir $@)/dummy; \ (cd $(dir $@) && zip -q $(notdir $@) dummy); \ diff --git a/core/base_rules.mk b/core/base_rules.mk index c68fba7..0a67d42 100644 --- a/core/base_rules.mk +++ b/core/base_rules.mk @@ -120,6 +120,8 @@ ifeq ($(my_module_path),) else ifeq (true,$(LOCAL_PROPRIETARY_MODULE)) partition_tag := _VENDOR + else ifeq (true,$(LOCAL_OEM_MODULE)) + partition_tag := _OEM else # The definition of should-install-to-system will be different depending # on which goal (e.g., sdk or just droid) is being built. @@ -429,10 +431,10 @@ full_java_lib_deps += $(full_static_java_libs) $(LOCAL_CLASSPATH) # This is set by packages that are linking to other packages that export # shared libraries, allowing them to make use of the code in the linked apk. -LOCAL_APK_LIBRARIES := $(strip $(LOCAL_APK_LIBRARIES)) -ifdef LOCAL_APK_LIBRARIES +apk_libraries := $(sort $(LOCAL_APK_LIBRARIES) $(LOCAL_RES_LIBRARIES)) +ifneq ($(apk_libraries),) link_apk_libraries := \ - $(foreach lib,$(LOCAL_APK_LIBRARIES), \ + $(foreach lib,$(apk_libraries), \ $(call intermediates-dir-for, \ APPS,$(lib),,COMMON)/classes.jar) diff --git a/core/binary.mk b/core/binary.mk index 9dab23f..d5709ca 100644 --- a/core/binary.mk +++ b/core/binary.mk @@ -141,6 +141,8 @@ endif ifeq ($(strip $(LOCAL_ADDRESS_SANITIZER)),true) LOCAL_CLANG := true + # Frame pointer based unwinder in ASan requires ARM frame setup. + LOCAL_ARM_MODE := arm my_cflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS) my_ldflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS) my_shared_libraries += $(ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES) @@ -450,6 +452,9 @@ proto_generated_obj_dir := $(intermediates)/proto proto_generated_objects := $(addprefix $(proto_generated_obj_dir)/, \ $(patsubst %.proto,%.pb.o,$(proto_sources_fullpath))) +# Auto-export the generated proto source dir. +LOCAL_EXPORT_C_INCLUDE_DIRS += $(proto_generated_cc_sources_dir) + # Ensure the transform-proto-to-cc rule is only defined once in multilib build. ifndef $(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined $(proto_generated_cc_sources): PRIVATE_PROTO_INCLUDES := $(TOP) @@ -459,6 +464,8 @@ $(proto_generated_cc_sources): $(proto_generated_cc_sources_dir)/%.pb.cc: %.prot $(transform-proto-to-cc) $(proto_generated_headers): $(proto_generated_cc_sources_dir)/%.pb.h: $(proto_generated_cc_sources_dir)/%.pb.cc + # This is just a dummy rule to make sure gmake doesn't skip updating the dependents. + @echo "Updated header file $<." $(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined := true endif # transform-proto-to-cc rule included only once @@ -914,7 +921,8 @@ $(LOCAL_INSTALLED_MODULE): | $(installed_static_library_notice_file_targets) ########################################################### export_includes := $(intermediates)/export_includes $(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDE_DIRS) -$(export_includes) : $(LOCAL_MODULE_MAKEFILE) +# Make sure .pb.h are already generated before any dependent source files get compiled. +$(export_includes) : $(LOCAL_MODULE_MAKEFILE) $(proto_generated_headers) @echo Export includes file: $< -- $@ $(hide) mkdir -p $(dir $@) && rm -f $@ ifdef LOCAL_EXPORT_C_INCLUDE_DIRS diff --git a/core/build_id.mk b/core/build_id.mk index aaf4185..221a2f3 100644 --- a/core/build_id.mk +++ b/core/build_id.mk @@ -18,6 +18,6 @@ # (like "CRB01"). It must be a single word, and is # capitalized by convention. -BUILD_ID := OPENMASTER +BUILD_ID := MASTER DISPLAY_BUILD_NUMBER := true diff --git a/core/clang/config.mk b/core/clang/config.mk index b8f76f2..7498ee3 100644 --- a/core/clang/config.mk +++ b/core/clang/config.mk @@ -68,9 +68,10 @@ CLANG_CONFIG_EXTRA_HOST_C_INCLUDES := $(LLVM_PREBUILTS_HEADER_PATH) CLANG_CONFIG_EXTRA_TARGET_C_INCLUDES := $(LLVM_PREBUILTS_HEADER_PATH) $(TARGET_OUT_HEADERS)/clang # Address sanitizer clang config -ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS := -fsanitize=address +ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan_$(TARGET_ARCH)_android +ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS := -fsanitize=address -fno-omit-frame-pointer ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS := -Wl,-u,__asan_preinit -ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES := libdl libasan_preload +ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES := libdl $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES := libasan # This allows us to use the superset of functionality that compiler-rt diff --git a/core/clear_vars.mk b/core/clear_vars.mk index bf8ab08..1902d57 100644 --- a/core/clear_vars.mk +++ b/core/clear_vars.mk @@ -88,9 +88,11 @@ LOCAL_COMPRESS_MODULE_SYMBOLS:= LOCAL_STRIP_MODULE:= LOCAL_JNI_SHARED_LIBRARIES:= LOCAL_JNI_SHARED_LIBRARIES_ABI:= +LOCAL_PREBUILT_JNI_LIBS:= LOCAL_JAR_MANIFEST:= LOCAL_INSTRUMENTATION_FOR:= LOCAL_APK_LIBRARIES:= +LOCAL_RES_LIBRARIES:= LOCAL_MANIFEST_INSTRUMENTATION_FOR:= LOCAL_AIDL_INCLUDES:= LOCAL_JARJAR_RULES:= @@ -126,6 +128,7 @@ LOCAL_PROTOC_FLAGS:= LOCAL_PROTO_JAVA_OUTPUT_PARAMS:= LOCAL_NO_CRT:= LOCAL_PROPRIETARY_MODULE:= +LOCAL_OEM_MODULE:= LOCAL_PRIVILEGED_MODULE:= LOCAL_MODULE_OWNER:= LOCAL_CTS_TEST_PACKAGE:= @@ -143,6 +146,7 @@ LOCAL_PREBUILT_MODULE_FILE:= LOCAL_POST_INSTALL_CMD:= LOCAL_DIST_BUNDLED_BINARIES:= LOCAL_HAL_STATIC_LIBRARIES:= +LOCAL_RMTYPEDEFS:= LOCAL_NO_SYNTAX_CHECK:= LOCAL_NO_STATIC_ANALYZER:= LOCAL_32_BIT_ONLY:= # '',true diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk index 81d0813..2a78a50 100644 --- a/core/combo/TARGET_linux-arm.mk +++ b/core/combo/TARGET_linux-arm.mk @@ -112,7 +112,7 @@ $(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += \ # into no-op in some builds while mesg is defined earlier. So we explicitly # disable "-Wunused-but-set-variable" here. ifneq ($(filter 4.6 4.6.% 4.7 4.7.% 4.8, $($(combo_2nd_arch_prefix)TARGET_GCC_VERSION)),) -$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -Wno-unused-but-set-variable -fno-builtin-sin \ +$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -fno-builtin-sin \ -fno-strict-volatile-bitfields endif diff --git a/core/combo/include/arch/darwin-x86/AndroidConfig.h b/core/combo/include/arch/darwin-x86/AndroidConfig.h index 44de4cd..54f3750 100644 --- a/core/combo/include/arch/darwin-x86/AndroidConfig.h +++ b/core/combo/include/arch/darwin-x86/AndroidConfig.h @@ -56,13 +56,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -/* #define HAVE_OOM_ADJ */ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/freebsd-x86/AndroidConfig.h b/core/combo/include/arch/freebsd-x86/AndroidConfig.h index 0734661..4267508 100644 --- a/core/combo/include/arch/freebsd-x86/AndroidConfig.h +++ b/core/combo/include/arch/freebsd-x86/AndroidConfig.h @@ -61,13 +61,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -/* #define HAVE_OOM_ADJ */ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/linux-arm/AndroidConfig.h b/core/combo/include/arch/linux-arm/AndroidConfig.h index 9253e7c..35eecfe 100644 --- a/core/combo/include/arch/linux-arm/AndroidConfig.h +++ b/core/combo/include/arch/linux-arm/AndroidConfig.h @@ -69,13 +69,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/linux-mips/AndroidConfig.h b/core/combo/include/arch/linux-mips/AndroidConfig.h index 2758153..33472d2 100644 --- a/core/combo/include/arch/linux-mips/AndroidConfig.h +++ b/core/combo/include/arch/linux-mips/AndroidConfig.h @@ -69,13 +69,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/linux-ppc/AndroidConfig.h b/core/combo/include/arch/linux-ppc/AndroidConfig.h index e6f9489..c68f354 100644 --- a/core/combo/include/arch/linux-ppc/AndroidConfig.h +++ b/core/combo/include/arch/linux-ppc/AndroidConfig.h @@ -56,13 +56,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/linux-x86/AndroidConfig.h b/core/combo/include/arch/linux-x86/AndroidConfig.h index 0740186..79b9cef 100644 --- a/core/combo/include/arch/linux-x86/AndroidConfig.h +++ b/core/combo/include/arch/linux-x86/AndroidConfig.h @@ -56,13 +56,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/target_linux-x86/AndroidConfig.h b/core/combo/include/arch/target_linux-x86/AndroidConfig.h index f55134a..d44a317 100644 --- a/core/combo/include/arch/target_linux-x86/AndroidConfig.h +++ b/core/combo/include/arch/target_linux-x86/AndroidConfig.h @@ -55,13 +55,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/windows/AndroidConfig.h b/core/combo/include/arch/windows/AndroidConfig.h index 0a52674..204740d 100644 --- a/core/combo/include/arch/windows/AndroidConfig.h +++ b/core/combo/include/arch/windows/AndroidConfig.h @@ -83,13 +83,6 @@ #endif /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -/* #define HAVE_OOM_ADJ */ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/config.mk b/core/config.mk index 31833fb..61f1d79 100644 --- a/core/config.mk +++ b/core/config.mk @@ -37,8 +37,7 @@ SRC_HEADERS := \ $(TOPDIR)frameworks/native/include \ $(TOPDIR)frameworks/native/opengl/include \ $(TOPDIR)frameworks/av/include \ - $(TOPDIR)frameworks/base/include \ - $(TOPDIR)external/skia/include + $(TOPDIR)frameworks/base/include SRC_HOST_HEADERS:=$(TOPDIR)tools/include SRC_LIBRARIES:= $(TOPDIR)libs SRC_SERVERS:= $(TOPDIR)servers @@ -390,6 +389,10 @@ JAVATAGS := build/tools/java-event-log-tags.py LLVM_RS_CC := $(HOST_OUT_EXECUTABLES)/llvm-rs-cc$(HOST_EXECUTABLE_SUFFIX) BCC_COMPAT := $(HOST_OUT_EXECUTABLES)/bcc_compat$(HOST_EXECUTABLE_SUFFIX) LINT := prebuilts/sdk/tools/lint +RMTYPEDEFS := $(HOST_OUT_EXECUTABLES)/rmtypedefs +APPEND2SIMG := $(HOST_OUT_EXECUTABLES)/append2simg +VERITY_SIGNER := $(HOST_OUT_EXECUTABLES)/verity_signer +BUILD_VERITY_TREE := $(HOST_OUT_EXECUTABLES)/build_verity_tree # ACP is always for the build OS, not for the host OS ACP := $(BUILD_OUT_EXECUTABLES)/acp$(BUILD_EXECUTABLE_SUFFIX) @@ -561,6 +564,7 @@ TARGET_AVAILABLE_SDK_VERSIONS := $(call numerically_sort,\ $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/android.jar))) INTERNAL_PLATFORM_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/public_api.txt +INTERNAL_PLATFORM_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/removed.txt # This is the standard way to name a directory containing prebuilt target # objects. E.g., prebuilt/$(TARGET_PREBUILT_TAG)/libc.so diff --git a/core/definitions.mk b/core/definitions.mk index e9871d6..8f8aa4d 100644 --- a/core/definitions.mk +++ b/core/definitions.mk @@ -1553,7 +1553,7 @@ $(hide) mkdir -p $(PRIVATE_CLASS_INTERMEDIATES_DIR) $(call unzip-jar-files,$(PRIVATE_STATIC_JAVA_LIBRARIES),$(PRIVATE_CLASS_INTERMEDIATES_DIR)) $(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list) $(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \ - find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \ + find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \ fi $(hide) tr ' ' '\n' < $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list \ | sort -u > $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq @@ -1582,8 +1582,13 @@ $(if $(PRIVATE_JAR_PACKAGES), $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DIR) -m $(foreach pkg, $(PRIVATE_JAR_PACKAGES), \ -not -path $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg))) \ | xargs rm -rf) -$(hide) jar $(if $(strip $(PRIVATE_JAR_MANIFEST)),-cfm,-cf) \ - $@ $(PRIVATE_JAR_MANIFEST) -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) . +$(if $(PRIVATE_RMTYPEDEFS), $(hide) $(RMTYPEDEFS) -v $(PRIVATE_CLASS_INTERMEDIATES_DIR)) +$(if $(PRIVATE_JAR_MANIFEST), \ + $(hide) sed -e 's/%BUILD_NUMBER%/$(BUILD_NUMBER)/' \ + $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf && \ + jar -cfm $@ $(dir $@)/manifest.mf \ + -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) ., \ + $(hide) jar -cf $@ -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) .) endef define transform-java-to-classes.jar @@ -1633,8 +1638,13 @@ $(if $(PRIVATE_JAR_PACKAGES), $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DIR) -m $(foreach pkg, $(PRIVATE_JAR_PACKAGES), \ -not -path $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg))) \ | xargs rm -rf) -$(hide) jar $(if $(strip $(PRIVATE_JAR_MANIFEST)),-cfm,-cf) \ - $@ $(PRIVATE_JAR_MANIFEST) -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) . +$(if $(PRIVATE_RMTYPEDEFS), $(hide) $(RMTYPEDEFS) -v $(PRIVATE_CLASS_INTERMEDIATES_DIR)) +$(if $(PRIVATE_JAR_MANIFEST), \ + $(hide) sed -e 's/%BUILD_NUMBER%/$(BUILD_NUMBER)/' \ + $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf && \ + jar -cfm $@ $(dir $@)/manifest.mf \ + -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) ., \ + $(hide) jar -cf $@ -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) .) $(hide) mv $(PRIVATE_CLASS_INTERMEDIATES_DIR)/newstamp $(PRIVATE_CLASS_INTERMEDIATES_DIR)/stamp endef @@ -1656,9 +1666,10 @@ endef define transform-classes.jar-to-dex @echo "target Dex: $(PRIVATE_MODULE)" @mkdir -p $(dir $@) +$(hide) rm -f $(dir $@)/classes*.dex $(hide) $(DX) \ $(if $(findstring windows,$(HOST_OS)),,-JXms16M -JXmx2048M) \ - --dex --output=$@ \ + --dex --output=$(dir $@) \ $(incremental_dex) \ $(if $(NO_OPTIMIZE_DX), \ --no-optimize) \ @@ -1718,11 +1729,7 @@ endef #TODO: update the manifest to point to the dex file define add-dex-to-package -$(if $(filter classes.dex,$(notdir $(PRIVATE_DEX_FILE))),\ -$(hide) zip -qj $@ $(PRIVATE_DEX_FILE),\ -$(hide) _adtp_classes_dex=$(dir $(PRIVATE_DEX_FILE))classes.dex; \ -cp $(PRIVATE_DEX_FILE) $$_adtp_classes_dex && \ -zip -qj $@ $$_adtp_classes_dex && rm -f $$_adtp_classes_dex) +$(hide) zip -qj $@ $(dir $(PRIVATE_DEX_FILE))/classes*.dex endef # Add java resources added by the current module. @@ -2129,17 +2136,19 @@ endef # $(1) target # $(2) stable api file # $(3) api file to be tested -# $(4) arguments for apicheck -# $(5) command to run if apicheck failed -# $(6) target dependent on this api check -# $(7) additional dependencies +# $(4) stable removed api file +# $(5) removed api file to be tested +# $(6) arguments for apicheck +# $(7) command to run if apicheck failed +# $(8) target dependent on this api check +# $(9) additional dependencies define check-api -$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp: $(2) $(3) $(APICHECK) $(7) +$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp: $(2) $(3) $(4) $(APICHECK) $(9) @echo "Checking API:" $(1) - $(hide) ( $(APICHECK_COMMAND) $(4) $(2) $(3) || ( $(5) ; exit 38 ) ) + $(hide) ( $(APICHECK_COMMAND) $(6) $(2) $(3) $(4) $(5) || ( $(7) ; exit 38 ) ) $(hide) mkdir -p $$(dir $$@) $(hide) touch $$@ -$(6): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp +$(8): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp endef ## Whether to build from source if prebuilt alternative exists diff --git a/core/droiddoc.mk b/core/droiddoc.mk index d5ddf08..2a9cfc6 100644 --- a/core/droiddoc.mk +++ b/core/droiddoc.mk @@ -131,15 +131,13 @@ $(full_target): PRIVATE_CUSTOM_TEMPLATE_DIR := $(LOCAL_DROIDDOC_CUSTOM_TEMPLATE_ $(full_target): PRIVATE_IN_CUSTOM_ASSET_DIR := $(LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR)/$(LOCAL_DROIDDOC_CUSTOM_ASSET_DIR) $(full_target): PRIVATE_OUT_ASSET_DIR := $(out_dir)/$(LOCAL_DROIDDOC_ASSET_DIR) $(full_target): PRIVATE_OUT_CUSTOM_ASSET_DIR := $(out_dir)/$(LOCAL_DROIDDOC_CUSTOM_ASSET_DIR) + +html_dir_files := ifneq ($(strip $(LOCAL_DROIDDOC_HTML_DIR)),) $(full_target): PRIVATE_DROIDDOC_HTML_DIR := -htmldir $(LOCAL_PATH)/$(LOCAL_DROIDDOC_HTML_DIR) +html_dir_files := $(shell find $(LOCAL_PATH)/$(LOCAL_DROIDDOC_HTML_DIR) -type f) else -$(full_target): PRIVATE_DROIDDOC_HTML_DIR := -endif -ifneq ($(strip $(LOCAL_ADDITIONAL_HTML_DIR)),) -$(full_target): PRIVATE_ADDITIONAL_HTML_DIR := -htmldir2 $(LOCAL_PATH)/$(LOCAL_ADDITIONAL_HTML_DIR) -else -$(full_target): PRIVATE_ADDITIONAL_HTML_DIR := +$(full_target): PRIVATE_DROIDDOC_HTML_DIR := endif ifneq ($(strip $(LOCAL_ADDITIONAL_HTML_DIR)),) $(full_target): PRIVATE_ADDITIONAL_HTML_DIR := -htmldir2 $(LOCAL_PATH)/$(LOCAL_ADDITIONAL_HTML_DIR) @@ -150,8 +148,6 @@ endif # TODO: not clear if this is used any more $(full_target): PRIVATE_LOCAL_PATH := $(LOCAL_PATH) -html_dir_files := $(shell find $(LOCAL_PATH)/$(LOCAL_DROIDDOC_HTML_DIR) -type f) - $(full_target): $(full_src_files) $(droiddoc_templates) $(droiddoc) $(html_dir_files) $(full_java_lib_deps) $(LOCAL_ADDITIONAL_DEPENDENCIES) @echo Docs droiddoc: $(PRIVATE_OUT_DIR) $(hide) mkdir -p $(dir $@) diff --git a/core/envsetup.mk b/core/envsetup.mk index 4cb389b..88f35a6 100644 --- a/core/envsetup.mk +++ b/core/envsetup.mk @@ -107,6 +107,7 @@ endif TARGET_COPY_OUT_SYSTEM := system TARGET_COPY_OUT_DATA := data TARGET_COPY_OUT_VENDOR := system/vendor +TARGET_COPY_OUT_OEM := oem TARGET_COPY_OUT_ROOT := root TARGET_COPY_OUT_RECOVERY := recovery @@ -207,6 +208,7 @@ HOST_OUT_HEADERS := $(HOST_OUT_INTERMEDIATES)/include HOST_OUT_INTERMEDIATE_LIBRARIES := $(HOST_OUT_INTERMEDIATES)/lib HOST_OUT_NOTICE_FILES := $(HOST_OUT_INTERMEDIATES)/NOTICE_FILES HOST_OUT_COMMON_INTERMEDIATES := $(HOST_COMMON_OUT_ROOT)/obj +HOST_OUT_FAKE := $(HOST_OUT)/fake_packages HOST_OUT_GEN := $(HOST_OUT)/gen HOST_OUT_COMMON_GEN := $(HOST_COMMON_OUT_ROOT)/gen @@ -281,6 +283,14 @@ $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDO $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(TARGET_OUT_VENDOR)/lib $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR_APPS) +TARGET_OUT_OEM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_OEM) +TARGET_OUT_OEM_EXECUTABLES:= $(TARGET_OUT_OEM)/bin +TARGET_OUT_OEM_SHARED_LIBRARIES:= $(TARGET_OUT_OEM)/lib +# We don't expect Java libraries in the oem.img. +# TARGET_OUT_OEM_JAVA_LIBRARIES:= $(TARGET_OUT_OEM)/framework +TARGET_OUT_OEM_APPS:= $(TARGET_OUT_OEM)/app +TARGET_OUT_OEM_ETC := $(TARGET_OUT_OEM)/etc + TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols TARGET_OUT_EXECUTABLES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/bin TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/lib diff --git a/core/host_java_library.mk b/core/host_java_library.mk index e5ebb11..2a8f18f 100644 --- a/core/host_java_library.mk +++ b/core/host_java_library.mk @@ -20,21 +20,64 @@ ####################################### include $(BUILD_SYSTEM)/host_java_library_common.mk +####################################### + +# Enable emma instrumentation only if the module asks so. +ifeq (true,$(LOCAL_EMMA_INSTRUMENT)) +ifneq (true,$(EMMA_INSTRUMENT)) +LOCAL_EMMA_INSTRUMENT := +endif +endif + +full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar +emma_intermediates_dir := $(intermediates.COMMON)/emma_out +# emma is hardcoded to use the leaf name of its input for the output file -- +# only the output directory can be changed +full_classes_emma_jar := $(emma_intermediates_dir)/lib/$(notdir $(full_classes_compiled_jar)) + +LOCAL_INTERMEDIATE_TARGETS += \ + $(full_classes_compiled_jar) \ + $(full_classes_emma_jar) + +####################################### include $(BUILD_SYSTEM)/base_rules.mk ####################################### -$(full_classes_compiled_jar): PRIVATE_JAVAC_DEBUG_FLAGS := -g +ifeq (true,$(LOCAL_EMMA_INSTRUMENT)) +$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILE := $(intermediates.COMMON)/coverage.em +$(full_classes_emma_jar): PRIVATE_EMMA_INTERMEDIATES_DIR := $(emma_intermediates_dir) +ifdef LOCAL_EMMA_COVERAGE_FILTER +$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILTER := $(LOCAL_EMMA_COVERAGE_FILTER) +else +# by default, avoid applying emma instrumentation onto emma classes itself, +# otherwise there will be exceptions thrown +$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILTER := *,-emma,-emmarun,-com.vladium.* +endif +# this rule will generate both $(PRIVATE_EMMA_COVERAGE_FILE) and +# $(full_classes_emma_jar) +$(full_classes_emma_jar) : $(full_classes_compiled_jar) | $(EMMA_JAR) + $(transform-classes.jar-to-emma) + +$(LOCAL_BUILT_MODULE) : $(full_classes_emma_jar) + @echo Copying: $@ + $(hide) $(ACP) -fp $< $@ -java_alternative_checked_module := +else # LOCAL_EMMA_INSTRUMENT +# Directly build into LOCAL_BUILT_MODULE. +full_classes_compiled_jar := $(LOCAL_BUILT_MODULE) +endif # LOCAL_EMMA_INSTRUMENT + +$(full_classes_compiled_jar): PRIVATE_JAVAC_DEBUG_FLAGS := -g # The layers file allows you to enforce a layering between java packages. # Run build/tools/java-layers.py for more details. layers_file := $(addprefix $(LOCAL_PATH)/, $(LOCAL_JAVA_LAYERS_FILE)) -$(LOCAL_BUILT_MODULE): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) -$(LOCAL_BUILT_MODULE): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) -$(LOCAL_BUILT_MODULE): PRIVATE_JAR_EXCLUDE_FILES := -$(LOCAL_BUILT_MODULE): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) -$(LOCAL_BUILT_MODULE): $(java_sources) $(java_resource_sources) $(full_java_lib_deps) \ +$(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) +$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) +$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := +$(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES := +$(full_classes_compiled_jar): PRIVATE_RMTYPEDEFS := +$(full_classes_compiled_jar): $(java_sources) $(java_resource_sources) $(full_java_lib_deps) \ $(jar_manifest_file) $(proto_java_sources_file_stamp) $(LOCAL_ADDITIONAL_DEPENDENCIES) $(transform-host-java-to-package) diff --git a/core/install_jni_libs.mk b/core/install_jni_libs.mk index 464a2a2..b9e70b1 100644 --- a/core/install_jni_libs.mk +++ b/core/install_jni_libs.mk @@ -5,9 +5,11 @@ # rs_compatibility_jni_libs (from java.mk) # my_module_path (from base_rules.mk) # partition_tag (from base_rules.mk) +# my_prebuilt_src_file (from prebuilt_internal.mk) # # Output variables: -# jni_shared_libraries, jni_shared_libraries_abi, if we are going to embed the libraries into the apk. +# jni_shared_libraries, jni_shared_libraries_abi, if we are going to embed the libraries into the apk; +# my_extracted_jni_libs, if we extract jni libs from prebuilt apk. # jni_shared_libraries := \ @@ -33,6 +35,10 @@ ifeq ($(filter $(TARGET_OUT)/% $(TARGET_OUT_VENDOR)/% $(TARGET_OUT_OEM)/%, $(my_ my_embed_jni := true endif +# App-specific lib path. +my_app_lib_path := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET$(partition_tag)_OUT_SHARED_LIBRARIES)/$(basename $(LOCAL_INSTALLED_MODULE_STEM)) +my_extracted_jni_libs := + ifdef my_embed_jni # App explicitly requires the prebuilt NDK stl shared libraies. # The NDK stl shared libraries should never go to the system image. @@ -74,12 +80,42 @@ my_leading_separator := ; else my_leading_separator := endif -my_app_lib_path := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET$(partition_tag)_OUT_SHARED_LIBRARIES)/$(basename $(LOCAL_INSTALLED_MODULE_STEM)) $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD += \ $(my_leading_separator)mkdir -p $(my_app_lib_path) \ $(foreach lib, $(my_jni_filenames), ;ln -sf ../$(lib) $(my_app_lib_path)/$(lib)) # Clear jni_shared_libraries to not embed it into the apk. jni_shared_libraries := -endif # $(jni_shared_libraries) not empty +endif # $(jni_shared_libraries) not empty endif # my_embed_jni + +ifdef LOCAL_PREBUILT_JNI_LIBS +# Install prebuilt JNI libs to the app specific lib path. +# Files like @path/to/libfoo.so (path inside the apk) are JNI libs extracted from the prebuilt apk; +# Files like path/to/libfoo.so (path relative to LOCAL_PATH) are prebuilts in the source tree. +my_extracted_jni_libs := $(patsubst @%,%, \ + $(filter @%, $(LOCAL_PREBUILT_JNI_LIBS))) +ifdef my_extracted_jni_libs +ifndef my_prebuilt_src_file +$(error No prebuilt apk to extract prebuilt jni libraries $(my_extracted_jni_libs)) +endif +# We use the first jni lib file as dependency. +my_installed_prebuilt_jni := $(my_app_lib_path)/$(notdir $(firstword $(my_extracted_jni_libs))) +$(my_installed_prebuilt_jni): PRIVATE_JNI_LIBS := $(my_extracted_jni_libs) +$(my_installed_prebuilt_jni): $(my_prebuilt_src_file) + @echo "Extract JNI libs ($@ <- $<)" + @mkdir -p $(dir $@) + $(hide) unzip -j -o -d $(dir $@) $< $(PRIVATE_JNI_LIBS) && touch $@ + +$(LOCAL_INSTALLED_MODULE) : | $(my_installed_prebuilt_jni) +endif + +my_prebulit_jni_libs := $(addprefix $(LOCAL_PATH)/, \ + $(filter-out @%, $(LOCAL_PREBUILT_JNI_LIBS))) +ifdef my_prebulit_jni_libs +$(foreach lib, $(my_prebulit_jni_libs), \ + $(eval $(call copy-one-file, $(lib), $(my_app_lib_path)/$(notdir $(lib))))) + +$(LOCAL_INSTALLED_MODULE) : | $(addprefix $(my_app_lib_path)/, $(notdir $(my_prebulit_jni_libs))) +endif +endif # LOCAL_PREBULT_JNI_LIBS diff --git a/core/java.mk b/core/java.mk index 8863ac2..824ae6a 100644 --- a/core/java.mk +++ b/core/java.mk @@ -72,10 +72,10 @@ 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 := classes-no-local.dex +built_dex_intermediate_leaf := no-local else full_classes_compiled_jar_leaf := classes-full-debug.jar -built_dex_intermediate_leaf := classes-with-local.dex +built_dex_intermediate_leaf := with-local endif ifeq ($(LOCAL_PROGUARD_ENABLED),disabled) @@ -96,7 +96,7 @@ emma_intermediates_dir := $(intermediates.COMMON)/emma_out # only the output directory can be changed full_classes_emma_jar := $(emma_intermediates_dir)/lib/$(jarjar_leaf) full_classes_proguard_jar := $(intermediates.COMMON)/$(proguard_jar_leaf) -built_dex_intermediate := $(intermediates.COMMON)/$(built_dex_intermediate_leaf) +built_dex_intermediate := $(intermediates.COMMON)/$(built_dex_intermediate_leaf)/classes.dex full_classes_stubs_jar := $(intermediates.COMMON)/stubs.jar ifeq ($(LOCAL_MODULE_CLASS)$(LOCAL_SRC_FILES)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),APPS) @@ -321,6 +321,10 @@ layers_file := $(addprefix $(LOCAL_PATH)/, $(LOCAL_JAVA_LAYERS_FILE)) $(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) $(full_classes_compiled_jar): PRIVATE_WARNINGS_ENABLE := $(LOCAL_WARNINGS_ENABLE) +ifdef LOCAL_RMTYPEDEFS +$(full_classes_compiled_jar): | $(RMTYPEDEFS) +endif + # Compile the java files to a .jar file. # This intentionally depends on java_sources, not all_java_sources. # Deps for generated source files must be handled separately, @@ -328,6 +332,7 @@ $(full_classes_compiled_jar): PRIVATE_WARNINGS_ENABLE := $(LOCAL_WARNINGS_ENABLE $(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := $(LOCAL_JAR_EXCLUDE_FILES) $(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES := $(LOCAL_JAR_PACKAGES) +$(full_classes_compiled_jar): PRIVATE_RMTYPEDEFS := $(LOCAL_RMTYPEDEFS) $(full_classes_compiled_jar): PRIVATE_DONT_DELETE_JAR_META_INF := $(LOCAL_DONT_DELETE_JAR_META_INF) $(full_classes_compiled_jar): $(java_sources) $(java_resource_sources) $(full_java_lib_deps) \ $(jar_manifest_file) $(layers_file) $(RenderScript_file_stamp) \ @@ -470,7 +475,9 @@ $(built_dex_intermediate): $(full_classes_proguard_jar) $(DX) $(transform-classes.jar-to-dex) $(built_dex): $(built_dex_intermediate) | $(ACP) @echo Copying: $@ - $(hide) $(ACP) -fp $< $@ + $(hide) mkdir -p $(dir $@) + $(hide) rm -f $(dir $@)/classes*.dex + $(hide) $(ACP) -fp $(dir $<)/classes*.dex $(dir $@) ifneq ($(GENERATE_DEX_DEBUG),) $(install-dex-debug) endif diff --git a/core/main.mk b/core/main.mk index eafeb71..7ef3462 100644 --- a/core/main.mk +++ b/core/main.mk @@ -189,12 +189,8 @@ ifeq ($(requires_openjdk), true) # java version is really openjdk ifeq ($(shell echo '$(java_version_str)' | grep -i openjdk),) $(info ************************************************************) -$(info You are attempting to build with an unsupported JDK.) -$(info $(space)) -$(info This build requires OpenJDK, but you are using:) +$(info You asked for an OpenJDK 7 build but your version is) $(info $(java_version_str).) -$(info Please follow the machine setup instructions at) -$(info $(space)$(space)$(space)$(space)https://source.android.com/source/download.html) $(info ************************************************************) $(error stop) endif # java version is not OpenJdk @@ -407,7 +403,7 @@ ifdef is_sdk_build sdk_repo_goal := $(strip $(filter sdk_repo,$(MAKECMDGOALS))) MAKECMDGOALS := $(strip $(filter-out sdk_repo,$(MAKECMDGOALS))) -ifneq ($(words $(filter-out $(INTERNAL_MODIFIER_TARGETS) checkbuild target-files-package,$(MAKECMDGOALS))),1) +ifneq ($(words $(filter-out $(INTERNAL_MODIFIER_TARGETS) checkbuild emulator_tests target-files-package,$(MAKECMDGOALS))),1) $(error The 'sdk' target may not be specified with any other targets) endif @@ -970,6 +966,7 @@ else # TARGET_BUILD_APPS $(foreach f,$(INSTALLED_RADIOIMAGE_TARGET), \ $(call dist-for-goals, droidcore, $(f))) + ifneq ($(ANDROID_BUILD_EMBEDDED),true) ifneq ($(TARGET_BUILD_PDK),true) $(call dist-for-goals, droidcore, \ $(APPS_ZIP) \ @@ -977,6 +974,7 @@ else # TARGET_BUILD_APPS $(PACKAGE_STATS_FILE) \ ) endif + endif ifeq ($(EMMA_INSTRUMENT),true) $(EMMA_META_ZIP) : $(INSTALLED_SYSTEMIMAGE) @@ -1040,7 +1038,7 @@ findbugs: $(INTERNAL_FINDBUGS_HTML_TARGET) $(INTERNAL_FINDBUGS_XML_TARGET) .PHONY: clean clean: - @rm -rf $(OUT_DIR) + @rm -rf $(OUT_DIR)/* @echo "Entire build directory removed." .PHONY: clobber diff --git a/core/package_internal.mk b/core/package_internal.mk index 5771e98..598c065 100644 --- a/core/package_internal.mk +++ b/core/package_internal.mk @@ -233,6 +233,7 @@ $(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(RenderScript_file_ $(proguard_options_file): $(R_file_stamp) +resource_export_package := ifdef LOCAL_EXPORT_PACKAGE_RESOURCES # Put this module's resources into a PRODUCT-agnositc package that # other packages can use to build their own PRODUCT-agnostic R.java (etc.) @@ -286,9 +287,19 @@ framework_res_package_export := \ framework_res_package_export_deps := \ $(dir $(framework_res_package_export))src/R.stamp endif # LOCAL_SDK_RES_VERSION -$(R_file_stamp): $(framework_res_package_export_deps) +all_library_res_package_exports := \ + $(framework_res_package_export) \ + $(foreach lib,$(LOCAL_RES_LIBRARIES),\ + $(call intermediates-dir-for,APPS,$(lib),,COMMON)/package-export.apk) + +all_library_res_package_export_deps := \ + $(framework_res_package_export_deps) \ + $(foreach lib,$(LOCAL_RES_LIBRARIES),\ + $(call intermediates-dir-for,APPS,$(lib),,COMMON)/src/R.stamp) + +$(resource_export_package) $(R_file_stamp): $(all_library_res_package_export_deps) $(LOCAL_INTERMEDIATE_TARGETS): \ - PRIVATE_AAPT_INCLUDES := $(framework_res_package_export) + PRIVATE_AAPT_INCLUDES := $(all_library_res_package_exports) endif # LOCAL_NO_STANDARD_LIBRARIES ifneq ($(full_classes_jar),) diff --git a/core/pathmap.mk b/core/pathmap.mk index ee79647..aaeb905 100644 --- a/core/pathmap.mk +++ b/core/pathmap.mk @@ -29,10 +29,8 @@ pathmap_INCL := \ bootloader:bootable/bootloader/legacy/include \ camera:system/media/camera/include \ - corecg:external/skia/include/core \ frameworks-base:frameworks/base/include \ frameworks-native:frameworks/native/include \ - graphics:external/skia/include/core \ libc:bionic/libc/include \ libhardware:hardware/libhardware/include \ libhardware_legacy:hardware/libhardware_legacy/include \ @@ -51,6 +49,7 @@ pathmap_INCL := \ audio-route:system/media/audio_route/include \ wilhelm:frameworks/wilhelm/include \ wilhelm-ut:frameworks/wilhelm/src/ut \ + mediandk:frameworks/av/media/ndk/ \ speex:external/speex/include # @@ -116,15 +115,24 @@ FRAMEWORKS_SUPPORT_SUBDIRS := \ v17/leanback # +# A list of all source roots under frameworks/support. +# +FRAMEWORKS_MULTIDEX_SUBDIRS := \ + multidex \ + multidex/instrumentation + +# # A version of FRAMEWORKS_SUPPORT_SUBDIRS that is expanded to full paths from # the root of the tree. # FRAMEWORKS_SUPPORT_JAVA_SRC_DIRS := \ - $(addprefix frameworks/support/,$(FRAMEWORKS_SUPPORT_SUBDIRS)) + $(addprefix frameworks/support/,$(FRAMEWORKS_SUPPORT_SUBDIRS)) \ + $(addprefix frameworks/,$(FRAMEWORKS_MULTIDEX_SUBDIRS)) # # A list of support library modules. # FRAMEWORKS_SUPPORT_JAVA_LIBRARIES := \ - $(foreach dir,$(FRAMEWORKS_SUPPORT_SUBDIRS),android-support-$(subst /,-,$(dir))) + $(foreach dir,$(FRAMEWORKS_SUPPORT_SUBDIRS),android-support-$(subst /,-,$(dir))) \ + $(foreach dir,$(FRAMEWORKS_MULTIDEX_SUBDIRS),android-support-$(subst /,-,$(dir))) diff --git a/core/pdk_config.mk b/core/pdk_config.mk index b0cccc9..f5fdd15 100644 --- a/core/pdk_config.mk +++ b/core/pdk_config.mk @@ -18,9 +18,14 @@ pdk fusion: $(DEFAULT_GOAL) # if PDK_FUSION_PLATFORM_ZIP is specified, do not override. ifndef PDK_FUSION_PLATFORM_ZIP +# Most PDK project paths should be using vendor/pdk/TARGET_DEVICE +# but some legacy ones (e.g. mini_armv7a_neon generic PDK) were setup +# with vendor/pdk/TARGET_PRODUCT. _pdk_fusion_default_platform_zip = $(wildcard \ vendor/pdk/$(TARGET_DEVICE)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)/platform/platform.zip \ -vendor/pdk/$(TARGET_DEVICE)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform/platform.zip) +vendor/pdk/$(TARGET_DEVICE)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform/platform.zip \ +vendor/pdk/$(TARGET_PRODUCT)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)/platform/platform.zip \ +vendor/pdk/$(TARGET_PRODUCT)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform/platform.zip) ifneq (,$(_pdk_fusion_default_platform_zip)) PDK_FUSION_PLATFORM_ZIP := $(word 1, $(_pdk_fusion_default_platform_zip)) TARGET_BUILD_PDK := true diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk index 8efb89e..bf519ee 100644 --- a/core/prebuilt_internal.mk +++ b/core/prebuilt_internal.mk @@ -105,6 +105,7 @@ endif endif # LOCAL_STRIP_MODULE not true +ifeq ($(LOCAL_MODULE_CLASS),APPS) PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES)) rs_compatibility_jni_libs := @@ -124,11 +125,9 @@ ifeq ($(LOCAL_CERTIFICATE),EXTERNAL) $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem endif ifeq ($(LOCAL_CERTIFICATE),) - ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),) - # It is now a build error to add a prebuilt .apk without - # specifying a key for it. - $(error No LOCAL_CERTIFICATE specified for prebuilt "$(my_prebuilt_src_file)") - endif + # It is now a build error to add a prebuilt .apk without + # specifying a key for it. + $(error No LOCAL_CERTIFICATE specified for prebuilt "$(my_prebuilt_src_file)") else ifeq ($(LOCAL_CERTIFICATE),PRESIGNED) # The magic string "PRESIGNED" means this package is already checked # signed with its release key. @@ -152,8 +151,6 @@ else $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem endif -ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),) - # Disable dex-preopt of prebuilts to save space LOCAL_DEX_PREOPT := false @@ -175,6 +172,9 @@ endif # LOCAL_DEX_PREOPT # Sign and align non-presigned .apks. $(built_module) : $(my_prebuilt_src_file) | $(ACP) $(ZIPALIGN) $(SIGNAPK_JAR) $(transform-prebuilt-to-target) +ifdef my_extracted_jni_libs + $(hide) zip -d $@ 'lib/*.so' # strip embedded JNI libraries. +endif ifneq ($(LOCAL_CERTIFICATE),PRESIGNED) $(sign-package) endif diff --git a/core/product.mk b/core/product.mk index 174b429..5693fe9 100644 --- a/core/product.mk +++ b/core/product.mk @@ -100,6 +100,12 @@ _product_var_list := \ PRODUCT_RUNTIMES \ PRODUCT_BOOT_JARS \ PRODUCT_DEX_PREOPT_IMAGE_IN_DATA \ + PRODUCT_SUPPORTS_VERITY \ + PRODUCT_OEM_PROPERTIES \ + PRODUCT_SYSTEM_PROPERTY_BLACKLIST \ + PRODUCT_VERITY_PARTITION \ + PRODUCT_VERITY_SIGNING_KEY \ + PRODUCT_VERITY_MOUNTPOINT define dump-product $(info ==== $(1) ====)\ diff --git a/core/product_config.mk b/core/product_config.mk index 61bdfb4..171c394 100644 --- a/core/product_config.mk +++ b/core/product_config.mk @@ -319,8 +319,10 @@ PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCT_AAPT_PREF_CONFIG)) # Everyone gets nodpi assets which are density-independent. PRODUCT_AAPT_CONFIG += nodpi +# Keep a copy of the space-separated config +PRODUCT_AAPT_CONFIG_SP := $(PRODUCT_AAPT_CONFIG) + # Convert spaces to commas. -comma := , PRODUCT_AAPT_CONFIG := \ $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG))) PRODUCT_AAPT_PREF_CONFIG := \ diff --git a/core/tasks/apicheck.mk b/core/tasks/apicheck.mk index 00b78b9..4711d17 100644 --- a/core/tasks/apicheck.mk +++ b/core/tasks/apicheck.mk @@ -42,6 +42,8 @@ $(eval $(call check-api, \ checkapi-last, \ $(SRC_API_DIR)/$(last_released_sdk_version).txt, \ $(INTERNAL_PLATFORM_API_FILE), \ + frameworks/base/api/removed.txt, \ + $(INTERNAL_PLATFORM_REMOVED_API_FILE), \ -hide 2 -hide 3 -hide 4 -hide 5 -hide 6 -hide 24 -hide 25 -hide 26 -hide 27 \ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -error 16 -error 17 -error 18 , \ @@ -56,6 +58,8 @@ $(eval $(call check-api, \ checkapi-current, \ frameworks/base/api/current.txt, \ $(INTERNAL_PLATFORM_API_FILE), \ + frameworks/base/api/removed.txt, \ + $(INTERNAL_PLATFORM_REMOVED_API_FILE), \ -error 2 -error 3 -error 4 -error 5 -error 6 \ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \ @@ -69,5 +73,7 @@ $(eval $(call check-api, \ update-api: $(INTERNAL_PLATFORM_API_FILE) | $(ACP) @echo Copying current.txt $(hide) $(ACP) $(INTERNAL_PLATFORM_API_FILE) frameworks/base/api/current.txt + @echo Copying removed.txt + $(hide) $(ACP) $(INTERNAL_PLATFORM_REMOVED_API_FILE) frameworks/base/api/removed.txt endif diff --git a/core/tasks/oem_image.mk b/core/tasks/oem_image.mk new file mode 100644 index 0000000..26b9aba --- /dev/null +++ b/core/tasks/oem_image.mk @@ -0,0 +1,46 @@ +# +# 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. +# + +# We build oem.img only if it's asked for. +ifneq ($(filter $(MAKECMDGOALS),oem_image),) +ifndef BOARD_OEMIMAGE_PARTITION_SIZE +$(error BOARD_OEMIMAGE_PARTITION_SIZE is not set.) +endif + +INTERNAL_OEMIMAGE_FILES := \ + $(filter $(TARGET_OUT_OEM)/%,$(ALL_DEFAULT_INSTALLED_MODULES)) + +oemimage_intermediates := \ + $(call intermediates-dir-for,PACKAGING,oem) +BUILT_OEMIMAGE_TARGET := $(PRODUCT_OUT)/oem.img +# We just build this directly to the install location. +INSTALLED_OEMIMAGE_TARGET := $(BUILT_OEMIMAGE_TARGET) + +$(INSTALLED_OEMIMAGE_TARGET) : $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_OEMIMAGE_FILES) + $(call pretty,"Target oem fs image: $@") + @mkdir -p $(TARGET_OUT_OEM) + @mkdir -p $(oemimage_intermediates) && rm -rf $(oemimage_intermediates)/oem_image_info.txt + $(call generate-userimage-prop-dictionary, $(oemimage_intermediates)/oem_image_info.txt, skip_fsck=true) + $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ + ./build/tools/releasetools/build_image.py \ + $(TARGET_OUT_OEM) $(oemimage_intermediates)/oem_image_info.txt $@ + $(hide) $(call assert-max-image-size,$@,$(BOARD_OEMIMAGE_PARTITION_SIZE)) + +.PHONY: oem_image +oem_image : $(INSTALLED_OEMIMAGE_TARGET) +$(call dist-for-goals, oem_image, $(INSTALLED_OEMIMAGE_TARGET)) + +endif # oem_image in $(MAKECMDGOALS) diff --git a/core/version_defaults.mk b/core/version_defaults.mk index 4929abb..432391f 100644 --- a/core/version_defaults.mk +++ b/core/version_defaults.mk @@ -41,7 +41,7 @@ ifeq "" "$(PLATFORM_VERSION)" # which is the version that we reveal to the end user. # Update this value when the platform version changes (rather # than overriding it somewhere else). Can be an arbitrary string. - PLATFORM_VERSION := KKWT + PLATFORM_VERSION := L endif ifeq "" "$(PLATFORM_SDK_VERSION)" @@ -59,7 +59,12 @@ endif ifeq "" "$(PLATFORM_VERSION_CODENAME)" # This is the current development code-name, if the build is not a final # release build. If this is a final release build, it is simply "REL". - PLATFORM_VERSION_CODENAME := KKWT + PLATFORM_VERSION_CODENAME := L + + # This is all of the development codenames that are active. Should be either + # the same as PLATFORM_VERSION_CODENAME or a comma-separated list of additional + # codenames after PLATFORM_VERSION_CODENAME. + PLATFORM_VERSION_ALL_CODENAMES := $(PLATFORM_VERSION_CODENAME),KKWT endif ifeq "" "$(DEFAULT_APP_TARGET_SDK)" diff --git a/envsetup.sh b/envsetup.sh index b5d43ac..e5bd72e 100644 --- a/envsetup.sh +++ b/envsetup.sh @@ -189,6 +189,24 @@ function setpaths() unset ANDROID_HOST_OUT export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT) + # If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH + # to ensure that the corresponding 'emulator' binaries are used. + case $(uname -s) in + Darwin) + ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/darwin-x86_64 + ;; + Linux) + ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/linux-x86_64 + ;; + *) + ANDROID_EMULATOR_PREBUILTS= + ;; + esac + if [ -n "$ANDROID_EMULATOR_PREBUILTS" -a -d "$ANDROID_EMULATOR_PREBUILTS" ]; then + PATH=$ANDROID_EMULATOR_PREBUILTS:$PATH + export ANDROID_EMULATOR_PREBUILTS + fi + # needed for building linux on MacOS # TODO: fix the path #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include @@ -549,12 +567,12 @@ function _lunch() complete -F _lunch lunch # Configures the build to build unbundled apps. -# Run tapas with one ore more app names (from LOCAL_PACKAGE_NAME) +# Run tapas with one or more app names (from LOCAL_PACKAGE_NAME) function tapas() { - local arch=$(echo -n $(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|armv5)$')) - local variant=$(echo -n $(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$')) - local apps=$(echo -n $(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|mips|armv5)$')) + local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|armv5)$' | xargs)" + local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)" + local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|mips|armv5)$' | xargs)" if [ $(echo $arch | wc -w) -gt 1 ]; then echo "tapas: Error: Multiple build archs supplied: $arch" diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk index fe64bcb..06a7d8a 100644 --- a/target/board/generic/device.mk +++ b/target/board/generic/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk index 354fb2a..11a6a31 100644 --- a/target/board/generic_arm64/device.mk +++ b/target/board/generic_arm64/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml PRODUCT_PACKAGES := \ diff --git a/target/board/generic_mips/device.mk b/target/board/generic_mips/device.mk index b182c4c..590f422 100644 --- a/target/board/generic_mips/device.mk +++ b/target/board/generic_mips/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf diff --git a/target/board/generic_mips64/device.mk b/target/board/generic_mips64/device.mk index 58fe976..015686e 100644 --- a/target/board/generic_mips64/device.mk +++ b/target/board/generic_mips64/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk index 089f584..b5b0faf 100644 --- a/target/board/generic_x86/device.mk +++ b/target/board/generic_x86/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml PRODUCT_PACKAGES := \ diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk index 5b002bd..aa0e5a4 100755 --- a/target/board/generic_x86_64/device.mk +++ b/target/board/generic_x86_64/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ system/core/rootdir/init.zygote64.rc:root/init.zygote64.rc diff --git a/target/board/vbox_x86/device.mk b/target/board/vbox_x86/device.mk index a44a87f..b51f801 100644 --- a/target/board/vbox_x86/device.mk +++ b/target/board/vbox_x86/device.mk @@ -29,6 +29,9 @@ LOCAL_KERNEL := prebuilts/qemu-kernel/x86/kernel-vbox PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ build/target/board/vbox_x86/init.vbox_x86.rc:root/init.vbox_x86.rc \ $(LOCAL_KERNEL):kernel diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk index fc407d3..a714f1f 100644 --- a/target/product/AndroidProducts.mk +++ b/target/product/AndroidProducts.mk @@ -63,5 +63,7 @@ PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/sdk.mk \ $(LOCAL_DIR)/sdk_x86.mk \ $(LOCAL_DIR)/sdk_mips.mk \ - $(LOCAL_DIR)/large_emu_hw.mk + $(LOCAL_DIR)/sdk_arm64.mk \ + $(LOCAL_DIR)/sdk_x86_64.mk \ + $(LOCAL_DIR)/sdk_mips64.mk endif diff --git a/target/product/base.mk b/target/product/base.mk index 4b8326d..6dd77a4 100644 --- a/target/product/base.mk +++ b/target/product/base.mk @@ -35,12 +35,14 @@ PRODUCT_PACKAGES += \ fsck_msdos \ ime \ input \ + inputflinger \ javax.obex \ libandroid \ libandroid_runtime \ libandroid_servers \ libaudioeffect_jni \ libaudioflinger \ + libaudiopolicy \ libbundlewrapper \ libcamera_client \ libcameraservice \ @@ -48,6 +50,7 @@ PRODUCT_PACKAGES += \ libeffectproxy \ libeffects \ libinput \ + libinputflinger \ libiprouteutil \ libjnigraphics \ libldnhncr \ @@ -77,6 +80,8 @@ PRODUCT_PACKAGES += \ libutils \ libvisualizer \ libvorbisidec \ + libmediandk \ + libwifi-service \ media \ media_cmd \ mediaserver \ @@ -93,7 +98,6 @@ PRODUCT_PACKAGES += \ racoon \ run-as \ schedtest \ - screenshot \ sdcard \ services \ settings \ diff --git a/target/product/core.mk b/target/product/core.mk index 8c88b94..a88e92f 100644 --- a/target/product/core.mk +++ b/target/product/core.mk @@ -22,16 +22,33 @@ PRODUCT_PACKAGES += \ BasicDreams \ Browser \ + Calculator \ + Calendar \ + CalendarProvider \ + CertInstaller \ Contacts \ + DeskClock \ DocumentsUI \ DownloadProviderUi \ + Email \ + Exchange2 \ ExternalStorageProvider \ + FusedLocation \ + InputDevices \ KeyChain \ + Keyguard \ + LatinIME \ + Launcher2 \ + ManagedProvisioning \ PicoTts \ PacProcessor \ libpac \ + PrintSpooler \ ProxyHandler \ + QuickSearchBox \ + Settings \ SharedStorageBackup \ + TeleService \ VpnDialogs $(call inherit-product, $(SRC_TARGET_DIR)/product/core_base.mk) diff --git a/target/product/core_64_bit.mk b/target/product/core_64_bit.mk index 5d7abcb..971b6bd 100644 --- a/target/product/core_64_bit.mk +++ b/target/product/core_64_bit.mk @@ -29,11 +29,5 @@ PRODUCT_COPY_FILES += system/core/rootdir/init.zygote32_64.rc:root/init.zygote32 # This line must be parsed before the one in core_minimal.mk PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote32_64 -# Temporary hack to prefer launching processes as 32 bit -# instead of 64 bit. -# -# STOPSHIP: Revert this to allow products to select it themselves -TARGET_PREFER_32_BIT_APPS := true - TARGET_SUPPORTS_32_BIT_APPS := true TARGET_SUPPORTS_64_BIT_APPS := true diff --git a/target/product/core_base.mk b/target/product/core_base.mk index 69bde63..d63e39f 100644 --- a/target/product/core_base.mk +++ b/target/product/core_base.mk @@ -30,7 +30,6 @@ PRODUCT_PACKAGES += \ libandroidfw \ libaudiopreprocessing \ libaudioutils \ - libbcc \ libfilterpack_imageproc \ libgabi++ \ libkeystore \ @@ -39,7 +38,6 @@ PRODUCT_PACKAGES += \ libportable \ libpowermanager \ libspeexresampler \ - libstagefright_chromium_http \ libstagefright_soft_aacdec \ libstagefright_soft_aacenc \ libstagefright_soft_amrdec \ @@ -63,7 +61,8 @@ PRODUCT_PACKAGES += \ mms-common \ requestsync \ telephony-common \ - voip-common + voip-common \ + wifi-service $(call inherit-product, $(SRC_TARGET_DIR)/product/core_minimal.mk) # Override the PRODUCT_BOOT_JARS set in core_minimal.mk. The order matters. @@ -82,4 +81,5 @@ PRODUCT_BOOT_JARS := \ android.policy \ services \ apache-xml \ - webviewchromium + webviewchromium \ + wifi-service diff --git a/target/product/core_minimal.mk b/target/product/core_minimal.mk index fc69973..7fbdee6 100644 --- a/target/product/core_minimal.mk +++ b/target/product/core_minimal.mk @@ -45,6 +45,7 @@ PRODUCT_PACKAGES += \ iptables \ keystore \ keystore.default \ + libbcc \ libOpenMAXAL \ libOpenSLES \ libdownmix \ @@ -58,7 +59,9 @@ PRODUCT_PACKAGES += \ screencap \ sensorservice \ uiautomator \ - webview + uncrypt \ + webview \ + wifi-service # The order of PRODUCT_BOOT_JARS matters. PRODUCT_BOOT_JARS := \ @@ -73,10 +76,11 @@ PRODUCT_BOOT_JARS := \ android.policy \ services \ apache-xml \ - webviewchromium + webviewchromium \ + wifi-service -PRODUCT_RUNTIMES := runtime_libdvm_default -PRODUCT_RUNTIMES += runtime_libart +PRODUCT_RUNTIMES := runtime_libart_default +PRODUCT_RUNTIMES += runtime_libdvm PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \ ro.zygote=zygote32 diff --git a/target/product/core_tiny.mk b/target/product/core_tiny.mk index 3e6cbd3..9c40206 100644 --- a/target/product/core_tiny.mk +++ b/target/product/core_tiny.mk @@ -21,21 +21,12 @@ PRODUCT_PACKAGES := \ ContactsProvider \ CertInstaller \ FusedLocation \ - InputDevices \ - bluetooth-health \ - hostapd \ - wpa_supplicant.conf + InputDevices PRODUCT_PACKAGES += \ - audio \ clatd \ clatd.conf \ - dhcpcd.conf \ - network \ - pand \ - pppd \ - sdptool \ - wpa_supplicant + pppd PRODUCT_PACKAGES += \ audio.primary.default \ @@ -71,7 +62,8 @@ PRODUCT_PACKAGES += \ make_ext4fs \ screencap \ sensorservice \ - uiautomator + uiautomator \ + uncrypt # The order matters PRODUCT_BOOT_JARS := \ @@ -92,11 +84,10 @@ PRODUCT_RUNTIMES := runtime_libdvm_default PRODUCT_PROPERTY_OVERRIDES += \ ro.carrier=unknown +$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) $(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk) # Overrides PRODUCT_BRAND := tiny PRODUCT_DEVICE := tiny PRODUCT_NAME := core_tiny - -$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) diff --git a/target/product/full_base.mk b/target/product/full_base.mk index 059697e..1daa523 100644 --- a/target/product/full_base.mk +++ b/target/product/full_base.mk @@ -26,7 +26,6 @@ PRODUCT_PACKAGES := \ libWnnEngDic \ libWnnJpnDic \ libwnndict \ - VideoEditor \ WAPPushManager PRODUCT_PACKAGES += \ diff --git a/target/product/full_base_telephony.mk b/target/product/full_base_telephony.mk index f98e9a2..2fd2ce8 100644 --- a/target/product/full_base_telephony.mk +++ b/target/product/full_base_telephony.mk @@ -27,7 +27,8 @@ PRODUCT_PROPERTY_OVERRIDES := \ ro.com.android.dataroaming=true PRODUCT_COPY_FILES := \ - device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml + device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ + frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony.mk) diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk index 12797f4..b4f2a7b 100644 --- a/target/product/generic_no_telephony.mk +++ b/target/product/generic_no_telephony.mk @@ -17,33 +17,15 @@ # This is a generic phone product that isn't specialized for a specific device. # It includes the base Android platform. -PRODUCT_POLICY := android.policy_phone - PRODUCT_PACKAGES := \ - DeskClock \ Bluetooth \ - Calculator \ - Calendar \ Camera2 \ - CertInstaller \ - Email \ - Exchange2 \ - FusedLocation \ Gallery2 \ - InputDevices \ - Keyguard \ - LatinIME \ - Launcher2 \ Music \ MusicFX \ OneTimeInitializer \ - PrintSpooler \ Provision \ - QuickSearchBox \ - Settings \ SystemUI \ - TeleService \ - CalendarProvider \ WallpaperCropper PRODUCT_PACKAGES += \ diff --git a/target/product/large_emu_hw.mk b/target/product/large_emu_hw.mk deleted file mode 100644 index a918c1d..0000000 --- a/target/product/large_emu_hw.mk +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright (C) 2007 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 is a generic product for devices with large display but not specialized -# for a specific device. It includes the base Android platform. - -PRODUCT_POLICY := android.policy_mid - -PRODUCT_PACKAGES := \ - CarHome \ - DeskClock \ - Bluetooth \ - Calculator \ - Calendar \ - CertInstaller \ - Email \ - Exchange2 \ - Gallery2 \ - LatinIME \ - Launcher2 \ - Music \ - Provision \ - QuickSearchBox \ - Settings \ - Sync \ - Updater \ - CalendarProvider \ - SyncProvider \ - bluetooth-health \ - hostapd \ - wpa_supplicant.conf - - -$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk) - -# Overrides -PRODUCT_BRAND := generic -PRODUCT_DEVICE := generic -PRODUCT_NAME := large_emu_hw diff --git a/target/product/sdk.mk b/target/product/sdk.mk index 5926f19..2e576c1 100644 --- a/target/product/sdk.mk +++ b/target/product/sdk.mk @@ -14,56 +14,38 @@ # limitations under the License. # -PRODUCT_POLICY := android.policy_phone PRODUCT_PROPERTY_OVERRIDES := PRODUCT_PACKAGES := \ - Calculator \ - DeskClock \ - Email \ - Exchange2 \ - FusedLocation \ + ApiDemos \ + CubeLiveWallpapers \ + CustomLocale \ + Development \ + DevelopmentSettings \ + Dialer \ + EmulatorSmokeTests \ + Fallback \ Gallery \ - Keyguard \ - Music \ - Mms \ - OpenWnn \ - PrintSpooler \ + GestureBuilder \ + LegacyCamera \ + librs_jni \ + libwnndict \ libWnnEngDic \ libWnnJpnDic \ - libwnndict \ - TeleService \ + LiveWallpapersPicker \ + Mms \ + Music \ + OpenWnn \ PinyinIME \ Protips \ - SoftKeyboard \ - SystemUI \ - Launcher2 \ - Development \ - DevelopmentSettings \ - Fallback \ - Settings \ + rild \ SdkSetup \ - CustomLocale \ - sqlite3 \ - InputDevices \ - LatinIME \ - CertInstaller \ - LiveWallpapersPicker \ - ApiDemos \ - GestureBuilder \ - CubeLiveWallpapers \ - QuickSearchBox \ - WidgetPreview \ - librs_jni \ - ConnectivityTest \ - GpsLocationTest \ - CalendarProvider \ - Calendar \ SmokeTest \ SmokeTestApp \ - rild \ - LegacyCamera \ - Dialer + SoftKeyboard \ + sqlite3 \ + SystemUI \ + WidgetPreview # Define the host tools and libs that are parts of the SDK. -include sdk/build/product_sdk.mk @@ -83,6 +65,9 @@ PRODUCT_COPY_FILES := \ frameworks/base/data/sounds/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \ frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \ frameworks/native/data/etc/android.hardware.camera.autofocus.xml:system/etc/permissions/android.hardware.camera.autofocus.xml \ @@ -103,14 +88,17 @@ $(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk) $(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk) -# Overrides -PRODUCT_BRAND := generic -PRODUCT_NAME := sdk -PRODUCT_DEVICE := generic +# include available languages for TTS in the system image +-include external/svox/pico/lang/PicoLangDeDeInSystem.mk +-include external/svox/pico/lang/PicoLangEnGBInSystem.mk +-include external/svox/pico/lang/PicoLangEnUsInSystem.mk +-include external/svox/pico/lang/PicoLangEsEsInSystem.mk +-include external/svox/pico/lang/PicoLangFrFrInSystem.mk +-include external/svox/pico/lang/PicoLangItItInSystem.mk # locale + densities. en_US is both first and in alphabetical order to # ensure this is the default locale. -PRODUCT_LOCALES = \ +PRODUCT_LOCALES := \ en_US \ ldpi \ hdpi \ @@ -174,10 +162,7 @@ PRODUCT_LOCALES = \ zh_CN \ zh_TW -# include available languages for TTS in the system image --include external/svox/pico/lang/PicoLangDeDeInSystem.mk --include external/svox/pico/lang/PicoLangEnGBInSystem.mk --include external/svox/pico/lang/PicoLangEnUsInSystem.mk --include external/svox/pico/lang/PicoLangEsEsInSystem.mk --include external/svox/pico/lang/PicoLangFrFrInSystem.mk --include external/svox/pico/lang/PicoLangItItInSystem.mk +# Overrides +PRODUCT_BRAND := generic +PRODUCT_NAME := sdk +PRODUCT_DEVICE := generic diff --git a/target/product/sdk_arm64.mk b/target/product/sdk_arm64.mk new file mode 100644 index 0000000..582a779 --- /dev/null +++ b/target/product/sdk_arm64.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2009 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 is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk) + +# Overrides +PRODUCT_BRAND := generic_arm64 +PRODUCT_NAME := sdk_arm64 +PRODUCT_DEVICE := generic_arm64 +PRODUCT_MODEL := Android SDK built for arm64 diff --git a/target/product/sdk_mips64.mk b/target/product/sdk_mips64.mk new file mode 100644 index 0000000..c00de06 --- /dev/null +++ b/target/product/sdk_mips64.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2009 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 is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk) + +# Overrides +PRODUCT_BRAND := generic_mips64 +PRODUCT_NAME := sdk_mips64 +PRODUCT_DEVICE := generic_mips64 +PRODUCT_MODEL := Android SDK built for mips64 diff --git a/target/product/sdk_x86.mk b/target/product/sdk_x86.mk index 873d0c0..6c5e746 100644 --- a/target/product/sdk_x86.mk +++ b/target/product/sdk_x86.mk @@ -19,7 +19,7 @@ # build quite specifically for the emulator, and might not be # entirely appropriate to inherit from for on-device configurations. -include $(SRC_TARGET_DIR)/product/sdk.mk +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk) # Overrides PRODUCT_BRAND := generic_x86 diff --git a/target/product/sdk_x86_64.mk b/target/product/sdk_x86_64.mk new file mode 100644 index 0000000..3816cf9 --- /dev/null +++ b/target/product/sdk_x86_64.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2009 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 is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk) + +# Overrides +PRODUCT_BRAND := generic_x86_64 +PRODUCT_NAME := sdk_x86_64 +PRODUCT_DEVICE := generic_x86_64 +PRODUCT_MODEL := Android SDK built for x86_64 diff --git a/target/product/security/Android.mk b/target/product/security/Android.mk new file mode 100644 index 0000000..5a40397 --- /dev/null +++ b/target/product/security/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) + +####################################### +# verity_key +include $(CLEAR_VARS) + +LOCAL_MODULE := verity_key +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +include $(BUILD_PREBUILT) diff --git a/target/product/security/verity_key b/target/product/security/verity_key Binary files differnew file mode 100644 index 0000000..8db965f --- /dev/null +++ b/target/product/security/verity_key diff --git a/target/product/security/verity_private_dev_key b/target/product/security/verity_private_dev_key new file mode 100644 index 0000000..92528e9 --- /dev/null +++ b/target/product/security/verity_private_dev_key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDQxdVrH2RB1eg5 +17/gBmLzW1Ds10RG6ctNZMhxppMOLnEZViKGv1VNRhxqK/JKTv2UujgZ94SJcDub +G+DwAwaGZKQqDYUa0VU2cng8TYPcnYGPdJ7Usckp6tdg64vns7e+VVf0dOyEovR+ +JyeYUz05OhUMYP9xJIhpA2XnXe5Ekb9iTFSYo9uBpoXDD4IY7aOqUxSbv9wMtyIp +dl+oTm0+kqRRi4KoxGHV0CzDseEUuWG/Kp/7aVF9Sg45NcC6KYvrGysUKA+Bt09O +feDn/HRpT9SfRElJa5DRms33UBUtnom15F4yd4vvFgubB0nkPOUuwfZhTFfgeuY4 +H2bHkjKbAgMBAAECggEAMpFYqkPGQvQO9cO+ZALoAM4Dgfp6PTrv1WUt7+lLAUpa +dqqYXk8F2Fu9EjJm03ziix237QI5Bhk7Nsy/5SK2d+L0qILx1JcTrsZ3PRQBdnRo +J1k2B4qwkQii9oTXNF4hiWaekUWo7E+ULOJLAuhWkf/xjTgJZ1xT9iuuiSYFSnIa +9ABNH0vCaKEkW/4ri6fdtXmO26C/ltJlnozl86x07PIFh4uBas7/40E8ykFP00CS +zdhMh+2DGyCb1Q0eJ1IfGILNatkLNEd2BHgQ7qNBkN9yShZfhvIPblr5gSUlZplX +diV20ZGLAfByKWgZZWKkwl9KzaisL/J/4dr2UlSVEQKBgQDxAYTsgoTkkP0TKzr3 +i3ljT8OuVOj6TwZVBJYe2MIJ3veivS3gWB53FpsKthbib7y8ifIakn15mQkNCK5R +7H7F5lvZCNnB6shY5Dz7nLJxKLALcAg+d12l3gTbFQeFDs0iQQJF7P8hs/GPF7kY +Layb7EF0uzYjyHJCKtFdaZaeZwKBgQDdwvCb7NJVeGTcE97etL+8acu9y4GlqKEF +o0Vkw8TjNKj/KuDkbkAk9hXxU1ZCmDU3y6r8CVHYl0Sqh08plEhkYB/j3sFy81zY +3xu/rLFysBwjeJHHlPjRTYkdKr9pABmm8NIEShvu9u8i+mpOhjbX72HxZL+i4Fou +gz58wEdBrQKBgG8CfyKdn+7UJe3tbLTXRquK8xxauhGJ0uXYPfmpZ/8596C7OOVs +UWQTQoj1hKb6RtolRCIfNbKL3hJl3D2aDG7Fg6r9m6fpqCzhvIE9FShwUF6EVRfI +zZb4JA5xqkwMnEpZ3V0uI/p3Mx3xFG3ho+8SLLhC/1YOHysBI/y+BQWjAoGAYiqQ +PkXYWhOAeleleeqDUdF3al3y1zVNimRbLJ7owjcmdEYz5YrUhEgXMIvWjIY6UKes +2gL6IynbMK3TIjHM1fojQ8jw04TdXfdtnizBJGbHHgCab8IHXwe2oZ2xu7ZapKbI +ITP5J5BSDabSdk49attB/Qy/NEeiRCK+/5RSNsUCgYAg6vX9VqMEkhPHeoFfdLGD +EQPPN6QLrQ4Zif0GKxH96znNSv0rXdNp9t0kyapdgzMuCwIEuOkCSiKgmfjTWnYO +qh5HMUuD2VbfWwI9jVujQMRmqiaFF7VxxA1bP5j1hJlI6cn1Fjlpi+NsNZN4nm3Q +92SEwX2vDgjrU0NAtFFL1Q== +-----END PRIVATE KEY----- diff --git a/target/product/verity.mk b/target/product/verity.mk new file mode 100644 index 0000000..b14eaa4 --- /dev/null +++ b/target/product/verity.mk @@ -0,0 +1,24 @@ +# +# 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. +# + +# Provides dependencies necessary for verified boot + +PRODUCT_SUPPORTS_VERITY := true +PRODUCT_VERITY_SIGNING_KEY := build/target/product/security/verity_private_dev_key +PRODUCT_VERITY_MOUNTPOINT := system + +PRODUCT_PACKAGES += \ + verity_key diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh index 46a73f8..593e5b5 100755 --- a/tools/buildinfo.sh +++ b/tools/buildinfo.sh @@ -8,6 +8,7 @@ echo "ro.build.display.id=$BUILD_DISPLAY_ID" echo "ro.build.version.incremental=$BUILD_NUMBER" echo "ro.build.version.sdk=$PLATFORM_SDK_VERSION" echo "ro.build.version.codename=$PLATFORM_VERSION_CODENAME" +echo "ro.build.version.all_codenames=$PLATFORM_VERSION_ALL_CODENAMES" echo "ro.build.version.release=$PLATFORM_VERSION" echo "ro.build.date=`date`" echo "ro.build.date.utc=`date +%s`" @@ -46,9 +47,10 @@ echo "ro.board.platform=$TARGET_BOARD_PLATFORM" echo "# ro.build.product is obsolete; use ro.product.device" echo "ro.build.product=$TARGET_DEVICE" -echo "# Do not try to parse ro.build.description or .fingerprint" +echo "# Do not try to parse description, fingerprint, or thumbprint" echo "ro.build.description=$PRIVATE_BUILD_DESC" echo "ro.build.fingerprint=$BUILD_FINGERPRINT" +echo "ro.build.thumbprint=$BUILD_THUMBPRINT" echo "ro.build.characteristics=$TARGET_AAPT_CHARACTERISTICS" echo "# end build properties" diff --git a/tools/droiddoc/templates-ds/package.cs b/tools/droiddoc/templates-ds/package.cs index ea3e4f4..d67d5d9 100644 --- a/tools/droiddoc/templates-ds/package.cs +++ b/tools/droiddoc/templates-ds/package.cs @@ -45,6 +45,7 @@ <?cs /if ?> <?cs /def ?> +<?cs call:class_table("Annotations", package.annotations) ?> <?cs call:class_table("Interfaces", package.interfaces) ?> <?cs call:class_table("Classes", package.classes) ?> <?cs call:class_table("Enums", package.enums) ?> diff --git a/tools/droiddoc/templates-sac/package.cs b/tools/droiddoc/templates-sac/package.cs index 99eaff2..abd49f1 100644 --- a/tools/droiddoc/templates-sac/package.cs +++ b/tools/droiddoc/templates-sac/package.cs @@ -45,6 +45,7 @@ <?cs /if ?> <?cs /def ?> +<?cs call:class_table("Annotations", package.annotations) ?> <?cs call:class_table("Interfaces", package.interfaces) ?> <?cs call:class_table("Classes", package.classes) ?> <?cs call:class_table("Enums", package.enums) ?> diff --git a/tools/droiddoc/templates-sdk/assets/css/resourcecards.css b/tools/droiddoc/templates-sdk/assets/css/resourcecards.css new file mode 100644 index 0000000..1222b04 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/css/resourcecards.css @@ -0,0 +1,371 @@ +/* content layout */ +.resource-widget.resource-flow-layout { + display: inline-block; + margin-right: -20px; + /* clearfix idiom */ } + .resource-widget.resource-flow-layout.col-1 { + width: 60px; } + .resource-widget.resource-flow-layout.col-2 { + width: 120px; } + .resource-widget.resource-flow-layout.col-3 { + width: 180px; } + .resource-widget.resource-flow-layout.col-4 { + width: 240px; } + .resource-widget.resource-flow-layout.col-5 { + width: 300px; } + .resource-widget.resource-flow-layout.col-6 { + width: 360px; } + .resource-widget.resource-flow-layout.col-7 { + width: 420px; } + .resource-widget.resource-flow-layout.col-8 { + width: 480px; } + .resource-widget.resource-flow-layout.col-9 { + width: 540px; } + .resource-widget.resource-flow-layout.col-10 { + width: 600px; } + .resource-widget.resource-flow-layout.col-11 { + width: 660px; } + .resource-widget.resource-flow-layout.col-12 { + width: 720px; } + .resource-widget.resource-flow-layout.col-13 { + width: 780px; } + .resource-widget.resource-flow-layout.col-14 { + width: 840px; } + .resource-widget.resource-flow-layout.col-15 { + width: 900px; } + .resource-widget.resource-flow-layout.col-16 { + width: 960px; } + .resource-widget.resource-flow-layout:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; } + * html .resource-widget.resource-flow-layout { + height: 1px; } + +.resource-card { + /* stuff that applies to all cards */ + display: -webkit-flex; + -webkit-transform: translateZ(0); + float: left; + position: relative; + margin-right: 20px; + margin-bottom: 20px; + background-color: #fff; + border-radius: 2px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); + opacity: 0.8; + overflow: hidden; + transition: 0.4s box-shadow ease, 0.4s opacity ease; + /* card templates */ + /* specific cards and customizations */ } + .resource-card .photo { + position: relative; + background-color: #eee; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + .resource-card.nophoto .photo:after { + content: ''; + display: block; + position: absolute; + left: 20px; + top: 20px; + right: 20px; + bottom: 20px; + opacity: 0.2; + background-position: center center; + background-repeat: no-repeat; + background-size: contain; } + .resource-card .icon { + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + opacity: 0; + transition: 0.4s ease; } + .resource-card:hover .icon { + opacity: 0.2; } + .resource-card:hover { + opacity: 1; + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.5); } + .resource-card.resource-card-youtube.nophoto .photo:after, .resource-card.resource-card-youtube .icon { + background-image: url(../images/card_video.png); } + .resource-card.resource-card-samples.nophoto .photo:after, .resource-card.resource-card-samples .icon { + background-image: url(../images/card_sample.png); } + .resource-card.resource-card-blog.nophoto .photo:after, .resource-card.resource-card-blog .icon { + background-image: url(../images/card_post.png); } + .resource-card.resource-card-training.nophoto .photo:after, .resource-card.resource-card-training .icon { + background-image: url(../images/card_training.png); } + .resource-card .resource-card-text { + color: #333333; } + .resource-card .title { + /*font-weight: 700;*/ + font-family: 'Roboto Condensed'; } + .resource-card .subtitle { + font-family: 'Roboto Condensed'; + text-transform: uppercase; + opacity: 0.3; } + .resource-card .abstract { + font-weight: 300; + font-family: 'Roboto'; } + .resource-card.resource-card-12x7 { + width: 700px; + height: 400px; + -webkit-flex-direction: column; } + .resource-card.resource-card-12x7 .photo { + -webkit-flex: 1 1 auto; + border-bottom: 1px solid #ddd; } + .resource-card.resource-card-12x7 .resource-card-text { + margin: 20px; + padding-right: 88px; } + .resource-card.resource-card-12x7 .icon { + position: absolute; + right: 20px; + bottom: 20px; + width: 48px; + height: 48px; } + .resource-card.resource-card-12x7 .title { + font-size: 36px; + line-height: 35px; + max-height: 70px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } + .resource-card.resource-card-12x7 .subtitle { + font-size: 18px; + line-height: 20px; + max-height: 20px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + max-height: 0; + margin-top: 0; + transition: 0.4s ease; } + .resource-card.resource-card-12x7:hover .subtitle { + margin-top: 10px; + max-height: 20px; } + .resource-card.resource-card-12x7 .abstract { + font-size: 18px; + margin-top: 0; + line-height: 25px; + max-height: 75px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + max-height: 0; + transition: 0.4s ease; } + .resource-card.resource-card-12x7:hover .abstract { + margin-top: 20px; + max-height: 75px; } + .resource-card.resource-card-8x6 { + width: 460px; + height: 340px; + -webkit-flex-direction: column; } + .resource-card.resource-card-8x6 .photo { + -webkit-flex: 1 1 auto; + border-bottom: 1px solid #ddd; } + .resource-card.resource-card-8x6 .resource-card-text { + margin: 20px; + padding-right: 88px; } + .resource-card.resource-card-8x6 .icon { + position: absolute; + right: 20px; + bottom: 20px; + width: 48px; + height: 48px; } + .resource-card.resource-card-8x6 .title { + font-size: 36px; + line-height: 35px; + max-height: 70px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } + .resource-card.resource-card-8x6 .subtitle { + font-size: 18px; + line-height: 20px; + max-height: 20px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + max-height: 0; + margin-top: 0; + transition: 0.4s ease; } + .resource-card.resource-card-8x6:hover .subtitle { + margin-top: 10px; + max-height: 20px; } + .resource-card.resource-card-8x6 .abstract { + font-size: 18px; + margin-top: 0; + line-height: 25px; + max-height: 75px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + max-height: 0; + transition: 0.4s ease; } + .resource-card.resource-card-8x6:hover .abstract { + margin-top: 20px; + max-height: 75px; } + .resource-card.resource-card-8x6 .icon { + width: 32px; + height: 32px; } + .resource-card.resource-card-8x6 .title { + font-size: 24px; + line-height: 25px; + max-height: 50px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } + .resource-card.resource-card-8x6 .abstract { + font-size: 16px; + margin-top: 10px; + line-height: 20px; + max-height: 60px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; } + .resource-card.resource-card-8x6 .subtitle { + font-size: 16px; + line-height: 20px; + max-height: 20px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + max-height: 0; + margin-top: 0; + transition: 0.4s ease; } + .resource-card.resource-card-8x6:hover .subtitle { + margin-top: 10px; + max-height: 20px; } + .resource-card.resource-card-8x6 .abstract { + font-size: 16px; + margin-top: 0; + line-height: 20px; + max-height: 60px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + max-height: 0; + transition: 0.4s ease; } + .resource-card.resource-card-8x6:hover .abstract { + margin-top: 10px; + max-height: 60px; } + .resource-card.resource-card-6x4 { + width: 340px; + height: 220px; + -webkit-flex-direction: column; } + .resource-card.resource-card-6x4 .photo { + -webkit-flex: 1 1 auto; + border-bottom: 1px solid #ddd; } + .resource-card.resource-card-6x4 .resource-card-text { + margin: 10px; + padding-right: 26px; } + .resource-card.resource-card-6x4 .icon { + position: absolute; + right: 10px; + bottom: 10px; + width: 16px; + height: 16px; } + .resource-card.resource-card-6x4 .title { + font-size: 16px; + line-height: 20px; + max-height: 40px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } + .resource-card.resource-card-6x4 .subtitle { + font-size: 13px; + line-height: 15px; + max-height: 30px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + max-height: 0; + margin-top: 0; + transition: 0.4s ease; } + .resource-card.resource-card-6x4:hover .subtitle { + max-height: 30px; } + .resource-card.resource-card-6x4 .abstract { + display: none; } + .resource-card.resource-card-6x4 .abstract { + font-size: 13px; + margin-top: 0; + line-height: 15px; + max-height: 30px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + max-height: 0; + display: block; + transition: 0.4s ease; } + .resource-card.resource-card-6x4:hover .abstract { + margin-top: 10px; + max-height: 30px; } + .resource-card.resource-card-4x3 { + width: 220px; + height: 160px; + -webkit-flex-direction: column; } + .resource-card.resource-card-4x3 .photo { + -webkit-flex: 1 1 auto; + border-bottom: 1px solid #ddd; } + .resource-card.resource-card-4x3 .resource-card-text { + margin: 10px; + padding-right: 26px; } + .resource-card.resource-card-4x3 .icon { + position: absolute; + right: 10px; + bottom: 10px; + width: 16px; + height: 16px; } + .resource-card.resource-card-4x3 .title { + font-size: 16px; + line-height: 20px; + max-height: 40px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } + .resource-card.resource-card-4x3 .subtitle { + font-size: 13px; + line-height: 15px; + max-height: 30px; + text-overflow: ellipsis; + display: -webkit-box; + overflow: hidden; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + max-height: 0; + margin-top: 0; + transition: 0.4s ease; } + .resource-card.resource-card-4x3:hover .subtitle { + max-height: 30px; } + .resource-card.resource-card-4x3 .abstract { + display: none; } diff --git a/tools/droiddoc/templates-sdk/assets/images/card_post.png b/tools/droiddoc/templates-sdk/assets/images/card_post.png Binary files differnew file mode 100644 index 0000000..e061ee9 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/card_post.png diff --git a/tools/droiddoc/templates-sdk/assets/images/card_sample.png b/tools/droiddoc/templates-sdk/assets/images/card_sample.png Binary files differnew file mode 100644 index 0000000..3dc36e0 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/card_sample.png diff --git a/tools/droiddoc/templates-sdk/assets/images/card_training.png b/tools/droiddoc/templates-sdk/assets/images/card_training.png Binary files differnew file mode 100644 index 0000000..5bb7c81 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/card_training.png diff --git a/tools/droiddoc/templates-sdk/assets/images/card_video.png b/tools/droiddoc/templates-sdk/assets/images/card_video.png Binary files differnew file mode 100644 index 0000000..807c0af --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/card_video.png diff --git a/tools/droiddoc/templates-sdk/assets/js/jd_tag_helpers.js b/tools/droiddoc/templates-sdk/assets/js/jd_tag_helpers.js new file mode 100644 index 0000000..d179cbc --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/js/jd_tag_helpers.js @@ -0,0 +1,106 @@ +function mergeArrays() { + var arr = arguments[0] || []; + for (var i = 1; i < arguments.length; i++) { + arr = arr.concat(arguments[i]); + } + return arr; +} + +var ALL_RESOURCES = mergeArrays( + DESIGN_RESOURCES, + DISTRIBUTE_RESOURCES, + GOOGLE_RESOURCES, + GUIDE_RESOURCES, + SAMPLES_RESOURCES, + TOOLS_RESOURCES, + TRAINING_RESOURCES, + YOUTUBE_RESOURCES, + BLOGGER_RESOURCES +); + +for (var i = 0; i < ALL_RESOURCES.length; i++) { + ALL_RESOURCES[i].index = i; +} + +function mergeMaps() { + var allRes = {}; + var offset = 0; + + for (var i = 0; i < arguments.length; i++) { + var r = arguments[i]; + for (var tag in r.map) { + allRes[tag] = allRes[tag] || []; + allRes[tag] = allRes[tag].concat(r.map[tag].map(function(i){ return ALL_RESOURCES[i + offset]; })); + } + offset += r.arr.length; + } + + return allRes; +} + +function setFromArray(arr) { + arr = arr || []; + var set = {}; + for (var i = 0; i < arr.length; i++) { + set[arr[i]] = true; + } + return set; +} + +function buildResourceLookupMap(resourceDict) { + var map = {}; + for (var key in resourceDict) { + var dictForKey = {}; + var srcArr = resourceDict[key]; + for (var i = 0; i < srcArr.length; i++) { + dictForKey[srcArr[i].index] = true; + } + map[key] = dictForKey; + } + return map; +} + +// Type lookups + +var ALL_RESOURCES_BY_TYPE = { + 'design': DESIGN_RESOURCES, + 'distribute': DISTRIBUTE_RESOURCES, + 'google': GOOGLE_RESOURCES, + 'guide': GUIDE_RESOURCES, + 'samples': SAMPLES_RESOURCES, + 'tools': TOOLS_RESOURCES, + 'training': TRAINING_RESOURCES, + 'youtube': YOUTUBE_RESOURCES, + 'blog': BLOGGER_RESOURCES +}; +var IS_RESOURCE_OF_TYPE = buildResourceLookupMap(ALL_RESOURCES_BY_TYPE); + +// Tag lookups + +var ALL_RESOURCES_BY_TAG = mergeMaps( + {map:DESIGN_BY_TAG,arr:DESIGN_RESOURCES}, + {map:DISTRIBUTE_BY_TAG,arr:DISTRIBUTE_RESOURCES}, + {map:GOOGLE_BY_TAG,arr:GOOGLE_RESOURCES}, + {map:GUIDE_BY_TAG,arr:GUIDE_RESOURCES}, + {map:SAMPLES_BY_TAG,arr:SAMPLES_RESOURCES}, + {map:TOOLS_BY_TAG,arr:TOOLS_RESOURCES}, + {map:TRAINING_BY_TAG,arr:TRAINING_RESOURCES}, + {map:YOUTUBE_BY_TAG,arr:YOUTUBE_RESOURCES}, + {map:BLOGGER_BY_TAG,arr:BLOGGER_RESOURCES} +); +var IS_RESOURCE_TAGGED = buildResourceLookupMap(ALL_RESOURCES_BY_TAG); + +// Language lookups + +var ALL_RESOURCES_BY_LANG = {}; +for (var i = 0; i < ALL_RESOURCES.length; i++) { + var res = ALL_RESOURCES[i]; + var lang = res.lang; + if (!lang) { + continue; + } + + ALL_RESOURCES_BY_LANG[lang] = ALL_RESOURCES_BY_LANG[lang] || []; + ALL_RESOURCES_BY_LANG[lang].push(res); +} +var IS_RESOURCE_IN_LANG = buildResourceLookupMap(ALL_RESOURCES_BY_LANG);
\ No newline at end of file diff --git a/tools/droiddoc/templates-sdk/assets/js/resourcecards.js b/tools/droiddoc/templates-sdk/assets/js/resourcecards.js new file mode 100644 index 0000000..fbba201 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/js/resourcecards.js @@ -0,0 +1,244 @@ +// Requires jd_tag_helpers.js and the data JS to be loaded. + +$(document).ready(function() { + $('.resource-widget').each(function() { + initResourceWidget(this); + }); +}); + + +function initResourceWidget(widget) { + var $widget = $(widget); + var isFlow, isCarousel; + isFlow = $widget.hasClass('resource-flow-layout'); + if (!isFlow) { + isCarousel = $widget.hasClass('resource-carousel-layout'); + } + + // find size of widget by pulling out its class name + var sizeCols = 1; + var m = $widget.get(0).className.match(/\bcol-(\d+)\b/); + if (m) { + sizeCols = parseInt(m[1], 10); + } + + var opts = { + source: $widget.data('source'), + cardSizes: ($widget.data('cardsizes') || '').split(','), + maxResults: parseInt($widget.data('maxresults') || '100'), + itemsPerPage: $widget.data('itemsperpage'), + sortOrder: $widget.data('sortorder'), + query: $widget.data('query'), + collectionId: $widget.data('collectionid'), + sizeCols: sizeCols + }; + + // run the search for the set of resources to show + var resources = buildResourceList(opts); + + if (isFlow) { + drawResourcesFlowWidget($widget, opts, resources); + } +} + + +function drawResourcesFlowWidget($widget, opts, resources) { + $widget.empty(); + var cardSizes = opts.cardSizes || ['4x3']; + + for (var i = 0; i < resources.length; i++) { + var resource = resources[i]; + + var cardSize = i >= cardSizes.length ? cardSizes[cardSizes.length - 1] : cardSizes[i]; + cardSize = cardSize.replace(/^\s+|\s+$/,''); + + var $card = $('<a>') + .addClass('resource-card resource-card-' + cardSize + ' resource-card-' + resource.type) + .attr('href', resource.url); + + $('<img>') + .addClass('photo') + .attr('src', resource.image || '') + .appendTo($card); + + var subtitle = resource.type; + if (resource.timestamp) { + var d = new Date(resource.timestamp); + // TODO: localize, humanize + subtitle = (1 + d.getMonth()) + '/' + d.getDate() + '/' + d.getFullYear() + ' on ' + subtitle; + } + + $('<div>') + .addClass('resource-card-text') + .append($('<div>').addClass('icon')) + .append($('<div>').addClass('title').text(resource.title)) + .append($('<div>').addClass('subtitle').text(subtitle)) + .append($('<div>').addClass('abstract').text(resource.summary)) + .appendTo($card); + + $card.appendTo($widget); + } + + $widget.find('.resource-card .photo').each(function() { + var src = $(this).attr('src'); + if (!src) { + $(this).parents('.resource-card').addClass('nophoto'); + $(this).replaceWith($('<div>') + .addClass('photo')); + } else { + $(this).replaceWith($('<div>') + .addClass('photo') + .css('background-image', 'url(' + $(this).attr('src') + ')')); + } + }); +} + + +function buildResourceList(opts) { + var maxResults = opts.maxResults || 100; + + switch (opts.source) { + case 'query': + var query = opts.query || ''; + var expressions = parseResourceQuery(query); + var alreadyAddedResources = {}; + var allResources = []; + for (var i = 0; i < expressions.length; i++) { + var clauses = expressions[i]; + + // build initial set of resources from first clause + var firstClause = clauses[0]; + var resources = []; + switch (firstClause.attr) { + case 'type': + resources = ALL_RESOURCES_BY_TYPE[firstClause.value]; + break; + case 'lang': + resources = ALL_RESOURCES_BY_LANG[firstClause.value]; + break; + case 'tag': + resources = ALL_RESOURCES_BY_TAG[firstClause.value]; + break; + } + resources = resources || []; + + // use additional clauses to filter corpus + if (clauses.length > 1) { + var otherClauses = clauses.slice(1); + resources = resources.filter(getResourceMatchesClausesFilter(otherClauses)); + } + + // filter out resources already added + if (i > 1) { + resources = resources.filter(getResourceNotAlreadyAddedFilter(alreadyAddedResources)); + } + + allResources = allResources.concat(resources); + if (allResources.length > maxResults) { + break; + } + } + if (opts.sortOrder) { + var attr = opts.sortOrder; + var desc = attr.charAt(0) == '-'; + if (desc) { + attr = attr.substring(1); + } + allResources = allResources.sort(function(x,y) { + return (desc ? -1 : 1) * (parseInt(x[attr], 10) - parseInt(y[attr], 10)); + }); + } + return allResources.slice(0, maxResults); + + case 'related': + // TODO + break; + + case 'collection': + // TODO + break; + } +} + + +function getResourceNotAlreadyAddedFilter(addedResources) { + return function(x) { + return !!addedResources[x]; + }; +} + + +function getResourceMatchesClausesFilter(clauses) { + return function(x) { + return doesResourceMatchClauses(x, clauses); + }; +} + + +function doesResourceMatchClauses(resource, clauses) { + for (var i = 0; i < clauses.length; i++) { + var map; + switch (clauses[i].attr) { + case 'type': + map = IS_RESOURCE_OF_TYPE[clauses[i].value]; + break; + case 'lang': + map = IS_RESOURCE_IN_LANG[clauses[i].value]; + break; + case 'tag': + map = IS_RESOURCE_TAGGED[clauses[i].value]; + break; + } + + if (!map || (!!clauses[i].negative ? map[resource.index] : !map[resource.index])) { + return false; + } + } + return true; +} + + +function parseResourceQuery(query) { + // Parse query into array of expressions (expression e.g. 'tag:foo + type:video') + var expressions = []; + var expressionStrs = query.split(',') || []; + for (var i = 0; i < expressionStrs.length; i++) { + var expr = expressionStrs[i] || ''; + + // Break expression into clauses (clause e.g. 'tag:foo') + var clauses = []; + var clauseStrs = expr.split(/(?=[\+\-])/); + for (var j = 0; j < clauseStrs.length; j++) { + var clauseStr = clauseStrs[j] || ''; + + // Get attribute and value from clause (e.g. attribute='tag', value='foo') + var parts = clauseStr.split(':'); + var clause = {}; + + clause.attr = parts[0].replace(/\s+/g,''); + if (clause.attr) { + if (clause.attr.charAt(0) == '+') { + clause.attr = clause.attr.substring(1); + } else if (clause.attr.charAt(0) == '-') { + clause.negative = true; + clause.attr = clause.attr.substring(1); + } + } + + if (parts.length > 1) { + clause.value = parts[1].replace(/\s+/g,''); + } + + clauses.push(clause); + } + + if (!clauses.length) { + continue; + } + + expressions.push(clauses); + } + + return expressions; +} + diff --git a/tools/droiddoc/templates-sdk/customizations.cs b/tools/droiddoc/templates-sdk/customizations.cs index f5f85fe..69a0d0f 100644 --- a/tools/droiddoc/templates-sdk/customizations.cs +++ b/tools/droiddoc/templates-sdk/customizations.cs @@ -268,6 +268,7 @@ def:default_left_nav() ?> <?cs if:subcount(class.package) ?> <ul> + <?cs call:list("Annotations", class.package.annotations) ?> <?cs call:list("Interfaces", class.package.interfaces) ?> <?cs call:list("Classes", class.package.classes) ?> <?cs call:list("Enums", class.package.enums) ?> @@ -276,6 +277,7 @@ def:default_left_nav() ?> </ul><?cs elif:subcount(package) ?> <ul> + <?cs call:class_link_list("Annotations", package.annotations) ?> <?cs call:class_link_list("Interfaces", package.interfaces) ?> <?cs call:class_link_list("Classes", package.classes) ?> <?cs call:class_link_list("Enums", package.enums) ?> diff --git a/tools/droiddoc/templates-sdk/head_tag.cs b/tools/droiddoc/templates-sdk/head_tag.cs index 0916b00..ff07a19 100644 --- a/tools/droiddoc/templates-sdk/head_tag.cs +++ b/tools/droiddoc/templates-sdk/head_tag.cs @@ -58,6 +58,13 @@ else </script> <script src="<?cs var:toroot ?>assets/js/docs.js" type="text/javascript"></script> +<!-- RESOURCES LIBRARY --> +<script src="<?cs if:android.whichdoc != 'online' ?>http:<?cs /if ?>//androiddevdocs-staging.appspot.com/ytblogger_lists_unified.js" type="text/javascript"></script> +<script src="<?cs var:toroot ?>jd_lists_unified.js" type="text/javascript"></script> +<script src="<?cs var:toroot ?>assets/js/jd_tag_helpers.js" type="text/javascript"></script> +<link href="<?cs var:toroot ?>assets/css/resourcecards.css" rel="stylesheet" type="text/css" /> +<script src="<?cs var:toroot ?>assets/js/resourcecards.js" type="text/javascript"></script> + <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-5831155-1']); diff --git a/tools/droiddoc/templates-sdk/package.cs b/tools/droiddoc/templates-sdk/package.cs index 99eaff2..abd49f1 100644 --- a/tools/droiddoc/templates-sdk/package.cs +++ b/tools/droiddoc/templates-sdk/package.cs @@ -45,6 +45,7 @@ <?cs /if ?> <?cs /def ?> +<?cs call:class_table("Annotations", package.annotations) ?> <?cs call:class_table("Interfaces", package.interfaces) ?> <?cs call:class_table("Classes", package.classes) ?> <?cs call:class_table("Enums", package.enums) ?> diff --git a/tools/post_process_props.py b/tools/post_process_props.py index 5d1b350..e43ca59 100755 --- a/tools/post_process_props.py +++ b/tools/post_process_props.py @@ -16,6 +16,9 @@ import sys +# Usage: post_process_props.py file.prop [blacklist_key, ...] +# Blacklisted keys are removed from the property file, if present + # See PROP_VALUE_MAX system_properties.h. # PROP_VALUE_MAX in system_properties.h includes the termination NUL, # so we decrease it by 1 here. @@ -82,8 +85,9 @@ class PropFile: for line in self.lines: if not line or line.startswith("#"): continue - key, value = line.split("=", 1) - props[key] = value + if "=" in line: + key, value = line.split("=", 1) + props[key] = value return props def get(self, name): @@ -101,6 +105,10 @@ class PropFile: return self.lines.append(key + value) + def delete(self, name): + key = name + "=" + self.lines = [ line for line in self.lines if not line.startswith(key) ] + def write(self, f): f.write("\n".join(self.lines)) f.write("\n") @@ -124,6 +132,10 @@ def main(argv): if not validate(properties): sys.exit(1) + # Drop any blacklisted keys + for key in argv[2:]: + properties.delete(key) + f = open(filename, 'w+') properties.write(f) f.close() diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py index f8f2ada..2fb9e23 100755 --- a/tools/releasetools/build_image.py +++ b/tools/releasetools/build_image.py @@ -24,6 +24,10 @@ import os import os.path import subprocess import sys +import commands +import shutil + +import simg_map def RunCommand(cmd): """ Echo and run the given command @@ -38,6 +42,171 @@ def RunCommand(cmd): p.communicate() return p.returncode +def GetVerityTreeSize(partition_size): + cmd = "build_verity_tree -s %d" + cmd %= partition_size + status, output = commands.getstatusoutput(cmd) + if status: + print output + return False, 0 + return True, int(output) + +def GetVerityMetadataSize(partition_size): + cmd = "system/extras/verity/build_verity_metadata.py -s %d" + cmd %= partition_size + status, output = commands.getstatusoutput(cmd) + if status: + print output + return False, 0 + return True, int(output) + +def AdjustPartitionSizeForVerity(partition_size): + """Modifies the provided partition size to account for the verity metadata. + + This information is used to size the created image appropriately. + Args: + partition_size: the size of the partition to be verified. + Returns: + The size of the partition adjusted for verity metadata. + """ + success, verity_tree_size = GetVerityTreeSize(partition_size) + if not success: + return 0; + success, verity_metadata_size = GetVerityMetadataSize(partition_size) + if not success: + return 0 + return partition_size - verity_tree_size - verity_metadata_size + +def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict): + cmd = ("build_verity_tree %s %s" % (sparse_image_path, verity_image_path)) + print cmd + status, output = commands.getstatusoutput(cmd) + if status: + print "Could not build verity tree! Error: %s" % output + return False + root, salt = output.split() + prop_dict["verity_root_hash"] = root + prop_dict["verity_salt"] = salt + return True + +def BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt, + block_device, signer_path, key): + cmd = ("system/extras/verity/build_verity_metadata.py %s %s %s %s %s %s %s" % + (image_size, + verity_metadata_path, + root_hash, + salt, + block_device, + signer_path, + key)) + print cmd + status, output = commands.getstatusoutput(cmd) + if status: + print "Could not build verity metadata! Error: %s" % output + return False + return True + +def Append2Simg(sparse_image_path, unsparse_image_path, error_message): + """Appends the unsparse image to the given sparse image. + + Args: + sparse_image_path: the path to the (sparse) image + unsparse_image_path: the path to the (unsparse) image + Returns: + True on success, False on failure. + """ + cmd = "append2simg %s %s" + cmd %= (sparse_image_path, unsparse_image_path) + print cmd + status, output = commands.getstatusoutput(cmd) + if status: + print "%s: %s" % (error_message, output) + return False + return True + +def BuildVerifiedImage(data_image_path, verity_image_path, verity_metadata_path): + if not Append2Simg(data_image_path, verity_metadata_path, "Could not append verity metadata!"): + return False + if not Append2Simg(data_image_path, verity_image_path, "Could not append verity tree!"): + return False + return True + +def UnsparseImage(sparse_image_path, replace=True): + img_dir = os.path.dirname(sparse_image_path) + unsparse_image_path = "unsparse_" + os.path.basename(sparse_image_path) + unsparse_image_path = os.path.join(img_dir, unsparse_image_path) + if os.path.exists(unsparse_image_path): + if replace: + os.unlink(unsparse_image_path) + else: + return True, unsparse_image_path + inflate_command = ["simg2img", sparse_image_path, unsparse_image_path] + exit_code = RunCommand(inflate_command) + if exit_code != 0: + os.remove(unsparse_image_path) + return False, None + return True, unsparse_image_path + +def MappedUnsparseImage(sparse_image_path, unsparse_image_path, + map_path, mapped_unsparse_image_path): + if simg_map.ComputeMap(sparse_image_path, unsparse_image_path, + map_path, mapped_unsparse_image_path): + return False + return True + +def MakeVerityEnabledImage(out_file, prop_dict): + """Creates an image that is verifiable using dm-verity. + + Args: + out_file: the location to write the verifiable image at + prop_dict: a dictionary of properties required for image creation and verification + Returns: + True on success, False otherwise. + """ + # get properties + image_size = prop_dict["partition_size"] + block_dev = prop_dict["verity_block_device"] + signer_key = prop_dict["verity_key"] + signer_path = prop_dict["verity_signer_cmd"] + + # make a tempdir + tempdir_name = os.path.join(os.path.dirname(out_file), "verity_images") + if os.path.exists(tempdir_name): + shutil.rmtree(tempdir_name) + os.mkdir(tempdir_name) + + # get partial image paths + verity_image_path = os.path.join(tempdir_name, "verity.img") + verity_metadata_path = os.path.join(tempdir_name, "verity_metadata.img") + + # build the verity tree and get the root hash and salt + if not BuildVerityTree(out_file, verity_image_path, prop_dict): + shutil.rmtree(tempdir_name) + return False + + # build the metadata blocks + root_hash = prop_dict["verity_root_hash"] + salt = prop_dict["verity_salt"] + if not BuildVerityMetadata(image_size, + verity_metadata_path, + root_hash, + salt, + block_dev, + signer_path, + signer_key): + shutil.rmtree(tempdir_name) + return False + + # build the full verified image + if not BuildVerifiedImage(out_file, + verity_image_path, + verity_metadata_path): + shutil.rmtree(tempdir_name) + return False + + shutil.rmtree(tempdir_name) + return True + def BuildImage(in_dir, prop_dict, out_file): """Build an image to out_file from in_dir with property prop_dict. @@ -52,6 +221,18 @@ def BuildImage(in_dir, prop_dict, out_file): build_command = [] fs_type = prop_dict.get("fs_type", "") run_fsck = False + + is_verity_partition = prop_dict.get("mount_point") == prop_dict.get("verity_mountpoint") + verity_supported = prop_dict.get("verity") == "true" + # adjust the partition size to make room for the hashes if this is to be verified + if verity_supported and is_verity_partition: + partition_size = int(prop_dict.get("partition_size")) + adjusted_size = AdjustPartitionSizeForVerity(partition_size) + if not adjusted_size: + return False + prop_dict["partition_size"] = str(adjusted_size) + prop_dict["original_partition_size"] = str(partition_size) + if fs_type.startswith("ext"): build_command = ["mkuserimg.sh"] if "extfs_sparse_flag" in prop_dict: @@ -59,8 +240,9 @@ def BuildImage(in_dir, prop_dict, out_file): run_fsck = True build_command.extend([in_dir, out_file, fs_type, prop_dict["mount_point"]]) - if "partition_size" in prop_dict: - build_command.append(prop_dict["partition_size"]) + build_command.append(prop_dict["partition_size"]) + if "timestamp" in prop_dict: + build_command.extend(["-T", str(prop_dict["timestamp"])]) if "selinux_fc" in prop_dict: build_command.append(prop_dict["selinux_fc"]) else: @@ -77,14 +259,14 @@ def BuildImage(in_dir, prop_dict, out_file): if exit_code != 0: return False + # create the verified image if this is to be verified + if verity_supported and is_verity_partition: + if not MakeVerityEnabledImage(out_file, prop_dict): + return False + if run_fsck and prop_dict.get("skip_fsck") != "true": - # Inflate the sparse image - unsparse_image = os.path.join( - os.path.dirname(out_file), "unsparse_" + os.path.basename(out_file)) - inflate_command = ["simg2img", out_file, unsparse_image] - exit_code = RunCommand(inflate_command) - if exit_code != 0: - os.remove(unsparse_image) + success, unsparse_image = UnsparseImage(out_file, replace=False) + if not success: return False # Run e2fsck on the inflated image file @@ -104,6 +286,10 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): mount_point: such as "system", "data" etc. """ d = {} + if "build.prop" in glob_dict: + bp = glob_dict["build.prop"] + if "ro.build.date.utc" in bp: + d["timestamp"] = bp["ro.build.date.utc"] def copy_prop(src_p, dest_p): if src_p in glob_dict: @@ -114,6 +300,11 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): "mkyaffs2_extra_flags", "selinux_fc", "skip_fsck", + "verity", + "verity_block_device", + "verity_key", + "verity_signer_cmd", + "verity_mountpoint" ) for p in common_props: copy_prop(p, p) @@ -131,6 +322,9 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): elif mount_point == "vendor": copy_prop("vendor_fs_type", "fs_type") copy_prop("vendor_size", "partition_size") + elif mount_point == "oem": + copy_prop("fs_type", "fs_type") + copy_prop("oem_size", "partition_size") return d @@ -169,6 +363,8 @@ def main(argv): mount_point = "cache" elif image_filename == "vendor.img": mount_point = "vendor" + elif image_filename == "oem.img": + mount_point = "oem" else: print >> sys.stderr, "error: unknown image file name ", image_filename exit(1) diff --git a/tools/releasetools/check_target_files_signatures b/tools/releasetools/check_target_files_signatures index 45d30a6..b2f46c1 100755 --- a/tools/releasetools/check_target_files_signatures +++ b/tools/releasetools/check_target_files_signatures @@ -41,8 +41,8 @@ Usage: check_target_file_signatures [flags] target_files import sys -if sys.hexversion < 0x02040000: - print >> sys.stderr, "Python 2.4 or newer is required." +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." sys.exit(1) import os diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index f179717..fea335e 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -84,17 +84,24 @@ def CloseInheritedPipes(): pass -def LoadInfoDict(zip): +def LoadInfoDict(input): """Read and parse the META/misc_info.txt key/value pairs from the input target files and return a dict.""" + def read_helper(fn): + if isinstance(input, zipfile.ZipFile): + return input.read(fn) + else: + path = os.path.join(input, *fn.split("/")) + try: + with open(path) as f: + return f.read() + except IOError, e: + if e.errno == errno.ENOENT: + raise KeyError(fn) d = {} try: - for line in zip.read("META/misc_info.txt").split("\n"): - line = line.strip() - if not line or line.startswith("#"): continue - k, v = line.split("=", 1) - d[k] = v + d = LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("\n")) except KeyError: # ok if misc_info.txt doesn't exist pass @@ -105,20 +112,20 @@ def LoadInfoDict(zip): if "mkyaffs2_extra_flags" not in d: try: - d["mkyaffs2_extra_flags"] = zip.read("META/mkyaffs2-extra-flags.txt").strip() + d["mkyaffs2_extra_flags"] = read_helper("META/mkyaffs2-extra-flags.txt").strip() except KeyError: # ok if flags don't exist pass if "recovery_api_version" not in d: try: - d["recovery_api_version"] = zip.read("META/recovery-api-version.txt").strip() + d["recovery_api_version"] = read_helper("META/recovery-api-version.txt").strip() except KeyError: raise ValueError("can't find recovery API version in input target-files") if "tool_extensions" not in d: try: - d["tool_extensions"] = zip.read("META/tool-extensions.txt").strip() + d["tool_extensions"] = read_helper("META/tool-extensions.txt").strip() except KeyError: # ok if extensions don't exist pass @@ -127,7 +134,7 @@ def LoadInfoDict(zip): d["fstab_version"] = "1" try: - data = zip.read("META/imagesizes.txt") + data = read_helper("META/imagesizes.txt") for line in data.split("\n"): if not line: continue name, value = line.split(" ", 1) @@ -152,33 +159,36 @@ def LoadInfoDict(zip): makeint("boot_size") makeint("fstab_version") - d["fstab"] = LoadRecoveryFSTab(zip, d["fstab_version"]) - d["build.prop"] = LoadBuildProp(zip) + d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"]) + d["build.prop"] = LoadBuildProp(read_helper) return d -def LoadBuildProp(zip): +def LoadBuildProp(read_helper): try: - data = zip.read("SYSTEM/build.prop") + data = read_helper("SYSTEM/build.prop") except KeyError: print "Warning: could not find SYSTEM/build.prop in %s" % zip data = "" + return LoadDictionaryFromLines(data.split("\n")) +def LoadDictionaryFromLines(lines): d = {} - for line in data.split("\n"): + for line in lines: line = line.strip() if not line or line.startswith("#"): continue - name, value = line.split("=", 1) - d[name] = value + if "=" in line: + name, value = line.split("=", 1) + d[name] = value return d -def LoadRecoveryFSTab(zip, fstab_version): +def LoadRecoveryFSTab(read_helper, fstab_version): class Partition(object): pass try: - data = zip.read("RECOVERY/RAMDISK/etc/recovery.fstab") + data = read_helper("RECOVERY/RAMDISK/etc/recovery.fstab") except KeyError: - print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab in %s." % zip + print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab" data = "" if fstab_version == 1: @@ -342,9 +352,12 @@ def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir, else: print "building image from target_files %s..." % (tree_subdir,) fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt" - return File(name, BuildBootableImage(os.path.join(unpack_dir, tree_subdir), - os.path.join(unpack_dir, fs_config), - info_dict)) + data = BuildBootableImage(os.path.join(unpack_dir, tree_subdir), + os.path.join(unpack_dir, fs_config), + info_dict) + if data: + return File(name, data) + return None def UnzipTemp(filename, pattern=None): @@ -725,11 +738,14 @@ class PasswordManager(object): return result -def ZipWriteStr(zip, filename, data, perms=0644): +def ZipWriteStr(zip, filename, data, perms=0644, compression=None): # use a fixed timestamp so the output is repeatable. zinfo = zipfile.ZipInfo(filename=filename, date_time=(2009, 1, 1, 0, 0, 0)) - zinfo.compress_type = zip.compression + if compression is None: + zinfo.compress_type = zip.compression + else: + zinfo.compress_type = compression zinfo.external_attr = perms << 16 zip.writestr(zinfo, data) @@ -756,6 +772,7 @@ class DeviceSpecificParams(object): if x == ".py": f = b info = imp.find_module(f, [d]) + print "loaded device-specific extensions from", path self.module = imp.load_module("device_specific", *info) except ImportError: print "unable to load device-specific module; assuming none" @@ -834,8 +851,8 @@ class File(object): t.flush() return t - def AddToZip(self, z): - ZipWriteStr(z, self.name, self.data) + def AddToZip(self, z, compression=None): + ZipWriteStr(z, self.name, self.data, compression=compression) DIFF_PROGRAM_BY_EXT = { ".gz" : "imgdiff", @@ -972,3 +989,95 @@ def ParseCertificate(data): save = True cert = "".join(cert).decode('base64') return cert + +def XDelta3(source_path, target_path, output_path): + diff_program = ["xdelta3", "-0", "-B", str(64<<20), "-e", "-f", "-s"] + diff_program.append(source_path) + diff_program.append(target_path) + diff_program.append(output_path) + p = Run(diff_program, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + p.communicate() + assert p.returncode == 0, "Couldn't produce patch" + +def XZ(path): + compress_program = ["xz", "-zk", "-9", "--check=crc32"] + compress_program.append(path) + p = Run(compress_program, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + p.communicate() + assert p.returncode == 0, "Couldn't compress patch" + +def MakeSystemPatch(source_file, target_file): + with tempfile.NamedTemporaryFile() as output_file: + XDelta3(source_file.name, target_file.name, output_file.name) + XZ(output_file.name) + with open(output_file.name + ".xz") as patch_file: + patch_data = patch_file.read() + os.unlink(patch_file.name) + return File("system.muimg.p", patch_data) + +def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img, + info_dict=None): + """Generate a binary patch that creates the recovery image starting + with the boot image. (Most of the space in these images is just the + kernel, which is identical for the two, so the resulting patch + should be efficient.) Add it to the output zip, along with a shell + script that is run from init.rc on first boot to actually do the + patching and install the new recovery image. + + recovery_img and boot_img should be File objects for the + corresponding images. info should be the dictionary returned by + common.LoadInfoDict() on the input target_files. + """ + + if info_dict is None: + info_dict = OPTIONS.info_dict + + diff_program = ["imgdiff"] + path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat") + if os.path.exists(path): + diff_program.append("-b") + diff_program.append(path) + bonus_args = "-b /system/etc/recovery-resource.dat" + else: + bonus_args = "" + + d = Difference(recovery_img, boot_img, diff_program=diff_program) + _, _, patch = d.ComputePatch() + output_sink("recovery-from-boot.p", patch) + + boot_type, boot_device = GetTypeAndDevice("/boot", info_dict) + recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict) + + sh = """#!/system/bin/sh +if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then + applypatch %(bonus_args)s %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p && log -t recovery "Installing new recovery image: succeeded" || log -t recovery "Installing new recovery image: failed" +else + log -t recovery "Recovery image already installed" +fi +""" % { 'boot_size': boot_img.size, + 'boot_sha1': boot_img.sha1, + 'recovery_size': recovery_img.size, + 'recovery_sha1': recovery_img.sha1, + 'boot_type': boot_type, + 'boot_device': boot_device, + 'recovery_type': recovery_type, + 'recovery_device': recovery_device, + 'bonus_args': bonus_args, + } + + # The install script location moved from /system/etc to /system/bin + # in the L release. Parse the init.rc file to find out where the + # target-files expects it to be, and put it there. + sh_location = "etc/install-recovery.sh" + try: + with open(os.path.join(input_dir, "BOOT", "RAMDISK", "init.rc")) as f: + for line in f: + m = re.match("^service flash_recovery /system/(\S+)\s*$", line) + if m: + sh_location = m.group(1) + print "putting script in", sh_location + break + except (OSError, IOError), e: + print "failed to read init.rc: %s" % (e,) + + output_sink(sh_location, sh) diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py index 426b713..f6b30e0 100644 --- a/tools/releasetools/edify_generator.py +++ b/tools/releasetools/edify_generator.py @@ -68,6 +68,19 @@ class EdifyGenerator(object): with temporary=True) to this one.""" self.script.extend(other.script) + def AssertOemProperty(self, name, value): + """Assert that a property on the OEM paritition matches a value.""" + if not name: + raise ValueError("must specify an OEM property") + if not value: + raise ValueError("must specify the OEM value") + cmd = ('file_getprop("/oem/oem.prop", "%s") == "%s" || ' + 'abort("This package expects the value \\"%s\\" for ' + '\\"%s\\" on the OEM partition; ' + 'this has value \\"" + file_getprop("/oem/oem.prop") + "\\".");' + ) % (name, value, name, value) + self.script.append(cmd) + def AssertSomeFingerprint(self, *fp): """Assert that the current system build fingerprint is one of *fp.""" if not fp: @@ -81,6 +94,19 @@ class EdifyGenerator(object): ) % (" or ".join(fp),) self.script.append(cmd) + def AssertSomeThumbprint(self, *fp): + """Assert that the current system build thumbprint is one of *fp.""" + if not fp: + raise ValueError("must specify some thumbprints") + cmd = ( + ' ||\n '.join([('file_getprop("/system/build.prop", ' + '"ro.build.thumbprint") == "%s"') + % i for i in fp]) + + ' ||\n abort("Package expects build thumbprint of %s; this ' + 'device has " + getprop("ro.build.thumbprint") + ".");' + ) % (" or ".join(fp),) + self.script.append(cmd) + def AssertOlderBuild(self, timestamp, timestamp_text): """Assert that the build on the device is older (or the same as) the given timestamp.""" @@ -178,6 +204,16 @@ class EdifyGenerator(object): (p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device, p.length, p.mount_point)) + def WipeBlockDevice(self, partition): + if partition != "/system": + raise ValueError(("WipeBlockDevice currently only works " + "on /system, not %s\n") % (partition,)) + fstab = self.info.get("fstab", None) + size = self.info.get("system_size", None) + device = fstab[partition].device + + self.script.append('wipe_block_device("%s", %s);' % (device, size)) + def DeleteFiles(self, file_list): """Delete all files in file_list.""" if not file_list: return @@ -212,7 +248,7 @@ class EdifyGenerator(object): cmd = "".join(cmd) self.script.append(self._WordWrap(cmd)) - def WriteRawImage(self, mount_point, fn): + def WriteRawImage(self, mount_point, fn, mapfn=None): """Write the given package file into the partition for the given mount point.""" @@ -226,8 +262,13 @@ class EdifyGenerator(object): 'write_raw_image(package_extract_file("%(fn)s"), "%(device)s");' % args) elif partition_type == "EMMC": - self.script.append( - 'package_extract_file("%(fn)s", "%(device)s");' % args) + if mapfn: + args["map"] = mapfn + self.script.append( + 'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args) + else: + self.script.append( + 'package_extract_file("%(fn)s", "%(device)s");' % args) else: raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type,)) @@ -293,6 +334,13 @@ class EdifyGenerator(object): if input_path is None: data = input_zip.read("OTA/bin/updater") else: - data = open(os.path.join(input_path, "updater")).read() + data = open(input_path, "rb").read() common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary", data, perms=0755) + + def Syspatch(self, filename, target_mapfile, target_sha, + source_mapfile, source_sha, patchfile): + """Applies a compressed binary patch to a block device.""" + call = 'syspatch("%s", "%s", "%s", "%s", "%s", "%s");' + self.script.append(call % (filename, target_mapfile, target_sha, + source_mapfile, source_sha, patchfile)) diff --git a/tools/releasetools/img_from_target_files b/tools/releasetools/img_from_target_files index e894c42..afaf24b 100755..120000 --- a/tools/releasetools/img_from_target_files +++ b/tools/releasetools/img_from_target_files @@ -1,270 +1 @@ -#!/usr/bin/env python -# -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Given a target-files zipfile, produces an image zipfile suitable for -use with 'fastboot update'. - -Usage: img_from_target_files [flags] input_target_files output_image_zip - - -b (--board_config) <file> - Deprecated. - - -z (--bootable_zip) - Include only the bootable images (eg 'boot' and 'recovery') in - the output. - -""" - -import sys - -if sys.hexversion < 0x02040000: - print >> sys.stderr, "Python 2.4 or newer is required." - sys.exit(1) - -import errno -import os -import re -import shutil -import subprocess -import tempfile -import zipfile - -# missing in Python 2.4 and before -if not hasattr(os, "SEEK_SET"): - os.SEEK_SET = 0 - -import build_image -import common - -OPTIONS = common.OPTIONS - - -def AddSystem(output_zip): - """Turn the contents of SYSTEM into a system image and store it in - output_zip.""" - - print "creating system.img..." - - img = tempfile.NamedTemporaryFile() - - # The name of the directory it is making an image out of matters to - # mkyaffs2image. It wants "system" but we have a directory named - # "SYSTEM", so create a symlink. - try: - os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"), - os.path.join(OPTIONS.input_tmp, "system")) - except OSError, e: - # bogus error on my mac version? - # File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem - # os.path.join(OPTIONS.input_tmp, "system")) - # OSError: [Errno 17] File exists - if (e.errno == errno.EEXIST): - pass - - image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, - "system") - fstab = OPTIONS.info_dict["fstab"] - if fstab: - image_props["fs_type" ] = fstab["/system"].fs_type - succ = build_image.BuildImage(os.path.join(OPTIONS.input_tmp, "system"), - image_props, img.name) - assert succ, "build system.img image failed" - - img.seek(os.SEEK_SET, 0) - data = img.read() - img.close() - - common.CheckSize(data, "system.img", OPTIONS.info_dict) - common.ZipWriteStr(output_zip, "system.img", data) - - -def AddVendor(output_zip): - """Turn the contents of VENDOR into vendor.img and store it in - output_zip.""" - - image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, - "vendor") - # The build system has to explicitly request for vendor.img. - if "fs_type" not in image_props: - return - - print "creating vendor.img..." - - img = tempfile.NamedTemporaryFile() - - # The name of the directory it is making an image out of matters to - # mkyaffs2image. It wants "vendor" but we have a directory named - # "VENDOR", so create a symlink or an empty directory if VENDOR does not - # exist. - if not os.path.exists(os.path.join(OPTIONS.input_tmp, "vendor")): - if os.path.exists(os.path.join(OPTIONS.input_tmp, "VENDOR")): - os.symlink(os.path.join(OPTIONS.input_tmp, "VENDOR"), - os.path.join(OPTIONS.input_tmp, "vendor")) - else: - os.mkdir(os.path.join(OPTIONS.input_tmp, "vendor")) - - img = tempfile.NamedTemporaryFile() - - fstab = OPTIONS.info_dict["fstab"] - if fstab: - image_props["fs_type" ] = fstab["/vendor"].fs_type - succ = build_image.BuildImage(os.path.join(OPTIONS.input_tmp, "vendor"), - image_props, img.name) - assert succ, "build vendor.img image failed" - - common.CheckSize(img.name, "vendor.img", OPTIONS.info_dict) - output_zip.write(img.name, "vendor.img") - img.close() - - -def AddUserdata(output_zip): - """Create an empty userdata image and store it in output_zip.""" - - image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, - "data") - # If no userdata_size is provided for extfs, skip userdata.img. - if (image_props.get("fs_type", "").startswith("ext") and - not image_props.get("partition_size")): - return - - print "creating userdata.img..." - - # The name of the directory it is making an image out of matters to - # mkyaffs2image. So we create a temp dir, and within it we create an - # empty dir named "data", and build the image from that. - temp_dir = tempfile.mkdtemp() - user_dir = os.path.join(temp_dir, "data") - os.mkdir(user_dir) - img = tempfile.NamedTemporaryFile() - - fstab = OPTIONS.info_dict["fstab"] - if fstab: - image_props["fs_type" ] = fstab["/data"].fs_type - succ = build_image.BuildImage(user_dir, image_props, img.name) - assert succ, "build userdata.img image failed" - - common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict) - output_zip.write(img.name, "userdata.img") - img.close() - os.rmdir(user_dir) - os.rmdir(temp_dir) - - -def AddCache(output_zip): - """Create an empty cache image and store it in output_zip.""" - - image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, - "cache") - # The build system has to explicitly request for cache.img. - if "fs_type" not in image_props: - return - - print "creating cache.img..." - - # The name of the directory it is making an image out of matters to - # mkyaffs2image. So we create a temp dir, and within it we create an - # empty dir named "cache", and build the image from that. - temp_dir = tempfile.mkdtemp() - user_dir = os.path.join(temp_dir, "cache") - os.mkdir(user_dir) - img = tempfile.NamedTemporaryFile() - - fstab = OPTIONS.info_dict["fstab"] - if fstab: - image_props["fs_type" ] = fstab["/cache"].fs_type - succ = build_image.BuildImage(user_dir, image_props, img.name) - assert succ, "build cache.img image failed" - - common.CheckSize(img.name, "cache.img", OPTIONS.info_dict) - output_zip.write(img.name, "cache.img") - img.close() - os.rmdir(user_dir) - os.rmdir(temp_dir) - - -def CopyInfo(output_zip): - """Copy the android-info.txt file from the input to the output.""" - output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"), - "android-info.txt") - - -def main(argv): - bootable_only = [False] - - def option_handler(o, a): - if o in ("-b", "--board_config"): - pass # deprecated - if o in ("-z", "--bootable_zip"): - bootable_only[0] = True - else: - return False - return True - - args = common.ParseOptions(argv, __doc__, - extra_opts="b:z", - extra_long_opts=["board_config=", - "bootable_zip"], - extra_option_handler=option_handler) - - bootable_only = bootable_only[0] - - if len(args) != 2: - common.Usage(__doc__) - sys.exit(1) - - OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0]) - OPTIONS.info_dict = common.LoadInfoDict(input_zip) - - # If this image was originally labelled with SELinux contexts, make sure we - # also apply the labels in our new image. During building, the "file_contexts" - # is in the out/ directory tree, but for repacking from target-files.zip it's - # in the root directory of the ramdisk. - if "selinux_fc" in OPTIONS.info_dict: - OPTIONS.info_dict["selinux_fc"] = os.path.join(OPTIONS.input_tmp, "BOOT", "RAMDISK", - "file_contexts") - - output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) - - common.GetBootableImage( - "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT").AddToZip(output_zip) - common.GetBootableImage( - "recovery.img", "recovery.img", OPTIONS.input_tmp, - "RECOVERY").AddToZip(output_zip) - - if not bootable_only: - AddSystem(output_zip) - AddVendor(output_zip) - AddUserdata(output_zip) - AddCache(output_zip) - CopyInfo(output_zip) - - print "cleaning up..." - output_zip.close() - shutil.rmtree(OPTIONS.input_tmp) - - print "done." - - -if __name__ == '__main__': - try: - common.CloseInheritedPipes() - main(sys.argv[1:]) - except common.ExternalError, e: - print - print " ERROR: %s" % (e,) - print - sys.exit(1) +img_from_target_files.py
\ No newline at end of file diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py new file mode 100755 index 0000000..596a47e --- /dev/null +++ b/tools/releasetools/img_from_target_files.py @@ -0,0 +1,301 @@ +#!/usr/bin/env python +# +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Given a target-files zipfile, produces an image zipfile suitable for +use with 'fastboot update'. + +Usage: img_from_target_files [flags] input_target_files output_image_zip + + -b (--board_config) <file> + Deprecated. + + -z (--bootable_zip) + Include only the bootable images (eg 'boot' and 'recovery') in + the output. + +""" + +import sys + +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." + sys.exit(1) + +import errno +import os +import re +import shutil +import subprocess +import tempfile +import zipfile + +# missing in Python 2.4 and before +if not hasattr(os, "SEEK_SET"): + os.SEEK_SET = 0 + +import build_image +import common + +OPTIONS = common.OPTIONS + + +def AddSystem(output_zip, sparse=True): + """Turn the contents of SYSTEM into a system image and store it in + output_zip.""" + data = BuildSystem(OPTIONS.input_tmp, OPTIONS.info_dict, sparse=sparse) + common.ZipWriteStr(output_zip, "system.img", data) + + +def BuildSystem(input_dir, info_dict, sparse=True, map_file=None): + print "creating system.img..." + + img = tempfile.NamedTemporaryFile() + + # The name of the directory it is making an image out of matters to + # mkyaffs2image. It wants "system" but we have a directory named + # "SYSTEM", so create a symlink. + try: + os.symlink(os.path.join(input_dir, "SYSTEM"), + os.path.join(input_dir, "system")) + except OSError, e: + # bogus error on my mac version? + # File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem + # os.path.join(OPTIONS.input_tmp, "system")) + # OSError: [Errno 17] File exists + if (e.errno == errno.EEXIST): + pass + + image_props = build_image.ImagePropFromGlobalDict(info_dict, "system") + fstab = info_dict["fstab"] + if fstab: + image_props["fs_type" ] = fstab["/system"].fs_type + succ = build_image.BuildImage(os.path.join(input_dir, "system"), + image_props, img.name) + assert succ, "build system.img image failed" + + mapdata = None + + if sparse: + img.seek(os.SEEK_SET, 0) + data = img.read() + img.close() + else: + success, name = build_image.UnsparseImage(img.name, replace=False) + if not success: + assert False, "unsparsing system.img failed" + + if map_file: + mmap = tempfile.NamedTemporaryFile() + mimg = tempfile.NamedTemporaryFile(delete=False) + success = build_image.MappedUnsparseImage( + img.name, name, mmap.name, mimg.name) + if not success: + assert False, "creating sparse map failed" + os.unlink(name) + name = mimg.name + + with open(mmap.name) as f: + mapdata = f.read() + + try: + with open(name) as f: + data = f.read() + finally: + os.unlink(name) + + if mapdata is None: + return data + else: + return mapdata, data + + +def AddVendor(output_zip): + """Turn the contents of VENDOR into vendor.img and store it in + output_zip.""" + + image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, + "vendor") + # The build system has to explicitly request for vendor.img. + if "fs_type" not in image_props: + return + + print "creating vendor.img..." + + img = tempfile.NamedTemporaryFile() + + # The name of the directory it is making an image out of matters to + # mkyaffs2image. It wants "vendor" but we have a directory named + # "VENDOR", so create a symlink or an empty directory if VENDOR does not + # exist. + if not os.path.exists(os.path.join(OPTIONS.input_tmp, "vendor")): + if os.path.exists(os.path.join(OPTIONS.input_tmp, "VENDOR")): + os.symlink(os.path.join(OPTIONS.input_tmp, "VENDOR"), + os.path.join(OPTIONS.input_tmp, "vendor")) + else: + os.mkdir(os.path.join(OPTIONS.input_tmp, "vendor")) + + img = tempfile.NamedTemporaryFile() + + fstab = OPTIONS.info_dict["fstab"] + if fstab: + image_props["fs_type" ] = fstab["/vendor"].fs_type + succ = build_image.BuildImage(os.path.join(OPTIONS.input_tmp, "vendor"), + image_props, img.name) + assert succ, "build vendor.img image failed" + + common.CheckSize(img.name, "vendor.img", OPTIONS.info_dict) + output_zip.write(img.name, "vendor.img") + img.close() + + +def AddUserdata(output_zip): + """Create an empty userdata image and store it in output_zip.""" + + image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, + "data") + # If no userdata_size is provided for extfs, skip userdata.img. + if (image_props.get("fs_type", "").startswith("ext") and + not image_props.get("partition_size")): + return + + print "creating userdata.img..." + + # The name of the directory it is making an image out of matters to + # mkyaffs2image. So we create a temp dir, and within it we create an + # empty dir named "data", and build the image from that. + temp_dir = tempfile.mkdtemp() + user_dir = os.path.join(temp_dir, "data") + os.mkdir(user_dir) + img = tempfile.NamedTemporaryFile() + + fstab = OPTIONS.info_dict["fstab"] + if fstab: + image_props["fs_type" ] = fstab["/data"].fs_type + succ = build_image.BuildImage(user_dir, image_props, img.name) + assert succ, "build userdata.img image failed" + + common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict) + output_zip.write(img.name, "userdata.img") + img.close() + os.rmdir(user_dir) + os.rmdir(temp_dir) + + +def AddCache(output_zip): + """Create an empty cache image and store it in output_zip.""" + + image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, + "cache") + # The build system has to explicitly request for cache.img. + if "fs_type" not in image_props: + return + + print "creating cache.img..." + + # The name of the directory it is making an image out of matters to + # mkyaffs2image. So we create a temp dir, and within it we create an + # empty dir named "cache", and build the image from that. + temp_dir = tempfile.mkdtemp() + user_dir = os.path.join(temp_dir, "cache") + os.mkdir(user_dir) + img = tempfile.NamedTemporaryFile() + + fstab = OPTIONS.info_dict["fstab"] + if fstab: + image_props["fs_type" ] = fstab["/cache"].fs_type + succ = build_image.BuildImage(user_dir, image_props, img.name) + assert succ, "build cache.img image failed" + + common.CheckSize(img.name, "cache.img", OPTIONS.info_dict) + output_zip.write(img.name, "cache.img") + img.close() + os.rmdir(user_dir) + os.rmdir(temp_dir) + + +def CopyInfo(output_zip): + """Copy the android-info.txt file from the input to the output.""" + output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"), + "android-info.txt") + + +def main(argv): + bootable_only = [False] + + def option_handler(o, a): + if o in ("-b", "--board_config"): + pass # deprecated + if o in ("-z", "--bootable_zip"): + bootable_only[0] = True + else: + return False + return True + + args = common.ParseOptions(argv, __doc__, + extra_opts="b:z", + extra_long_opts=["board_config=", + "bootable_zip"], + extra_option_handler=option_handler) + + bootable_only = bootable_only[0] + + if len(args) != 2: + common.Usage(__doc__) + sys.exit(1) + + OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0]) + OPTIONS.info_dict = common.LoadInfoDict(input_zip) + + # If this image was originally labelled with SELinux contexts, make sure we + # also apply the labels in our new image. During building, the "file_contexts" + # is in the out/ directory tree, but for repacking from target-files.zip it's + # in the root directory of the ramdisk. + if "selinux_fc" in OPTIONS.info_dict: + OPTIONS.info_dict["selinux_fc"] = os.path.join(OPTIONS.input_tmp, "BOOT", "RAMDISK", + "file_contexts") + + output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) + + common.GetBootableImage( + "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT").AddToZip(output_zip) + common.GetBootableImage( + "recovery.img", "recovery.img", OPTIONS.input_tmp, + "RECOVERY").AddToZip(output_zip) + + if not bootable_only: + AddSystem(output_zip) + AddVendor(output_zip) + AddUserdata(output_zip) + AddCache(output_zip) + CopyInfo(output_zip) + + print "cleaning up..." + output_zip.close() + shutil.rmtree(OPTIONS.input_tmp) + + print "done." + + +if __name__ == '__main__': + try: + common.CloseInheritedPipes() + main(sys.argv[1:]) + except common.ExternalError, e: + print + print " ERROR: %s" % (e,) + print + sys.exit(1) diff --git a/tools/releasetools/make_recovery_patch b/tools/releasetools/make_recovery_patch new file mode 100755 index 0000000..08d1450 --- /dev/null +++ b/tools/releasetools/make_recovery_patch @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# +# 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. + +import sys + +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." + sys.exit(1) + +import os +import common + +OPTIONS = common.OPTIONS + +def main(argv): + # def option_handler(o, a): + # return False + + args = common.ParseOptions(argv, __doc__) + input_dir, output_dir = args + + OPTIONS.info_dict = common.LoadInfoDict(input_dir) + + recovery_img = common.GetBootableImage("recovery.img", "recovery.img", + input_dir, "RECOVERY") + boot_img = common.GetBootableImage("boot.img", "boot.img", + input_dir, "BOOT") + + if not recovery_img or not boot_img: + sys.exit(0) + + def output_sink(fn, data): + with open(os.path.join(output_dir, "SYSTEM", *fn.split("/")), "wb") as f: + f.write(data) + + common.MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files index 8d3f6ce..cbfc087 100755 --- a/tools/releasetools/ota_from_target_files +++ b/tools/releasetools/ota_from_target_files @@ -21,7 +21,7 @@ a full OTA is produced. Usage: ota_from_target_files [flags] input_target_files output_ota_package - -b (--board_config) <file> + --board_config <file> Deprecated. -k (--package_key) <key> Key to use to sign the package (default is @@ -37,6 +37,10 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package Generate an incremental OTA using the given target-files zip as the starting build. + -o (--oem_settings) <file> + Use the file to specify the expected OEM-specific properties + on the OEM partition of the intended device. + -w (--wipe_user_data) Generate an OTA package that will wipe the user data partition when installed. @@ -57,12 +61,22 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package first, so that any changes made to the system partition are done using the new recovery (new kernel, etc.). + --block + Generate a block-based OTA if possible. Will fall back to a + file-based OTA if the target_files is older and doesn't support + block-based OTAs. + + -b (--binary) <file> + Use the given binary as the update-binary in the output package, + instead of the binary in the build's target_files. Use for + development only. + """ import sys -if sys.hexversion < 0x02040000: - print >> sys.stderr, "Python 2.4 or newer is required." +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." sys.exit(1) import copy @@ -80,7 +94,9 @@ except ImportError: from sha import sha as sha1 import common +import img_from_target_files import edify_generator +import build_image OPTIONS = common.OPTIONS OPTIONS.package_key = None @@ -95,6 +111,9 @@ OPTIONS.aslr_mode = True OPTIONS.worker_threads = 3 OPTIONS.two_step = False OPTIONS.no_signing = False +OPTIONS.block_based = False +OPTIONS.updater_binary = None +OPTIONS.oem_source = None def MostPopularKey(d, default): """Given a dict, return the key corresponding to the largest @@ -347,64 +366,41 @@ def SignOutput(temp_zip_name, output_zip_name): whole_file=True) -def AppendAssertions(script, info_dict): - device = GetBuildProp("ro.product.device", info_dict) - script.AssertDevice(device) - - -def MakeRecoveryPatch(input_tmp, output_zip, recovery_img, boot_img): - """Generate a binary patch that creates the recovery image starting - with the boot image. (Most of the space in these images is just the - kernel, which is identical for the two, so the resulting patch - should be efficient.) Add it to the output zip, along with a shell - script that is run from init.rc on first boot to actually do the - patching and install the new recovery image. - - recovery_img and boot_img should be File objects for the - corresponding images. info should be the dictionary returned by - common.LoadInfoDict() on the input target_files. - - Returns an Item for the shell script, which must be made - executable. - """ - - diff_program = ["imgdiff"] - path = os.path.join(input_tmp, "SYSTEM", "etc", "recovery-resource.dat") - if os.path.exists(path): - diff_program.append("-b") - diff_program.append(path) - bonus_args = "-b /system/etc/recovery-resource.dat" +def AppendAssertions(script, info_dict, oem_dict = None): + oem_props = info_dict.get("oem_fingerprint_properties") + if oem_props is None: + device = GetBuildProp("ro.product.device", info_dict) + script.AssertDevice(device) else: - bonus_args = "" + if oem_dict is None: + raise common.ExternalError("No OEM file provided to answer expected assertions") + for prop in oem_props.split(): + if oem_dict.get(prop) is None: + raise common.ExternalError("The OEM file is missing the property %s" % prop) + script.AssertOemProperty(prop, oem_dict.get(prop)) - d = common.Difference(recovery_img, boot_img, diff_program=diff_program) - _, _, patch = d.ComputePatch() - common.ZipWriteStr(output_zip, "recovery/recovery-from-boot.p", patch) - Item.Get("system/recovery-from-boot.p", dir=False) - boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict) - recovery_type, recovery_device = common.GetTypeAndDevice("/recovery", OPTIONS.info_dict) +def HasRecoveryPatch(target_files_zip): + try: + target_files_zip.getinfo("SYSTEM/recovery-from-boot.p") + return True + except KeyError: + return False + +def GetOemProperty(name, oem_props, oem_dict, info_dict): + if oem_props is not None and name in oem_props: + return oem_dict[name] + return GetBuildProp(name, info_dict) - sh = """#!/system/bin/sh -if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then - log -t recovery "Installing new recovery image" - applypatch %(bonus_args)s %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p -else - log -t recovery "Recovery image already installed" -fi -""" % { 'boot_size': boot_img.size, - 'boot_sha1': boot_img.sha1, - 'recovery_size': recovery_img.size, - 'recovery_sha1': recovery_img.sha1, - 'boot_type': boot_type, - 'boot_device': boot_device, - 'recovery_type': recovery_type, - 'recovery_device': recovery_device, - 'bonus_args': bonus_args, - } - common.ZipWriteStr(output_zip, "recovery/etc/install-recovery.sh", sh) - return Item.Get("system/etc/install-recovery.sh", dir=False) +def CalculateFingerprint(oem_props, oem_dict, info_dict): + if oem_props is None: + return GetBuildProp("ro.build.fingerprint", info_dict) + return "%s/%s/%s:%s" % ( + GetOemProperty("ro.product.brand", oem_props, oem_dict, info_dict), + GetOemProperty("ro.product.name", oem_props, oem_dict, info_dict), + GetOemProperty("ro.product.device", oem_props, oem_dict, info_dict), + GetBuildProp("ro.build.thumbprint", info_dict)) def WriteFullOTAPackage(input_zip, output_zip): # TODO: how to determine this? We don't know what version it will @@ -412,9 +408,17 @@ def WriteFullOTAPackage(input_zip, output_zip): # change very often. script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict) - metadata = {"post-build": GetBuildProp("ro.build.fingerprint", - OPTIONS.info_dict), - "pre-device": GetBuildProp("ro.product.device", + oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties") + oem_dict = None + if oem_props is not None: + if OPTIONS.oem_source is None: + raise common.ExternalError("OEM source required for this build") + script.Mount("/oem") + oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) + + metadata = {"post-build": CalculateFingerprint( + oem_props, oem_dict, OPTIONS.info_dict), + "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict, OPTIONS.info_dict), "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict), @@ -429,12 +433,15 @@ def WriteFullOTAPackage(input_zip, output_zip): metadata=metadata, info_dict=OPTIONS.info_dict) + has_recovery_patch = HasRecoveryPatch(input_zip) + block_based = OPTIONS.block_based and has_recovery_patch + if not OPTIONS.omit_prereq: ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict) ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict) script.AssertOlderBuild(ts, ts_text) - AppendAssertions(script, OPTIONS.info_dict) + AppendAssertions(script, OPTIONS.info_dict, oem_dict) device_specific.FullOTA_Assertions() # Two-step package strategy (in chronological order, which is *not* @@ -478,37 +485,55 @@ else if get_stage("%(bcb_dev)s", "stage") == "3/3" then device_specific.FullOTA_InstallBegin() - script.ShowProgress(0.5, 0) + system_progress = 0.75 if OPTIONS.wipe_user_data: - script.FormatPartition("/data") + system_progress -= 0.1 if "selinux_fc" in OPTIONS.info_dict: WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip) - script.FormatPartition("/system") - script.Mount("/system") - script.UnpackPackageDir("recovery", "/system") - script.UnpackPackageDir("system", "/system") + script.ShowProgress(system_progress, 30) + if block_based: + mapdata, data = img_from_target_files.BuildSystem( + OPTIONS.input_tmp, OPTIONS.info_dict, + sparse=False, map_file=True) + + common.ZipWriteStr(output_zip, "system.map", mapdata) + common.ZipWriteStr(output_zip, "system.muimg", data) + script.WipeBlockDevice("/system") + script.WriteRawImage("/system", "system.muimg", mapfn="system.map") + else: + script.FormatPartition("/system") + script.Mount("/system") + if not has_recovery_patch: + script.UnpackPackageDir("recovery", "/system") + script.UnpackPackageDir("system", "/system") - symlinks = CopySystemFiles(input_zip, output_zip) - script.MakeSymlinks(symlinks) + symlinks = CopySystemFiles(input_zip, output_zip) + script.MakeSymlinks(symlinks) boot_img = common.GetBootableImage("boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") - MakeRecoveryPatch(OPTIONS.input_tmp, output_zip, recovery_img, boot_img) - Item.GetMetadata(input_zip) - Item.Get("system").SetPermissions(script) + if not has_recovery_patch: + def output_sink(fn, data): + common.ZipWriteStr(output_zip, "recovery/" + fn, data) + Item.Get("system/" + fn, dir=False) + + common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, + recovery_img, boot_img) + + Item.GetMetadata(input_zip) + Item.Get("system").SetPermissions(script) common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict) common.ZipWriteStr(output_zip, "boot.img", boot_img.data) - script.ShowProgress(0.2, 0) - script.ShowProgress(0.2, 10) + script.ShowProgress(0.05, 5) script.WriteRawImage("/boot", "boot.img") - script.ShowProgress(0.1, 0) + script.ShowProgress(0.2, 10) device_specific.FullOTA_InstallEnd() if OPTIONS.extra_script is not None: @@ -516,6 +541,10 @@ else if get_stage("%(bcb_dev)s", "stage") == "3/3" then script.UnmountAll() + if OPTIONS.wipe_user_data: + script.ShowProgress(0.1, 10) + script.FormatPartition("/data") + if OPTIONS.two_step: script.AppendExtra(""" set_stage("%(bcb_dev)s", ""); @@ -528,7 +557,7 @@ reboot_now("%(bcb_dev)s", ""); endif; endif; """ % bcb_dev) - script.AddToZip(input_zip, output_zip) + script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) WriteMetadata(metadata, output_zip) def WritePolicyConfig(file_context, output_zip): @@ -560,7 +589,7 @@ def GetBuildProp(prop, info_dict): try: return info_dict.get("build.prop", {})[prop] except KeyError: - raise common.ExternalError("couldn't find %s in build.prop" % (property,)) + raise common.ExternalError("couldn't find %s in build.prop" % (prop,)) def AddToKnownPaths(filename, known_paths): if filename[-1] == "/": @@ -573,7 +602,7 @@ def AddToKnownPaths(filename, known_paths): known_paths.add(path) dirs.pop() -def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): +def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip): source_version = OPTIONS.source_info_dict["recovery_api_version"] target_version = OPTIONS.target_info_dict["recovery_api_version"] @@ -599,6 +628,303 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): metadata=metadata, info_dict=OPTIONS.info_dict) + source_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.source_info_dict) + target_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.target_info_dict) + metadata["pre-build"] = source_fp + metadata["post-build"] = target_fp + + source_boot = common.GetBootableImage( + "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", + OPTIONS.source_info_dict) + target_boot = common.GetBootableImage( + "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT") + updating_boot = (not OPTIONS.two_step and + (source_boot.data != target_boot.data)) + + source_recovery = common.GetBootableImage( + "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY", + OPTIONS.source_info_dict) + target_recovery = common.GetBootableImage( + "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") + updating_recovery = (source_recovery.data != target_recovery.data) + + with tempfile.NamedTemporaryFile() as src_file: + with tempfile.NamedTemporaryFile() as tgt_file: + print "building source system image..." + src_file = tempfile.NamedTemporaryFile() + src_mapdata, src_data = img_from_target_files.BuildSystem( + OPTIONS.source_tmp, OPTIONS.source_info_dict, + sparse=False, map_file=True) + + src_sys_sha1 = sha1(src_data).hexdigest() + print "source system sha1:", src_sys_sha1 + src_file.write(src_data) + + print "building target system image..." + tgt_file = tempfile.NamedTemporaryFile() + tgt_mapdata, tgt_data = img_from_target_files.BuildSystem( + OPTIONS.target_tmp, OPTIONS.target_info_dict, + sparse=False, map_file=True) + tgt_sys_sha1 = sha1(tgt_data).hexdigest() + print "target system sha1:", tgt_sys_sha1 + tgt_sys_len = len(tgt_data) + tgt_file.write(tgt_data) + + system_type, system_device = common.GetTypeAndDevice("/system", OPTIONS.info_dict) + system_patch = common.MakeSystemPatch(src_file, tgt_file) + + TestBlockPatch(src_data, src_mapdata, system_patch.data, tgt_mapdata, tgt_sys_sha1) + src_data = None + tgt_data = None + + system_patch.AddToZip(output_zip, compression=zipfile.ZIP_STORED) + src_mapfilename = system_patch.name + ".src.map" + common.ZipWriteStr(output_zip, src_mapfilename, src_mapdata) + tgt_mapfilename = system_patch.name + ".tgt.map" + common.ZipWriteStr(output_zip, tgt_mapfilename, tgt_mapdata) + + oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties") + oem_dict = None + if oem_props is not None: + if OPTIONS.oem_source is None: + raise common.ExternalError("OEM source required for this build") + script.Mount("/oem") + oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) + + AppendAssertions(script, OPTIONS.target_info_dict, oem_dict) + device_specific.IncrementalOTA_Assertions() + + # Two-step incremental package strategy (in chronological order, + # which is *not* the order in which the generated script has + # things): + # + # if stage is not "2/3" or "3/3": + # do verification on current system + # write recovery image to boot partition + # set stage to "2/3" + # reboot to boot partition and restart recovery + # else if stage is "2/3": + # write recovery image to recovery partition + # set stage to "3/3" + # reboot to recovery partition and restart recovery + # else: + # (stage must be "3/3") + # perform update: + # patch system files, etc. + # force full install of new boot image + # set up system to update recovery partition on first boot + # complete script normally (allow recovery to mark itself finished and reboot) + + if OPTIONS.two_step: + if not OPTIONS.info_dict.get("multistage_support", None): + assert False, "two-step packages not supported by this build" + fs = OPTIONS.info_dict["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} + common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data) + script.AppendExtra(""" +if get_stage("%(bcb_dev)s", "stage") == "2/3" then +""" % bcb_dev) + script.AppendExtra("sleep(20);\n"); + script.WriteRawImage("/recovery", "recovery.img") + script.AppendExtra(""" +set_stage("%(bcb_dev)s", "3/3"); +reboot_now("%(bcb_dev)s", "recovery"); +else if get_stage("%(bcb_dev)s", "stage") != "3/3" then +""" % bcb_dev) + + script.Print("Verifying current system...") + + device_specific.IncrementalOTA_VerifyBegin() + + if oem_props is None: + script.AssertSomeFingerprint(source_fp, target_fp) + else: + script.AssertSomeThumbprint( + GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), + GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) + + if updating_boot: + d = common.Difference(target_boot, source_boot) + _, _, d = d.ComputePatch() + print "boot target: %d source: %d diff: %d" % ( + target_boot.size, source_boot.size, len(d)) + + common.ZipWriteStr(output_zip, "patch/boot.img.p", d) + + boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict) + + script.PatchCheck("%s:%s:%d:%s:%d:%s" % + (boot_type, boot_device, + source_boot.size, source_boot.sha1, + target_boot.size, target_boot.sha1)) + + device_specific.IncrementalOTA_VerifyEnd() + + if OPTIONS.two_step: + script.WriteRawImage("/boot", "recovery.img") + script.AppendExtra(""" +set_stage("%(bcb_dev)s", "2/3"); +reboot_now("%(bcb_dev)s", ""); +else +""" % bcb_dev) + + script.Comment("---- start making changes here ----") + + device_specific.IncrementalOTA_InstallBegin() + + script.Print("Patching system image...") + script.Syspatch(system_device, + tgt_mapfilename, tgt_sys_sha1, + src_mapfilename, src_sys_sha1, + system_patch.name) + + if OPTIONS.two_step: + common.ZipWriteStr(output_zip, "boot.img", target_boot.data) + script.WriteRawImage("/boot", "boot.img") + print "writing full boot image (forced by two-step mode)" + + if not OPTIONS.two_step: + if updating_boot: + # Produce the boot image by applying a patch to the current + # contents of the boot partition, and write it back to the + # partition. + script.Print("Patching boot image...") + script.ApplyPatch("%s:%s:%d:%s:%d:%s" + % (boot_type, boot_device, + source_boot.size, source_boot.sha1, + target_boot.size, target_boot.sha1), + "-", + target_boot.size, target_boot.sha1, + source_boot.sha1, "patch/boot.img.p") + print "boot image changed; including." + else: + print "boot image unchanged; skipping." + + # Do device-specific installation (eg, write radio image). + device_specific.IncrementalOTA_InstallEnd() + + if OPTIONS.extra_script is not None: + script.AppendExtra(OPTIONS.extra_script) + + if OPTIONS.wipe_user_data: + script.Print("Erasing user data...") + script.FormatPartition("/data") + + if OPTIONS.two_step: + script.AppendExtra(""" +set_stage("%(bcb_dev)s", ""); +endif; +endif; +""" % bcb_dev) + + script.SetProgress(1) + script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) + WriteMetadata(metadata, output_zip) + +def ParseMap(map_str): + x = map_str.split() + assert int(x[0]) == 4096 + assert int(x[1]) == len(x)-2 + return int(x[0]), [int(i) for i in x[2:]] + +def TestBlockPatch(src_muimg, src_map, patch_data, tgt_map, tgt_sha1): + src_blksize, src_regions = ParseMap(src_map) + tgt_blksize, tgt_regions = ParseMap(tgt_map) + + with tempfile.NamedTemporaryFile() as src_file,\ + tempfile.NamedTemporaryFile() as patch_file,\ + tempfile.NamedTemporaryFile() as tgt_file,\ + tempfile.NamedTemporaryFile() as src_map_file,\ + tempfile.NamedTemporaryFile() as tgt_map_file: + + src_total = sum(src_regions) * src_blksize + src_file.truncate(src_total) + p = 0 + for i in range(0, len(src_regions), 2): + c, dc = src_regions[i:i+2] + src_file.write(src_muimg[p:(p+c*src_blksize)]) + p += c*src_blksize + src_file.seek(dc*src_blksize, 1) + assert src_file.tell() == src_total + + patch_file.write(patch_data) + + tgt_total = sum(tgt_regions) * tgt_blksize + tgt_file.truncate(tgt_total) + + src_map_file.write(src_map) + tgt_map_file.write(tgt_map) + + src_file.flush() + src_map_file.flush() + patch_file.flush() + tgt_file.flush() + tgt_map_file.flush() + + p = common.Run(["syspatch_host", src_file.name, src_map_file.name, + patch_file.name, tgt_file.name, tgt_map_file.name], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdoutdata, _ = p.communicate() + if p.returncode != 0: + print stdoutdata + raise ValueError("failed to reconstruct target system image from patch") + + h = sha1() + for i in range(0, len(tgt_regions), 2): + c, dc = tgt_regions[i:i+2] + h.update(tgt_file.read(c*tgt_blksize)) + tgt_file.seek(dc*tgt_blksize, 1) + + if h.hexdigest() != tgt_sha1: + raise ValueError("patch reconstructed incorrect target system image") + + print "test of system image patch succeeded" + + +def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): + target_has_recovery_patch = HasRecoveryPatch(target_zip) + source_has_recovery_patch = HasRecoveryPatch(source_zip) + + if (OPTIONS.block_based and + target_has_recovery_patch and + source_has_recovery_patch): + return WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip) + + source_version = OPTIONS.source_info_dict["recovery_api_version"] + target_version = OPTIONS.target_info_dict["recovery_api_version"] + + if source_version == 0: + print ("WARNING: generating edify script for a source that " + "can't install it.") + script = edify_generator.EdifyGenerator(source_version, + OPTIONS.target_info_dict) + + oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties") + oem_dict = None + if oem_props is not None: + if OPTIONS.oem_source is None: + raise common.ExternalError("OEM source required for this build") + script.Mount("/oem") + oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) + + metadata = {"pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict, + OPTIONS.source_info_dict), + "post-timestamp": GetBuildProp("ro.build.date.utc", + OPTIONS.target_info_dict), + } + + device_specific = common.DeviceSpecificParams( + source_zip=source_zip, + source_version=source_version, + target_zip=target_zip, + target_version=target_version, + output_zip=output_zip, + script=script, + metadata=metadata, + info_dict=OPTIONS.info_dict) + print "Loading target..." target_data = LoadSystemFiles(target_zip) print "Loading source..." @@ -655,7 +981,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): if d is None or len(d) > tf.size * OPTIONS.patch_threshold or \ path not in known_paths: # patch is almost as big as the file; don't bother patching - # or a patch + rename cannot take place due to the target + # or a patch + rename cannot take place due to the target # directory not existing tf.AddToZip(output_zip) verbatim_targets.append((tf.name, tf.size)) @@ -667,14 +993,21 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): patch_list.append((tf, sf, tf.size, common.sha1(d).hexdigest())) largest_source_size = max(largest_source_size, sf.size) - source_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.source_info_dict) - target_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.target_info_dict) + script.Mount("/system") + + target_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.target_info_dict) + source_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.source_info_dict) + + if oem_props is None: + script.AssertSomeFingerprint(source_fp, target_fp) + else: + script.AssertSomeThumbprint( + GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), + GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) + metadata["pre-build"] = source_fp metadata["post-build"] = target_fp - script.Mount("/system") - script.AssertSomeFingerprint(source_fp, target_fp) - source_boot = common.GetBootableImage( "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", OPTIONS.source_info_dict) @@ -696,7 +1029,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): # 0.1 for unpacking verbatim files, symlinking, and doing the # device-specific commands. - AppendAssertions(script, OPTIONS.target_info_dict) + AppendAssertions(script, OPTIONS.target_info_dict, oem_dict) device_specific.IncrementalOTA_Assertions() # Two-step incremental package strategy (in chronological order, @@ -744,9 +1077,6 @@ else if get_stage("%(bcb_dev)s", "stage") != "3/3" then device_specific.IncrementalOTA_VerifyBegin() script.ShowProgress(0.1, 0) - total_verify_size = float(sum([i[1].size for i in patch_list]) + 1) - if updating_boot: - total_verify_size += source_boot.size so_far = 0 for tf, sf, size, patch_sha in patch_list: @@ -754,7 +1084,6 @@ else if get_stage("%(bcb_dev)s", "stage") != "3/3" then script.SkipNextActionIfTargetExists(tf.name, tf.sha1) script.PatchCheck("/"+sf.name, tf.sha1, sf.sha1) so_far += sf.size - script.SetProgress(so_far / total_verify_size) if updating_boot: d = common.Difference(target_boot, source_boot) @@ -771,7 +1100,6 @@ else if get_stage("%(bcb_dev)s", "stage") != "3/3" then source_boot.size, source_boot.sha1, target_boot.size, target_boot.sha1)) so_far += source_boot.size - script.SetProgress(so_far / total_verify_size) if patch_list or updating_recovery or updating_boot: script.CacheFreeSpaceCheck(largest_source_size) @@ -795,10 +1123,6 @@ else script.WriteRawImage("/boot", "boot.img") print "writing full boot image (forced by two-step mode)" - if OPTIONS.wipe_user_data: - script.Print("Erasing user data...") - script.FormatPartition("/data") - script.Print("Removing unneeded files...") script.DeleteFiles(["/"+i[0] for i in verbatim_targets] + ["/"+i for i in sorted(source_data) @@ -854,10 +1178,15 @@ else # For older builds where recovery-resource.dat is not present, we # use only the boot image as the source. - MakeRecoveryPatch(OPTIONS.target_tmp, output_zip, - target_recovery, target_boot) - script.DeleteFiles(["/system/recovery-from-boot.p", - "/system/etc/install-recovery.sh"]) + if not target_has_recovery_patch: + def output_sink(fn, data): + common.ZipWriteStr(output_zip, "recovery/" + fn, data) + Item.Get("system/" + fn, dir=False) + + common.MakeRecoveryPatch(OPTIONS.target_tmp, output_sink, + target_recovery, target_boot) + script.DeleteFiles(["/system/recovery-from-boot.p", + "/system/etc/install-recovery.sh"]) print "recovery image changed; including as patch from boot." else: print "recovery image unchanged; skipping." @@ -889,7 +1218,7 @@ else script.Print("Unpacking new files...") script.UnpackPackageDir("system", "/system") - if updating_recovery: + if updating_recovery and not target_has_recovery_patch: script.Print("Unpacking new recovery...") script.UnpackPackageDir("recovery", "/system") @@ -934,6 +1263,10 @@ else script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p") script.SetPermissions("/system/build.prop", 0, 0, 0644, None, None) + if OPTIONS.wipe_user_data: + script.Print("Erasing user data...") + script.FormatPartition("/data") + if OPTIONS.two_step: script.AppendExtra(""" set_stage("%(bcb_dev)s", ""); @@ -941,14 +1274,14 @@ endif; endif; """ % bcb_dev) - script.AddToZip(target_zip, output_zip) + script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) WriteMetadata(metadata, output_zip) def main(argv): def option_handler(o, a): - if o in ("-b", "--board_config"): + if o == "--board_config": pass # deprecated elif o in ("-k", "--package_key"): OPTIONS.package_key = a @@ -958,6 +1291,8 @@ def main(argv): OPTIONS.wipe_user_data = True elif o in ("-n", "--no_prereq"): OPTIONS.omit_prereq = True + elif o in ("-o", "--oem_settings"): + OPTIONS.oem_source = a elif o in ("-e", "--extra_script"): OPTIONS.extra_script = a elif o in ("-a", "--aslr_mode"): @@ -969,14 +1304,18 @@ def main(argv): OPTIONS.worker_threads = int(a) elif o in ("-2", "--two_step"): OPTIONS.two_step = True - elif o in ("--no_signing"): + elif o == "--no_signing": OPTIONS.no_signing = True + elif o == "--block": + OPTIONS.block_based = True + elif o in ("-b", "--binary"): + OPTIONS.updater_binary = a else: return False return True args = common.ParseOptions(argv, __doc__, - extra_opts="b:k:i:d:wne:a:2", + extra_opts="b:k:i:d:wne:a:2o:", extra_long_opts=["board_config=", "package_key=", "incremental_from=", @@ -987,6 +1326,9 @@ def main(argv): "aslr_mode=", "two_step", "no_signing", + "block", + "binary=", + "oem_settings=", ], extra_option_handler=option_handler) @@ -1015,11 +1357,23 @@ def main(argv): print "--- target info ---" common.DumpInfoDict(OPTIONS.info_dict) + # If the caller explicitly specified the device-specific extensions + # path via -s/--device_specific, use that. Otherwise, use + # META/releasetools.py if it is present in the target target_files. + # Otherwise, take the path of the file from 'tool_extensions' in the + # info dict and look for that in the local filesystem, relative to + # the current directory. + if OPTIONS.device_specific is None: - OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None) + from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py") + if os.path.exists(from_input): + print "(using device-specific extensions from target_files)" + OPTIONS.device_specific = from_input + else: + OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None) + if OPTIONS.device_specific is not None: - OPTIONS.device_specific = os.path.normpath(OPTIONS.device_specific) - print "using device-specific extensions in", OPTIONS.device_specific + OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific) if OPTIONS.no_signing: output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) @@ -1039,6 +1393,9 @@ def main(argv): OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source) OPTIONS.target_info_dict = OPTIONS.info_dict OPTIONS.source_info_dict = common.LoadInfoDict(source_zip) + if "selinux_fc" in OPTIONS.source_info_dict: + OPTIONS.source_info_dict["selinux_fc"] = os.path.join(OPTIONS.source_tmp, "BOOT", "RAMDISK", + "file_contexts") if OPTIONS.package_key is None: OPTIONS.package_key = OPTIONS.source_info_dict.get( "default_system_dev_certificate", diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks index ab24706..5398cec 100755 --- a/tools/releasetools/sign_target_files_apks +++ b/tools/releasetools/sign_target_files_apks @@ -67,8 +67,8 @@ Usage: sign_target_files_apks [flags] input_target_files output_target_files import sys -if sys.hexversion < 0x02040000: - print >> sys.stderr, "Python 2.4 or newer is required." +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." sys.exit(1) import base64 @@ -77,6 +77,7 @@ import copy import errno import os import re +import shutil import subprocess import tempfile import zipfile @@ -139,14 +140,40 @@ def SignApk(data, keyname, pw): return data -def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): +def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info, + apk_key_map, key_passwords): maxsize = max([len(os.path.basename(i.filename)) for i in input_tf_zip.infolist() if i.filename.endswith('.apk')]) + rebuild_recovery = False + + tmpdir = tempfile.mkdtemp() + def write_to_temp(fn, attr, data): + fn = os.path.join(tmpdir, fn) + if fn.endswith("/"): + fn = os.path.join(tmpdir, fn) + os.mkdir(fn) + else: + d = os.path.dirname(fn) + if d and not os.path.exists(d): + os.makedirs(d) + + if attr >> 16 == 0xa1ff: + os.symlink(data, fn) + else: + with open(fn, "wb") as f: + f.write(data) for info in input_tf_zip.infolist(): data = input_tf_zip.read(info.filename) out_info = copy.copy(info) + + if (info.filename.startswith("BOOT/") or + info.filename.startswith("RECOVERY/") or + info.filename.startswith("META/") or + info.filename == "SYSTEM/etc/recovery-resource.dat"): + write_to_temp(info.filename, info.external_attr, data) + if info.filename.endswith(".apk"): name = os.path.basename(info.filename) key = apk_key_map[name] @@ -163,14 +190,43 @@ def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): print "rewriting %s:" % (info.filename,) new_data = RewriteProps(data) output_tf_zip.writestr(out_info, new_data) + if info.filename == "RECOVERY/RAMDISK/default.prop": + write_to_temp(info.filename, info.external_attr, new_data) elif info.filename.endswith("mac_permissions.xml"): print "rewriting %s with new keys." % (info.filename,) new_data = ReplaceCerts(data) output_tf_zip.writestr(out_info, new_data) + elif info.filename in ("SYSTEM/recovery-from-boot.p", + "SYSTEM/bin/install-recovery.sh"): + rebuild_recovery = True + elif (OPTIONS.replace_ota_keys and + info.filename in ("RECOVERY/RAMDISK/res/keys", + "SYSTEM/etc/security/otacerts.zip")): + # don't copy these files if we're regenerating them below + pass else: # a non-APK file; copy it verbatim output_tf_zip.writestr(out_info, data) + if OPTIONS.replace_ota_keys: + new_recovery_keys = ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info) + if new_recovery_keys: + write_to_temp("RECOVERY/RAMDISK/res/keys", 0755 << 16, new_recovery_keys) + + if rebuild_recovery: + recovery_img = common.GetBootableImage( + "recovery.img", "recovery.img", tmpdir, "RECOVERY", info_dict=misc_info) + boot_img = common.GetBootableImage( + "boot.img", "boot.img", tmpdir, "BOOT", info_dict=misc_info) + + def output_sink(fn, data): + output_tf_zip.writestr("SYSTEM/"+fn, data) + + common.MakeRecoveryPatch(tmpdir, output_sink, recovery_img, boot_img, + info_dict=misc_info) + + shutil.rmtree(tmpdir) + def ReplaceCerts(data): """Given a string of data, replace all occurences of a set @@ -265,7 +321,8 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): for k in keylist: m = re.match(r"^(.*)\.x509\.pem$", k) if not m: - raise common.ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,)) + raise common.ExternalError( + "can't parse \"%s\" from META/otakeys.txt" % (k,)) k = m.group(1) mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem") @@ -287,10 +344,11 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")] + mapped_keys + extra_recovery_keys, stdout=subprocess.PIPE) - data, _ = p.communicate() + new_recovery_keys, _ = p.communicate() if p.returncode != 0: raise common.ExternalError("failed to run dumpkeys") - common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", data) + common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", + new_recovery_keys) # SystemUpdateActivity uses the x509.pem version of the keys, but # put into a zipfile system/etc/security/otacerts.zip. @@ -304,6 +362,8 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip", tempfile.getvalue()) + return new_recovery_keys + def BuildKeyMap(misc_info, key_mapping_options): for s, d in key_mapping_options: @@ -375,10 +435,8 @@ def main(argv): CheckAllApksSigned(input_zip, apk_key_map) key_passwords = common.GetKeyPasswords(set(apk_key_map.values())) - SignApks(input_zip, output_zip, apk_key_map, key_passwords) - - if OPTIONS.replace_ota_keys: - ReplaceOtaKeys(input_zip, output_zip, misc_info) + ProcessTargetFiles(input_zip, output_zip, misc_info, + apk_key_map, key_passwords) input_zip.close() output_zip.close() diff --git a/tools/releasetools/simg_map.py b/tools/releasetools/simg_map.py new file mode 100644 index 0000000..22dc863 --- /dev/null +++ b/tools/releasetools/simg_map.py @@ -0,0 +1,148 @@ +#! /usr/bin/env python + +# Copyright (C) 2012 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 getopt, posixpath, signal, struct, sys + +def main(): + if len(sys.argv) == 4: + print("No sparse_image_file specified") + usage(me) + + sparse_fn = sys.argv[1] + unsparse_fn = sys.argv[2] + map_file = sys.argv[3] + mapped_unsparse_fn = sys.argv[4] + + return ComputeMap(sparse_fn, unsparse_fn, map_file, mapped_unsparse_fn) + + +def ComputeMap(sparse_fn, unsparse_fn, map_file, mapped_unsparse_fn): + care_map = [] + + with open(sparse_fn, "rb") as FH: + header_bin = FH.read(28) + header = struct.unpack("<I4H4I", header_bin) + + magic = header[0] + major_version = header[1] + minor_version = header[2] + file_hdr_sz = header[3] + chunk_hdr_sz = header[4] + blk_sz = header[5] + total_blks = header[6] + total_chunks = header[7] + image_checksum = header[8] + + if magic != 0xED26FF3A: + print("%s: %s: Magic should be 0xED26FF3A but is 0x%08X" + % (me, path, magic)) + return 1 + if major_version != 1 or minor_version != 0: + print("%s: %s: I only know about version 1.0, but this is version %u.%u" + % (me, path, major_version, minor_version)) + return 1 + if file_hdr_sz != 28: + print("%s: %s: The file header size was expected to be 28, but is %u." + % (me, path, file_hdr_sz)) + return 1 + if chunk_hdr_sz != 12: + print("%s: %s: The chunk header size was expected to be 12, but is %u." + % (me, path, chunk_hdr_sz)) + return 1 + + print("%s: Total of %u %u-byte output blocks in %u input chunks." + % (sparse_fn, total_blks, blk_sz, total_chunks)) + + offset = 0 + for i in range(total_chunks): + header_bin = FH.read(12) + header = struct.unpack("<2H2I", header_bin) + chunk_type = header[0] + reserved1 = header[1] + chunk_sz = header[2] + total_sz = header[3] + data_sz = total_sz - 12 + + if chunk_type == 0xCAC1: + if data_sz != (chunk_sz * blk_sz): + print("Raw chunk input size (%u) does not match output size (%u)" + % (data_sz, chunk_sz * blk_sz)) + return 1 + else: + care_map.append((1, chunk_sz)) + FH.seek(data_sz, 1) + + elif chunk_type == 0xCAC2: + print("Fill chunks are not supported") + return 1 + + elif chunk_type == 0xCAC3: + if data_sz != 0: + print("Don't care chunk input size is non-zero (%u)" % (data_sz)) + return 1 + else: + care_map.append((0, chunk_sz)) + + elif chunk_type == 0xCAC4: + print("CRC32 chunks are not supported") + + else: + print("Unknown chunk type 0x%04X not supported" % (chunk_type,)) + return 1 + + offset += chunk_sz + + if total_blks != offset: + print("The header said we should have %u output blocks, but we saw %u" + % (total_blks, offset)) + + junk_len = len(FH.read()) + if junk_len: + print("There were %u bytes of extra data at the end of the file." + % (junk_len)) + return 1 + + last_kind = None + new_care_map = [] + for kind, size in care_map: + if kind != last_kind: + new_care_map.append((kind, size)) + last_kind = kind + else: + new_care_map[-1] = (kind, new_care_map[-1][1] + size) + + if new_care_map[0][0] == 0: + new_care_map.insert(0, (1, 0)) + if len(new_care_map) % 2: + new_care_map.append((0, 0)) + + with open(map_file, "w") as fmap: + fmap.write("%d\n%d\n" % (blk_sz, len(new_care_map))) + for _, sz in new_care_map: + fmap.write("%d\n" % sz) + + with open(unsparse_fn, "rb") as fin: + with open(mapped_unsparse_fn, "wb") as fout: + for k, sz in care_map: + data = fin.read(sz * blk_sz) + if k: + fout.write(data) + else: + assert data == "\x00" * len(data) + +if __name__ == "__main__": + sys.exit(main()) |