eclair snapshot

This commit is contained in:
Jean-Baptiste Queru
2009-11-12 18:45:15 -08:00
parent 2589265c77
commit e6b4e5b20a
103 changed files with 7817 additions and 1147 deletions

View File

@@ -21,6 +21,30 @@
# "buildspec.mk" should never be checked in to source control.
######################################################################
# Choose a product to build for. Look in the products directory for ones
# that work.
ifndef TARGET_PRODUCT
#TARGET_PRODUCT:=generic
endif
# Choose a variant to build. If you don't pick one, the default is eng.
# User is what we ship. Userdebug is that, with a few flags turned on
# for debugging. Eng has lots of extra tools for development.
ifndef TARGET_BUILD_VARIANT
#TARGET_BUILD_VARIANT:=user
#TARGET_BUILD_VARIANT:=userdebug
#TARGET_BUILD_VARIANT:=eng
endif
# Choose additional targets to always install, even when building
# minimal targets like "make droid". This takes simple target names
# like "Browser" or "MyApp", the names used by LOCAL_MODULE or
# LOCAL_PACKAGE_NAME. Modules listed here will always be installed in
# /system, even if they'd usually go in /data.
ifndef CUSTOM_MODULES
#CUSTOM_MODULES:=
endif
# Uncomment this if you want the simulator, otherwise, build for arm
ifndef TARGET_SIMULATOR
#TARGET_SIMULATOR:=true
@@ -50,21 +74,6 @@ endif
#HOST_CUSTOM_DEBUG_CFLAGS:=
#TARGET_CUSTOM_DEBUG_CFLAGS:=
# Choose a product to build for. Look in the products directory for ones
# that work.
ifndef TARGET_PRODUCT
#TARGET_PRODUCT:=generic
endif
# Choose additional targets to always install, even when building
# minimal targets like "make droid". This takes simple target names
# like "Browser" or "MyApp", the names used by LOCAL_MODULE or
# LOCAL_PACKAGE_NAME. Modules listed here will always be installed in
# /system, even if they'd usually go in /data.
ifndef CUSTOM_MODULES
#CUSTOM_MODULES:=
endif
# Choose additional locales, like "en_US" or "it_IT", to add to any
# built product. Any locales that appear in CUSTOM_LOCALES but not in
# the locale list for the selected product will be added to the end
@@ -88,10 +97,16 @@ ifndef NO_FALLBACK_FONT
#NO_FALLBACK_FONT:=true
endif
# To enabled instrumentation in webcore based apps like gmail and
# To enable instrumentation in webcore based apps like gmail and
# the browser, define WEBCORE_INSTRUMENTATION:=true
ifndef WEBCORE_INSTRUMENTATION
#WEBCORE_INSTRUMENTATION:=true
#endif
endif
# To enable SVG in webcore define ENABLE_SVG:=true
ifndef ENABLE_SVG
#ENABLE_SVG:=true
endif
# when the build system changes such that this file must be updated, this
# variable will be changed. After you have modified this file with the new

View File

@@ -18,7 +18,7 @@
# WHEN DOING SO, DELETE ANY "add-clean-step" ENTRIES THAT HAVE PILED UP.
# **********************************************************************
#
INTERNAL_CLEAN_BUILD_VERSION := 2
INTERNAL_CLEAN_BUILD_VERSION := 3
#
# ***********************************************************************
# Do not touch INTERNAL_CLEAN_BUILD_VERSION if you've added a clean step!
@@ -31,7 +31,7 @@ INTERNAL_CLEAN_BUILD_VERSION := 2
#
# E.g.:
# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/external/zlib/)
# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
#
# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
# files that are missing or have been moved.
@@ -54,38 +54,10 @@ INTERNAL_CLEAN_BUILD_VERSION := 2
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/etc/NOTICE.html)
# Remove generated java files after CL 126153
$(call add-clean-step, find $(OUT_DIR) -type f -name "*.java" -print0 | xargs -0 rm -f)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sapphire/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates/led)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/mountd)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/mountd.conf)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Browser_intermediates)
$(call add-clean-step, rm -f vendor/google/apps/Talk/res/drawable/%*)
$(call add-clean-step, rm -rf $(OUT_DIR)/product/*/obj/SHARED_LIBRARIES/libandroid_runtime_intermediates/android_os_NetStat.o)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/*/obj/SHARED_LIBRARIES/libjni_andpyime_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/*/obj/SHARED_LIBRARIES/share)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/*/obj/SHARED_LIBRARIES/libwebcore_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/PinyinIME_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/com.android.inputmethod.pinyin.lib_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/PinyinIMEGoogleService_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/com.android.inputmethod.pinyin.lib_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/PinyinIMEGoogleService_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/*/obj)
$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/bin/tcpdump)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/location)
$(call add-clean-step, rm -rf $(OUT_DIR)/product/*/obj/SHARED_LIBRARIES/lib?camera_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/product/*/obj/STATIC_LIBRARIES/lib?camera_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/*/obj/SHARED_LIBRARIES/libwebcore_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/ringtones/Silence.ogg)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/ringtones/notifications/Silence.ogg)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************

View File

@@ -118,6 +118,7 @@ $(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE)
PRODUCT_BRAND="$(PRODUCT_BRAND)" \
PRODUCT_DEFAULT_LANGUAGE="$(call default-locale-language,$(PRODUCT_LOCALES))" \
PRODUCT_DEFAULT_REGION="$(call default-locale-region,$(PRODUCT_LOCALES))" \
PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
PRODUCT_MODEL="$(PRODUCT_MODEL)" \
PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \
@@ -299,7 +300,7 @@ else # TARGET_BOOTIMAGE_USE_EXT2 != true
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES)
$(call pretty,"Target boot image: $@")
$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) --output $@
$(hide) $(call assert-max-file-size,$@,$(BOARD_BOOTIMAGE_MAX_SIZE),raw)
$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE),raw)
endif # TARGET_BOOTIMAGE_USE_EXT2
else # TARGET_NO_KERNEL
@@ -501,7 +502,7 @@ endif
# Recovery image
# If neither TARGET_NO_KERNEL nor TARGET_NO_RECOVERY are true
ifeq (,$(filter true, $(TARGET_NO_KERNEL) $(TARGET_NO_RECOVERY)))
ifeq (,$(filter true, $(TARGET_NO_KERNEL) $(TARGET_NO_RECOVERY) $(BUILD_TINY_ANDROID)))
INSTALLED_RECOVERYIMAGE_TARGET := $(PRODUCT_OUT)/recovery.img
@@ -577,7 +578,7 @@ $(INSTALLED_RECOVERYIMAGE_TARGET): $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) \
$(MKBOOTFS) $(TARGET_RECOVERY_ROOT_OUT) | $(MINIGZIP) > $(recovery_ramdisk)
$(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) --output $@
@echo ----- Made recovery image -------- $@
$(hide) $(call assert-max-file-size,$@,$(BOARD_RECOVERYIMAGE_MAX_SIZE),raw)
$(hide) $(call assert-max-image-size,$@,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE),raw)
else
INSTALLED_RECOVERYIMAGE_TARGET :=
@@ -662,7 +663,7 @@ endif
$(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH) | $(ACP)
@echo "Install system fs image: $@"
$(copy-file-to-target)
$(hide) $(call assert-max-file-size,$@ $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_MAX_SIZE),yaffs)
$(hide) $(call assert-max-image-size,$@ $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE),yaffs)
systemimage: $(INSTALLED_SYSTEMIMAGE)
@@ -671,7 +672,7 @@ systemimage-nodeps snod: $(filter-out systemimage-nodeps snod,$(MAKECMDGOALS)) \
| $(INTERNAL_MKUSERFS)
@echo "make $@: ignoring dependencies"
$(call build-systemimage-target,$(INSTALLED_SYSTEMIMAGE))
$(hide) $(call assert-max-file-size,$(INSTALLED_SYSTEMIMAGE),$(BOARD_SYSTEMIMAGE_MAX_SIZE),yaffs)
$(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMIMAGE),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE),yaffs)
#######
## system tarball
@@ -708,7 +709,7 @@ define build-userdataimage-target
$(call pretty,"Target userdata fs image: $(INSTALLED_USERDATAIMAGE_TARGET)")
@mkdir -p $(TARGET_OUT_DATA)
$(call build-userimage-ext2-target,$(TARGET_OUT_DATA),$(INSTALLED_USERDATAIMAGE_TARGET),userdata,)
$(hide) $(call assert-max-file-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_MAX_SIZE),yaffs)
$(hide) $(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE),yaffs)
endef
else # TARGET_USERIMAGES_USE_EXT2 != true
@@ -718,7 +719,7 @@ define build-userdataimage-target
$(call pretty,"Target userdata fs image: $(INSTALLED_USERDATAIMAGE_TARGET)")
@mkdir -p $(TARGET_OUT_DATA)
$(hide) $(MKYAFFS2) -f $(TARGET_OUT_DATA) $(INSTALLED_USERDATAIMAGE_TARGET)
$(hide) $(call assert-max-file-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_MAX_SIZE),yaffs)
$(hide) $(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE),yaffs)
endef
endif # TARGET_USERIMAGES_USE_EXT2
@@ -813,6 +814,13 @@ $(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools)
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_API_VERSION := $(RECOVERY_API_VERSION)
ifeq ($(TARGET_RELEASETOOLS_EXTENSIONS),)
# default to common dir for device vendor
$(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_DEVICE_DIR)/../common
else
$(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_RELEASETOOLS_EXTENSIONS)
endif
# Depending on the various images guarantees that the underlying
# directories are up-to-date.
$(BUILT_TARGET_FILES_PACKAGE): \
@@ -841,6 +849,9 @@ ifdef INSTALLED_2NDBOOTLOADER_TARGET
endif
ifdef BOARD_KERNEL_CMDLINE
$(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/RECOVERY/cmdline
endif
ifdef BOARD_KERNEL_BASE
$(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/RECOVERY/base
endif
@# Components of the boot image
$(hide) mkdir -p $(zip_root)/BOOT
@@ -856,11 +867,12 @@ endif
ifdef BOARD_KERNEL_CMDLINE
$(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
endif
ifdef INSTALLED_RADIOIMAGE_TARGET
@# The radio image
$(hide) mkdir -p $(zip_root)/RADIO
$(hide) $(ACP) $(INSTALLED_RADIOIMAGE_TARGET) $(zip_root)/RADIO/image
ifdef BOARD_KERNEL_BASE
$(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/BOOT/base
endif
$(hide) $(foreach t,$(INSTALLED_RADIOIMAGE_TARGET),\
mkdir -p $(zip_root)/RADIO; \
$(ACP) $(t) $(zip_root)/RADIO/$(notdir $(t));)
@# Contents of the system image
$(hide) $(call package_files-copy-root, \
$(SYSTEMIMAGE_SOURCE_DIR),$(zip_root)/SYSTEM)
@@ -878,10 +890,11 @@ endif
$(hide) echo "$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt
$(hide) echo "$(PRIVATE_RECOVERY_API_VERSION)" > $(zip_root)/META/recovery-api-version.txt
$(hide) echo "blocksize $(BOARD_FLASH_BLOCK_SIZE)" > $(zip_root)/META/imagesizes.txt
$(hide) echo "boot $(BOARD_BOOTIMAGE_MAX_SIZE)" >> $(zip_root)/META/imagesizes.txt
$(hide) echo "recovery $(BOARD_RECOVERYIMAGE_MAX_SIZE)" >> $(zip_root)/META/imagesizes.txt
$(hide) echo "system $(BOARD_SYSTEMIMAGE_MAX_SIZE)" >> $(zip_root)/META/imagesizes.txt
$(hide) echo "userdata $(BOARD_USERDATAIMAGE_MAX_SIZE)" >> $(zip_root)/META/imagesizes.txt
$(hide) echo "boot $(call image-size-from-data-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt
$(hide) echo "recovery $(call image-size-from-data-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt
$(hide) echo "system $(call image-size-from-data-size,$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt
$(hide) echo "userdata $(call image-size-from-data-size,$(BOARD_USERDATAIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt
$(hide) echo "$(tool_extensions)" > $(zip_root)/META/tool-extensions.txt
@# Zip everything up, preserving symlinks
$(hide) (cd $(zip_root) && zip -qry ../$(notdir $@) .)
@@ -904,9 +917,17 @@ INTERNAL_OTA_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
$(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
ifeq ($(TARGET_OTA_SCRIPT_MODE),)
# default to "auto"
$(INTERNAL_OTA_PACKAGE_TARGET): scriptmode := auto
else
$(INTERNAL_OTA_PACKAGE_TARGET): scriptmode := $(TARGET_OTA_SCRIPT_MODE)
endif
$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) otatools
@echo "Package OTA: $@"
$(hide) ./build/tools/releasetools/ota_from_target_files \
-m $(scriptmode) \
-p $(HOST_OUT) \
-k $(KEY_CERT_PAIR) \
$(BUILT_TARGET_FILES_PACKAGE) $@
@@ -1030,9 +1051,17 @@ 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) otatools
@echo "Package: $@"
$(hide) ./build/tools/releasetools/img_from_target_files \
-s $(extensions) \
-p $(HOST_OUT) \
$(BUILT_TARGET_FILES_PACKAGE) $@

View File

@@ -7,10 +7,10 @@ To make these errors go away, you have two choices:
errors above.
2) You can update current.xml by executing the following command:
make update-api
To check in the revised current.xml, you will need approval from the android API council.
To submit the revised current.xml to the main Android repository,
you will need approval.
******************************

View File

@@ -272,8 +272,10 @@ $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SOURCE_INTERMEDIATES_DIR := $(intermediat
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAVA_SOURCES := $(all_java_sources)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAVA_OBJECTS := $(patsubst %.java,%.class,$(LOCAL_SRC_FILES))
ifeq ($(my_prefix),TARGET_)
ifeq ($(LOCAL_SDK_VERSION),)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-files,core)
endif
endif
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_EXTRA_JAR_ARGS := $(extra_jar_args)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ASSET_DIR := $(LOCAL_ASSET_DIR)
@@ -350,7 +352,6 @@ $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_PATH:=$(LOCAL_PATH)
$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_POST_PROCESS_COMMAND:= $(LOCAL_POST_PROCESS_COMMAND)
$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_AAPT_FLAGS:= $(LOCAL_AAPT_FLAGS)
$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_JAVA_LIBRARIES:= $(LOCAL_JAVA_LIBRARIES)
#TODO: add this: $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_ADDITIONAL_DEPENDENCIES:= $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_ALL_JAVA_LIBRARIES:= $(full_java_libs)
$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_IS_HOST_MODULE := $(LOCAL_IS_HOST_MODULE)

View File

@@ -87,7 +87,7 @@ yacc_objects := $(yacc_cpps:$(LOCAL_CPP_EXTENSION)=.o)
ifneq ($(strip $(yacc_cpps)),)
$(yacc_cpps): $(intermediates)/%$(LOCAL_CPP_EXTENSION): \
$(TOPDIR)$(LOCAL_PATH)/%.y \
$(lex_cpps) $(PRIVATE_ADDITIONAL_DEPENDENCIES)
$(lex_cpps) $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(call transform-y-to-cpp,$(PRIVATE_CPP_EXTENSION))
$(yacc_headers): $(intermediates)/%.h: $(intermediates)/%$(LOCAL_CPP_EXTENSION)
@@ -115,7 +115,7 @@ $(lex_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
$(lex_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
$(lex_objects): $(intermediates)/%.o: \
$(intermediates)/%$(LOCAL_CPP_EXTENSION) \
$(PRIVATE_ADDITIONAL_DEPENDENCIES) \
$(LOCAL_ADDITIONAL_DEPENDENCIES) \
$(yacc_headers)
$(transform-$(PRIVATE_HOST)cpp-to-o)
endif
@@ -142,7 +142,7 @@ cpp_objects := $(cpp_arm_objects) $(cpp_normal_objects)
ifneq ($(strip $(cpp_objects)),)
$(cpp_objects): $(intermediates)/%.o: \
$(TOPDIR)$(LOCAL_PATH)/%$(LOCAL_CPP_EXTENSION) \
$(yacc_cpps) $(PRIVATE_ADDITIONAL_DEPENDENCIES)
$(yacc_cpps) $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(transform-$(PRIVATE_HOST)cpp-to-o)
-include $(cpp_objects:%.o=%.P)
endif
@@ -159,7 +159,7 @@ ifneq ($(strip $(gen_cpp_objects)),)
# TODO: support compiling certain generated files as arm.
$(gen_cpp_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
$(gen_cpp_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
$(gen_cpp_objects): $(intermediates)/%.o: $(intermediates)/%$(LOCAL_CPP_EXTENSION) $(yacc_cpps) $(PRIVATE_ADDITIONAL_DEPENDENCIES)
$(gen_cpp_objects): $(intermediates)/%.o: $(intermediates)/%$(LOCAL_CPP_EXTENSION) $(yacc_cpps) $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(transform-$(PRIVATE_HOST)cpp-to-o)
-include $(gen_cpp_objects:%.o=%.P)
endif
@@ -172,7 +172,7 @@ gen_S_sources := $(filter %.S,$(LOCAL_GENERATED_SOURCES))
gen_S_objects := $(gen_S_sources:%.S=%.o)
ifneq ($(strip $(gen_S_sources)),)
$(gen_S_objects): $(intermediates)/%.o: $(intermediates)/%.S $(PRIVATE_ADDITIONAL_DEPENDENCIES)
$(gen_S_objects): $(intermediates)/%.o: $(intermediates)/%.S $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(transform-$(PRIVATE_HOST)s-to-o)
-include $(gen_S_objects:%.o=%.P)
endif
@@ -181,7 +181,7 @@ gen_s_sources := $(filter %.s,$(LOCAL_GENERATED_SOURCES))
gen_s_objects := $(gen_s_sources:%.s=%.o)
ifneq ($(strip $(gen_s_objects)),)
$(gen_s_objects): $(intermediates)/%.o: $(intermediates)/%.s $(PRIVATE_ADDITIONAL_DEPENDENCIES)
$(gen_s_objects): $(intermediates)/%.o: $(intermediates)/%.s $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(transform-$(PRIVATE_HOST)s-to-o-no-deps)
-include $(gen_s_objects:%.o=%.P)
endif
@@ -206,11 +206,28 @@ $(c_normal_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
c_objects := $(c_arm_objects) $(c_normal_objects)
ifneq ($(strip $(c_objects)),)
$(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c $(yacc_cpps) $(PRIVATE_ADDITIONAL_DEPENDENCIES)
$(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c $(yacc_cpps) $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(transform-$(PRIVATE_HOST)c-to-o)
-include $(c_objects:%.o=%.P)
endif
###########################################################
## C: Compile generated .c files to .o.
###########################################################
gen_c_sources := $(filter %.c,$(LOCAL_GENERATED_SOURCES))
gen_c_objects := $(gen_c_sources:%.c=%.o)
ifneq ($(strip $(gen_c_objects)),)
# Compile all generated files as thumb.
# TODO: support compiling certain generated files as arm.
$(gen_c_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
$(gen_c_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
$(gen_c_objects): $(intermediates)/%.o: $(intermediates)/%.c $(yacc_cpps) $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(transform-$(PRIVATE_HOST)c-to-o)
-include $(gen_c_objects:%.o=%.P)
endif
###########################################################
## ObjC: Compile .m files to .o
###########################################################
@@ -232,7 +249,7 @@ asm_sources_S := $(filter %.S,$(LOCAL_SRC_FILES))
asm_objects_S := $(addprefix $(intermediates)/,$(asm_sources_S:.S=.o))
ifneq ($(strip $(asm_objects_S)),)
$(asm_objects_S): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.S $(PRIVATE_ADDITIONAL_DEPENDENCIES)
$(asm_objects_S): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.S $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(transform-$(PRIVATE_HOST)s-to-o)
-include $(asm_objects_S:%.o=%.P)
endif
@@ -241,7 +258,7 @@ asm_sources_s := $(filter %.s,$(LOCAL_SRC_FILES))
asm_objects_s := $(addprefix $(intermediates)/,$(asm_sources_s:.s=.o))
ifneq ($(strip $(asm_objects_s)),)
$(asm_objects_s): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.s $(PRIVATE_ADDITIONAL_DEPENDENCIES)
$(asm_objects_s): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.s $(LOCAL_ADDITIONAL_DEPENDENCIES)
$(transform-$(PRIVATE_HOST)s-to-o-no-deps)
-include $(asm_objects_s:%.o=%.P)
endif
@@ -261,6 +278,7 @@ all_objects := \
$(gen_cpp_objects) \
$(gen_asm_objects) \
$(c_objects) \
$(gen_c_objects) \
$(yacc_objects) \
$(lex_objects) \
$(addprefix $(TOPDIR)$(LOCAL_PATH)/,$(LOCAL_PREBUILT_OBJ_FILES))

947
core/build-system.html Normal file
View File

@@ -0,0 +1,947 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
A lot of people read this document template. Please keep it clean:
- keep the document xhtml-compliant, as many people use validating editors
- check your edits for typos, spelling errors, and questionable grammar
- prefer css styles to formatting tags like <font>, <tt>, etc.
- keep it human-readable and human-editable in a plain text editor:
- strive to keep lines wrapped at 80 columns, unless a link prevents it
- use plenty of whitespace
- try to pretty-format (wrt nesting and indenting) any hairy html
- check your inline javascript for errors using the javascript console
Your readers will be very appreciative.
-->
<head>
<title>Android Build System</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="../android.css" type="text/css" rel="stylesheet" />
<!-- commenting out so the xhtml validator doesn't whine about < and &&;
the browser should still find the script tag. -->
<script language="JavaScript1.2" type="text/javascript">
<!--
function highlight(name) {
if (document.getElementsByTagName) {
tags = [ 'span', 'div', 'tr', 'td' ];
for (i in tags) {
elements = document.getElementsByTagName(tags[i]);
if (elements) {
for (j = 0; j < elements.length; j++) {
elementName = elements[j].getAttribute("class");
if (elementName == name) {
elements[j].style.backgroundColor = "#C0F0C0";
} else if (elementName && elementName.indexOf("rev") == 0) {
elements[j].style.backgroundColor = "#FFFFFF";
}
}
}
}
}
}
//-->
</script>
<!-- this style sheet is for the style of the toc -->
<link href="toc.css" type="text/css" rel="stylesheet" />
<style type="text/css">
.warning {
border: 1px solid red;
padding: 8px;
color: red;
}
pre.prettyprint {
margin-top: 0;
}
li {
margin-top: 8px;
}
</style>
</head>
<body onload="prettyPrint()">
<h1><a name="My_Project_" />Android Build System</h1>
<!-- Status is one of: Draft, Current, Needs Update, Obsolete -->
<p style="text-align:center">
<strong>Status:</strong> <em>Draft </em> &nbsp;
<small>(as of May 18, 2006)</small>
</p>
<p><b>Contents</b></p>
<!-- this div expands out to a list of contents based on the H2 and H3 headings.
Believe it! -->
<div id="nav" class="nav-2-levels"></div>
<h2>Objective</h2>
<p>The primary goals of reworking the build system are (1) to make dependencies
work more reliably, so that when files need to rebuilt, they are, and (2) to
improve performance of the build system so that unnecessary modules are not
rebuilt, and so doing a top-level build when little or nothing needs to be done
for a build takes as little time as possible.</p>
<h2>Principles and Use Cases and Policy</h2>
<p>Given the above objective, these are the overall principles and use cases
that we will support. This is not an exhaustive list.</p>
<h3>Multiple Targets</h3>
<p>It needs to be possible to build the Android platform for multiple targets.
This means:</p>
<ul>
<li>The build system will support building tools for the host platform,
both ones that are used in the build process itself, and developer tools
like the simulator.</li>
<li>The build system will need to be able to build tools on Linux
(definitely Goobuntu and maybe Grhat), MacOS, and to some degree on
Windows.</li>
<li>The build system will need to be able to build the OS on Linux, and in
the short-term, MacOS. Note that this is a conscious decision to stop
building the OS on Windows. We are going to rely on the emulator there
and not attempt to use the simulator. This is a requirement change now
that the emulator story is looking brighter.</li>
</ul>
<h3>Non-Recursive Make</h3>
<p>To achieve the objectives, the build system will be rewritten to use make
non-recursively. For more background on this, read <a href="http://aegis.sourceforge.net/auug97.pdf">Recursive Make Considered Harmful</a>. For those that don't
want PDF, here is the
<a href="http://72.14.203.104/search?q=cache:HwuX7YF2uBIJ:aegis.sourceforge.net/auug97.pdf&hl=en&gl=us&ct=clnk&cd=2&client=firefox">Google translated version</a>.
<h3>Rapid Compile-Test Cycles</h3>
<p>When developing a component, for example a C++ shared library, it must be
possible to easily rebuild just that component, and not have to wait more than a
couple seconds for dependency checks, and not have to wait for unneeded
components to be built.</p>
<h3>Both Environment and Config File Based Settings</h3>
<p>To set the target, and other options, some people on the team like to have a
configuration file in a directory so they do not have an environment setup
script to run, and others want an environment setup script to run so they can
run builds in different terminals on the same tree, or switch back and forth
in one terminal. We will support both.</p>
<h3>Object File Directory / make clean</h3>
<p>Object files and other intermediate files will be generated into a directory
that is separate from the source tree. The goal is to have make clean be
"rm -rf <obj>" in the tree root directory. The primary goals of
this are to simplify searching the source tree, and to make "make clean" more
reliable.</p>
<h3>SDK</h3>
<p>The SDK will be a tarball that will allow non-OS-developers to write apps.
The apps will actually be built by first building the SDK, and then building
the apps against that SDK. This will hopefully (1) make writing apps easier
for us, because we won't have to rebuild the OS as much, and we can use the
standard java-app development tools, and (2) allow us to dog-food the SDK, to
help ensure its quality. Cedric has suggested (and I agree) that apps built
from the SDK should be built with ant. Stay tuned for more details as we
figure out exactly how this will work.</p>
<h3>Dependecies</h3>
<p>Dependencies should all be automatic. Unless there is a custom tool involved
(e.g. the webkit has several), the dependencies for shared and static libraries,
.c, .cpp, .h, .java, java libraries, etc., should all work without intervention
in the Android.mk file.</p>
<h3>Hiding command lines</h3>
<p>The default of the build system will be to hide the command lines being
executed for make steps. It will be possible to override this by specifying
the showcommands pseudo-target, and possibly by setting an environment
variable.</p>
<h3>Wildcard source files</h3>
<p>Wildcarding source file will be discouraged. It may be useful in some
scenarios. The default <code>$(wildcard *)</code> will not work due to the
current directory being set to the root of the build tree.<p>
<h3>Multiple targets in one directory</h3>
<p>It will be possible to generate more than one target from a given
subdirectory. For example, libutils generates a shared library for the target
and a static library for the host.</p>
<h3>Makefile fragments for modules</h3>
<p><b>Android.mk</b> is the standard name for the makefile fragments that
control the building of a given module. Only the top directory should
have a file named "Makefile".</p>
<h3>Use shared libraries</h3>
<p>Currently, the simulator is not built to use shared libraries. This should
be fixed, and now is a good time to do it. This implies getting shared
libraries to work on Mac OS.</p>
<h2>Nice to Have</h2>
<p>These things would be nice to have, and this is a good place to record them,
however these are not promises.</p>
<h3>Simultaneous Builds</h3>
<p>The hope is to be able to do two builds for different combos in the same
tree at the same time, but this is a stretch goal, not a requirement.
Doing two builds in the same tree, not at the same time must work. (update:
it's looking like we'll get the two builds at the same time working)</p>
<h3>Deleting headers (or other dependecies)</h3>
<p>Problems can arise if you delete a header file that is referenced in
".d" files. The easy way to deal with this is "make clean". There
should be a better way to handle it. (from fadden)</p>
<p>One way of solving this is introducing a dependency on the directory. The
problem is that this can create extra dependecies and slow down the build.
It's a tradeoff.</p>
<h3>Multiple builds</h3>
<p>General way to perform builds across the set of known platforms. This
would make it easy to perform multiple platform builds when testing a
change, and allow a wide-scale "make clean". Right now the buildspec.mk
or environment variables need to be updated before each build. (from fadden)</p>
<h3>Aftermarket Locales and Carrier</h3>
<p>We will eventually need to add support for creating locales and carrier
customizations to the SDK, but that will not be addressed right now.</p>
<h2><a id="usage"/>Usage</h2>
<p>You've read (or scrolled past) all of the motivations for this build system,
and you want to know how to use it. This is the place.</p>
<h3>Your first build</h3>
<p>The <a href="../building.html">Building</a> document describes how do do
builds.</p>
<h3>build/envsetup.sh functions</h3>
If you source the file build/envsetup.sh into your bash environment,
<code>. build/envsetup.sh</code>you'll get a few helpful shell functions:
<ul>
<li><b>printconfig</b> - Prints the current configuration as set by the
lunch and choosecombo commands.</li>
<li><b>m</b> - Runs <code>make</code> from the top of the tree. This is
useful because you can run make from within subdirectories. If you have the
<code>TOP</code> environment variable set, it uses that. If you don't, it looks
up the tree from the current directory, trying to find the top of the tree.</li>
<li><b>croot</b> - <code>cd</code> to the top of the tree.</li>
<li><b>sgrep</b> - grep for the regex you provide in all .c, .cpp, .h, .java,
and .xml files below the current directory.</li>
</ul>
<h3>Build flavors/types</h3>
<p>
When building for a particular product, it's often useful to have minor
variations on what is ultimately the final release build. These are the
currently-defined "flavors" or "types" (we need to settle on a real name
for these).
</p>
<table border=1>
<tr>
<td>
<code>eng<code>
</td>
<td>
This is the default flavor. A plain "<code>make</code>" is the
same as "<code>make eng</code>". <code>droid</code> is an alias
for <code>eng</code>.
<ul>
<li>Installs modules tagged with: <code>eng</code>, <code>debug</code>,
<code>user</code>, and/or <code>development</code>.
<li>Installs non-APK modules that have no tags specified.
<li>Installs APKs according to the product definition files, in
addition to tagged APKs.
<li><code>ro.secure=0</code>
<li><code>ro.debuggable=1</code>
<li><code>ro.kernel.android.checkjni=1</code>
<li><code>adb</code> is enabled by default.
</td>
</tr>
<tr>
<td>
<code>user<code>
</td>
<td>
"<code>make user</code>"
<p>
This is the flavor intended to be the final release bits.
<ul>
<li>Installs modules tagged with <code>user</code>.
<li>Installs non-APK modules that have no tags specified.
<li>Installs APKs according to the product definition files; tags
are ignored for APK modules.
<li><code>ro.secure=1</code>
<li><code>ro.debuggable=0</code>
<li><code>adb</code> is disabled by default.
</td>
</tr>
<tr>
<td>
<code>userdebug<code>
</td>
<td>
"<code>make userdebug</code>"
<p>
The same as <code>user</code>, except:
<ul>
<li>Also installs modules tagged with <code>debug</code>.
<li><code>ro.debuggable=1</code>
<li><code>adb</code> is enabled by default.
</td>
</tr>
</table>
<p>
If you build one flavor and then want to build another, you should run
"<code>make installclean</code>" between the two makes to guarantee that
you don't pick up files installed by the previous flavor. "<code>make
clean</code>" will also suffice, but it takes a lot longer.
</p>
<h3>More pseudotargets</h3>
<p>Sometimes you want to just build one thing. The following pseudotargets are
there for your convenience:</p>
<ul>
<li><b>droid</b> - <code>make droid</code> is the normal build. This target
is here because the default target has to have a name.</li>
<li><b>all</b> - <code>make all</code> builds everything <code>make
droid</code> does, plus everything whose <code>LOCAL_MODULE_TAGS</code> do not
include the "droid" tag. The build server runs this to make sure
that everything that is in the tree and has an Android.mk builds.</li>
<li><b>clean-$(LOCAL_MODULE)</b> and <b>clean-$(LOCAL_PACKAGE_NAME)</b> -
Let you selectively clean one target. For example, you can type
<code>make clean-libutils</code> and it will delete libutils.so and all of the
intermediate files, or you can type <code>make clean-Home</code> and it will
clean just the Home app.</li>
<li><b>clean</b> - <code>make clean</code> deletes all of the output and
intermediate files for this configuration. This is the same as <code>rm -rf
out/&lt;configuration&gt;/</code></li>
<li><b>clobber</b> - <code>make clobber</code> deletes all of the output
and intermediate files for all configurations. This is the same as
<code>rm -rf out/</code>.</li>
<li><b>dataclean</b> - <code>make dataclean</code> deletes contents of the data
directory inside the current combo directory. This is especially useful on the
simulator and emulator, where the persistent data remains present between
builds.</li>
<li><b>showcommands</b> - <code>showcommands</code> is a modifier target
which causes the build system to show the actual command lines for the build
steps, instead of the brief descriptions. Most people don't like seeing the
actual commands, because they're quite long and hard to read, but if you need
to for debugging purposes, you can add <code>showcommands</code> to the list
of targets you build. For example <code>make showcommands</code> will build
the default android configuration, and <code>make runtime showcommands</code>
will build just the runtime, and targets that it depends on, while displaying
the full command lines. Please note that there are a couple places where the
commands aren't shown here. These are considered bugs, and should be fixed,
but they're often hard to track down. Please let
<a href="mailto:android-build-team">android-build-team</a> know if you find
any.</li>
<li><b>LOCAL_MODULE</b> - Anything you specify as a <code>LOCAL_MODULE</code>
in an Android.mk is made into a pseudotarget. For example, <code>make
runtime</code> might be shorthand for <code>make
out/linux-x86-debug/system/bin/runtime</code> (which would work), and
<code>make libkjs</code> might be shorthand for <code>make
out/linux-x86-debug/system/lib/libkjs.so</code> (which would also work).</li>
<li><b>targets</b> - <code>make targets</code> will print a list of all of
the LOCAL_MODULE names you can make.</li>
</ul>
<h3><a name="templates"/>How to add another component to the build - Android.mk templates</h3>
<p>You have a new library, a new app, or a new executable. For each of the
common types of modules, there is a corresponding file in the templates
directory. It will usually be enough to copy one of these, and fill in your
own values. Some of the more esoteric values are not included in the
templates, but are instead just documented here, as is the documentation
on using custom tools to generate files.</p>
<p>Mostly, you can just look for the TODO comments in the templates and do
what it says. Please remember to delete the TODO comments when you're done
to keep the files clean. The templates have minimal documentation in them,
because they're going to be copied, and when that gets stale, the copies just
won't get updated. So read on...</p>
<h4>Apps</h4>
<p>Use the <code>templates/apps</code> file.</p>
<p>This template is pretty self-explanitory. See the variables below for more
details.</p>
<h4>Java Libraries</h4>
<p>Use the <code>templates/java_library</code> file.</p>
<p>The interesting thing here is the value of LOCAL_MODULE, which becomes
the name of the jar file. (Actually right now, we're not making jar files yet,
just directories of .class files, but the directory is named according to
what you put in LOCAL_MODULE). This name will be what goes in the
LOCAL_JAVA_LIBRARIES variable in modules that depend on your java library.</p>
<h4>C/C++ Executables</h4>
<p>Use the <code>templates/executable</code> file, or the
<code>templates/executable_host</code> file.</p>
<p>This template has a couple extra options that you usually don't need.
Please delete the ones you don't need, and remove the TODO comments. It makes
the rest of them easier to read, and you can always refer back to the templates
if you need them again later.</p>
<p>By default, on the target these are built into /system/bin, and on the
host, they're built into <combo>/host/bin. These can be overridden by setting
<code>LOCAL_MODULE_PATH</code>. See
<a href="#moving-targets">Putting targets elsewhere</a>
for more.</p>
<h4>Shared Libraries</h4>
<p>Use the <code>templates/shared_library</code> file, or the
<code>templates/shared_library_host</code> file.</p>
<p>Remember that on the target, we use shared libraries, and on the host,
we use static libraries, since executable size isn't as big an issue, and it
simplifies distribution in the SDK.</p>
<h4>Static Libraries</h4>
<p>Use the <code>templates/static_library</code> file, or the
<code>templates/static_library_host</code> file.</p>
<p>Remember that on the target, we use shared libraries, and on the host,
we use static libraries, since executable size isn't as big an issue, and it
simplifies distribution in the SDK.</p>
<h4><a name="custom-tools"/>Using Custom Tools</h4>
<p>If you have a tool that generates source files for you, it's possible
to have the build system get the dependencies correct for it. Here are
a couple of examples. <code>$@</code> is the make built-in variable for
"the current target." The <font color=red>red</font> parts are the parts you'll
need to change.</p>
<p>You need to put this after you have declared <code>LOCAL_PATH</code> and
<code>LOCAL_MODULE</code>, because the <code>$(local-intermediates-dir)</code>
and <code>$(local-host-intermediates-dir)</code> macros use these variables
to determine where to put the files.
<h5>Example 1</h5>
<p>Here, there is one generated file, called
chartables.c, which doesn't depend on anything. And is built by the tool
built to $(HOST_OUT_EXECUTABLES)/dftables. Note on the second to last line
that a dependency is created on the tool.</p>
<pre>
intermediates:= $(local-intermediates-dir)
GEN := $(intermediates)/<font color=red>chartables.c</font>
$(GEN): PRIVATE_CUSTOM_TOOL = <font color=red>$(HOST_OUT_EXECUTABLES)/dftables $@</font>
$(GEN): <font color=red>$(HOST_OUT_EXECUTABLES)/dftables</font>
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
</pre>
<h5>Example 2</h5>
<p>Here as a hypothetical example, we use use cat as if it were to transform
a file. Pretend that it does something useful. Note how we use a
target-specific variable called PRIVATE_INPUT_FILE to store the name of the
input file.</p>
<pre>
intermediates:= $(local-intermediates-dir)
GEN := $(intermediates)/<font color=red>file.c</font>
$(GEN): PRIVATE_INPUT_FILE := $(LOCAL_PATH)/<font color=red>input.file</font>
$(GEN): PRIVATE_CUSTOM_TOOL = <font color=red>cat $(PRIVATE_INPUT_FILE) &gt; $@</font>
$(GEN): <font color=red>$(LOCAL_PATH)/file.c</font>
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
</pre>
<h5>Example 3</h5>
<p>If you have several files that are all similar in
name, and use the same tool, you can combine them. (here the *.lut.h files are
the generated ones, and the *.cpp files are the input files)</p>
<pre>
intermediates:= $(local-intermediates-dir)
GEN := $(addprefix $(intermediates)<font color=red>/kjs/, \
array_object.lut.h \
bool_object.lut.h \</font>
)
$(GEN): PRIVATE_CUSTOM_TOOL = <font color=red>perl libs/WebKitLib/WebKit/JavaScriptCore/kjs/create_hash_table $< -i > $@</font>
$(GEN): $(intermediates)/<font color=red>%.lut.h</font> : $(LOCAL_PATH)/<font color=red>%.cpp</font>
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
</pre>
<h3><a name="platform-specific"/>Platform specific conditionals</h3>
<p>Sometimes you need to set flags specifically for different platforms. Here
is a list of which values the different build-system defined variables will be
set to and some examples.</p>
<p>For a device build, <code>TARGET_OS</code> is <code>linux</code> (we're using
linux!), and <code>TARGET_ARCH</code> is <code>arm</code>.</p>
<p>For a simulator build, <code>TARGET_OS</code> and <code>TARGET_ARCH</code>
are set to the same as <code>HOST_OS</code> and <code>HOST_ARCH</code> are
on your platform. <code>TARGET_PRODUCT</code> is the name of the target
hardware/product you are building for. The value <code>sim</code> is used
for the simulator. We haven't thought through the full extent of customization
that will happen here, but likely there will be additional UI configurations
specified here as well.</p>
<table cellspacing=25>
<tr>
<td valign=top align=center>
<b>HOST_OS</b><br/>
linux<br/>
darwin<br/>
(cygwin)
</td>
<td valign=top align=center>
<b>HOST_ARCH</b><br/>
x86
</td>
<td valign=top align=center>
<b>HOST_BUILD_TYPE</b><br/>
release<br/>
debug
</td>
</tr>
<tr>
<td valign=top align=center>
<b>TARGET_OS</b><br/>
linux<br/>
darwin<br/>
(cygwin)
</td>
<td valign=top align=center>
<b>TARGET_ARCH</b><br/>
arm<br/>
x86
</td>
<td valign=top align=center>
<b>TARGET_BUILD_TYPE</b><br/>
release<br/>
debug
</td>
<td valign=top align=center>
<b>TARGET_PRODUCT</b><br/>
sim<br/>
dream<br/>
sooner
</td>
</tr>
</table>
<h4>TARGET_SIMULATOR</h4>
<p>If we're building the simulator, as opposed to the arm or emulator builds,
<code>TARGET_SIMULATOR</code> will be set to <code>true</code>.
<h4>Some Examples</h4>
<pre>ifeq ($(TARGET_SIMULATOR),true)
LOCAL_CFLAGS += -DSIMULATOR
endif
ifeq ($(TARGET_BUILD_TYPE),release)
LOCAL_CFLAGS += -DNDEBUG=1
endif
# from libutils
ifeq ($(TARGET_OS),linux)
# Use the futex based mutex and condition variable
# implementation from android-arm because it's shared mem safe
LOCAL_SRC_FILES += futex_synchro.c
LOCAL_LDLIBS += -lrt -ldl
endif
</pre>
<h3><a name="moving-modules"/>Putting modules elsewhere</h3>
<p>If you have modules that normally go somewhere, and you need to have them
build somewhere else, read this. One use of this is putting files on
the root filesystem instead of where they normally go in /system. Add these
lines to your Android.mk:</p>
<pre>
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
</pre>
<p>For executables and libraries, you need to also specify a
<code>LOCAL_UNSTRIPPED_PATH</code> location, because on target builds, we keep
the unstripped executables so GDB can find the symbols.</code>
<p>Look in <code>config/envsetup.make</code> for all of the variables defining
places to build things.</p>
<p>FYI: If you're installing an executable to /sbin, you probably also want to
set <code>LOCAL_FORCE_STATIC_EXCUTABLE := true</code> in your Android.mk, which
will force the linker to only accept static libraries.</p>
<h3>Android.mk variables</h3>
<p>These are the variables that you'll commonly see in Android.mk files, listed
alphabetically.</p>
<p>But first, a note on variable naming:
<ul>
<li><b>LOCAL_</b> - These variables are set per-module. They are cleared
by the <code>include $(CLEAR_VARS)</code> line, so you can rely on them
being empty after including that file. Most of the variables you'll use
in most modules are LOCAL_ variables.</li>
<li><b>PRIVATE_</b> - These variables are make-target-specific variables. That
means they're only usable within the commands for that module. It also
means that they're unlikely to change behind your back from modules that
are included after yours. This
<a href="http://www.gnu.org/software/make/manual/make.html#Target_002dspecific">link to the make documentation</a>
describes more about target-specific variables. Please note that there
are a couple of these laying around the tree that aren't prefixed with
PRIVATE_. It is safe, and they will be fixed as they are discovered.
Sorry for the confusion.</li>
<li><b>INTERNAL_</b> - These variables are critical to functioning of
the build system, so you shouldn't create variables named like this, and
you probably shouldn't be messing with these variables in your makefiles.
</li>
<li><b>HOST_</b> and <b>TARGET_</b> - These contain the directories
and definitions that are specific to either the host or the target builds.
Do not set variables that start with HOST_ or TARGET_ in your makefiles.
</li>
<li><b>BUILD_</b> and <b>CLEAR_VARS</b> - These contain the names of
well-defined template makefiles to include. Some examples are CLEAR_VARS
and BUILD_HOST_PACKAGE.</li>
<li>Any other name is fair-game for you to use in your Android.mk. However,
remember that this is a non-recursive build system, so it is possible that
your variable will be changed by another Android.mk included later, and be
different when the commands for your rule / module are executed.</li>
</ul>
</p>
<h4>LOCAL_ASSET_FILES</h4>
<p>In Android.mk files that <code>include $(BUILD_PACKAGE)</code> set this
to the set of files you want built into your app. Usually:</p>
<p><code>LOCAL_ASSET_FILES += $(call find-subdir-assets)</code></p>
<p>This will probably change when we switch to ant for the apps' build
system.</p>
<h4>LOCAL_CC</h4>
<p>If you want to use a different C compiler for this module, set LOCAL_CC
to the path to the compiler. If LOCAL_CC is blank, the appropriate default
compiler is used.</p>
<h4>LOCAL_CXX</h4>
<p>If you want to use a different C++ compiler for this module, set LOCAL_CXX
to the path to the compiler. If LOCAL_CXX is blank, the appropriate default
compiler is used.</p>
<h4>LOCAL_CFLAGS</h4>
<p>If you have additional flags to pass into the C or C++ compiler, add
them here. For example:</p>
<p><code>LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1</code></p>
<h4>LOCAL_CPPFLAGS</h4>
<p>If you have additional flags to pass into <i>only</i> the C++ compiler, add
them here. For example:</p>
<p><code>LOCAL_CPPFLAGS += -ffriend-injection</code></p>
<code>LOCAL_CPPFLAGS</code> is guaranteed to be after <code>LOCAL_CFLAGS</code>
on the compile line, so you can use it to override flags listed in
<code>LOCAL_CFLAGS</code>.
<h4>LOCAL_CPP_EXTENSION</h4>
<p>If your C++ files end in something other than "<code>.cpp</code>",
you can specify the custom extension here. For example:</p>
<p><code>LOCAL_CPP_EXTENSION := .cc</code></p>
Note that all C++ files for a given module must have the same
extension; it is not currently possible to mix different extensions.
<h4>LOCAL_NO_DEFAULT_COMPILER_FLAGS</h4>
<p>Normally, the compile line for C and C++ files includes global include
paths and global cflags. If <code>LOCAL_NO_DEFAULT_COMPILER_FLAGS</code>
is non-empty, none of the default includes or flags will be used when compiling
C and C++ files in this module.
<code>LOCAL_C_INCLUDES</code>, <code>LOCAL_CFLAGS</code>, and
<code>LOCAL_CPPFLAGS</code> will still be used in this case, as will
any <code>DEBUG_CFLAGS</code> that are defined for the module.
<h4>LOCAL_COPY_HEADERS</h4>
<p class=warning>This will be going away.</p>
<p>The set of files to copy to the install include tree. You must also
supply <code>LOCAL_COPY_HEADERS_TO</code>.</p>
<p>This is going away because copying headers messes up the error messages, and
may lead to people editing those headers instead of the correct ones. It also
makes it easier to do bad layering in the system, which we want to avoid. We
also aren't doing a C/C++ SDK, so there is no ultimate requirement to copy any
headers.</p>
<h4>LOCAL_COPY_HEADERS_TO</h4>
<p class=warning>This will be going away.</p>
<p>The directory within "include" to copy the headers listed in
<code>LOCAL_COPY_HEADERS</code> to.</p>
<p>This is going away because copying headers messes up the error messages, and
may lead to people editing those headers instead of the correct ones. It also
makes it easier to do bad layering in the system, which we want to avoid. We
also aren't doing a C/C++ SDK, so there is no ultimate requirement to copy any
headers.</p>
<h4>LOCAL_C_INCLUDES</h4>
<p>Additional directories to instruct the C/C++ compilers to look for header
files in. These paths are rooted at the top of the tree. Use
<code>LOCAL_PATH</code> if you have subdirectories of your own that you
want in the include paths. For example:</p>
<p><code>
LOCAL_C_INCLUDES += extlibs/zlib-1.2.3<br/>
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
</code></p>
<p>You should not add subdirectories of include to
<code>LOCAL_C_INCLUDES</code>, instead you should reference those files
in the <code>#include</code> statement with their subdirectories. For
example:</p>
<p><code>#include &lt;utils/KeyedVector.h&gt;</code><br/>
not <code><s>#include &lt;KeyedVector.h&gt;</s></code></p>
<p>There are some components that are doing this wrong, and should be cleaned
up.</p>
<h4>LOCAL_MODULE_TAGS</h4>
<p>Set <code>LOCAL_MODULE_TAGS</code> to any number of whitespace-separated
tags. If the tag list is empty or contains <code>droid</code>, the module
will get installed as part of a <code>make droid</code>. Otherwise, it will
only get installed by running <code>make &lt;your-module&gt;</code>
or with the <code>make all</code> pseudotarget.</p>
<h4>LOCAL_REQUIRED_MODULES</h4>
<p>Set <code>LOCAL_REQUIRED_MODULES</code> to any number of whitespace-separated
module names, like "libblah" or "Email". If this module is installed, all
of the modules that it requires will be installed as well. This can be
used to, e.g., ensure that necessary shared libraries or providers are
installed when a given app is installed.
<h4>LOCAL_FORCE_STATIC_EXECUTABLE</h4>
<p>If your executable should be linked statically, set
<code>LOCAL_FORCE_STATIC_EXECUTABLE:=true</code>. There is a very short
list of libraries that we have in static form (currently only libc). This is
really only used for executables in /sbin on the root filesystem.</p>
<h4>LOCAL_GENERATED_SOURCES</h4>
<p>Files that you add to <code>LOCAL_GENERATED_SOURCES</code> will be
automatically generated and then linked in when your module is built.
See the <a href="#custom-tools">Custom Tools</a> template makefile for an
example.</p>
<h4>LOCAL_JAVA_LIBRARIES</h4>
<p>When linking Java apps and libraries, <code>LOCAL_JAVA_LIBRARIES</code>
specifies which sets of java classes to include. Currently there are
two of these: <code>core</code> and <code>framework</code>.
In most cases, it will look like this:</p>
<p><code>LOCAL_JAVA_LIBRARIES := core framework</code></p>
<p>Note that setting <code>LOCAL_JAVA_LIBRARIES</code> is not necessary
(and is not allowed) when building an APK with
"<code>include $(BUILD_PACKAGE)</code>". The appropriate libraries
will be included automatically.</p>
<h4>LOCAL_LDFLAGS</h4>
<p>You can pass additional flags to the linker by setting
<code>LOCAL_LDFLAGS</code>. Keep in mind that the order of parameters is
very important to ld, so test whatever you do on all platforms.</p>
<h4>LOCAL_LDLIBS</h4>
<p><code>LOCAL_LDLIBS</code> allows you to specify additional libraries
that are not part of the build for your executable or library. Specify
the libraries you want in -lxxx format; they're passed directly to the
link line. However, keep in mind that there will be no dependency generated
for these libraries. It's most useful in simulator builds where you want
to use a library preinstalled on the host. The linker (ld) is a particularly
fussy beast, so it's sometimes necessary to pass other flags here if you're
doing something sneaky. Some examples:</p>
<p><code>LOCAL_LDLIBS += -lcurses -lpthread<br/>
LOCAL_LDLIBS += -Wl,-z,origin
</code></p>
<h4>LOCAL_NO_MANIFEST</h4>
<p>If your package doesn't have a manifest (AndroidManifest.xml), then
set <code>LOCAL_NO_MANIFEST:=true</code>. The common resources package
does this.</p>
<h4>LOCAL_PACKAGE_NAME</h4>
<p><code>LOCAL_PACKAGE_NAME</code> is the name of an app. For example,
Dialer, Contacts, etc. This will probably change or go away when we switch
to an ant-based build system for the apps.</p>
<h4>LOCAL_PATH</h4>
<p>The directory your Android.mk file is in. You can set it by putting the
following as the first line in your Android.mk:</p>
<p><code>LOCAL_PATH := $(my-dir)</code></p>
<p>The <code>my-dir</code> macro uses the
<code><a href="http://www.gnu.org/software/make/manual/make.html#MAKEFILE_005fLIST-Variable">MAKEFILE_LIST</a></code>
variable, so you must call it before you include any other makefiles. Also,
consider that any subdirectories you inlcude might reset LOCAL_PATH, so do your
own stuff before you include them. This also means that if you try to write
several <code>include</code> lines that reference <code>LOCAL_PATH</code>,
it won't work, because those included makefiles might reset LOCAL_PATH.
<h4>LOCAL_POST_PROCESS_COMMAND</h4>
<p>For host executables, you can specify a command to run on the module
after it's been linked. You might have to go through some contortions
to get variables right because of early or late variable evaluation:</p>
<p><code>module := $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)<br/>
LOCAL_POST_PROCESS_COMMAND := /Developer/Tools/Rez -d __DARWIN__ -t APPL\<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-d __WXMAC__ -o $(module) Carbon.r
</code></p>
<h4>LOCAL_PREBUILT_EXECUTABLES</h4>
<p>When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to
executables that you want copied. They're located automatically into the
right bin directory.</p>
<h4>LOCAL_PREBUILT_LIBS</h4>
<p>When including $(BUILD_PREBUILT) or $(BUILD_HOST_PREBUILT), set these to
libraries that you want copied. They're located automatically into the
right lib directory.</p>
<h4>LOCAL_SHARED_LIBRARIES</h4>
<p>These are the libraries you directly link against. You don't need to
pass transitively included libraries. Specify the name without the suffix:</p>
<p><code>LOCAL_SHARED_LIBRARIES := \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;libutils \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;libui \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;libaudio \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;libexpat \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;libsgl
</code></p>
<h4>LOCAL_SRC_FILES</h4>
<p>The build system looks at <code>LOCAL_SRC_FILES</code> to know what source
files to compile -- .cpp .c .y .l .java. For lex and yacc files, it knows
how to correctly do the intermediate .h and .c/.cpp files automatically. If
the files are in a subdirectory of the one containing the Android.mk, prefix
them with the directory name:</p>
<p><code>LOCAL_SRC_FILES := \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;file1.cpp \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;dir/file2.cpp
</code></p>
<h4>LOCAL_STATIC_LIBRARIES</h4>
<p>These are the static libraries that you want to include in your module.
Mostly, we use shared libraries, but there are a couple of places, like
executables in sbin and host executables where we use static libraries instead.
<p><code>LOCAL_STATIC_LIBRARIES := \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;libutils \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;libtinyxml
</code></p>
<h4>LOCAL_MODULE</h4>
<p><code>LOCAL_MODULE</code> is the name of what's supposed to be generated
from your Android.mk. For exmample, for libkjs, the <code>LOCAL_MODULE</code>
is "libkjs" (the build system adds the appropriate suffix -- .so .dylib .dll).
For app modules, use <code>LOCAL_PACKAGE_NAME</code> instead of
<code>LOCAL_MODULE</code>. We're planning on switching to ant for the apps,
so this might become moot.</p>
<h4>LOCAL_MODULE_PATH</h4>
<p>Instructs the build system to put the module somewhere other than what's
normal for its type. If you override this, make sure you also set
<code>LOCAL_UNSTRIPPED_PATH</code> if it's an executable or a shared library
so the unstripped binary has somewhere to go. An error will occur if you forget
to.</p>
<p>See <a href="#moving-modules">Putting modules elsewhere</a> for more.</p>
<h4>LOCAL_UNSTRIPPED_PATH</h4>
<p>Instructs the build system to put the unstripped version of the module
somewhere other than what's normal for its type. Usually, you override this
because you overrode <code>LOCAL_MODULE_PATH</code> for an executable or a
shared library. If you overrode <code>LOCAL_MODULE_PATH</code>, but not
<code>LOCAL_UNSTRIPPED_PATH</code>, an error will occur.</p>
<p>See <a href="#moving-modules">Putting modules elsewhere</a> for more.</p>
<h4>LOCAL_WHOLE_STATIC_LIBRARIES</h4>
<p>These are the static libraries that you want to include in your module without allowing
the linker to remove dead code from them. This is mostly useful if you want to add a static library
to a shared library and have the static library's content exposed from the shared library.
<p><code>LOCAL_WHOLE_STATIC_LIBRARIES := \<br/>
&nbsp;&nbsp;&nbsp;&nbsp;libsqlite3_android<br/>
</code></p>
<h4>LOCAL_YACCFLAGS</h4>
<p>Any flags to pass to invocations of yacc for your module. A known limitation
here is that the flags will be the same for all invocations of YACC for your
module. This can be fixed. If you ever need it to be, just ask.</p>
<p><code>LOCAL_YACCFLAGS := -p kjsyy</code></p>
<h2>Implementation Details</h2>
<p>You should never have to touch anything in the config directory unless
you're adding a new platform, new tools, or adding new features to the
build system. In general, please consult with the build system owner(s)
(<a href="mailto:android-build-team">android-build-team</a>) before you go
mucking around in here. That said, here are some notes on what's going on
under the hood.</p>
<h3>Environment Setup / buildspec.mk Versioning</h3>
<p>In order to make easier for people when the build system changes, when
it is necessary to make changes to buildspec.mk or to rerun the environment
setup scripts, they contain a version number in the variable
BUILD_ENV_SEQUENCE_NUMBER. If this variable does not match what the build
system expects, it fails printing an error message explaining what happened.
If you make a change that requires an update, you need to update two places
so this message will be printed.
<ul>
<li>In config/envsetup.make, increment the
CORRECT_BUILD_ENV_SEQUENCE_NUMBER definition.</li>
<li>In buildspec.mk.default, update the BUILD_ENV_SEQUENCE_DUMBER
definition to match the one in config/envsetup.make</li>
</ul>
The scripts automatically get the value from the build system, so they will
trigger the warning as well.
</p>
<h3>Additional makefile variables</h3>
<p>You probably shouldn't use these variables. Please consult
<a href="mailto:android-build-team">android-build-team</a> before using them.
These are mostly there for workarounds for other issues, or things that aren't
completely done right.</p>
<h4>LOCAL_ADDITIONAL_DEPENDENCIES</h4>
<p>If your module needs to depend on anything else that
isn't actually built in to it, you can add those make targets to
<code>LOCAL_ADDITIONAL_DEPENDENCIES</code>. Usually this is a workaround
for some other dependency that isn't created automatically.</p>
<h4>LOCAL_BUILT_MODULE</h4>
<p>When a module is built, the module is created in an intermediate
directory then copied to its final location. LOCAL_BUILT_MODULE is
the full path to the intermediate file. See LOCAL_INSTALLED_MODULE
for the path to the final installed location of the module.</p>
<h4>LOCAL_HOST</h4>
<p>Set by the host_xxx.make includes to tell base_rules.make and the other
includes that we're building for the host. Kenneth did this as part of
openbinder, and I would like to clean it up so the rules, includes and
definitions aren't duplicated for host and target.</p>
<h4>LOCAL_INSTALLED_MODULE</h4>
<p>The fully qualified path name of the final location of the module.
See LOCAL_BUILT_MODULE for the location of the intermediate file that
the make rules should actually be constructing.</p>
<h4>LOCAL_REPLACE_VARS</h4>
<p>Used in some stuff remaining from the openbinder for building scripts
with particular values set,</p>
<h4>LOCAL_SCRIPTS</h4>
<p>Used in some stuff remaining from the openbinder build system that we
might find handy some day.</p>
<h4>LOCAL_MODULE_CLASS</h4>
<p>Which kind of module this is. This variable is used to construct other
variable names used to locate the modules. See base_rules.make and
envsetup.make.</p>
<h4>LOCAL_MODULE_NAME</h4>
<p>Set to the leaf name of the LOCAL_BUILT_MODULE. I'm not sure,
but it looks like it's just used in the WHO_AM_I variable to identify
in the pretty printing what's being built.</p>
<h4>LOCAL_MODULE_SUFFIX</h4>
<p>The suffix that will be appended to <code>LOCAL_MODULE</code> to form
<code>LOCAL_MODULE_NAME</code>. For example, .so, .a, .dylib.</p>
<h4>LOCAL_STRIP_MODULE</h4>
<p>Calculated in base_rules.make to determine if this module should actually
be stripped or not, based on whether <code>LOCAL_STRIPPABLE_MODULE</code>
is set, and whether the combo is configured to ever strip modules. With
Iliyan's stripping tool, this might change.</p>
<h4>LOCAL_STRIPPABLE_MODULE</h4>
<p>Set by the include makefiles if that type of module is strippable.
Executables and shared libraries are.</p>
<h4>LOCAL_SYSTEM_SHARED_LIBRARIES</h4>
<p>Used while building the base libraries: libc, libm, libdl. Usually
it should be set to "none," as it is in $(CLEAR_VARS). When building
these libraries, it's set to the ones they link against. For example,
libc, libstdc++ and libdl don't link against anything, and libm links against
libc. Normally, when the value is none, these libraries are automatically
linked in to executables and libraries, so you don't need to specify them
manually.</p>
</body>
</html>

View File

@@ -23,7 +23,7 @@
# (like "TC1-RC5"). It must be a single word, and is
# capitalized by convention.
#
BUILD_ID := Donut
BUILD_ID := ECLAIR
# DISPLAY_BUILD_NUMBER should only be set for development branches,
# If set, the BUILD_NUMBER (cl) is appended to the BUILD_ID for

View File

@@ -87,6 +87,8 @@ LOCAL_CERTIFICATE:=
LOCAL_SDK_VERSION:=
LOCAL_NO_EMMA_INSTRUMENT:=
LOCAL_NO_EMMA_COMPILE:=
LOCAL_PROGUARD_ENABLED:= # '',optonly,full,custom
LOCAL_PROGUARD_FLAGS:=
# Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to
# iterate over thousands of entries every time.

View File

@@ -0,0 +1,23 @@
# Configuration for Linux on ARM.
# Generating binaries for the ARMv4T architecture and higher
#
# Supporting armv4 (without thumb) does not make much sense since
# it's mostly an obsoleted instruction set architecture (only available
# in StrongArm and arm8). Supporting armv4 will require a lot of conditional
# code in assembler source since the bx (branch and exchange) instruction is
# not supported.
#
$(warning ARMv4t support is currently a work in progress. It does not work right now!)
ARCH_ARM_HAVE_THUMB_SUPPORT := false
ARCH_ARM_HAVE_THUMB_INTERWORKING := false
ARCH_ARM_HAVE_64BIT_DATA := false
ARCH_ARM_HAVE_HALFWORD_MULTIPLY := false
ARCH_ARM_HAVE_CLZ := false
ARCH_ARM_HAVE_FFS := false
DEFAULT_TARGET_CPU := arm920t
# Note: Hard coding the 'tune' value here is probably not ideal,
# and a better solution should be found in the future.
#
arch_variant_cflags := -march=armv4t -mtune=arm920t -D__ARM_ARCH_4T__

View File

@@ -0,0 +1,7 @@
# At the moment, use the same settings than the one
# for armv5te, since TARGET_ARCH_VARIANT := armv5te-vfp
# will only be used to select an optimized VFP-capable assembly
# interpreter loop for Dalvik.
#
include $(BUILD_COMBOS)/arch/arm/armv5te.mk

View File

@@ -0,0 +1,21 @@
# Configuration for Linux on ARM.
# Generating binaries for the ARMv5TE architecture and higher
#
ARCH_ARM_HAVE_THUMB_SUPPORT := true
ARCH_ARM_HAVE_FAST_INTERWORKING := true
ARCH_ARM_HAVE_64BIT_DATA := true
ARCH_ARM_HAVE_HALFWORD_MULTIPLY := true
ARCH_ARM_HAVE_CLZ := true
ARCH_ARM_HAVE_FFS := true
# Note: Hard coding the 'tune' value here is probably not ideal,
# and a better solution should be found in the future.
#
arch_variant_cflags := \
-march=armv5te \
-mtune=xscale \
-D__ARM_ARCH_5__ \
-D__ARM_ARCH_5T__ \
-D__ARM_ARCH_5E__ \
-D__ARM_ARCH_5TE__

View File

@@ -0,0 +1,22 @@
# Configuration for Linux on ARM.
# Generating binaries for the ARMv7-a architecture and higher
#
ARCH_ARM_HAVE_THUMB_SUPPORT := true
ARCH_ARM_HAVE_FAST_INTERWORKING := true
ARCH_ARM_HAVE_64BIT_DATA := true
ARCH_ARM_HAVE_HALFWORD_MULTIPLY := true
ARCH_ARM_HAVE_CLZ := true
ARCH_ARM_HAVE_FFS := true
ARCH_ARM_HAVE_VFP := true
ARCH_ARM_HAVE_NEON := true
# Note: Hard coding the 'tune' value here is probably not ideal,
# and a better solution should be found in the future.
#
arch_variant_cflags := \
-march=armv7-a \
-mfloat-abi=softfp \
-mfpu=neon
arch_variant_ldflags := \
-Wl,--fix-cortex-a8

View File

@@ -1,10 +1,44 @@
# Configuration for Linux on ARM.
# Included by combo/select.make
# You can set TARGET_ARCH_VARIANT to use an arch version other
# than ARMv5TE. Each value should correspond to a file named
# $(BUILD_COMBOS)/arch/<name>.mk which must contain
# makefile variable definitions similar to the preprocessor
# defines in system/core/include/arch/<combo>/AndroidConfig.h. Their
# purpose is to allow module Android.mk files to selectively compile
# different versions of code based upon the funtionality and
# instructions available in a given architecture version.
#
# The blocks also define specific arch_variant_cflags, which
# include defines, and compiler settings for the given architecture
# version.
#
ifeq ($(strip $(TARGET_ARCH_VARIANT)),)
TARGET_ARCH_VARIANT := armv5te
endif
# TARGET_ARCH_VARIANT used to be called TARGET_ARCH_VERSION
# to avoid any weirdness, issue an error message if the latter
# is defined.
#
ifneq ($(strip $(TARGET_ARCH_VERSION)),)
$(info Definition for TARGET_ARCH_VERSION encountered !)
$(info This variable has been renamed TARGET_ARCH_VARIANT, please update your build files !!)
$(error Aborting the build.)
endif
TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
$(error Unknown ARM architecture version: $(TARGET_ARCH_VARIANT))
endif
include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
# You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
ifeq ($(strip $($(combo_target)TOOLS_PREFIX)),)
$(combo_target)TOOLS_PREFIX := \
prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-eabi-4.2.1/bin/arm-eabi-
prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
endif
$(combo_target)CC := $($(combo_target)TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
@@ -21,11 +55,19 @@ TARGET_arm_CFLAGS := -O2 \
-funswitch-loops \
-finline-limit=300
# Modules can choose to compile some source as thumb. As
# non-thumb enabled targets are supported, this is treated
# as a 'hint'. If thumb is not enabled, these files are just
# compiled as ARM.
ifeq ($(ARCH_ARM_HAVE_THUMB_SUPPORT),true)
TARGET_thumb_CFLAGS := -mthumb \
-Os \
-fomit-frame-pointer \
-fno-strict-aliasing \
-finline-limit=64
else
TARGET_thumb_CFLAGS := $(TARGET_arm_CFLAGS)
endif
# Set FORCE_ARM_DEBUGGING to "true" in your buildspec.mk
# or in your environment to force a full arm build, even for
@@ -37,26 +79,35 @@ TARGET_thumb_CFLAGS := -mthumb \
# with -mlong-calls. When built at -O0, those libraries are
# too big for a thumb "BL <label>" to go from one end to the other.
ifeq ($(FORCE_ARM_DEBUGGING),true)
TARGET_arm_CFLAGS += -fno-omit-frame-pointer
TARGET_arm_CFLAGS += -fno-omit-frame-pointer -fno-strict-aliasing
TARGET_thumb_CFLAGS += -marm -fno-omit-frame-pointer
endif
## on some hosts, the target cross-compiler is not available so do not run this command
ifneq ($(wildcard $($(combo_target)CC)),)
$(combo_target)LIBGCC := $(shell $($(combo_target)CC) -mthumb-interwork -print-libgcc-file-name)
endif
android_config_h := $(call select-android-config-h,linux-arm)
arch_include_dir := $(dir $(android_config_h))
$(combo_target)GLOBAL_CFLAGS += \
-march=armv5te -mtune=xscale \
-msoft-float -fpic \
-mthumb-interwork \
-ffunction-sections \
-funwind-tables \
-fstack-protector \
-fno-short-enums \
-D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ \
-D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ \
-include $(call select-android-config-h,linux-arm)
$(arch_variant_cflags) \
-include $(android_config_h) \
-I $(arch_include_dir)
$(combo_target)GLOBAL_LDFLAGS += \
$(arch_variant_ldflags)
# We only need thumb interworking in cases where thumb support
# is available in the architecture, and just to be sure, (and
# since sometimes thumb-interwork appears to be default), we
# specifically disable when thumb support is unavailable.
ifeq ($(ARCH_ARM_HAVE_THUMB_SUPPORT),true)
$(combo_target)GLOBAL_CFLAGS += -mthumb-interwork
else
$(combo_target)GLOBAL_CFLAGS += -mno-thumb-interwork
endif
$(combo_target)GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
@@ -75,6 +126,15 @@ libm_root := bionic/libm
libstdc++_root := bionic/libstdc++
libthread_db_root := bionic/libthread_db
## on some hosts, the target cross-compiler is not available so do not run this command
ifneq ($(wildcard $($(combo_target)CC)),)
# We compile with the global cflags to ensure that
# any flags which affect libgcc are correctly taken
# into account.
$(combo_target)LIBGCC := $(shell $($(combo_target)CC) $($(combo_target)GLOBAL_CFLAGS) -print-libgcc-file-name)
endif
# unless CUSTOM_KERNEL_HEADERS is defined, we're going to use
# symlinks located in out/ to point to the appropriate kernel
# headers. see 'config/kernel_headers.make' for more details
@@ -120,6 +180,7 @@ $(TARGET_CXX) \
$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
-o $@ \
$(PRIVATE_LDFLAGS) \
$(TARGET_GLOBAL_LDFLAGS) \
$(TARGET_LIBGCC)
endef
@@ -136,6 +197,7 @@ $(TARGET_CXX) -nostdlib -Bdynamic -Wl,-T,$(BUILD_SYSTEM)/armelf.x \
$(PRIVATE_ALL_OBJECTS) \
$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
$(PRIVATE_LDFLAGS) \
$(TARGET_GLOBAL_LDFLAGS) \
$(TARGET_LIBGCC) \
$(TARGET_CRTEND_O)
endef
@@ -147,6 +209,7 @@ $(TARGET_CXX) -nostdlib -Bstatic -Wl,-T,$(BUILD_SYSTEM)/armelf.x \
$(TARGET_GLOBAL_LD_DIRS) \
$(TARGET_CRTBEGIN_STATIC_O) \
$(PRIVATE_LDFLAGS) \
$(TARGET_GLOBAL_LDFLAGS) \
$(PRIVATE_ALL_OBJECTS) \
$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
$(TARGET_LIBGCC) \

View File

@@ -39,6 +39,7 @@ $(combo_target)HAVE_KERNEL_MODULES := 0
# These flags might (will) be overridden by the target makefiles
$(combo_target)GLOBAL_CFLAGS := -fno-exceptions -Wno-multichar
$(combo_target)RELEASE_CFLAGS := -O2 -g -fno-strict-aliasing
$(combo_target)GLOBAL_LDFLAGS :=
$(combo_target)GLOBAL_ARFLAGS := crs
$(combo_target)EXECUTABLE_SUFFIX :=

View File

@@ -75,11 +75,11 @@ SHOW_COMMANDS:= $(filter showcommands,$(MAKECMDGOALS))
# ###############################################################
# These can be changed to modify both host and device modules.
COMMON_GLOBAL_CFLAGS:= -DANDROID -fmessage-length=0 -W -Wall -Wno-unused
COMMON_GLOBAL_CFLAGS:= -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith
COMMON_RELEASE_CFLAGS:= -DNDEBUG -UDEBUG
COMMON_GLOBAL_CPPFLAGS:= -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Wnon-virtual-dtor
COMMON_RELEASE_CPPFLAGS:= -DNDEBUG -UDEBUG
COMMON_GLOBAL_CPPFLAGS:= $(COMMON_GLOBAL_CFLAGS) -Wsign-promo
COMMON_RELEASE_CPPFLAGS:= $(COMMON_RELEASE_CFLAGS)
# Set the extensions used for various packages
COMMON_PACKAGE_SUFFIX := .zip
@@ -87,7 +87,13 @@ COMMON_JAVA_PACKAGE_SUFFIX := .jar
COMMON_ANDROID_PACKAGE_SUFFIX := .apk
# list of flags to turn specific warnings in to errors
TARGET_ERROR_FLAGS := -Werror=return-type
TARGET_ERROR_FLAGS := -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point
# TODO: do symbol compression
TARGET_COMPRESS_MODULE_SYMBOLS := false
# Default is to prelink modules.
TARGET_PRELINK_MODULE := true
# ###############################################################
# Include sub-configuration files
@@ -105,6 +111,32 @@ TARGET_ERROR_FLAGS := -Werror=return-type
# are specific to the user's build configuration.
include $(BUILD_SYSTEM)/envsetup.mk
# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
# or under vendor/*/$(TARGET_DEVICE). Search in both places, but
# make sure only one exists.
# Real boards should always be associated with an OEM vendor.
board_config_mk := \
$(strip $(wildcard \
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \
))
ifeq ($(board_config_mk),)
$(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))
endif
ifneq ($(words $(board_config_mk)),1)
$(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))
endif
include $(board_config_mk)
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
board_config_mk :=
# Clean up/verify variables defined by the board config file.
TARGET_BOOTLOADER_BOARD_NAME := $(strip $(TARGET_BOOTLOADER_BOARD_NAME))
TARGET_CPU_ABI := $(strip $(TARGET_CPU_ABI))
ifeq ($(TARGET_CPU_ABI),)
$(error No TARGET_CPU_ABI defined by board config: $(board_config_mk))
endif
# $(1): os/arch
define select-android-config-h
system/core/include/arch/$(1)/AndroidConfig.h
@@ -167,6 +199,7 @@ MKTARBALL := build/tools/mktarball.sh
TUNE2FS := tune2fs
E2FSCK := e2fsck
JARJAR := java -jar $(HOST_OUT_JAVA_LIBRARIES)/jarjar.jar
PROGUARD := external/proguard/bin/proguard.sh
# dx is java behind a shell script; no .exe necessary.
DX := $(HOST_OUT_EXECUTABLES)/dx
@@ -259,10 +292,6 @@ HOST_GLOBAL_CPPFLAGS += $(HOST_RELEASE_CPPFLAGS)
TARGET_GLOBAL_CFLAGS += $(TARGET_RELEASE_CFLAGS)
TARGET_GLOBAL_CPPFLAGS += $(TARGET_RELEASE_CPPFLAGS)
# TODO: do symbol compression
TARGET_COMPRESS_MODULE_SYMBOLS := false
TARGET_PRELINK_MODULE := true
PREBUILT_IS_PRESENT := $(if $(wildcard prebuilt/Android.mk),true)

View File

@@ -109,7 +109,14 @@ endef
# Figure out where we are.
define my-dir
$(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST),$(MAKEFILE_LIST))))
$(strip \
$(eval md_file_ := $$(lastword $$(MAKEFILE_LIST))) \
$(if $(filter $(CLEAR_VARS),$(md_file_)), \
$(error LOCAL_PATH must be set before including $$(CLEAR_VARS)) \
, \
$(patsubst %/,%,$(dir $(md_file_))) \
) \
)
endef
###########################################################
@@ -128,7 +135,8 @@ endef
# $(1): directory to search under
# Ignores $(1)/Android.mk
define first-makefiles-under
$(shell build/tools/findleaves.sh --mindepth=2 $(1) Android.mk)
$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git \
--mindepth=2 $(1) Android.mk)
endef
###########################################################
@@ -1166,6 +1174,7 @@ $(hide) $(AAPT) package $(PRIVATE_AAPT_FLAGS) -m -z \
$(addprefix -S , $(PRIVATE_RESOURCE_DIR)) \
$(addprefix -A , $(PRIVATE_ASSET_DIR)) \
$(addprefix -I , $(PRIVATE_AAPT_INCLUDES)) \
$(addprefix -G , $(PRIVATE_PROGUARD_OPTIONS_FILE)) \
$(addprefix --min-sdk-version , $(DEFAULT_APP_TARGET_SDK)) \
$(addprefix --target-sdk-version , $(DEFAULT_APP_TARGET_SDK)) \
$(addprefix --version-code , $(PLATFORM_SDK_VERSION)) \
@@ -1264,11 +1273,12 @@ endef
#TODO: use a smaller -Xmx value for most libraries;
# only core.jar and framework.jar need a heap this big.
# Avoid the memory arguments on Windows, dx fails to load for some reason with them.
define transform-classes.jar-to-dex
@echo "target Dex: $(PRIVATE_MODULE)"
@mkdir -p $(dir $@)
$(hide) $(DX) -JXms16M \
-JXmx1536M \
$(hide) $(DX) \
$(if $(findstring windows,$(HOST_OS)),,-JXms16M -JXmx1536M) \
--dex --output=$@ \
$(if $(NO_OPTIMIZE_DX), \
--no-optimize) \
@@ -1324,11 +1334,9 @@ $(hide) (cd $(dir $@) && zip -r $(notdir $@) lib)
$(hide) rm -rf $(dir $@)lib
endef
#TODO: use aapt instead of zip, once it supports junking the path
# (so adding "xxx/yyy/classes.dex" appears as "classes.dex")
#TODO: update the manifest to point to the dex file
define add-dex-to-package
$(hide) zip -qj $@ $(PRIVATE_DEX_FILE)
$(hide) $(AAPT) add -k $@ $(PRIVATE_DEX_FILE)
endef
define add-java-resources-to-package
@@ -1587,7 +1595,7 @@ $(if $(2), \
echo "$$printname total size is $$total"; \
img_blocksize=$(call image-size-from-data-size,$(BOARD_FLASH_BLOCK_SIZE)); \
if [ "$(3)" == "yaffs" ]; then \
reservedblocks=5; \
reservedblocks=8; \
else \
reservedblocks=0; \
fi; \
@@ -1607,6 +1615,37 @@ $(if $(2), \
)
endef
# Like assert-max-file-size, but the second argument is a partition
# size, which we'll convert to a max image size before checking it
# against the files.
#
# $(1): The file(s) to check (often $@)
# $(2): The partition size.
define assert-max-image-size
$(if $(2), \
$(call assert-max-file-size,$(1),$(call image-size-from-data-size,$(2))), \
true)
endef
###########################################################
## Define device-specific radio files
###########################################################
# Copy a radio image file to the output location, and add it to
# INSTALLED_RADIOIMAGE_TARGET.
# $(1): filename
define add-radio-file
$(eval $(call add-radio-file-internal,$(1)))
endef
define add-radio-file-internal
INSTALLED_RADIOIMAGE_TARGET += $$(PRODUCT_OUT)/$(1)
ALL_PREBUILT += $$(PRODUCT_OUT)/$(1)
$$(PRODUCT_OUT)/$(1) : $$(LOCAL_PATH)/$(1) | $$(ACP)
$$(transform-prebuilt-to-target)
endef
###########################################################
## Other includes
###########################################################

View File

@@ -173,7 +173,7 @@ ifeq ($(TARGET_SIMULATOR),true)
# under product/) are actually host-dependent.
# But, the debug type is controlled by TARGET_BUILD_TYPE and not
# HOST_BUILD_TYPE.
TARGET_PRODUCT_OUT_ROOT := $(HOST_OUT_$(TARGET_BUILD_TYPE))/product
TARGET_PRODUCT_OUT_ROOT := $(HOST_OUT_$(TARGET_BUILD_TYPE))/pr
else
TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product
endif
@@ -270,7 +270,7 @@ ifeq ($(TARGET_SIMULATOR),true)
ABP:=$(ABP):$(TARGET_OUT_EXECUTABLES)
else
# this should be copied to HOST_OUT_EXECUTABLES instead
ABP:=$(ABP):$(PWD)/prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-eabi-4.2.1/bin
ABP:=$(ABP):$(PWD)/prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-eabi-4.4.0/bin
endif
ANDROID_BUILD_PATHS := $(ABP)
ANDROID_PREBUILTS := prebuilt/$(HOST_PREBUILT_TAG)
@@ -335,5 +335,3 @@ $(info HOST_BUILD_TYPE=$(HOST_BUILD_TYPE))
$(info BUILD_ID=$(BUILD_ID))
$(info ============================================)
endif

View File

@@ -1,7 +1,11 @@
if [[ "x$ANDROID_JAVA_HOME" != x && -e $ANDROID_JAVA_HOME/lib/tools.jar ]] ; then
if [ "x$ANDROID_JAVA_HOME" != x ] && [ -e "$ANDROID_JAVA_HOME/lib/tools.jar" ] ; then
echo $ANDROID_JAVA_HOME/lib/tools.jar
else
JAVAC=$(which javac)
if [ -z "$JAVAC" ] ; then
echo "Please-install-JDK-5.0,-update-12-or-higher,-which-you-can-download-from-java.sun.com"
exit 1
fi
while [ -L $JAVAC ] ; do
LSLINE=$(ls -l $JAVAC)
JAVAC=$(echo -n $LSLINE | sed -e "s/.* -> //")

View File

@@ -68,7 +68,8 @@ emma_intermediates_dir := $(intermediates.COMMON)/emma_out
# the emma tool
full_classes_emma_jar := $(emma_intermediates_dir)/lib/$(full_classes_compiled_jar_leaf)
full_classes_stubs_jar := $(intermediates.COMMON)/stubs.jar
full_classes_jarjar_jar := $(full_classes_jar)
full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
full_classes_proguard_jar := $(full_classes_jar)
built_dex := $(intermediates.COMMON)/classes.dex
LOCAL_INTERMEDIATE_TARGETS += \
@@ -174,15 +175,14 @@ $(full_classes_emma_jar): $(full_classes_compiled_jar)
$(PRIVATE_EMMA_COVERAGE_FILE): $(full_classes_emma_jar)
else
$(full_classes_emma_jar): $(full_classes_compiled_jar) | $(ACP)
@echo Copying $<
@echo Copying: $<
$(copy-file-to-target)
endif
# Run jarjar if necessary, otherwise just copy the file. This is the last
# part of this step, so the output of this command is full_classes_jar.
# Run jarjar if necessary, otherwise just copy the file.
ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
$(full_classes_jarjar_jar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
$(full_classes_jarjar_jar): $(full_classes_emma_jar) | jarjar
$(full_classes_jarjar_jar): $(full_classes_emma_jar) | $(JARJAR)
@echo JarJar: $@
$(hide) $(JARJAR) process $(PRIVATE_JARJAR_RULES) $< $@
else
@@ -191,6 +191,40 @@ $(full_classes_jarjar_jar): $(full_classes_emma_jar) | $(ACP)
$(hide) $(ACP) $< $@
endif
# Run proguard if necessary, otherwise just copy the file. This is the last
# part of this step, so the output of this command is full_classes_jar.
ifneq ($(strip $(LOCAL_PROGUARD_ENABLED)),)
proguard_dictionary := $(intermediates.COMMON)/proguard_dictionary
proguard_flags := $(addprefix -libraryjars ,$(full_java_libs)) \
-include $(BUILD_SYSTEM)/proguard.flags \
-forceprocessing \
-printmapping $(proguard_dictionary)
ifeq ($(strip $(LOCAL_PROGUARD_ENABLED)),full)
# full
else
ifeq ($(strip $(LOCAL_PROGUARD_ENABLED)),optonly)
# optonly
proguard_flags += -dontobfuscate
else
ifeq ($(strip $(LOCAL_PROGUARD_ENABLED)),custom)
# custom
else
$(warning while processing: $(LOCAL_MODULE))
$(error invalid value for LOCAL_PROGUARD_ENABLED: $(LOCAL_PROGUARD_ENABLED))
endif
endif
endif
$(full_classes_proguard_jar): PRIVATE_PROGUARD_FLAGS := $(proguard_flags) $(LOCAL_PROGUARD_FLAGS)
$(full_classes_proguard_jar): $(full_classes_emma_jar) | $(PROGUARD)
@echo Proguard: $@
$(hide) $(PROGUARD) -injars $< -outjars $@ $(PRIVATE_PROGUARD_FLAGS)
else
$(full_classes_proguard_jar): $(full_classes_emma_jar) | $(ACP)
@echo Copying: $@
$(hide) $(ACP) $< $@
endif
# Override PRIVATE_INTERMEDIATES_DIR so that install-dex-debug
# will work even when intermediates != intermediates.COMMON.
$(built_dex): PRIVATE_INTERMEDIATES_DIR := $(intermediates.COMMON)

View File

@@ -54,6 +54,12 @@ include $(BUILD_SYSTEM)/config.mk
# be generated correctly
include $(BUILD_SYSTEM)/cleanbuild.mk
VERSION_CHECK_SEQUENCE_NUMBER := 1
-include $(OUT_DIR)/versions_checked.mk
ifneq ($(VERSION_CHECK_SEQUENCE_NUMBER),$(VERSIONS_CHECKED))
$(info Checking build tools versions...)
ifneq ($(HOST_OS),windows)
ifneq ($(HOST_OS)-$(HOST_ARCH),darwin-ppc)
# check for a case sensitive file system
@@ -123,6 +129,10 @@ endif
endif # windows
$(shell echo 'VERSIONS_CHECKED := $(VERSION_CHECK_SEQUENCE_NUMBER)' \
> $(OUT_DIR)/versions_checked.mk)
endif
# These are the modifier targets that don't do anything themselves, but
# change the behavior of the build.
# (must be defined before including definitions.make)
@@ -220,7 +230,8 @@ ifeq ($(TARGET_BUILD_VARIANT),eng)
tags_to_install := user debug eng
# Don't require the setup wizard on eng builds
ADDITIONAL_BUILD_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\
$(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES)))
$(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))) \
ro.setupwizard.mode=OPTIONAL
endif
## tests ##
@@ -241,8 +252,16 @@ tags_to_install := user debug eng
ADDITIONAL_BUILD_PROPERTIES += xmpp.auto-presence=true
ADDITIONAL_BUILD_PROPERTIES += ro.config.nocheckin=yes
else # !sdk
# Enable sync for non-sdk builds only (sdk builds lack SubscribedFeedsProvider).
ADDITIONAL_BUILD_PROPERTIES += ro.config.sync=yes
endif
## precise GC ##
ifneq ($(filter dalvik.gc.type-precise,$(PRODUCT_TAGS)),)
# Enabling type-precise GC results in larger optimized DEX files. The
# additional storage requirements for ".odex" files can cause /system
# to overflow on some devices, so this is configured separately for
# each product.
ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.dexopt-flags=m=y
endif
# Install an apns-conf.xml file if one's not already being installed.
@@ -256,7 +275,7 @@ endif
# If we're on an eng or tests build, but not on the sdk, and we have
# a better one, use that instead.
ifneq ($(filter eng tests,$(TARGET_BUILD_VARIANT)),)
ifdef is_sdk_build
ifndef is_sdk_build
apns_to_use := $(wildcard vendor/google/etc/apns-conf.xml)
ifneq ($(strip $(apns_to_use)),)
PRODUCT_COPY_FILES := \
@@ -267,6 +286,7 @@ ifneq ($(filter eng tests,$(TARGET_BUILD_VARIANT)),)
endif
ADDITIONAL_BUILD_PROPERTIES += net.bt.name=Android
ADDITIONAL_BUILD_PROPERTIES += ro.config.sync=yes
# enable vm tracing in files for now to help track
# the cause of ANRs in the content process
@@ -317,8 +337,6 @@ endif
# Bring in all modules that need to be built.
ifneq ($(dont_bother),true)
subdir_makefiles :=
ifeq ($(HOST_OS),windows)
SDK_ONLY := true
endif
@@ -338,6 +356,7 @@ subdirs := \
dalvik/tools/hprof-conv \
development/emulator/mksdcard \
development/tools/line_endings \
development/tools/sdklauncher \
development/host \
external/expat \
external/libpng \
@@ -371,6 +390,7 @@ subdirs += \
development/tools/sdkstats \
development/tools/sdkmanager \
development/tools/mkstubs \
development/tools/layoutopt \
frameworks/base \
frameworks/base/tools/layoutlib \
external/googleclient \
@@ -390,8 +410,6 @@ ifeq ($(BUILD_TINY_ANDROID), true)
# TINY_ANDROID is a super-minimal build configuration, handy for board
# bringup and very low level debugging
INTERNAL_DEFAULT_DOCS_TARGETS :=
subdirs := \
bionic \
system/core \
@@ -410,7 +428,6 @@ else # !BUILD_TINY_ANDROID
#
# Typical build; include any Android.mk files we can find.
#
INTERNAL_DEFAULT_DOCS_TARGETS := offline-sdk-docs
subdirs := $(TOP)
FULL_BUILD := true
@@ -419,41 +436,6 @@ endif # !BUILD_TINY_ANDROID
endif # !SDK_ONLY
# Can't use first-makefiles-under here because
# --mindepth=2 makes the prunes not work.
subdir_makefiles += \
$(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk)
# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
# or under vendor/*/$(TARGET_DEVICE). Search in both places, but
# make sure only one exists.
# Real boards should always be associated with an OEM vendor.
board_config_mk := \
$(strip $(wildcard \
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \
))
ifeq ($(board_config_mk),)
$(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))
endif
ifneq ($(words $(board_config_mk)),1)
$(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))
endif
include $(board_config_mk)
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
board_config_mk :=
# Clean up/verify variables defined by the board config file.
TARGET_BOOTLOADER_BOARD_NAME := $(strip $(TARGET_BOOTLOADER_BOARD_NAME))
TARGET_CPU_ABI := $(strip $(TARGET_CPU_ABI))
ifeq ($(TARGET_CPU_ABI),)
$(error No TARGET_CPU_ABI defined by board config: $(board_config_mk))
endif
#
# Include all of the makefiles in the system
#
ifneq ($(ONE_SHOT_MAKEFILE),)
# We've probably been invoked by the "mm" shell function
# with a subdirectory's makefile.
@@ -465,14 +447,25 @@ include $(ONE_SHOT_MAKEFILE)
# would have been with a normal make.
CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS),))
FULL_BUILD :=
INTERNAL_DEFAULT_DOCS_TARGETS :=
# Stub out the notice targets, which probably aren't defined
# when using ONE_SHOT_MAKEFILE.
NOTICE-HOST-%: ;
NOTICE-TARGET-%: ;
else
else # ONE_SHOT_MAKEFILE
#
# Include all of the makefiles in the system
#
# Can't use first-makefiles-under here because
# --mindepth=2 makes the prunes not work.
subdir_makefiles := \
$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)
include $(subdir_makefiles)
endif
endif # ONE_SHOT_MAKEFILE
# -------------------------------------------------------------------
# All module makefiles have been included at this point.
# -------------------------------------------------------------------
@@ -673,7 +666,6 @@ droidcore: files \
$(INSTALLED_BOOTIMAGE_TARGET) \
$(INSTALLED_RECOVERYIMAGE_TARGET) \
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INTERNAL_DEFAULT_DOCS_TARGETS) \
$(INSTALLED_FILES_FILE)
# The actual files built by the droidcore target changes depending

View File

@@ -53,13 +53,13 @@ $(foreach t,$(1), \
$(eval LOCAL_MODULE := $(word 1,$(tw))) \
$(eval LOCAL_SRC_FILES := $(word 2,$(tw))) \
, \
$(eval LOCAL_MODULE := $(basename $(t))) \
$(eval LOCAL_MODULE := $(basename $(notdir $(t)))) \
$(eval LOCAL_SRC_FILES := $(t)) \
) \
$(if $(6), \
$(eval LOCAL_BUILT_MODULE_STEM := $(6)) \
, \
$(eval LOCAL_BUILT_MODULE_STEM := $(LOCAL_SRC_FILES)) \
$(eval LOCAL_BUILT_MODULE_STEM := $(notdir $(LOCAL_SRC_FILES))) \
) \
$(eval LOCAL_MODULE_SUFFIX := $(suffix $(LOCAL_SRC_FILES))) \
$(eval include $(BUILD_PREBUILT)) \

View File

@@ -186,7 +186,9 @@ endef
define _import-node
$(eval _include_stack := $(2) $$(_include_stack))
$(call clear-var-list, $(3))
$(eval LOCAL_PATH := $(patsubst %/,%,$(dir $(2))))
$(eval include $(2))
$(eval LOCAL_PATH :=)
$(call copy-var-list, $(1).$(2), $(3))
$(call clear-var-list, $(3))

View File

@@ -20,12 +20,19 @@ else
# We can't use xxx_OUT_STATIC_LIBRARIES because it points into
# device-obj or host-obj.
module_installed_filename := \
$(patsubst $(PRODUCT_OUT)%,%,$($(my_prefix)OUT_SHARED_LIBRARIES))/$(notdir $(LOCAL_BUILT_MODULE))
$(patsubst $(PRODUCT_OUT)%,%,$($(my_prefix)OUT_SHARED_LIBRARIES))/$(notdir $(LOCAL_BUILT_MODULE))
else
ifeq ($(LOCAL_MODULE_CLASS),JAVA_LIBRARIES)
# Stick the static java libraries with the regular java libraries.
module_leaf := $(notdir $(LOCAL_BUILT_MODULE))
# javalib.jar is the default name for the build module (and isn't meaningful)
# If that's what we have, substitute the module name instead. These files
# aren't included on the device, so this name is synthetic anyway.
ifeq ($(module_leaf),javalib.jar)
module_leaf := $(LOCAL_MODULE).jar
endif
module_installed_filename := \
$(patsubst $(PRODUCT_OUT)%,%,$($(my_prefix)OUT_JAVA_LIBRARIES))/$(notdir $(LOCAL_BUILT_MODULE))
$(patsubst $(PRODUCT_OUT)%,%,$($(my_prefix)OUT_JAVA_LIBRARIES))/$(module_leaf)
else
$(error Cannot determine where to install NOTICE file for $(LOCAL_MODULE))
endif # JAVA_LIBRARIES

View File

@@ -111,6 +111,11 @@ endif
LOCAL_BUILT_MODULE_STEM := package.apk
proguard_options_file := $(package_expected_intermediates_COMMON)/proguard_options
ifneq ($(strip $(LOCAL_PROGUARD_ENABLED)),custom)
LOCAL_PROGUARD_FLAGS := -include $(proguard_options_file) $(LOCAL_PROGUARD_FLAGS)
endif
# The dex files go in the package, so we don't
# want to install them separately for this module.
old_DONT_INSTALL_DEX_FILES := $(DONT_INSTALL_DEX_FILES)
@@ -143,6 +148,7 @@ endif
$(R_file_stamp): PRIVATE_RESOURCE_PUBLICS_OUTPUT := \
$(intermediates.COMMON)/public_resources.xml
$(R_file_stamp): PRIVATE_PROGUARD_OPTIONS_FILE := $(proguard_options_file)
$(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(AAPT) | $(ACP)
@echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
@rm -f $@
@@ -164,6 +170,8 @@ $(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(AAPT) | $(ACP)
$(ACP) -fpt $$GENERATED_R_FILE $@ || exit 32; \
done; \
$(proguard_options_file): $(R_file_stamp)
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.)

View File

@@ -28,8 +28,8 @@
#
pathmap_INCL := \
bluedroid:system/bluetooth/bluedroid/include \
bluez-libs:external/bluez/libs/include \
bluez-utils:external/bluez/utils \
bluez:external/bluetooth/bluez \
glib:external/bluetooth/glib \
bootloader:bootable/bootloader/legacy/include \
corecg:external/skia/include/core \
dbus:external/dbus \
@@ -76,7 +76,6 @@ FRAMEWORKS_BASE_SUBDIRS := \
$(addsuffix /java, \
core \
graphics \
im \
location \
media \
opengl \

View File

@@ -26,6 +26,8 @@ else
prebuilt_module_is_a_library :=
endif
PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
# Ensure that prebuilt .apks have been aligned.
ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),)
$(LOCAL_BUILT_MODULE) : $(LOCAL_PATH)/$(LOCAL_SRC_FILES) | $(ZIPALIGN)

View File

@@ -27,7 +27,7 @@ libsysutils.so 0xAF400000
liba2dp.so 0xAEE00000
audio.so 0xAED00000
input.so 0xAEC00000
libhcid.so 0xAEB00000
libbluetoothd.so 0xAEB00000
libbluedroid.so 0xAEA00000
libbluetooth.so 0xAE900000
libdbus.so 0xAE800000
@@ -50,8 +50,10 @@ libdvm.so 0xAD000000
# graphics
libpixelflinger.so 0xACF00000
# libcorecg is for backward-compatibility with donut
libcorecg.so 0xACE00000
libsurfaceflinger.so 0xACD00000
libGLES_android.so 0xACC80000
libagl.so 0xACC00000
libGLESv1_CM.so 0xACB00000
@@ -60,15 +62,24 @@ libOpenVG_CM.so 0xAC900000
libOpenVGU_CM.so 0xAC800000
libEGL.so 0xAC700000
libacc.so 0xAC600000
libexif.so 0xAC500000
libui.so 0xAC400000
libsgl.so 0xAC000000
# libsgl is for backward-compatibility with donut
libsgl.so 0xAC200000
libskia.so 0xAC000000
librs_jni.so 0xABF00000
libRS.so 0xAB900000
# audio
libspeech.so 0xAB800000
libaudiopolicy.so 0xAB880000
libaudiopolicygeneric.so 0xAB800000
libsoundpool.so 0xAB780000
libaudio.so 0xAB700000
libsonivox.so 0xAB600000
libsoundpool.so 0xAB500000
libspeech.so 0xAB600000
libsonivox.so 0xAB500000
libvorbisidec.so 0xAB400000
libmedia_jni.so 0xAB300000
libmediaplayerservice.so 0xAB280000
@@ -80,6 +91,7 @@ libaudioflinger.so 0xAB000000
libsqlite.so 0xAAC00000
libexpat.so 0xAAB00000
libwebcore.so 0xAA000000
libbinder.so 0xA9D80000
libutils.so 0xA9D00000
libcameraservice.so 0xA9C80000
libhardware.so 0xA9C70000
@@ -89,7 +101,7 @@ libsystem_server.so 0xA9A00000
libime.so 0xA9800000
libgps.so 0xA9700000
libcamera.so 0xA9680000
libqcamera.so 0xA9400000
liboemcamera.so 0xA9400000
# pv libraries
libpvasf.so 0xA7C26000
@@ -105,6 +117,7 @@ libomx_aacdec_sharedlibrary.so 0xA7700000
libomx_amrdec_sharedlibrary.so 0xA76A0000
libomx_amrenc_sharedlibrary.so 0xA7680000
libomx_avcdec_sharedlibrary.so 0xA7660000
libomx_avcenc_sharedlibrary.so 0xA7610000
libomx_m4vdec_sharedlibrary.so 0xA75C0000
libomx_m4venc_sharedlibrary.so 0xA7590000
libomx_mp3dec_sharedlibrary.so 0xA7450000
@@ -149,3 +162,4 @@ librpc.so 0x9A400000
libtrace_test.so 0x9A300000
libsrec_jni.so 0x9A200000
libcerttool_jni.so 0x9A100000

View File

@@ -68,7 +68,8 @@ _product_var_list := \
PRODUCT_SDK_ADDON_NAME \
PRODUCT_SDK_ADDON_COPY_FILES \
PRODUCT_SDK_ADDON_COPY_MODULES \
PRODUCT_SDK_ADDON_DOC_MODULE
PRODUCT_SDK_ADDON_DOC_MODULE \
PRODUCT_DEFAULT_WIFI_CHANNELS
define dump-product
$(info ==== $(1) ====)\

View File

@@ -193,6 +193,12 @@ ifneq (,$(extra_locales))
extra_locales :=
endif
# Default to medium-density assets.
# (Can be overridden in the device config, e.g.: PRODUCT_LOCALES += hdpi)
PRODUCT_LOCALES := $(strip \
$(PRODUCT_LOCALES) \
$(if $(filter %dpi,$(PRODUCT_LOCALES)),,mdpi))
# Assemble the list of options.
PRODUCT_AAPT_CONFIG := $(PRODUCT_LOCALES)
@@ -214,6 +220,9 @@ ifndef PRODUCT_MANUFACTURER
PRODUCT_MANUFACTURER := unknown
endif
PRODUCT_DEFAULT_WIFI_CHANNELS := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))
# Which policy should this product use
PRODUCT_POLICY := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_POLICY))

7
core/proguard.flags Normal file
View File

@@ -0,0 +1,7 @@
# see http://sourceforge.net/tracker/?func=detail&aid=2787465&group_id=54750&atid=474707
-optimizations !code/simplification/arithmetic
-allowaccessmodification
# Some classes in the libraries extend package private classes to chare common functionality
# that isn't explicitly part of the API
-dontskipnonpubliclibraryclasses

View File

@@ -68,7 +68,9 @@ CTS_CASE_LIST := \
CtsAppTestCases \
CtsContentTestCases \
CtsDatabaseTestCases \
CtsGestureTestCases \
CtsDpiTestCases \
CtsDpiTestCases2 \
CtsGestureTestCases \
CtsGraphicsTestCases \
CtsHardwareTestCases \
CtsLocationTestCases \
@@ -77,6 +79,7 @@ CTS_CASE_LIST := \
CtsPermissionTestCases \
CtsPermission2TestCases \
CtsProviderTestCases \
CtsSpeechTestCases \
CtsTelephonyTestCases \
CtsTextTestCases \
CtsUtilTestCases \

View File

@@ -15,21 +15,34 @@
#
products_pdf := $(OUT_DIR)/products.pdf
products_graph := $(products_pdf:%.pdf=%.dot)
# This rule doens't include any nodes that don't inherit from
$(products_graph):
@echo Product graph DOT: $@
$(hide) ( \
echo 'digraph {'; \
echo 'graph [ ratio=.5 ];'; \
$(foreach p,$(ALL_PRODUCTS), \
$(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), \
echo \"$(d)\" -\> \"$(p)\";)) \
$(foreach prod, \
$(sort $(foreach p,$(ALL_PRODUCTS), \
$(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), \
$(d))) \
$(foreach p,$(ALL_PRODUCTS),$(p))), \
echo \"$(prod)\" [ label=\"$(dir $(prod))\\n$(notdir $(prod))\"];) \
echo '}' \
) > $@
# This rule doesn't include any nodes that don't inherit from
# anything or don't have anything inherit from them, to make the
# graph more readable. To add that, add this line to the rule
# below:
# $(foreach p,$(ALL_PRODUCTS), echo \"$(p)\";) \
$(products_pdf):
$(hide) ( \
echo 'digraph {'; \
$(foreach p,$(ALL_PRODUCTS), \
$(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), \
echo \"$(d)\" -\> \"$(p)\";)) \
echo '}' \
) | dot -Tpdf -Nshape=box -o $@
$(products_pdf): $(products_graph)
@echo Product graph PDF: $@
dot -Tpdf -Nshape=box -o $@ $<
product-graph: $(products_pdf)

View File

@@ -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 := 1.6
PLATFORM_VERSION := Eclair
endif
ifeq "" "$(PLATFORM_SDK_VERSION)"
@@ -53,13 +53,13 @@ ifeq "" "$(PLATFORM_SDK_VERSION)"
# intermediate builds). During development, this number remains at the
# SDK version the branch is based on and PLATFORM_VERSION_CODENAME holds
# the code-name of the new development work.
PLATFORM_SDK_VERSION := 4
PLATFORM_SDK_VERSION := 5
endif
ifeq "" "$(PLATFORM_VERSION_CODENAME)"
# If the build is not a final release build, then this is the current
# development code-name. If this is a final release build, it is simply "REL".
PLATFORM_VERSION_CODENAME := REL
# 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 := Eclair
endif
ifeq "" "$(DEFAULT_APP_TARGET_SDK)"

View File

@@ -102,7 +102,7 @@ function setpaths()
# and in with the new
CODE_REVIEWS=
prebuiltdir=$(getprebuilt)
export ANDROID_EABI_TOOLCHAIN=$prebuiltdir/toolchain/arm-eabi-4.2.1/bin
export ANDROID_EABI_TOOLCHAIN=$prebuiltdir/toolchain/arm-eabi-4.4.0/bin
export ANDROID_TOOLCHAIN=$ANDROID_EABI_TOOLCHAIN
export ANDROID_QTOOLS=$T/development/emulator/qtools
export ANDROID_BUILD_PATHS=:$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_QTOOLS:$ANDROID_TOOLCHAIN:$ANDROID_EABI_TOOLCHAIN$CODE_REVIEWS
@@ -596,6 +596,8 @@ function mm()
# Find the closest Android.mk file.
T=$(gettop)
local M=$(findmakefile)
# Remove the path to top as the makefilepath needs to be relative
local M=`echo $M|sed 's:'$T'/::'`
if [ ! "$T" ]; then
echo "Couldn't locate the top of the tree. Try setting TOP."
elif [ ! "$M" ]; then
@@ -634,6 +636,7 @@ function mmm()
ARGS="$ARGS showcommands"
else
echo "No Android.mk in $DIR."
return 1
fi
fi
done
@@ -653,6 +656,26 @@ function croot()
fi
}
function cproj()
{
TOPFILE=build/core/envsetup.mk
# We redirect cd to /dev/null in case it's aliased to
# a command that prints something as a side-effect
# (like pushd)
local HERE=$PWD
T=
while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
T=$PWD
if [ -f "$T/Android.mk" ]; then
cd $T
return
fi
cd .. > /dev/null
done
cd $HERE > /dev/null
echo "can't find Android.mk"
}
function pid()
{
local EXE="$1"
@@ -718,14 +741,14 @@ case `uname -s` in
Darwin)
function sgrep()
{
find -E . -type f -iregex '.*\.(c|h|cpp|S|java|xml)' -print0 | xargs -0 grep --color -n "$@"
find -E . -type f -iregex '.*\.(c|h|cpp|S|java|xml|sh|mk)' -print0 | xargs -0 grep --color -n "$@"
}
;;
*)
function sgrep()
{
find . -type f -iregex '.*\.\(c\|h\|cpp\|S\|java\|xml\)' -print0 | xargs -0 grep --color -n "$@"
find . -type f -iregex '.*\.\(c\|h\|cpp\|S\|java\|xml\|sh\|mk\)' -print0 | xargs -0 grep --color -n "$@"
}
;;
esac
@@ -944,14 +967,7 @@ function runtest()
echo "Couldn't locate the top of the tree. Try setting TOP." >&2
return
fi
(cd "$T" && development/testrunner/runtest.py $@)
}
# TODO: Remove this some time after 1 June 2009
function runtest_py()
{
echo "runtest_py is obsolete; use runtest instead" >&2
return 1
("$T"/development/testrunner/runtest.py $@)
}
function godir () {

1103
history/cupcake.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -20,11 +20,8 @@ else
INSTALLED_KERNEL_TARGET :=
endif
ifneq ($(strip $(TARGET_NO_RADIOIMAGE)),true)
INSTALLED_RADIOIMAGE_TARGET := $(PRODUCT_OUT)/radio.img
else
INSTALLED_RADIOIMAGE_TARGET :=
endif
# Use the add-radio-file function to add values to this variable.
INSTALLED_RADIOIMAGE_TARGET :=
ifeq (,$(wildcard $(TARGET_DEVICE_DIR)/AndroidBoard.mk))
ifeq (,$(wildcard $(TARGET_DEVICE_DIR)/Android.mk))

View File

@@ -1,12 +1,11 @@
# config.mk
#
#
# Product-specific compile-time definitions.
#
# The generic product target doesn't have any hardware-specific pieces.
TARGET_NO_BOOTLOADER := true
TARGET_NO_KERNEL := true
TARGET_NO_RADIOIMAGE := true
TARGET_CPU_ABI := armeabi
HAVE_HTC_AUDIO_DRIVER := true
BOARD_USES_GENERIC_AUDIO := true

View File

@@ -3,7 +3,8 @@ PRODUCT_NAME :=
PRODUCT_DEVICE :=
PRODUCT_POLICY := android.policy_phone
PRODUCT_PROPERTY_OVERRIDES := \
ro.config.notification_sound=F1_New_SMS.ogg
ro.config.notification_sound=OnTheHunt.ogg \
ro.config.alarm_alert=Alarm_Classic.ogg
PRODUCT_PACKAGES := \
framework-res \
@@ -25,4 +26,3 @@ PRODUCT_PACKAGES := \
UserDictionaryProvider \
PackageInstaller \
Bugreport

View File

@@ -3,11 +3,17 @@
# you should derive from generic_with_google.mk
PRODUCT_PACKAGES := \
AccountAndSyncSettings \
AlarmClock \
AlarmProvider \
Bluetooth \
Calculator \
Calendar \
Camera \
CertInstaller \
DrmProvider \
Email \
Gallery \
LatinIME \
Mms \
Music \
@@ -15,7 +21,6 @@ PRODUCT_PACKAGES := \
Sync \
Updater \
CalendarProvider \
SubscribedFeedsProvider \
SyncProvider
$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)

View File

@@ -4,13 +4,16 @@
# from generic.mk
PRODUCT_PACKAGES := \
GoogleContactsProvider \
ContactsProvider \
GoogleContactsSyncAdapter \
GoogleSubscribedFeedsProvider \
com.google.android.gtalkservice \
com.google.android.datamessaging \
com.google.android.maps
PRODUCT_COPY_FILES := \
vendor/google/frameworks/maps/com.google.android.maps.xml:system/etc/permissions/com.google.android.maps.xml \
vendor/google/frameworks/datamessaging/com.google.android.datamessaging.xml:system/etc/permissions/com.google.android.datamessaging.xml \
vendor/google/apps/GTalkService/com.google.android.gtalkservice.xml:system/etc/permissions/com.google.android.gtalkservice.xml

View File

@@ -1,7 +1,8 @@
PRODUCT_POLICY := android.policy_phone
PRODUCT_PROPERTY_OVERRIDES := \
ro.config.notification_sound=F1_New_SMS.ogg
ro.config.notification_sound=OnTheHunt.ogg \
ro.config.alarm_alert=Alarm_Classic.ogg
PRODUCT_BRAND := generic
PRODUCT_NAME := min_dev
PRODUCT_DEVICE := generic

View File

@@ -1,6 +1,7 @@
PRODUCT_PROPERTY_OVERRIDES :=
PRODUCT_PACKAGES := \
AccountAndSyncSettings \
AlarmClock \
Camera \
Calculator \
@@ -23,12 +24,15 @@ PRODUCT_PACKAGES := \
libWnnEngDic \
libWnnJpnDic \
libwnndict \
CertInstaller \
LiveWallpapersPicker \
ApiDemos \
GestureBuilder \
SoftKeyboard
PRODUCT_COPY_FILES := \
development/data/etc/vold.conf:system/etc/vold.conf
development/data/etc/vold.conf:system/etc/vold.conf \
frameworks/base/data/etc/android.hardware.camera.autofocus.xml:system/etc/permissions/android.hardware.camera.autofocus.xml
$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
@@ -37,6 +41,9 @@ PRODUCT_BRAND := generic
PRODUCT_NAME := sdk
PRODUCT_DEVICE := generic
PRODUCT_LOCALES := \
ldpi \
hdpi \
mdpi \
en_US \
en_GB \
en_CA \
@@ -64,3 +71,10 @@ PRODUCT_LOCALES := \
ru_RU \
ko_KR
# 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

222
tools/adbs Executable file
View File

@@ -0,0 +1,222 @@
#!/usr/bin/env python
# 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.
import os
import re
import string
import sys
###############################################################################
# match "#00 pc 0003f52e /system/lib/libdvm.so" for example
###############################################################################
trace_line = re.compile("(.*)(\#[0-9]+) (..) ([0-9a-f]{8}) ([^\r\n \t]*)")
# returns a list containing the function name and the file/lineno
def CallAddr2Line(lib, addr):
global symbols_dir
global addr2line_cmd
global cppfilt_cmd
if lib != "":
cmd = addr2line_cmd + \
" -f -e " + symbols_dir + lib + " 0x" + addr
stream = os.popen(cmd)
lines = stream.readlines()
list = map(string.strip, lines)
else:
list = []
if list != []:
# Name like "move_forward_type<JavaVMOption>" causes troubles
mangled_name = re.sub('<', '\<', list[0]);
mangled_name = re.sub('>', '\>', mangled_name);
cmd = cppfilt_cmd + " " + mangled_name
stream = os.popen(cmd)
list[0] = stream.readline()
stream.close()
list = map(string.strip, list)
else:
list = [ "(unknown)", "(unknown)" ]
return list
###############################################################################
# similar to CallAddr2Line, but using objdump to find out the name of the
# containing function of the specified address
###############################################################################
def CallObjdump(lib, addr):
global objdump_cmd
global symbols_dir
unknown = "(unknown)"
uname = os.uname()[0]
if uname == "Darwin":
proc = os.uname()[-1]
if proc == "i386":
uname = "darwin-x86"
else:
uname = "darwin-ppc"
elif uname == "Linux":
uname = "linux-x86"
if lib != "":
next_addr = string.atoi(addr, 16) + 1
cmd = objdump_cmd \
+ " -C -d --start-address=0x" + addr + " --stop-address=" \
+ str(next_addr) \
+ " " + symbols_dir + lib
stream = os.popen(cmd)
lines = stream.readlines()
map(string.strip, lines)
stream.close()
else:
return unknown
# output looks like
#
# file format elf32-littlearm
#
# Disassembly of section .text:
#
# 0000833c <func+0x4>:
# 833c: 701a strb r2, [r3, #0]
#
# we want to extract the "func" part
num_lines = len(lines)
if num_lines < 2:
return unknown
func_name = lines[num_lines-2]
func_regexp = re.compile("(^.*\<)(.*)(\+.*\>:$)")
components = func_regexp.match(func_name)
if components is None:
return unknown
return components.group(2)
###############################################################################
# determine the symbols directory in the local build
###############################################################################
def FindSymbolsDir():
global symbols_dir
try:
path = os.environ['ANDROID_PRODUCT_OUT'] + "/symbols"
except:
cmd = "CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core " \
+ "SRC_TARGET_DIR=build/target make -f build/core/envsetup.mk " \
+ "dumpvar-abs-TARGET_OUT_UNSTRIPPED"
stream = os.popen(cmd)
str = stream.read()
stream.close()
path = str.strip()
if (not os.path.exists(path)):
print path + " not found!"
sys.exit(1)
symbols_dir = path
###############################################################################
# determine the path of binutils
###############################################################################
def SetupToolsPath():
global addr2line_cmd
global objdump_cmd
global cppfilt_cmd
global symbols_dir
uname = os.uname()[0]
if uname == "Darwin":
proc = os.uname()[-1]
if proc == "i386":
uname = "darwin-x86"
else:
uname = "darwin-ppc"
elif uname == "Linux":
uname = "linux-x86"
prefix = "./prebuilt/" + uname + "/toolchain/arm-eabi-4.4.0/bin/"
addr2line_cmd = prefix + "arm-eabi-addr2line"
if (not os.path.exists(addr2line_cmd)):
try:
prefix = os.environ['ANDROID_BUILD_TOP'] + "/prebuilt/" + uname + \
"/toolchain/arm-eabi-4.4.0/bin/"
except:
prefix = "";
addr2line_cmd = prefix + "arm-eabi-addr2line"
if (not os.path.exists(addr2line_cmd)):
print addr2line_cmd + " not found!"
sys.exit(1)
objdump_cmd = prefix + "arm-eabi-objdump"
cppfilt_cmd = prefix + "arm-eabi-c++filt"
###############################################################################
# look up the function and file/line number for a raw stack trace line
# groups[0]: log tag
# groups[1]: stack level
# groups[2]: "pc"
# groups[3]: code address
# groups[4]: library name
###############################################################################
def SymbolTranslation(groups):
lib_name = groups[4]
code_addr = groups[3]
caller = CallObjdump(lib_name, code_addr)
func_line_pair = CallAddr2Line(lib_name, code_addr)
# If a callee is inlined to the caller, objdump will see the caller's
# address but addr2line will report the callee's address. So the printed
# format is desgined to be "caller<-callee file:line"
if (func_line_pair[0] != caller):
print groups[0] + groups[1] + " " + caller + "<-" + \
' '.join(func_line_pair[:]) + " "
else:
print groups[0] + groups[1] + " " + ' '.join(func_line_pair[:]) + " "
###############################################################################
if __name__ == '__main__':
# pass the options to adb
adb_cmd = "adb " + ' '.join(sys.argv[1:])
# setup addr2line_cmd and objdump_cmd
SetupToolsPath()
# setup the symbols directory
FindSymbolsDir()
# invoke the adb command and filter its output
stream = os.popen(adb_cmd)
while (True):
line = stream.readline()
# EOF reached
if (line == ''):
break
# remove the trailing \n
line = line.strip()
# see if this is a stack trace line
match = trace_line.match(line)
if (match):
groups = match.groups()
# translate raw address into symbols
SymbolTranslation(groups)
else:
print line
# adb itself aborts
stream.close()

View File

@@ -127,7 +127,7 @@ public class ApiCheck {
}
private static class MakeHandler extends DefaultHandler {
private ApiInfo mApi;
private PackageInfo mCurrentPackage;
private ClassInfo mCurrentClass;
@@ -139,8 +139,9 @@ public class ApiCheck {
super();
mApi = new ApiInfo();
}
public void startElement(String uri, String localName, String qName,
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) {
if (qName.equals("package")) {
mCurrentPackage = new PackageInfo(attributes.getValue("name"),
@@ -150,25 +151,25 @@ public class ApiCheck {
// push the old outer scope for later recovery, then set
// up the new current class object
mClassScope.push(mCurrentClass);
mCurrentClass = new ClassInfo(attributes.getValue("name"),
mCurrentClass = new ClassInfo(attributes.getValue("name"),
mCurrentPackage,
attributes.getValue("extends") ,
qName.equals("interface"),
qName.equals("interface"),
Boolean.valueOf(
attributes.getValue("abstract")),
Boolean.valueOf(
attributes.getValue("static")),
Boolean.valueOf(
attributes.getValue("final")),
attributes.getValue("deprecated"),
attributes.getValue("deprecated"),
attributes.getValue("visibility"),
SourcePositionInfo.fromXml(attributes.getValue("source")),
mCurrentClass);
} else if (qName.equals("method")) {
mCurrentMethod = new MethodInfo(attributes.getValue("name"),
mCurrentMethod = new MethodInfo(attributes.getValue("name"),
attributes.getValue("return") ,
Boolean.valueOf(
attributes.getValue("abstract")),
attributes.getValue("abstract")),
Boolean.valueOf(
attributes.getValue("native")),
Boolean.valueOf(
@@ -178,11 +179,11 @@ public class ApiCheck {
Boolean.valueOf(
attributes.getValue("final")),
attributes.getValue("deprecated"),
attributes.getValue("visibility"),
attributes.getValue("visibility"),
SourcePositionInfo.fromXml(attributes.getValue("source")),
mCurrentClass);
} else if (qName.equals("constructor")) {
mCurrentMethod = new ConstructorInfo(attributes.getValue("name"),
mCurrentMethod = new ConstructorInfo(attributes.getValue("name"),
attributes.getValue("type") ,
Boolean.valueOf(
attributes.getValue("static")),
@@ -193,7 +194,7 @@ public class ApiCheck {
SourcePositionInfo.fromXml(attributes.getValue("source")),
mCurrentClass);
} else if (qName.equals("field")) {
FieldInfo fInfo = new FieldInfo(attributes.getValue("name"),
FieldInfo fInfo = new FieldInfo(attributes.getValue("name"),
attributes.getValue("type") ,
Boolean.valueOf(
attributes.getValue("transient")),
@@ -218,6 +219,8 @@ public class ApiCheck {
mCurrentClass.addInterface(attributes.getValue("name"));
}
}
@Override
public void endElement(String uri, String localName, String qName) {
if (qName.equals("method")) {
mCurrentClass.addMethod((MethodInfo) mCurrentMethod);

View File

@@ -41,6 +41,7 @@ public class Errors
return this.msg.compareTo(that.msg);
}
@Override
public String toString() {
return this.pos.toString() + this.msg;
}
@@ -115,7 +116,7 @@ public class Errors
public static Error CHANGED_CLASS = new Error(23, WARNING);
public static Error CHANGED_DEPRECATED = new Error(24, WARNING);
public static Error CHANGED_SYNCHRONIZED = new Error(25, ERROR);
public static Error[] ERRORS = {
PARSE_ERROR,
ADDED_PACKAGE,

View File

@@ -80,6 +80,7 @@ public class SourcePositionInfo implements Comparable
return new SourcePositionInfo(that.file, line, 0);
}
@Override
public String toString()
{
if (this.file == null) {

View File

@@ -17,7 +17,7 @@ ifneq ($(TARGET_SIMULATOR),true)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := applypatch.c bsdiff.c freecache.c imgpatch.c utils.c
LOCAL_SRC_FILES := applypatch.c bspatch.c freecache.c imgpatch.c utils.c
LOCAL_MODULE := libapplypatch
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += external/bzip2 external/zlib bootable/recovery
@@ -47,12 +47,12 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := imgdiff.c utils.c
LOCAL_SRC_FILES := imgdiff.c utils.c bsdiff.c
LOCAL_MODULE := imgdiff
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += external/zlib
LOCAL_STATIC_LIBRARIES += libz
LOCAL_C_INCLUDES += external/zlib external/bzip2
LOCAL_STATIC_LIBRARIES += libz libbz
include $(BUILD_HOST_EXECUTABLE)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* 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.
@@ -14,239 +14,397 @@
* limitations under the License.
*/
// This file is a nearly line-for-line copy of bspatch.c from the
// bsdiff-4.3 distribution; the primary differences being how the
// input and output data are read and the error handling. Running
// applypatch with the -l option will display the bsdiff license
// notice.
/*
* Most of this code comes from bsdiff.c from the bsdiff-4.3
* distribution, which is:
*/
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
/*-
* Copyright 2003-2005 Colin Percival
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <bzlib.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mincrypt/sha.h"
#include "applypatch.h"
#define MIN(x,y) (((x)<(y)) ? (x) : (y))
void ShowBSDiffLicense() {
puts("The bsdiff library used herein is:\n"
"\n"
"Copyright 2003-2005 Colin Percival\n"
"All rights reserved\n"
"\n"
"Redistribution and use in source and binary forms, with or without\n"
"modification, are permitted providing that the following conditions\n"
"are met:\n"
"1. Redistributions of source code must retain the above copyright\n"
" notice, this list of conditions and the following disclaimer.\n"
"2. Redistributions in binary form must reproduce the above copyright\n"
" notice, this list of conditions and the following disclaimer in the\n"
" documentation and/or other materials provided with the distribution.\n"
"\n"
"THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
"IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
"ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n"
"DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"
"DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
"OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n"
"HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n"
"STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n"
"IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
"POSSIBILITY OF SUCH DAMAGE.\n"
"\n------------------\n\n"
"This program uses Julian R Seward's \"libbzip2\" library, available\n"
"from http://www.bzip.org/.\n"
);
}
static off_t offtin(u_char *buf)
static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h)
{
off_t y;
off_t i,j,k,x,tmp,jj,kk;
y=buf[7]&0x7F;
y=y*256;y+=buf[6];
y=y*256;y+=buf[5];
y=y*256;y+=buf[4];
y=y*256;y+=buf[3];
y=y*256;y+=buf[2];
y=y*256;y+=buf[1];
y=y*256;y+=buf[0];
if(len<16) {
for(k=start;k<start+len;k+=j) {
j=1;x=V[I[k]+h];
for(i=1;k+i<start+len;i++) {
if(V[I[k+i]+h]<x) {
x=V[I[k+i]+h];
j=0;
};
if(V[I[k+i]+h]==x) {
tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
j++;
};
};
for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
if(j==1) I[k]=-1;
};
return;
};
if(buf[7]&0x80) y=-y;
x=V[I[start+len/2]+h];
jj=0;kk=0;
for(i=start;i<start+len;i++) {
if(V[I[i]+h]<x) jj++;
if(V[I[i]+h]==x) kk++;
};
jj+=start;kk+=jj;
return y;
i=start;j=0;k=0;
while(i<jj) {
if(V[I[i]+h]<x) {
i++;
} else if(V[I[i]+h]==x) {
tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
j++;
} else {
tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
k++;
};
};
while(jj+j<kk) {
if(V[I[jj+j]+h]==x) {
j++;
} else {
tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
k++;
};
};
if(jj>start) split(I,V,start,jj-start,h);
for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
if(jj==kk-1) I[jj]=-1;
if(start+len>kk) split(I,V,kk,start+len-kk,h);
}
static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize)
{
off_t buckets[256];
off_t i,h,len;
int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
const char* patch_filename, ssize_t patch_offset,
SinkFn sink, void* token, SHA_CTX* ctx) {
for(i=0;i<256;i++) buckets[i]=0;
for(i=0;i<oldsize;i++) buckets[old[i]]++;
for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
for(i=255;i>0;i--) buckets[i]=buckets[i-1];
buckets[0]=0;
unsigned char* new_data;
ssize_t new_size;
if (ApplyBSDiffPatchMem(old_data, old_size, patch_filename, patch_offset,
&new_data, &new_size) != 0) {
return -1;
}
for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
I[0]=oldsize;
for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
V[oldsize]=0;
for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
I[0]=-1;
if (sink(new_data, new_size, token) < new_size) {
fprintf(stderr, "short write of output: %d (%s)\n", errno, strerror(errno));
return 1;
}
if (ctx) {
SHA_update(ctx, new_data, new_size);
}
free(new_data);
for(h=1;I[0]!=-(oldsize+1);h+=h) {
len=0;
for(i=0;i<oldsize+1;) {
if(I[i]<0) {
len-=I[i];
i-=I[i];
} else {
if(len) I[i-len]=-len;
len=V[I[i]]+1-i;
split(I,V,i,len,h);
i+=len;
len=0;
};
};
if(len) I[i-len]=-len;
};
return 0;
for(i=0;i<oldsize+1;i++) I[V[i]]=i;
}
int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
const char* patch_filename, ssize_t patch_offset,
unsigned char** new_data, ssize_t* new_size) {
static off_t matchlen(u_char *old,off_t oldsize,u_char *new,off_t newsize)
{
off_t i;
FILE* f;
if ((f = fopen(patch_filename, "rb")) == NULL) {
fprintf(stderr, "failed to open patch file\n");
return 1;
}
for(i=0;(i<oldsize)&&(i<newsize);i++)
if(old[i]!=new[i]) break;
// File format:
// 0 8 "BSDIFF40"
// 8 8 X
// 16 8 Y
// 24 8 sizeof(newfile)
// 32 X bzip2(control block)
// 32+X Y bzip2(diff block)
// 32+X+Y ??? bzip2(extra block)
// with control block a set of triples (x,y,z) meaning "add x bytes
// from oldfile to x bytes from the diff block; copy y bytes from the
// extra block; seek forwards in oldfile by z bytes".
fseek(f, patch_offset, SEEK_SET);
unsigned char header[32];
if (fread(header, 1, 32, f) < 32) {
fprintf(stderr, "failed to read patch file header\n");
return 1;
}
if (memcmp(header, "BSDIFF40", 8) != 0) {
fprintf(stderr, "corrupt bsdiff patch file header (magic number)\n");
return 1;
}
ssize_t ctrl_len, data_len;
ctrl_len = offtin(header+8);
data_len = offtin(header+16);
*new_size = offtin(header+24);
if (ctrl_len < 0 || data_len < 0 || *new_size < 0) {
fprintf(stderr, "corrupt patch file header (data lengths)\n");
return 1;
}
fclose(f);
int bzerr;
#define OPEN_AT(f, bzf, offset) \
FILE* f; \
BZFILE* bzf; \
if ((f = fopen(patch_filename, "rb")) == NULL) { \
fprintf(stderr, "failed to open patch file\n"); \
return 1; \
} \
if (fseeko(f, offset+patch_offset, SEEK_SET)) { \
fprintf(stderr, "failed to seek in patch file\n"); \
return 1; \
} \
if ((bzf = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0)) == NULL) { \
fprintf(stderr, "failed to bzReadOpen in patch file (%d)\n", bzerr); \
return 1; \
}
OPEN_AT(cpf, cpfbz2, 32);
OPEN_AT(dpf, dpfbz2, 32+ctrl_len);
OPEN_AT(epf, epfbz2, 32+ctrl_len+data_len);
#undef OPEN_AT
*new_data = malloc(*new_size);
if (*new_data == NULL) {
fprintf(stderr, "failed to allocate %d bytes of memory for output file\n",
(int)*new_size);
return 1;
}
off_t oldpos = 0, newpos = 0;
off_t ctrl[3];
off_t len_read;
int i;
unsigned char buf[8];
while (newpos < *new_size) {
// Read control data
for (i = 0; i < 3; ++i) {
len_read = BZ2_bzRead(&bzerr, cpfbz2, buf, 8);
if (len_read < 8 || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
fprintf(stderr, "corrupt patch (read control)\n");
return 1;
}
ctrl[i] = offtin(buf);
}
// Sanity check
if (newpos + ctrl[0] > *new_size) {
fprintf(stderr, "corrupt patch (new file overrun)\n");
return 1;
}
// Read diff string
len_read = BZ2_bzRead(&bzerr, dpfbz2, *new_data + newpos, ctrl[0]);
if (len_read < ctrl[0] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
fprintf(stderr, "corrupt patch (read diff)\n");
return 1;
}
// Add old data to diff string
for (i = 0; i < ctrl[0]; ++i) {
if ((oldpos+i >= 0) && (oldpos+i < old_size)) {
(*new_data)[newpos+i] += old_data[oldpos+i];
}
}
// Adjust pointers
newpos += ctrl[0];
oldpos += ctrl[0];
// Sanity check
if (newpos + ctrl[1] > *new_size) {
fprintf(stderr, "corrupt patch (new file overrun)\n");
return 1;
}
// Read extra string
len_read = BZ2_bzRead(&bzerr, epfbz2, *new_data + newpos, ctrl[1]);
if (len_read < ctrl[1] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
fprintf(stderr, "corrupt patch (read extra)\n");
return 1;
}
// Adjust pointers
newpos += ctrl[1];
oldpos += ctrl[2];
}
BZ2_bzReadClose(&bzerr, cpfbz2);
BZ2_bzReadClose(&bzerr, dpfbz2);
BZ2_bzReadClose(&bzerr, epfbz2);
fclose(cpf);
fclose(dpf);
fclose(epf);
return 0;
return i;
}
static off_t search(off_t *I,u_char *old,off_t oldsize,
u_char *new,off_t newsize,off_t st,off_t en,off_t *pos)
{
off_t x,y;
if(en-st<2) {
x=matchlen(old+I[st],oldsize-I[st],new,newsize);
y=matchlen(old+I[en],oldsize-I[en],new,newsize);
if(x>y) {
*pos=I[st];
return x;
} else {
*pos=I[en];
return y;
}
};
x=st+(en-st)/2;
if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
return search(I,old,oldsize,new,newsize,x,en,pos);
} else {
return search(I,old,oldsize,new,newsize,st,x,pos);
};
}
static void offtout(off_t x,u_char *buf)
{
off_t y;
if(x<0) y=-x; else y=x;
buf[0]=y%256;y-=buf[0];
y=y/256;buf[1]=y%256;y-=buf[1];
y=y/256;buf[2]=y%256;y-=buf[2];
y=y/256;buf[3]=y%256;y-=buf[3];
y=y/256;buf[4]=y%256;y-=buf[4];
y=y/256;buf[5]=y%256;y-=buf[5];
y=y/256;buf[6]=y%256;y-=buf[6];
y=y/256;buf[7]=y%256;
if(x<0) buf[7]|=0x80;
}
// This is main() from bsdiff.c, with the following changes:
//
// - old, oldsize, new, newsize are arguments; we don't load this
// data from files. old and new are owned by the caller; we
// don't free them at the end.
//
// - the "I" block of memory is owned by the caller, who passes a
// pointer to *I, which can be NULL. This way if we call
// bsdiff() multiple times with the same 'old' data, we only do
// the qsufsort() step the first time.
//
int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* new, off_t newsize,
const char* patch_filename)
{
int fd;
off_t *I;
off_t scan,pos,len;
off_t lastscan,lastpos,lastoffset;
off_t oldscore,scsc;
off_t s,Sf,lenf,Sb,lenb;
off_t overlap,Ss,lens;
off_t i;
off_t dblen,eblen;
u_char *db,*eb;
u_char buf[8];
u_char header[32];
FILE * pf;
BZFILE * pfbz2;
int bz2err;
if (*IP == NULL) {
off_t* V;
*IP = malloc((oldsize+1) * sizeof(off_t));
V = malloc((oldsize+1) * sizeof(off_t));
qsufsort(*IP, V, old, oldsize);
free(V);
}
I = *IP;
if(((db=malloc(newsize+1))==NULL) ||
((eb=malloc(newsize+1))==NULL)) err(1,NULL);
dblen=0;
eblen=0;
/* Create the patch file */
if ((pf = fopen(patch_filename, "w")) == NULL)
err(1, "%s", patch_filename);
/* Header is
0 8 "BSDIFF40"
8 8 length of bzip2ed ctrl block
16 8 length of bzip2ed diff block
24 8 length of new file */
/* File is
0 32 Header
32 ?? Bzip2ed ctrl block
?? ?? Bzip2ed diff block
?? ?? Bzip2ed extra block */
memcpy(header,"BSDIFF40",8);
offtout(0, header + 8);
offtout(0, header + 16);
offtout(newsize, header + 24);
if (fwrite(header, 32, 1, pf) != 1)
err(1, "fwrite(%s)", patch_filename);
/* Compute the differences, writing ctrl as we go */
if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
scan=0;len=0;
lastscan=0;lastpos=0;lastoffset=0;
while(scan<newsize) {
oldscore=0;
for(scsc=scan+=len;scan<newsize;scan++) {
len=search(I,old,oldsize,new+scan,newsize-scan,
0,oldsize,&pos);
for(;scsc<scan+len;scsc++)
if((scsc+lastoffset<oldsize) &&
(old[scsc+lastoffset] == new[scsc]))
oldscore++;
if(((len==oldscore) && (len!=0)) ||
(len>oldscore+8)) break;
if((scan+lastoffset<oldsize) &&
(old[scan+lastoffset] == new[scan]))
oldscore--;
};
if((len!=oldscore) || (scan==newsize)) {
s=0;Sf=0;lenf=0;
for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
if(old[lastpos+i]==new[lastscan+i]) s++;
i++;
if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
};
lenb=0;
if(scan<newsize) {
s=0;Sb=0;
for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
if(old[pos-i]==new[scan-i]) s++;
if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
};
};
if(lastscan+lenf>scan-lenb) {
overlap=(lastscan+lenf)-(scan-lenb);
s=0;Ss=0;lens=0;
for(i=0;i<overlap;i++) {
if(new[lastscan+lenf-overlap+i]==
old[lastpos+lenf-overlap+i]) s++;
if(new[scan-lenb+i]==
old[pos-lenb+i]) s--;
if(s>Ss) { Ss=s; lens=i+1; };
};
lenf+=lens-overlap;
lenb-=lens;
};
for(i=0;i<lenf;i++)
db[dblen+i]=new[lastscan+i]-old[lastpos+i];
for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
eb[eblen+i]=new[lastscan+lenf+i];
dblen+=lenf;
eblen+=(scan-lenb)-(lastscan+lenf);
offtout(lenf,buf);
BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
if (bz2err != BZ_OK)
errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
offtout((scan-lenb)-(lastscan+lenf),buf);
BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
if (bz2err != BZ_OK)
errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
offtout((pos-lenb)-(lastpos+lenf),buf);
BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
if (bz2err != BZ_OK)
errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
lastscan=scan-lenb;
lastpos=pos-lenb;
lastoffset=pos-scan;
};
};
BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
if (bz2err != BZ_OK)
errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
/* Compute size of compressed ctrl data */
if ((len = ftello(pf)) == -1)
err(1, "ftello");
offtout(len-32, header + 8);
/* Write compressed diff data */
if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
BZ2_bzWrite(&bz2err, pfbz2, db, dblen);
if (bz2err != BZ_OK)
errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
if (bz2err != BZ_OK)
errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
/* Compute size of compressed diff data */
if ((newsize = ftello(pf)) == -1)
err(1, "ftello");
offtout(newsize - len, header + 16);
/* Write compressed extra data */
if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
BZ2_bzWrite(&bz2err, pfbz2, eb, eblen);
if (bz2err != BZ_OK)
errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
if (bz2err != BZ_OK)
errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
/* Seek to the beginning, write the header, and close the file */
if (fseeko(pf, 0, SEEK_SET))
err(1, "fseeko");
if (fwrite(header, 32, 1, pf) != 1)
err(1, "fwrite(%s)", patch_filename);
if (fclose(pf))
err(1, "fclose");
/* Free the memory we used */
free(db);
free(eb);
return 0;
}

252
tools/applypatch/bspatch.c Normal file
View File

@@ -0,0 +1,252 @@
/*
* 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.
*/
// This file is a nearly line-for-line copy of bspatch.c from the
// bsdiff-4.3 distribution; the primary differences being how the
// input and output data are read and the error handling. Running
// applypatch with the -l option will display the bsdiff license
// notice.
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <bzlib.h>
#include "mincrypt/sha.h"
#include "applypatch.h"
void ShowBSDiffLicense() {
puts("The bsdiff library used herein is:\n"
"\n"
"Copyright 2003-2005 Colin Percival\n"
"All rights reserved\n"
"\n"
"Redistribution and use in source and binary forms, with or without\n"
"modification, are permitted providing that the following conditions\n"
"are met:\n"
"1. Redistributions of source code must retain the above copyright\n"
" notice, this list of conditions and the following disclaimer.\n"
"2. Redistributions in binary form must reproduce the above copyright\n"
" notice, this list of conditions and the following disclaimer in the\n"
" documentation and/or other materials provided with the distribution.\n"
"\n"
"THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
"IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
"ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n"
"DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"
"DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
"OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n"
"HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n"
"STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n"
"IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
"POSSIBILITY OF SUCH DAMAGE.\n"
"\n------------------\n\n"
"This program uses Julian R Seward's \"libbzip2\" library, available\n"
"from http://www.bzip.org/.\n"
);
}
static off_t offtin(u_char *buf)
{
off_t y;
y=buf[7]&0x7F;
y=y*256;y+=buf[6];
y=y*256;y+=buf[5];
y=y*256;y+=buf[4];
y=y*256;y+=buf[3];
y=y*256;y+=buf[2];
y=y*256;y+=buf[1];
y=y*256;y+=buf[0];
if(buf[7]&0x80) y=-y;
return y;
}
int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
const char* patch_filename, ssize_t patch_offset,
SinkFn sink, void* token, SHA_CTX* ctx) {
unsigned char* new_data;
ssize_t new_size;
if (ApplyBSDiffPatchMem(old_data, old_size, patch_filename, patch_offset,
&new_data, &new_size) != 0) {
return -1;
}
if (sink(new_data, new_size, token) < new_size) {
fprintf(stderr, "short write of output: %d (%s)\n", errno, strerror(errno));
return 1;
}
if (ctx) {
SHA_update(ctx, new_data, new_size);
}
free(new_data);
return 0;
}
int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
const char* patch_filename, ssize_t patch_offset,
unsigned char** new_data, ssize_t* new_size) {
FILE* f;
if ((f = fopen(patch_filename, "rb")) == NULL) {
fprintf(stderr, "failed to open patch file\n");
return 1;
}
// File format:
// 0 8 "BSDIFF40"
// 8 8 X
// 16 8 Y
// 24 8 sizeof(newfile)
// 32 X bzip2(control block)
// 32+X Y bzip2(diff block)
// 32+X+Y ??? bzip2(extra block)
// with control block a set of triples (x,y,z) meaning "add x bytes
// from oldfile to x bytes from the diff block; copy y bytes from the
// extra block; seek forwards in oldfile by z bytes".
fseek(f, patch_offset, SEEK_SET);
unsigned char header[32];
if (fread(header, 1, 32, f) < 32) {
fprintf(stderr, "failed to read patch file header\n");
return 1;
}
if (memcmp(header, "BSDIFF40", 8) != 0) {
fprintf(stderr, "corrupt bsdiff patch file header (magic number)\n");
return 1;
}
ssize_t ctrl_len, data_len;
ctrl_len = offtin(header+8);
data_len = offtin(header+16);
*new_size = offtin(header+24);
if (ctrl_len < 0 || data_len < 0 || *new_size < 0) {
fprintf(stderr, "corrupt patch file header (data lengths)\n");
return 1;
}
fclose(f);
int bzerr;
#define OPEN_AT(f, bzf, offset) \
FILE* f; \
BZFILE* bzf; \
if ((f = fopen(patch_filename, "rb")) == NULL) { \
fprintf(stderr, "failed to open patch file\n"); \
return 1; \
} \
if (fseeko(f, offset+patch_offset, SEEK_SET)) { \
fprintf(stderr, "failed to seek in patch file\n"); \
return 1; \
} \
if ((bzf = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0)) == NULL) { \
fprintf(stderr, "failed to bzReadOpen in patch file (%d)\n", bzerr); \
return 1; \
}
OPEN_AT(cpf, cpfbz2, 32);
OPEN_AT(dpf, dpfbz2, 32+ctrl_len);
OPEN_AT(epf, epfbz2, 32+ctrl_len+data_len);
#undef OPEN_AT
*new_data = malloc(*new_size);
if (*new_data == NULL) {
fprintf(stderr, "failed to allocate %d bytes of memory for output file\n",
(int)*new_size);
return 1;
}
off_t oldpos = 0, newpos = 0;
off_t ctrl[3];
off_t len_read;
int i;
unsigned char buf[8];
while (newpos < *new_size) {
// Read control data
for (i = 0; i < 3; ++i) {
len_read = BZ2_bzRead(&bzerr, cpfbz2, buf, 8);
if (len_read < 8 || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
fprintf(stderr, "corrupt patch (read control)\n");
return 1;
}
ctrl[i] = offtin(buf);
}
// Sanity check
if (newpos + ctrl[0] > *new_size) {
fprintf(stderr, "corrupt patch (new file overrun)\n");
return 1;
}
// Read diff string
len_read = BZ2_bzRead(&bzerr, dpfbz2, *new_data + newpos, ctrl[0]);
if (len_read < ctrl[0] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
fprintf(stderr, "corrupt patch (read diff)\n");
return 1;
}
// Add old data to diff string
for (i = 0; i < ctrl[0]; ++i) {
if ((oldpos+i >= 0) && (oldpos+i < old_size)) {
(*new_data)[newpos+i] += old_data[oldpos+i];
}
}
// Adjust pointers
newpos += ctrl[0];
oldpos += ctrl[0];
// Sanity check
if (newpos + ctrl[1] > *new_size) {
fprintf(stderr, "corrupt patch (new file overrun)\n");
return 1;
}
// Read extra string
len_read = BZ2_bzRead(&bzerr, epfbz2, *new_data + newpos, ctrl[1]);
if (len_read < ctrl[1] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
fprintf(stderr, "corrupt patch (read extra)\n");
return 1;
}
// Adjust pointers
newpos += ctrl[1];
oldpos += ctrl[2];
}
BZ2_bzReadClose(&bzerr, cpfbz2);
BZ2_bzReadClose(&bzerr, dpfbz2);
BZ2_bzReadClose(&bzerr, epfbz2);
fclose(cpf);
fclose(dpf);
fclose(epf);
return 0;
}

View File

@@ -119,6 +119,7 @@
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include "zlib.h"
#include "imgdiff.h"
@@ -134,6 +135,8 @@ typedef struct {
size_t source_start;
size_t source_len;
off_t* I; // used by bsdiff
// --- for CHUNK_DEFLATE chunks only: ---
// original (compressed) deflate data
@@ -167,6 +170,10 @@ static int fileentry_compare(const void* a, const void* b) {
}
}
// from bsdiff.c
int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* new, off_t newsize,
const char* patch_filename);
unsigned char* ReadZip(const char* filename,
int* num_chunks, ImageChunk** chunks,
int include_pseudo_chunk) {
@@ -278,6 +285,7 @@ unsigned char* ReadZip(const char* filename,
curr->len = st.st_size;
curr->data = img;
curr->filename = NULL;
curr->I = NULL;
++curr;
++*num_chunks;
}
@@ -292,6 +300,7 @@ unsigned char* ReadZip(const char* filename,
curr->deflate_len = temp_entries[nextentry].deflate_len;
curr->deflate_data = img + pos;
curr->filename = temp_entries[nextentry].filename;
curr->I = NULL;
curr->len = temp_entries[nextentry].uncomp_len;
curr->data = malloc(curr->len);
@@ -336,6 +345,7 @@ unsigned char* ReadZip(const char* filename,
}
curr->data = img + pos;
curr->filename = NULL;
curr->I = NULL;
pos += curr->len;
++*num_chunks;
@@ -400,6 +410,7 @@ unsigned char* ReadImage(const char* filename,
curr->type = CHUNK_NORMAL;
curr->len = GZIP_HEADER_LEN;
curr->data = p;
curr->I = NULL;
pos += curr->len;
p += curr->len;
@@ -407,6 +418,7 @@ unsigned char* ReadImage(const char* filename,
curr->type = CHUNK_DEFLATE;
curr->filename = NULL;
curr->I = NULL;
// We must decompress this chunk in order to discover where it
// ends, and so we can put the uncompressed data and its length
@@ -452,6 +464,7 @@ unsigned char* ReadImage(const char* filename,
curr->start = pos;
curr->len = GZIP_FOOTER_LEN;
curr->data = img+pos;
curr->I = NULL;
pos += curr->len;
p += curr->len;
@@ -475,6 +488,7 @@ unsigned char* ReadImage(const char* filename,
*chunks = realloc(*chunks, *num_chunks * sizeof(ImageChunk));
ImageChunk* curr = *chunks + (*num_chunks-1);
curr->start = pos;
curr->I = NULL;
// 'pos' is not the offset of the start of a gzip chunk, so scan
// forward until we find a gzip header.
@@ -591,43 +605,12 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) {
}
}
char stemp[] = "/tmp/imgdiff-src-XXXXXX";
char ttemp[] = "/tmp/imgdiff-tgt-XXXXXX";
char ptemp[] = "/tmp/imgdiff-patch-XXXXXX";
mkstemp(stemp);
mkstemp(ttemp);
mkstemp(ptemp);
FILE* f = fopen(stemp, "wb");
if (f == NULL) {
fprintf(stderr, "failed to open src chunk %s: %s\n",
stemp, strerror(errno));
return NULL;
}
if (fwrite(src->data, 1, src->len, f) != src->len) {
fprintf(stderr, "failed to write src chunk to %s: %s\n",
stemp, strerror(errno));
return NULL;
}
fclose(f);
f = fopen(ttemp, "wb");
if (f == NULL) {
fprintf(stderr, "failed to open tgt chunk %s: %s\n",
ttemp, strerror(errno));
return NULL;
}
if (fwrite(tgt->data, 1, tgt->len, f) != tgt->len) {
fprintf(stderr, "failed to write tgt chunk to %s: %s\n",
ttemp, strerror(errno));
return NULL;
}
fclose(f);
char cmd[200];
sprintf(cmd, "bsdiff %s %s %s", stemp, ttemp, ptemp);
if (system(cmd) != 0) {
fprintf(stderr, "failed to run bsdiff: %s\n", strerror(errno));
int r = bsdiff(src->data, src->len, &(src->I), tgt->data, tgt->len, ptemp);
if (r != 0) {
fprintf(stderr, "bsdiff() failed: %d\n", r);
return NULL;
}
@@ -641,8 +624,6 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) {
unsigned char* data = malloc(st.st_size);
if (tgt->type == CHUNK_NORMAL && tgt->len <= st.st_size) {
unlink(stemp);
unlink(ttemp);
unlink(ptemp);
tgt->type = CHUNK_RAW;
@@ -652,7 +633,7 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) {
*size = st.st_size;
f = fopen(ptemp, "rb");
FILE* f = fopen(ptemp, "rb");
if (f == NULL) {
fprintf(stderr, "failed to open patch %s: %s\n", ptemp, strerror(errno));
return NULL;
@@ -663,8 +644,6 @@ unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) {
}
fclose(f);
unlink(stemp);
unlink(ttemp);
unlink(ptemp);
tgt->source_start = src->start;
@@ -784,6 +763,14 @@ ImageChunk* FindChunkByName(const char* name,
return NULL;
}
void DumpChunks(ImageChunk* chunks, int num_chunks) {
int i;
for (i = 0; i < num_chunks; ++i) {
printf("chunk %d: type %d start %d len %d\n",
i, chunks[i].type, chunks[i].start, chunks[i].len);
}
}
int main(int argc, char** argv) {
if (argc != 4 && argc != 5) {
usage:
@@ -829,14 +816,29 @@ int main(int argc, char** argv) {
// Verify that the source and target images have the same chunk
// structure (ie, the same sequence of deflate and normal chunks).
if (!zip_mode) {
// Merge the gzip header and footer in with any adjacent
// normal chunks.
MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks);
MergeAdjacentNormalChunks(src_chunks, &num_src_chunks);
}
if (num_src_chunks != num_tgt_chunks) {
fprintf(stderr, "source and target don't have same number of chunks!\n");
printf("source chunks:\n");
DumpChunks(src_chunks, num_src_chunks);
printf("target chunks:\n");
DumpChunks(tgt_chunks, num_tgt_chunks);
return 1;
}
for (i = 0; i < num_src_chunks; ++i) {
if (src_chunks[i].type != tgt_chunks[i].type) {
fprintf(stderr, "source and target don't have same chunk "
"structure! (chunk %d)\n", i);
printf("source chunks:\n");
DumpChunks(src_chunks, num_src_chunks);
printf("target chunks:\n");
DumpChunks(tgt_chunks, num_tgt_chunks);
return 1;
}
}

View File

@@ -7,11 +7,14 @@
typedef struct mapentry mapentry;
#define MAX_ALIASES 10
struct mapentry
{
mapentry *next;
unsigned base;
char name[0];
char *names[MAX_ALIASES];
int num_names;
};
static mapentry *maplist = 0;
@@ -22,14 +25,13 @@ static mapentry *maplist = 0;
*/
#define PRELINK_MIN 0x90000000
#define PRELINK_MAX 0xB0000000
#define PRELINK_MAX 0xBFFFFFFF
void pm_init(const char *file)
{
unsigned line = 0;
char buf[256];
char *x;
unsigned n;
FILE *fp;
mapentry *me;
unsigned last = -1UL;
@@ -65,26 +67,52 @@ void pm_init(const char *file)
continue;
}
n = strtoul(x, 0, 16);
/* Note that this is not the only bounds check. If a library's size
exceeds its slot as defined in the prelink map, the prelinker will
exit with an error. See pm_report_library_size_in_memory().
*/
FAILIF((n < PRELINK_MIN) || (n > PRELINK_MAX),
"%s:%d base 0x%08x out of range.\n",
file, line, n);
me = malloc(sizeof(mapentry) + strlen(buf) + 1);
FAILIF(me == NULL, "Out of memory parsing %s\n", file);
if (isalpha(*x)) {
/* Assume that this is an alias, and look through the list of
already-installed libraries.
*/
me = maplist;
while(me) {
/* The strlen() call ignores the newline at the end of x */
if (!strncmp(me->names[0], x, strlen(me->names[0]))) {
PRINT("Aliasing library %s to %s at %08x\n",
buf, x, me->base);
break;
}
me = me->next;
}
FAILIF(!me, "Nonexistent alias %s -> %s\n", buf, x);
}
else {
unsigned n = strtoul(x, 0, 16);
/* Note that this is not the only bounds check. If a library's
size exceeds its slot as defined in the prelink map, the
prelinker will exit with an error. See
pm_report_library_size_in_memory().
*/
FAILIF((n < PRELINK_MIN) || (n > PRELINK_MAX),
"%s:%d base 0x%08x out of range.\n",
file, line, n);
FAILIF(last <= n, "The prelink map is not in descending order "
"at entry %s (%08x)!\n", buf, n);
last = n;
me->base = n;
strcpy(me->name, buf);
me->next = maplist;
maplist = me;
me = malloc(sizeof(mapentry));
FAILIF(me == NULL, "Out of memory parsing %s\n", file);
FAILIF(last <= n, "The prelink map is not in descending order "
"at entry %s (%08x)!\n", buf, n);
last = n;
me->base = n;
me->next = maplist;
me->num_names = 0;
maplist = me;
}
FAILIF(me->num_names >= MAX_ALIASES,
"Too many aliases for library %s, maximum is %d.\n",
me->names[0],
MAX_ALIASES);
me->names[me->num_names] = strdup(buf);
me->num_names++;
}
fclose(fp);
@@ -99,41 +127,44 @@ void pm_report_library_size_in_memory(const char *name,
{
char *x;
mapentry *me;
int n;
x = strrchr(name,'/');
if(x) name = x+1;
for(me = maplist; me; me = me->next){
if(!strcmp(name, me->name)) {
off_t slot = me->next ? me->next->base : PRELINK_MAX;
slot -= me->base;
FAILIF(fsize > slot,
"prelink map error: library %s@0x%08x is too big "
"at %lld bytes, it runs %lld bytes into "
"library %s@0x%08x!\n",
me->name, me->base, fsize, fsize - slot,
me->next->name, me->next->base);
break;
for (n = 0; n < me->num_names; n++) {
if(!strcmp(name, me->names[n])) {
off_t slot = me->next ? me->next->base : PRELINK_MAX;
slot -= me->base;
FAILIF(fsize > slot,
"prelink map error: library %s@0x%08x is too big "
"at %lld bytes, it runs %lld bytes into "
"library %s@0x%08x!\n",
me->names[0], me->base, fsize, fsize - slot,
me->next->names[0], me->next->base);
return;
}
}
}
FAILIF(!me,"library '%s' not in prelink map\n", name);
FAILIF(1, "library '%s' not in prelink map\n", name);
}
unsigned pm_get_next_link_address(const char *lookup_name)
{
char *x;
mapentry *me;
int n;
x = strrchr(lookup_name,'/');
if(x) lookup_name = x+1;
for(me = maplist; me; me = me->next){
if(!strcmp(lookup_name, me->name)) {
return me->base;
}
}
FAILIF(1==1,"library '%s' not in prelink map\n", lookup_name);
for(me = maplist; me; me = me->next)
for (n = 0; n < me->num_names; n++)
if(!strcmp(lookup_name, me->names[n]))
return me->base;
FAILIF(1, "library '%s' not in prelink map\n", lookup_name);
return 0;
}

View File

@@ -7,6 +7,8 @@
#include <unistd.h>
#include <dirent.h>
#include <fnmatch.h>
#include <string.h>
#include <stdlib.h>
static bool
is_comment_line(const char* p)

View File

@@ -10,6 +10,7 @@
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <host/CopyFile.h>
using namespace std;

View File

@@ -24,6 +24,7 @@ echo "ro.product.cpu.abi=$TARGET_CPU_ABI"
echo "ro.product.manufacturer=$PRODUCT_MANUFACTURER"
echo "ro.product.locale.language=$PRODUCT_DEFAULT_LANGUAGE"
echo "ro.product.locale.region=$PRODUCT_DEFAULT_REGION"
echo "ro.wifi.channels=$PRODUCT_DEFAULT_WIFI_CHANNELS"
echo "ro.board.platform=$TARGET_BOARD_PLATFORM"
echo "# ro.build.product is obsolete; use ro.product.device"

View File

@@ -77,6 +77,13 @@ ifdef sign_dexpreopt
$(shell echo "$(p) $(PACKAGES.$(p).CERTIFICATE) $(PACKAGES.$(p).PRIVATE_KEY)" >> $(dexpreopt_package_certs_file)))
endif
# The kernel used for ARMv7 system images is different
ifeq ($(TARGET_ARCH_VARIANT),armv7-a)
BUILD_DEXPREOPT_KERNEL := prebuilt/android-arm/kernel/kernel-qemu-armv7
else
BUILD_DEXPREOPT_KERNEL := prebuilt/android-arm/kernel/kernel-qemu
endif
# Build an optimized image from the unoptimized image
BUILT_DEXPREOPT_SYSTEMIMAGE := $(intermediates)/system.img
$(BUILT_DEXPREOPT_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE_UNOPT)
@@ -99,7 +106,7 @@ $(BUILT_DEXPREOPT_SYSTEMIMAGE):
$(hide) \
PATH=$(HOST_OUT_EXECUTABLES):$$PATH \
$(DEXPREOPT) \
--kernel prebuilt/android-arm/kernel/kernel-qemu \
--kernel $(BUILD_DEXPREOPT_KERNEL) \
--ramdisk $(BUILT_DEXPREOPT_RAMDISK) \
--image $(BUILT_SYSTEMIMAGE_UNOPT) \
--system $(PRODUCT_OUT) \

View File

@@ -35,6 +35,7 @@ class AnnotationInstanceInfo
return mElementValues;
}
@Override
public String toString()
{
StringBuilder str = new StringBuilder();

View File

@@ -98,7 +98,8 @@ public class AttrTagInfo extends TagInfo
public FieldInfo reference() {
return REF_COMMAND.equals(mCommand) ? mRefField : null;
}
@Override
public String name() {
return NAME_COMMAND.equals(mCommand) ? mAttrName : null;
}
@@ -107,6 +108,7 @@ public class AttrTagInfo extends TagInfo
return DESCRIPTION_COMMAND.equals(mCommand) ? mDescrComment : null;
}
@Override
public void makeHDF(HDF data, String base)
{
super.makeHDF(data, base);

View File

@@ -101,7 +101,7 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
mSelfFields = null;
mSelfAttributes = null;
mDeprecatedKnown = false;
Arrays.sort(mEnumConstants, FieldInfo.comparator);
Arrays.sort(mInnerClasses, ClassInfo.comparator);
}
@@ -111,16 +111,16 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
// objects
selfAttributes();
}
public void init3(TypeInfo[] types, ClassInfo[] realInnerClasses){
mTypeParameters = types;
mRealInnerClasses = realInnerClasses;
}
public ClassInfo[] getRealInnerClasses(){
return mRealInnerClasses;
}
public TypeInfo[] getTypeParameters(){
return mTypeParameters;
}
@@ -146,6 +146,7 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
}
}
@Override
public ContainerInfo parent()
{
return this;
@@ -351,7 +352,7 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
{
return comment().briefTags();
}
public boolean isDeprecated() {
boolean deprecated = false;
if (!mDeprecatedKnown) {
@@ -378,7 +379,7 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
public TagInfo[] deprecatedTags()
{
// should we also do the interfaces?
// Should we also do the interfaces?
return comment().deprecatedTags();
}
@@ -551,7 +552,7 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
public MethodInfo[] allSelfMethods() {
return mAllSelfMethods;
}
public void addMethod(MethodInfo method) {
MethodInfo[] methods = new MethodInfo[mAllSelfMethods.length + 1];
int i = 0;
@@ -596,7 +597,7 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
}
}
}
//constructors too
for (MethodInfo m: constructors()) {
for (AttrTagInfo tag: m.comment().attrTags()) {
@@ -1136,7 +1137,11 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
if (kind != null) {
data.setValue(base + ".kind", kind);
}
if (cl.mIsIncluded) {
data.setValue(base + ".included", "true");
}
// xml attributes
i=0;
for (AttributeInfo attr: cl.selfAttributes()) {
@@ -1170,6 +1175,7 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
}
}
@Override
public boolean isHidden()
{
int val = mHidden;
@@ -1301,7 +1307,7 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
return f;
}
}
// then look at our enum constants (these are really fields, maybe
// they should be mixed into fields(). not sure)
for (FieldInfo f: enumConstants()) {
@@ -1346,11 +1352,11 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
return false;
}
}
public void setNonWrittenConstructors(MethodInfo[] nonWritten) {
mNonWrittenConstructors = nonWritten;
}
public MethodInfo[] getNonWrittenConstructors() {
return mNonWrittenConstructors;
}
@@ -1377,23 +1383,24 @@ public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Sco
}
return null;
}
public void setHiddenMethods(MethodInfo[] mInfo){
mHiddenMethods = mInfo;
}
public MethodInfo[] getHiddenMethods(){
return mHiddenMethods;
}
@Override
public String toString(){
return this.qualifiedName();
}
public void setReasonIncluded(String reason) {
mReasonIncluded = reason;
}
public String getReasonIncluded() {
return mReasonIncluded;
return mReasonIncluded;
}
private ClassDoc mClass;

View File

@@ -157,7 +157,7 @@ public class Comment
else if (name.equals("@literal")) {
mInlineTagsList.add(new LiteralTagInfo(name, name, text, pos));
}
else if (name.equals("@hide") || name.equals("@doconly")) {
else if (name.equals("@hide") || name.equals("@pending") || name.equals("@doconly")) {
// nothing
}
else if (name.equals("@attr")) {
@@ -206,7 +206,7 @@ public class Comment
for (int i=0; i<N; i++) {
if (mInlineTagsList.get(i).name().equals("@more")) {
more = i;
}
}
}
if (more >= 0) {
for (int i=0; i<more; i++) {
@@ -225,7 +225,7 @@ public class Comment
}
}
mBriefTagsList.add(t);
}
}
}
@@ -307,12 +307,12 @@ public class Comment
mHidden = 0;
return false;
}
boolean b = mText.indexOf("@hide") >= 0;
boolean b = mText.indexOf("@hide") >= 0 || mText.indexOf("@pending") >= 0;
mHidden = b ? 1 : 0;
return b;
}
}
public boolean isDocOnly() {
if (mDocOnly >= 0) {
return mDocOnly != 0;
@@ -391,5 +391,5 @@ public class Comment
ArrayList<TagInfo> mUndeprecateTagsList = new ArrayList<TagInfo>();
ArrayList<AttrTagInfo> mAttrTagsList = new ArrayList<AttrTagInfo>();
}

View File

@@ -238,6 +238,7 @@ public class Converter
}
private static Cache mClasses = new Cache()
{
@Override
protected Object make(Object o)
{
ClassDoc c = (ClassDoc)o;
@@ -268,19 +269,21 @@ public class Converter
}
return cl;
}
@Override
protected void made(Object o, Object r)
{
if (mClassesNeedingInit == null) {
initClass((ClassDoc)o, (ClassInfo)r);
((ClassInfo)r).init2();
}
}
}
@Override
ClassInfo[] all()
{
return (ClassInfo[])mCache.values().toArray(new ClassInfo[mCache.size()]);
}
};
private static MethodInfo[] getHiddenMethods(MethodDoc[] methods){
if (methods == null) return null;
ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
@@ -342,7 +345,7 @@ public class Converter
}
return out.toArray(new MethodInfo[out.size()]);
}
private static MethodInfo[] convertNonWrittenConstructors(ConstructorDoc[] methods)
{
if (methods == null) return null;
@@ -367,6 +370,7 @@ public class Converter
}
private static Cache mMethods = new Cache()
{
@Override
protected Object make(Object o)
{
if (o instanceof AnnotationTypeElementDoc) {
@@ -374,7 +378,7 @@ public class Converter
MethodInfo result = new MethodInfo(
m.getRawCommentText(),
Converter.convertTypes(m.typeParameters()),
m.name(), m.signature(),
m.name(), m.signature(),
Converter.obtainClass(m.containingClass()),
Converter.obtainClass(m.containingClass()),
m.isPublic(), m.isProtected(),
@@ -399,7 +403,7 @@ public class Converter
MethodInfo result = new MethodInfo(
m.getRawCommentText(),
Converter.convertTypes(m.typeParameters()),
m.name(), m.signature(),
m.name(), m.signature(),
Converter.obtainClass(m.containingClass()),
Converter.obtainClass(m.containingClass()),
m.isPublic(), m.isProtected(),
@@ -424,7 +428,7 @@ public class Converter
MethodInfo result = new MethodInfo(
m.getRawCommentText(),
Converter.convertTypes(m.typeParameters()),
m.name(), m.signature(),
m.name(), m.signature(),
Converter.obtainClass(m.containingClass()),
Converter.obtainClass(m.containingClass()),
m.isPublic(), m.isProtected(),
@@ -472,6 +476,7 @@ public class Converter
}
private static Cache mFields = new Cache()
{
@Override
protected Object make(Object o)
{
FieldDoc f = (FieldDoc)o;
@@ -496,6 +501,7 @@ public class Converter
}
private static Cache mPackagees = new Cache()
{
@Override
protected Object make(Object o)
{
PackageDoc p = (PackageDoc)o;
@@ -510,7 +516,8 @@ public class Converter
}
private static Cache mTypes = new Cache()
{
protected Object make(Object o)
@Override
protected Object make(Object o)
{
Type t = (Type)o;
String simpleTypeName;
@@ -524,6 +531,7 @@ public class Converter
Converter.obtainClass(t.asClassDoc()));
return ti;
}
@Override
protected void made(Object o, Object r)
{
Type t = (Type)o;
@@ -545,8 +553,9 @@ public class Converter
Converter.convertTypes(t.asWildcardType().extendsBounds()));
}
}
@Override
protected Object keyFor(Object o)
{
{
Type t = (Type)o;
String keyString = o.getClass().getName() + "/" + o.toString() + "/";
if (t.asParameterizedType() != null){
@@ -584,13 +593,13 @@ public class Converter
}else{
keyString += "NoWildCardType//";
}
return keyString;
}
};
private static MemberInfo obtainMember(MemberDoc o)
@@ -599,6 +608,7 @@ public class Converter
}
private static Cache mMembers = new Cache()
{
@Override
protected Object make(Object o)
{
if (o instanceof MethodDoc) {
@@ -633,6 +643,7 @@ public class Converter
}
private static Cache mAnnotationInstances = new Cache()
{
@Override
protected Object make(Object o)
{
AnnotationDesc a = (AnnotationDesc)o;

View File

@@ -40,7 +40,7 @@ public class DroidDoc
private static final int TYPE_WIDGET = 1;
private static final int TYPE_LAYOUT = 2;
private static final int TYPE_LAYOUT_PARAM = 3;
public static final int SHOW_PUBLIC = 0x00000001;
public static final int SHOW_PROTECTED = 0x00000003;
public static final int SHOW_PACKAGE = 0x00000007;
@@ -84,7 +84,7 @@ public class DroidDoc
}
return false;
}
public static boolean start(RootDoc r)
{
String keepListFile = null;
@@ -95,6 +95,7 @@ public class DroidDoc
String stubsDir = null;
//Create the dependency graph for the stubs directory
boolean apiXML = false;
boolean noDocs = false;
String apiFile = null;
String debugStubsFile = "";
HashSet<String> stubPackages = null;
@@ -187,6 +188,9 @@ public class DroidDoc
apiXML = true;
apiFile = a[1];
}
else if (a[0].equals("-nodocs")) {
noDocs = true;
}
else if (a[0].equals("-since")) {
sinceTagger.addVersion(a[1], a[2]);
}
@@ -200,62 +204,70 @@ public class DroidDoc
// Set up the data structures
Converter.makeInfo(r);
// Files for proofreading
if (proofreadFile != null) {
Proofread.initProofread(proofreadFile);
if (!noDocs) {
long startTime = System.nanoTime();
// Apply @since tags from the XML file
sinceTagger.tagAll(Converter.rootClasses());
// Files for proofreading
if (proofreadFile != null) {
Proofread.initProofread(proofreadFile);
}
if (todoFile != null) {
TodoFile.writeTodoFile(todoFile);
}
// HTML Pages
if (ClearPage.htmlDir != null) {
writeHTMLPages();
}
// Navigation tree
NavTree.writeNavTree(javadocDir);
// Packages Pages
writePackages(javadocDir
+ (ClearPage.htmlDir!=null
? "packages" + htmlExtension
: "index" + htmlExtension));
// Classes
writeClassLists();
writeClasses();
writeHierarchy();
// writeKeywords();
// Lists for JavaScript
writeLists();
if (keepListFile != null) {
writeKeepList(keepListFile);
}
// Sample Code
for (SampleCode sc: sampleCodes) {
sc.write();
}
// Index page
writeIndex();
Proofread.finishProofread(proofreadFile);
if (sdkValuePath != null) {
writeSdkValues(sdkValuePath);
}
long time = System.nanoTime() - startTime;
System.out.println("DroidDoc took " + (time / 1000000000) + " sec. to write docs to "
+ ClearPage.outputDir);
}
if (todoFile != null) {
TodoFile.writeTodoFile(todoFile);
}
// Apply @since tags from the XML file
sinceTagger.tagAll(Converter.rootClasses());
// HTML Pages
if (ClearPage.htmlDir != null) {
writeHTMLPages();
}
// Navigation tree
NavTree.writeNavTree(javadocDir);
// Packages Pages
writePackages(javadocDir
+ (ClearPage.htmlDir!=null
? "packages" + htmlExtension
: "index" + htmlExtension));
// Classes
writeClassLists();
writeClasses();
writeHierarchy();
// writeKeywords();
// Lists for JavaScript
writeLists();
if (keepListFile != null) {
writeKeepList(keepListFile);
}
// Sample Code
for (SampleCode sc: sampleCodes) {
sc.write();
}
// Index page
writeIndex();
Proofread.finishProofread(proofreadFile);
// Stubs
if (stubsDir != null) {
Stubs.writeStubs(stubsDir, apiXML, apiFile, stubPackages);
}
if (sdkValuePath != null) {
writeSdkValues(sdkValuePath);
}
Errors.printErrors();
return !Errors.hadError;
}
@@ -401,6 +413,9 @@ public class DroidDoc
if (option.equals("-apixml")) {
return 2;
}
if (option.equals("-nodocs")) {
return 1;
}
if (option.equals("-since")) {
return 3;
}
@@ -777,7 +792,7 @@ public class DroidDoc
data.setValue("package.since", pkg.getSince());
data.setValue("package.descr", "...description...");
makeClassListHDF(data, "package.interfaces",
makeClassListHDF(data, "package.interfaces",
ClassInfo.sortByName(pkg.interfaces()));
makeClassListHDF(data, "package.classes",
ClassInfo.sortByName(pkg.ordinaryClasses()));
@@ -871,7 +886,7 @@ public class DroidDoc
HDF data = makeHDF();
Collections.sort(keywords);
int i=0;
for (KeywordEntry entry: keywords) {
String base = "keywords." + entry.firstChar() + "." + i;
@@ -964,10 +979,11 @@ public class DroidDoc
}
/**
* Returns true if the given element has an @hide annotation.
* Returns true if the given element has an @hide or @pending annotation.
*/
private static boolean hasHideAnnotation(Doc doc) {
return doc.getRawCommentText().indexOf("@hide") != -1;
String comment = doc.getRawCommentText();
return comment.indexOf("@hide") != -1 || comment.indexOf("@pending") != -1;
}
/**
@@ -1059,7 +1075,7 @@ public class DroidDoc
if (methodName.equals("getRawCommentText")) {
return filterComment((String) method.invoke(target, args));
}
// escape "&" in disjunctive types.
if (proxy instanceof Type && methodName.equals("toString")) {
return ((String) method.invoke(target, args))
@@ -1114,7 +1130,7 @@ public class DroidDoc
throw new RuntimeException("invalid scope for object " + scoped);
}
}
/**
* Collect the values used by the Dev tools and write them in files packaged with the SDK
* @param output the ouput directory for the files.
@@ -1124,16 +1140,16 @@ public class DroidDoc
ArrayList<String> broadcastActions = new ArrayList<String>();
ArrayList<String> serviceActions = new ArrayList<String>();
ArrayList<String> categories = new ArrayList<String>();
ArrayList<ClassInfo> layouts = new ArrayList<ClassInfo>();
ArrayList<ClassInfo> widgets = new ArrayList<ClassInfo>();
ArrayList<ClassInfo> layoutParams = new ArrayList<ClassInfo>();
ClassInfo[] classes = Converter.allClasses();
// Go through all the fields of all the classes, looking SDK stuff.
for (ClassInfo clazz : classes) {
// first check constant fields for the SdkConstant annotation.
FieldInfo[] fields = clazz.allSelfFields();
for (FieldInfo field : fields) {
@@ -1162,7 +1178,7 @@ public class DroidDoc
}
}
}
// Now check the class for @Widget or if its in the android.widget package
// (unless the class is hidden or abstract, or non public)
if (clazz.isHidden() == false && clazz.isPublic() && clazz.isAbstract() == false) {
@@ -1181,7 +1197,7 @@ public class DroidDoc
}
}
}
if (annotated == false) {
// lets check if this is inside android.widget
PackageInfo pckg = clazz.containingPackage();
@@ -1221,7 +1237,7 @@ public class DroidDoc
Collections.sort(categories);
writeValues(output + "/categories.txt", categories);
// before writing the list of classes, we do some checks, to make sure the layout params
// are enclosed by a layout class (and not one that has been declared as a widget)
for (int i = 0 ; i < layoutParams.size();) {
@@ -1233,10 +1249,10 @@ public class DroidDoc
i++;
}
}
writeClasses(output + "/widgets.txt", widgets, layouts, layoutParams);
}
/**
* Writes a list of values into a text files.
* @param pathname the absolute os path of the output file.
@@ -1248,7 +1264,7 @@ public class DroidDoc
try {
fw = new FileWriter(pathname, false);
bw = new BufferedWriter(fw);
for (String value : values) {
bw.append(value).append('\n');
}
@@ -1282,7 +1298,7 @@ public class DroidDoc
try {
fw = new FileWriter(pathname, false);
bw = new BufferedWriter(fw);
// write the 3 types of classes.
for (ClassInfo clazz : widgets) {
writeClass(bw, clazz, 'W');
@@ -1325,7 +1341,7 @@ public class DroidDoc
}
writer.append('\n');
}
/**
* Checks the inheritance of {@link ClassInfo} objects. This method return
* <ul>
@@ -1333,7 +1349,7 @@ public class DroidDoc
* <li>{@link #TYPE_WIDGET}: if the class extends <code>android.view.View</code></li>
* <li>{@link #TYPE_LAYOUT_PARAM}: if the class extends <code>android.view.ViewGroup$LayoutParams</code></li>
* <li>{@link #TYPE_NONE}: in all other cases</li>
* </ul>
* </ul>
* @param clazz the {@link ClassInfo} to check.
*/
private static int checkInheritance(ClassInfo clazz) {
@@ -1344,12 +1360,12 @@ public class DroidDoc
} else if ("android.view.ViewGroup.LayoutParams".equals(clazz.qualifiedName())) {
return TYPE_LAYOUT_PARAM;
}
ClassInfo parent = clazz.superclass();
if (parent != null) {
return checkInheritance(parent);
}
return TYPE_NONE;
}
}

View File

@@ -41,6 +41,7 @@ public class Errors
return this.msg.compareTo(that.msg);
}
@Override
public String toString() {
String whereText = this.pos == null ? "unknown: " : this.pos.toString() + ':';
return whereText + this.msg;

View File

@@ -26,7 +26,7 @@ public class FieldInfo extends MemberInfo
return a.name().compareTo(b.name());
}
};
public FieldInfo(String name, ClassInfo containingClass, ClassInfo realContainingClass,
boolean isPublic, boolean isProtected,
boolean isPackagePrivate, boolean isPrivate,
@@ -92,7 +92,7 @@ public class FieldInfo extends MemberInfo
{
return constantLiteralValue(mConstantValue);
}
public boolean isDeprecated() {
boolean deprecated = false;
if (!mDeprecatedKnown) {
@@ -124,7 +124,7 @@ public class FieldInfo extends MemberInfo
if (val instanceof Boolean
|| val instanceof Byte
|| val instanceof Short
|| val instanceof Integer)
|| val instanceof Integer)
{
str = val.toString();
}
@@ -291,6 +291,7 @@ public class FieldInfo extends MemberInfo
}
}
@Override
public boolean isExecutable()
{
return false;

View File

@@ -115,6 +115,7 @@ public abstract class MemberInfo extends DocInfo implements Comparable, Scoped
return mIsSynthetic;
}
@Override
public ContainerInfo parent()
{
return mContainingClass;
@@ -130,7 +131,7 @@ public abstract class MemberInfo extends DocInfo implements Comparable, Scoped
{
return mKind;
}
public AnnotationInstanceInfo[] annotations()
{
return mAnnotations;

View File

@@ -25,9 +25,9 @@ public class MethodInfo extends MemberInfo
return a.name().compareTo(b.name());
}
};
private class InlineTags implements InheritedTags
{
{
public TagInfo[] tags()
{
return comment().tags();
@@ -42,7 +42,7 @@ public class MethodInfo extends MemberInfo
}
}
}
private static void addInterfaces(ClassInfo[] ifaces, ArrayList<ClassInfo> queue)
{
for (ClassInfo i: ifaces) {
@@ -79,7 +79,7 @@ public class MethodInfo extends MemberInfo
}
return null;
}
private static void addRealInterfaces(ClassInfo[] ifaces, ArrayList<ClassInfo> queue)
{
for (ClassInfo i: ifaces) {
@@ -92,7 +92,7 @@ public class MethodInfo extends MemberInfo
addInterfaces(i.realInterfaces(), queue);
}
}
public MethodInfo findRealOverriddenMethod(String name, String signature, HashSet notStrippable) {
if (mReturnType == null) {
// ctor
@@ -103,7 +103,7 @@ public class MethodInfo extends MemberInfo
}
ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
if (containingClass().realSuperclass() != null &&
if (containingClass().realSuperclass() != null &&
containingClass().realSuperclass().isAbstract()) {
queue.add(containingClass());
}
@@ -121,7 +121,7 @@ public class MethodInfo extends MemberInfo
}
return null;
}
public MethodInfo findSuperclassImplementation(HashSet notStrippable) {
if (mReturnType == null) {
// ctor
@@ -138,7 +138,7 @@ public class MethodInfo extends MemberInfo
}
ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
if (containingClass().realSuperclass() != null &&
if (containingClass().realSuperclass() != null &&
containingClass().realSuperclass().isAbstract()) {
queue.add(containingClass());
}
@@ -154,7 +154,7 @@ public class MethodInfo extends MemberInfo
}
return null;
}
public ClassInfo findRealOverriddenClass(String name, String signature) {
if (mReturnType == null) {
// ctor
@@ -165,7 +165,7 @@ public class MethodInfo extends MemberInfo
}
ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
if (containingClass().realSuperclass() != null &&
if (containingClass().realSuperclass() != null &&
containingClass().realSuperclass().isAbstract()) {
queue.add(containingClass());
}
@@ -199,7 +199,7 @@ public class MethodInfo extends MemberInfo
}
}
}
private class ReturnTags implements InheritedTags {
public TagInfo[] tags() {
return comment().returnTags();
@@ -213,7 +213,7 @@ public class MethodInfo extends MemberInfo
}
}
}
public boolean isDeprecated() {
boolean deprecated = false;
if (!mDeprecatedKnown) {
@@ -237,7 +237,7 @@ public class MethodInfo extends MemberInfo
}
return mIsDeprecated;
}
public TypeInfo[] getTypeParameters(){
return mTypeParameters;
}
@@ -274,7 +274,7 @@ public class MethodInfo extends MemberInfo
// The underlying MethodDoc for an interface's declared methods winds up being marked
// non-abstract. Correct that here by looking at the immediate-parent class, and marking
// this method abstract if it is an unimplemented interface method.
// this method abstract if it is an unimplemented interface method.
if (containingClass.isInterface()) {
isAbstract = true;
}
@@ -448,7 +448,7 @@ public class MethodInfo extends MemberInfo
+ tag.parameterName() + "'");
}
}
// get our parent's tags to fill in the blanks
MethodInfo overridden = this.findOverriddenMethod(name(), signature());
if (overridden != null) {
@@ -508,7 +508,7 @@ public class MethodInfo extends MemberInfo
{
return mParameters;
}
public boolean matchesParams(String[] params, String[] dimensions)
{
@@ -589,6 +589,7 @@ public class MethodInfo extends MemberInfo
return result;
}
@Override
public boolean isExecutable()
{
return true;
@@ -617,21 +618,23 @@ public class MethodInfo extends MemberInfo
{
return mDefaultAnnotationElementValue;
}
public void setVarargs(boolean set){
mIsVarargs = set;
}
public boolean isVarArgs(){
return mIsVarargs;
}
@Override
public String toString(){
return this.name();
}
public void setReason(String reason) {
mReasonOpened = reason;
}
public String getReason() {
return mReasonOpened;
}

View File

@@ -57,11 +57,13 @@ public class PackageInfo extends DocInfo implements ContainerInfo
return s;
}
@Override
public ContainerInfo parent()
{
return null;
}
@Override
public boolean isHidden()
{
return comment().isHidden();

View File

@@ -76,6 +76,7 @@ public class ParamTagInfo extends ParsedTagInfo
return mParameterName;
}
@Override
public void makeHDF(HDF data, String base)
{
data.setValue(base + ".name", parameterName());

View File

@@ -36,7 +36,7 @@ import java.util.regex.Matcher;
* Both tags accept either a filename and an id or just a filename. If no id
* is provided, the entire file is copied. If an id is provided, the lines
* in the given file between the first two lines containing BEGIN_INCLUDE(id)
* and END_INCLUDE(id), for the given id, are copied. The id may be only
* and END_INCLUDE(id), for the given id, are copied. The id may be only
* letters, numbers and underscore (_).
*
* Four examples:
@@ -274,6 +274,7 @@ public class SampleTagInfo extends TagInfo
return result.substring(0);
}
@Override
public void makeHDF(HDF data, String base)
{
data.setValue(base + ".name", name());

View File

@@ -45,6 +45,7 @@ public class SeeTagInfo extends TagInfo
return linkReference().label;
}
@Override
public void makeHDF(HDF data, String base)
{
LinkReference linkRef = linkReference();

View File

@@ -76,6 +76,7 @@ public class SourcePositionInfo implements Comparable
return new SourcePositionInfo(that.file, line, 0);
}
@Override
public String toString()
{
return file + ':' + line;

View File

@@ -249,6 +249,7 @@ public class TypeInfo
}
}
@Override
public String toString(){
String returnString = "";
returnString += "Primitive?: " + mIsPrimitive + " TypeVariable?: " +

View File

@@ -73,9 +73,10 @@ def:custom_masthead() ?>
call:default_search_box() ?><?cs
if:reference ?>
<div id="api-level-toggle">
<label for="apiLevelControl"><a href="<?cs var:toroot ?>guide/appendix/api-levels.html">Filter by API Level</a>: </label>
<select id="apiLevelControl">
<!-- option elements added by buildApiLevelToggle() -->
<input type="checkbox" id="apiLevelCheckbox" onclick="toggleApiLevelSelector(this)" />
<label for="apiLevelCheckbox" class="disabled">Filter by API Level: </label>
<select id="apiLevelSelector">
<!-- option elements added by buildApiLevelSelector() -->
</select>
</div>
<script>
@@ -85,7 +86,7 @@ def:custom_masthead() ?>
if:!last(since) ?>, <?cs /if ?><?cs
/each
?> ];
buildApiLevelToggle();
buildApiLevelSelector();
</script><?cs
/if ?>
</div><!-- headerRight -->

View File

@@ -1,66 +0,0 @@
<ul>
<li><div><a href="<?cs var:toroot ?>index.html">Home</a></div></li>
<li><div><a href="<?cs var:toroot ?>what-is-android.html">What is Android?</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/index.html">Getting Started</a></div>
<ul>
<li><div><a href="<?cs var:toroot ?>intro/installing.html">Installing the SDK</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/upgrading.html">Upgrading the SDK</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/develop-and-debug.html">Developing/Debugging</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/hello-android.html">Hello Android</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/anatomy.html">Anatomy of an App</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/tutorial.html">Notepad Tutorial</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/tools.html">Development Tools</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/appmodel.html">Application Model</a></div></li>
<li><div><a href="<?cs var:toroot ?>intro/lifecycle.html">Application Life Cycle</a></div></li>
</ul>
</li>
<li><div><div><a href="<?cs var:toroot ?>devel/index.html">Developing Applications</a></div>
<ul>
<li><div><a href="<?cs var:toroot ?>devel/implementing-ui.html">Implementing a UI</a></div></li>
<li><div><a href="<?cs var:toroot ?>devel/building-blocks.html">Building Blocks</a></div></li>
<li><div><a href="<?cs var:toroot ?>devel/data.html">Data Storage and Retrieval</a></div></li>
<li><div><a href="<?cs var:toroot ?>devel/security.html">Security Model</a></div></li>
<li><div><a href="<?cs var:toroot ?>devel/resources-i18n.html">Resources and i18n</a></div></li>
</ul>
</li>
<li><div><a href="<?cs var:toroot ?>toolbox/index.html">Developer Toolbox</a></div>
<ul>
<li><div><a href="<?cs var:toroot ?>toolbox/philosophy.html">Design Philosophy</a></div></li>
<li><div><a href="<?cs var:toroot ?>toolbox/custom-components.html">Building Custom Components</a></div></li>
<li><div><a href="<?cs var:toroot ?>toolbox/optional-apis.html">Optional APIs</a></div></li>
</ul>
</li>
<li><div><a href="<?cs var:toroot ?>samples/index.html">Sample Code</a></div>
<ul>
<li><div><a href="<?cs var:toroot ?>samples/ApiDemos/index.html">API Demos</a></div></li>
<li><div><a href="<?cs var:toroot ?>samples/LunarLander/index.html">Lunar Lander</a></div></li>
<li><div><a href="<?cs var:toroot ?>samples/NotePad/index.html">Note Pad</a></div></li>
</ul>
</li>
<li> <a href="<?cs var:toroot ?>reference/index.html"><strong>Reference Information</strong></a>
<ul>
<li><a href="<?cs var:toroot ?>reference/packages.html">Package Index</a></li>
<li><a href="<?cs var:toroot ?>reference/classes.html">Class Index</a></li>
<li><a href="<?cs var:toroot ?>reference/hierarchy.html">Class Hierarchy</a></li>
<li><a href="<?cs var:toroot ?>reference/view-gallery.html">List of Views</a></li>
<li><a href="<?cs var:toroot ?>reference/available-intents.html">List of Intents</a></li>
<li><a href="<?cs var:toroot ?>reference/android/Manifest.permission.html">List of Permissions</a></li>
<li><a href="<?cs var:toroot ?>reference/available-resources.html">List of Resource Types</a></li>
<li><a href="<?cs var:toroot ?>reference/aidl.html">Android IDL</a></li>
<li><a href="<?cs var:toroot ?>reference/glossary.html">Glossary</a></li>
<li><a href="<?cs var:toroot ?>reference/keywords.html">Index</a></li>
</ul>
</li>
<li><div><a href="<?cs var:toroot ?>kb/index.html">FAQs</a></div>
<ul>
<li><div><a href="<?cs var:toroot ?>kb/general.html">General</a></div></li>
<li><div><a href="<?cs var:toroot ?>kb/commontasks.html">Common Tasks</a></div></li>
<li><div><a href="<?cs var:toroot ?>kb/troubleshooting.html">Troubleshooting</a></div></li>
<li><div><a href="<?cs var:toroot ?>kb/licensingandoss.html">Open Source Licensing</a></div></li>
<li><div><a href="<?cs var:toroot ?>kb/framework.html">Application Framework</a></div></li>
<li><div><a href="<?cs var:toroot ?>kb/security.html">Security</a></div></li>
</ul>
</li>
<li><div><a href="<?cs var:toroot ?>roadmap.html">Roadmap</a></div></li>
<li><div><a href="<?cs var:toroot ?>goodies/index.html">Goodies</a></div></li>
</ul>

View File

@@ -5,80 +5,82 @@
elif:home ?>home<?cs
elif:community ?>community<?cs
elif:videos ?>videos<?cs /if ?>">
<li id="home-link"><a href="<?cs var:toroot ?><?cs if:android.whichdoc != "online" ?>offline.html<?cs else ?>index.html<?cs /if ?>">
<li id="home-link"><a href="<?cs var:toroot ?><?cs
if:android.whichdoc != "online" ?>offline.html<?cs
else ?>index.html<?cs /if ?>">
<?cs if:!sdk.redirect ?>
<span class="en">Home</span>
<span class="de">Startseite</span>
<span class="es"></span>
<span class="fr"></span>
<span class="it"></span>
<span class="ja"></span>
<span class="zh-CN"></span>
<span class="zh-TW"></span>
<span style="display:none" class="de">Startseite</span>
<span style="display:none" class="es"></span>
<span style="display:none" class="fr"></span>
<span style="display:none" class="it"></span>
<span style="display:none" class="ja"></span>
<span style="display:none" class="zh-CN"></span>
<span style="display:none" class="zh-TW"></span>
<?cs /if ?>
</a></li>
<li id="sdk-link"><a href="<?cs var:toroot ?>sdk/<?cs var:sdk.current ?>/index.html">
<li id="sdk-link"><a href="<?cs var:toroot ?>sdk/index.html">
<span class="en">SDK</span>
</a></li>
<li id="guide-link"><a href="<?cs var:toroot ?>guide/index.html" onClick="return loadLast('guide')">
<?cs if:!sdk.redirect ?>
<span class="en">Dev Guide</span>
<span class="de">Handbuch</span>
<span class="es">Guía</span>
<span class="fr">Guide</span>
<span class="it">Guida</span>
<span class="ja"></span>
<span class="zh-CN"></span>
<span class="zh-TW"></span>
<span style="display:none" class="de">Handbuch</span>
<span style="display:none" class="es">Guía</span>
<span style="display:none" class="fr">Guide</span>
<span style="display:none" class="it">Guida</span>
<span style="display:none" class="ja"></span>
<span style="display:none" class="zh-CN"></span>
<span style="display:none" class="zh-TW"></span>
<?cs /if ?>
</a></li>
<li id="reference-link"><a href="<?cs var:toroot ?>reference/packages.html" onClick="return loadLast('reference')">
<?cs if:!sdk.redirect ?>
<span class="en">Reference</span>
<span class="de">Referenz</span>
<span class="es">Referencia</span>
<span class="fr">Référence</span>
<span class="it">Riferimento</span>
<span class="ja"></span>
<span class="zh-CN"></span>
<span class="zh-TW"></span>
<span style="display:none" class="de">Referenz</span>
<span style="display:none" class="es">Referencia</span>
<span style="display:none" class="fr">Référence</span>
<span style="display:none" class="it">Riferimento</span>
<span style="display:none" class="ja"></span>
<span style="display:none" class="zh-CN"></span>
<span style="display:none" class="zh-TW"></span>
<?cs /if ?>
</a></li>
<li><a href="http://android-developers.blogspot.com" onClick="return requestAppendHL(this.href)">
<?cs if:!sdk.redirect ?>
<span class="en">Blog</span>
<span class="de"></span>
<span class="es"></span>
<span class="fr"></span>
<span class="it"></span>
<span class="ja"></span>
<span class="zh-CN"></span>
<span class="zh-TW"></span>
<span style="display:none" class="de"></span>
<span style="display:none" class="es"></span>
<span style="display:none" class="fr"></span>
<span style="display:none" class="it"></span>
<span style="display:none" class="ja"></span>
<span style="display:none" class="zh-CN"></span>
<span style="display:none" class="zh-TW"></span>
<?cs /if ?>
</a></li>
<li id="videos-link"><a href="<?cs var:toroot ?>videos/index.html" onClick="return loadLast('videos')">
<?cs if:!sdk.redirect ?>
<span class="en">Videos</span>
<span class="de"></span>
<span class="es"></span>
<span class="fr"></span>
<span class="it"></span>
<span class="ja"></span>
<span class="zh-CN"></span>
<span class="zh-TW"></span>
<span style="display:none" class="de"></span>
<span style="display:none" class="es"></span>
<span style="display:none" class="fr"></span>
<span style="display:none" class="it"></span>
<span style="display:none" class="ja"></span>
<span style="display:none" class="zh-CN"></span>
<span style="display:none" class="zh-TW"></span>
<?cs /if ?>
</a></li>
<li id="community-link"><a href="<?cs var:toroot ?>community/index.html">
<?cs if:!sdk.redirect ?>
<span class="en">Community</span>
<span class="de"></span>
<span class="es">Comunidad</span>
<span class="fr">Communauté</span>
<span class="it"></span>
<span class="ja"></span>
<span class="zh-CN"></span>
<span class="zh-TW"></span>
<span style="display:none" class="de"></span>
<span style="display:none" class="es">Comunidad</span>
<span style="display:none" class="fr">Communauté</span>
<span style="display:none" class="it"></span>
<span style="display:none" class="ja"></span>
<span style="display:none" class="zh-CN"></span>
<span style="display:none" class="zh-TW"></span>
<?cs /if ?>
</a></li>

View File

@@ -33,28 +33,29 @@
<div class="g-unit" id="doc-content" >
<div id="jd-header" class="guide-header" >
<span class="crumb">&nbsp;</span>
<h1><?cs if:android.whichdoc == "online" ?>Download <?cs /if ?><?cs var:page.title ?></h1>
<h1><?cs if:android.whichdoc == "online" ?>Download the <?cs /if ?><?cs var:page.title ?></h1>
</div>
<div id="jd-content">
<p><em><?cs
if:ndk ?><?cs
var:ndk.date ?><?cs
<?cs
if:ndk ?><p><em><?cs
var:ndk.date ?></em></p><?cs
else ?><?cs
var:sdk.date ?><?cs
/if ?></em>
</p>
if:android.whichdoc == "online" ?><p><em><?cs
var:sdk.date ?></em></p><?cs
/if ?><?cs
/if ?>
<?cs if:sdk.not_latest_version ?>
<div class="special">
<p><strong>This is NOT the current Android SDK release.</strong></p>
<p><a href="/sdk/<?cs var:sdk.current ?>/index.html">Download the current Android SDK</a></p>
<p><a href="/sdk/index.html">Download the current Android SDK</a></p>
</div>
<?cs /if ?>
<?cs if:android.whichdoc != "online" && !android.preview ?>
<p>The sections below provide an overview of the SDK package. </p>
<!-- <p>The sections below provide an overview of how to install the SDK package. </p> -->
<?cs else ?>
<?cs if:ndk ?>
@@ -62,10 +63,10 @@
<p>The Android NDK is a companion tool to the Android SDK that lets Android
application developers build performance-critical portions of their apps in
native code. It is designed for use <em>only</em> in conjunction with the
Android SDK, so if you have not already installed the Android 1.5 SDK, please do
so before downloading the NDK. Also, please read <a href="#overview">What is the
Android NDK?</a> to get an understanding of what the NDK offers and whether it
will be useful to you.</p>
Android SDK, so if you have not already installed the latest Android SDK, please
do so before downloading the NDK. Also, please read <a href="#overview">What is
the Android NDK?</a> to get an understanding of what the NDK offers and whether
it will be useful to you.</p>
<p>Select the download package that is appropriate for your development
computer. </p>
@@ -110,16 +111,49 @@ computer. </p>
Android 1.6 and we are pleased to announce the availability of an early look
SDK to give you a head-start on developing applications for it. </p>
<p>The Android 1.6 platform includes a variety of improvements and new
features for users and developers. Additionally, the SDK itself introduces
several new capabilities that enable you to develop applications more
efficiently. See the <a href="features.html">Android 1.6 Highlights</a>
document for a list of highlights.</p>
<?cs /if ?>
<p>The Android <?cs var:sdk.preview.version ?> platform includes a variety of
improvements and new features for users and developers. Additionally, the SDK
itself introduces several new capabilities that enable you to develop
applications more efficiently. See the <a href="features.html">Android <?cs
var:sdk.preview.version ?> Platform Highlights</a> document for a list of
highlights.</p>
<?cs /if ?>
<?cs # end if NDK ... the following is for the SDK ?>
<p>Before downloading, please read the <a href="requirements.html">
System Requirements</a> document. As you start the download, you will also need to review and agree to
the Terms and Conditions that govern the use of the Android SDK. </p>
<div class="toggle-content special">
<p>The Android SDK has changed! If you've worked with the Android SDK before,
you will notice several important differences:</p>
<div class="toggle-content-toggleme" style="display:none">
<ul style="padding-bottom:.0;">
<li style="margin-top:.5em">The SDK downloadable package includes <em>only</em>
the latest version of the Android SDK Tools.</li>
<li>Once you've installed the SDK, you now use the Android SDK and AVD Manager
to download all of the SDK components that you need, such as Android platforms,
SDK add-ons, tools, and documentation. </li>
<li>The new approach is modular &mdash; you can install only the components you
need and update any or all components without affecting other parts of your
development environment.</li>
<li>In short, once you've installed the new SDK, you will not need to download
an SDK package again. Instead, you will use the Android SDK and AVD Manager to
keep your development environment up-to-date. </li>
</ul>
<p style="margin-top:0">If you are currently using the Android 1.6 SDK, you
do not need to install the new SDK, because your existing SDK already
includes the Android SDK and AVD Manager tool. To develop against Android
2.0, for example, you can just download the Android 2.0 platform (and
updated SDK Tools) into your existing SDK. Refer to <a
href="adding-components.html">Adding SDK Components</a>.</p>
</div>
<a href='#' class='toggle-content-button show' onclick="toggleContent(this);return false;">
<span>show more</span><span style='display:none'>show less</span>
</a>
</div>
<p>If you are new to the Android SDK, please read the <a href="#quickstart">Quick Start</a>,
below, for an overview of how to install and set up the SDK.</p>
<table class="download">
<tr>
@@ -156,7 +190,7 @@ the Terms and Conditions that govern the use of the Android SDK. </p>
<tr class="alt-color">
<td>ADT Plugin for Eclipse <?cs var:adt.zip_version ?></td>
<td>
<a href="<?cs var:toroot ?>sdk/download.html?v=<?cs var:adt.zip_download ?>"><?cs var:adt.zip_download ?></a>
<a href="http://dl.google.com/android/<?cs var:adt.zip_download ?>"><?cs var:adt.zip_download ?></a>
</td>
<td><?cs var:adt.zip_bytes ?> bytes</td>
<td><?cs var:adt.zip_checksum ?></td>
@@ -170,14 +204,17 @@ the Terms and Conditions that govern the use of the Android SDK. </p>
<?cs if:android.whichdoc != "online" && sdk.preview ?>
<p>Welcome developers! The next release of the Android platform will be
Android 1.6 and we are pleased to announce the availability of an early look SDK
to give you a head-start on developing applications for it. </p>
Android <?cs var:sdk.preview.version ?> and we are pleased to announce the
availability of an early look SDK to give you a head-start on developing
applications for it. </p>
<p>The Android 1.6 platform includes a variety of improvements and new features
for users and developers. Additionally, the SDK itself introduces several new
capabilities that enable you to develop applications more efficiently.
See the <a href="http://developer.android.com/sdk/preview/features.html">
Android 1.6 Highlights</a> document for a list of highlights.</p>
<p>The Android <?cs var:sdk.preview.version ?> platform includes a variety of
improvements and new features for users and developers. Additionally, the SDK
itself introduces several new capabilities that enable you to develop
applications more efficiently. See the <a
href="http://developer.android.com/sdk/preview/features.html">Android
<?cs var:sdk.preview.version ?> Highlights</a> document for a list of
highlights.</p>
<?cs /if ?>
<?cs call:tag_list(root.descr) ?>

View File

@@ -48,11 +48,12 @@ a:visited code {
}
input, select,
textarea, option {
textarea, option, label {
font-family:inherit;
font-size:inherit;
padding:0;
margin:0;
vertical-align:middle;
}
option {
@@ -81,6 +82,7 @@ pre {
padding:10px;
margin:0 0 1em 1em;
overflow:auto;
line-height:inherit; /* fixes vertical scrolling in webkit */
}
h1,h2,h3,h4,h5 {
@@ -194,7 +196,7 @@ hr.blue {
height: 114px;
position:relative;
z-index:100;
min-width:576px;
min-width:675px; /* min width for the tabs, before they wrap */
padding:0 10px;
border-bottom:3px solid #94b922;
}

View File

@@ -339,9 +339,12 @@ links to summary tables) */
}
#api-level-toggle {
float:right;
padding:0 10px;
font-size:11px;
float:right;
}
#api-level-toggle label.disabled {
color:#999;
}
@@ -660,7 +663,27 @@ h5.jd-tagtitle {
div.special {
padding: .5em 1em 1em 1em;
margin: 0 0 1em;
background-color: #ddf0f2;
background-color: #DAF3FC;
border:1px solid #d3ecf5;
border-radius:5px;
-moz-border-radius:5px;
-webkit-border-radius:5px;
}
.toggle-content-toggleme {
display:none;
}
.toggle-content-button {
font-size:.9em;
line-height:.9em;
text-decoration:none;
position:relative;
top:5px;
}
.toggle-content-button:hover {
text-decoration:underline;
}
div.special p {
@@ -751,6 +774,8 @@ ul.no-style {
font-weight: bold;
color: red;
text-decoration: none;
vertical-align:top;
line-height:.9em;
}
pre.classic {

View File

@@ -10,6 +10,7 @@ var NAV_PREF_PANELS = "panels";
var nav_pref;
var toRoot;
var isMobile = false; // true if mobile, so we can adjust some layout
var isIE6 = false; // true if IE6
function addLoadEvent(newfun) {
var current = window.onload;
@@ -24,17 +25,24 @@ function addLoadEvent(newfun) {
}
var agent = navigator['userAgent'];
// If a mobile phone, set flag and do mobile setup
if ((agent.indexOf("Mobile") != -1) ||
(agent.indexOf("BlackBerry") != -1) ||
(agent.indexOf("Mini") != -1)) {
isMobile = true;
addLoadEvent(mobileSetup);
// If not a mobile browser, set the onresize event for IE6, and others
} else if (agent.indexOf("MSIE 6.0") != -1) {
isIE6 = true;
addLoadEvent(function() {
window.onresize = resizeAll;
});
} else {
addLoadEvent(function() {
window.onresize = resizeHeight;
});
}
addLoadEvent(function() {
window.onresize = resizeAll;
});
function mobileSetup() {
$("body").css({'overflow':'auto'});
$("html").css({'overflow':'auto'});
@@ -50,7 +58,7 @@ addLoadEvent( function() {
var lists = document.createElement("script");
lists.setAttribute("type","text/javascript");
lists.setAttribute("src", toRoot+"reference/lists.js");
$("head").append($(lists));
document.getElementsByTagName("head")[0].appendChild(lists);
} );
function setToRoot(root) {
@@ -60,8 +68,12 @@ function setToRoot(root) {
function restoreWidth(navWidth) {
var windowWidth = $(window).width() + "px";
content.css({marginLeft:parseInt(navWidth) + 6 + "px", //account for 6px-wide handle-bar
width:parseInt(windowWidth) - parseInt(navWidth) - 6 + "px"});
content.css({marginLeft:parseInt(navWidth) + 6 + "px"}); //account for 6px-wide handle-bar
if (isIE6) {
content.css({width:parseInt(windowWidth) - parseInt(navWidth) - 6 + "px"}); // necessary in order for scrollbars to be visible
}
sidenav.css({width:navWidth});
resizePackagesNav.css({width:navWidth});
classesNav.css({width:navWidth});
@@ -99,14 +111,14 @@ function readCookie(cookie) {
}
function writeCookie(cookie, val, section, expiration) {
if (!val) return;
if (val==undefined) return;
section = section == null ? "_" : "_"+section+"_";
if (expiration == null) {
var date = new Date();
date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week
expiration = date.toGMTString();
}
document.cookie = cookie_namespace+section+cookie+"="+val+"; expires="+expiration+"; path=/";
document.cookie = cookie_namespace + section + cookie + "=" + val + "; expires=" + expiration+"; path=/";
}
function init() {
@@ -124,7 +136,7 @@ function init() {
}
if (!isMobile) {
$("#resize-packages-nav").resizable({handles: "s", resize: function(e, ui) { resizeHeight(); } });
$("#resize-packages-nav").resizable({handles: "s", resize: function(e, ui) { resizePackagesHeight(); } });
$(".side-nav-resizable").resizable({handles: "e", resize: function(e, ui) { resizeWidth(); } });
var cookieWidth = readCookie(cookiePath+'width');
var cookieHeight = readCookie(cookiePath+'height');
@@ -156,8 +168,8 @@ function highlightNav(fullPageName) {
var htmlPos = fullPageName.lastIndexOf(".html", fullPageName.length);
var pathPageName = fullPageName.slice(firstSlashPos, htmlPos + 5);
var link = $("#devdoc-nav a[href$='"+ pathPageName+"']");
if ((link.length == 0) && ((fullPageName.indexOf("/guide/") != -1) || (fullPageName.indexOf("/sdk/") != -1))) {
// if there's no match, then let's backstep through the directory until we find an index.html page that matches our ancestor directories (only for dev guide and sdk)
if ((link.length == 0) && (fullPageName.indexOf("/guide/") != -1)) {
// if there's no match, then let's backstep through the directory until we find an index.html page that matches our ancestor directories (only for dev guide)
lastBackstep = pathPageName.lastIndexOf("/");
while (link.length == 0) {
backstepDirectory = pathPageName.lastIndexOf("/", lastBackstep);
@@ -174,23 +186,46 @@ function highlightNav(fullPageName) {
}
}
function resizeHeight() {
/* Resize the height of the nav panels in the reference,
* and save the new size to a cookie */
function resizePackagesHeight() {
var windowHeight = ($(window).height() - HEADER_HEIGHT);
var swapperHeight = windowHeight - 13;
$("#swapper").css({height:swapperHeight + "px"});
sidenav.css({height:windowHeight + "px"});
content.css({height:windowHeight + "px"});
var swapperHeight = windowHeight - 13; // move 13px for swapper link at the bottom
resizePackagesNav.css({maxHeight:swapperHeight + "px"});
classesNav.css({height:swapperHeight - parseInt(resizePackagesNav.css("height")) + "px"});
$("#swapper").css({height:swapperHeight + "px"});
$("#packages-nav").css({height:parseInt(resizePackagesNav.css("height")) - 6 + "px"}); //move 6px for handle
devdocNav.css({height:sidenav.css("height")});
$("#nav-tree").css({height:swapperHeight + "px"});
var basePath = getBaseUri(location.pathname);
var section = basePath.substring(1,basePath.indexOf("/",1));
writeCookie("height", resizePackagesNav.css("height"), section, null);
}
/* Resize the height of the side-nav and doc-content divs,
* which creates the frame effect */
function resizeHeight() {
// Get the window height and always resize the doc-content and side-nav divs
var windowHeight = ($(window).height() - HEADER_HEIGHT);
content.css({height:windowHeight + "px"});
sidenav.css({height:windowHeight + "px"});
var href = location.href;
// If in the reference docs, also resize the "swapper", "classes-nav", and "nav-tree" divs
if (href.indexOf("/reference/") != -1) {
var swapperHeight = windowHeight - 13;
$("#swapper").css({height:swapperHeight + "px"});
$("#classes-nav").css({height:swapperHeight - parseInt(resizePackagesNav.css("height")) + "px"});
$("#nav-tree").css({height:swapperHeight + "px"});
// If in the dev guide docs, also resize the "devdoc-nav" div
} else if (href.indexOf("/guide/") != -1) {
$("#devdoc-nav").css({height:sidenav.css("height")});
}
}
/* Resize the width of the "side-nav" and the left margin of the "doc-content" div,
* which creates the resizable side bar */
function resizeWidth() {
var windowWidth = $(window).width() + "px";
if (sidenav.length) {
@@ -198,24 +233,27 @@ function resizeWidth() {
} else {
var sidenavWidth = 0;
}
content.css({marginLeft:parseInt(sidenavWidth) + 6 + "px", //account for 6px-wide handle-bar
width:parseInt(windowWidth) - parseInt(sidenavWidth) - 6 + "px"});
content.css({marginLeft:parseInt(sidenavWidth) + 6 + "px"}); //account for 6px-wide handle-bar
if (isIE6) {
content.css({width:parseInt(windowWidth) - parseInt(sidenavWidth) - 6 + "px"}); // necessary in order to for scrollbars to be visible
}
resizePackagesNav.css({width:sidenavWidth});
classesNav.css({width:sidenavWidth});
$("#packages-nav").css({width:sidenavWidth});
var basePath = getBaseUri(location.pathname);
var section = basePath.substring(1,basePath.indexOf("/",1));
writeCookie("width", sidenavWidth, section, null);
}
/* For IE6 only,
* because it can't properly perform auto width for "doc-content" div,
* avoiding this for all browsers provides better performance */
function resizeAll() {
if (!isMobile) {
resizeHeight();
if ($(".side-nav-resizable").length) {
resizeWidth();
}
}
resizeHeight();
resizeWidth();
}
function getBaseUri(uri) {
@@ -448,3 +486,18 @@ function getLangPref() {
}
return (lang != 0) ? lang : 'en';
}
function toggleContent(obj) {
var button = $(obj);
var div = $(obj.parentNode);
var toggleMe = $(".toggle-content-toggleme",div);
if (button.hasClass("show")) {
toggleMe.slideDown();
button.removeClass("show").addClass("hide");
} else {
toggleMe.slideUp();
button.removeClass("hide").addClass("show");
}
$("span", button).toggle();
}

View File

@@ -1,48 +1,78 @@
/* API LEVEL TOGGLE */
addLoadEvent(changeApiLevel);
var API_LEVEL_ENABLED_COOKIE = "api_level_enabled";
var API_LEVEL_COOKIE = "api_level";
var minLevel = 1;
function buildApiLevelToggle() {
var maxLevel = SINCE_DATA.length;
var userApiLevel = readCookie(API_LEVEL_COOKIE);
if (userApiLevel != 0) {
selectedLevel = userApiLevel;
} else {
selectedLevel = maxLevel;
}
function toggleApiLevelSelector(checkbox) {
var date = new Date();
date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
var expiration = date.toGMTString();
if (checkbox.checked) {
$("#apiLevelSelector").removeAttr("disabled");
$("#api-level-toggle label").removeClass("disabled");
writeCookie(API_LEVEL_ENABLED_COOKIE, 1, null, expiration);
} else {
$("#apiLevelSelector").attr("disabled","disabled");
$("#api-level-toggle label").addClass("disabled");
writeCookie(API_LEVEL_ENABLED_COOKIE, 0, null, expiration);
}
changeApiLevel();
}
function buildApiLevelSelector() {
var maxLevel = SINCE_DATA.length;
var userApiLevelEnabled = readCookie(API_LEVEL_ENABLED_COOKIE);
var userApiLevel = readCookie(API_LEVEL_COOKIE);
userApiLevel = userApiLevel == 0 ? maxLevel : userApiLevel; // If there's no cookie (zero), use the max by default
if (userApiLevelEnabled == 0) {
$("#apiLevelSelector").attr("disabled","disabled");
} else {
$("#apiLevelCheckbox").attr("checked","checked");
$("#api-level-toggle label").removeClass("disabled");
}
minLevel = $("body").attr("class");
var select = $("#apiLevelControl").html("").change(changeApiLevel);
for (var i = maxLevel-1; i >= 0; i--) {
var option = $("<option />").attr("value",""+SINCE_DATA[i]).append(""+SINCE_DATA[i]);
// if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
select.append(option);
}
var select = $("#apiLevelSelector").html("").change(changeApiLevel);
for (var i = maxLevel-1; i >= 0; i--) {
var option = $("<option />").attr("value",""+SINCE_DATA[i]).append(""+SINCE_DATA[i]);
// if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
select.append(option);
}
// get the DOM element and use setAttribute cuz IE6 fails when using jquery .attr('selected',true)
var selectedLevelItem = $("#apiLevelControl option[value='"+selectedLevel+"']").get(0);
var selectedLevelItem = $("#apiLevelSelector option[value='"+userApiLevel+"']").get(0);
selectedLevelItem.setAttribute('selected',true);
}
function changeApiLevel() {
var selectedLevel = $("#apiLevelControl option:selected").val();
toggleVisisbleApis(selectedLevel, "body");
var maxLevel = SINCE_DATA.length;
var userApiLevelEnabled = readCookie(API_LEVEL_ENABLED_COOKIE);
var selectedLevel = maxLevel;
if (userApiLevelEnabled == 0) {
toggleVisisbleApis(selectedLevel, "body");
} else {
selectedLevel = $("#apiLevelSelector option:selected").val();
toggleVisisbleApis(selectedLevel, "body");
var date = new Date();
date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
var expiration = date.toGMTString();
writeCookie(API_LEVEL_COOKIE, selectedLevel, null, expiration);
}
var date = new Date();
date.setTime(date.getTime()+(50*365*24*60*60*1000)); // keep this for 50 years
writeCookie(API_LEVEL_COOKIE, selectedLevel, null, date);
if (selectedLevel < minLevel) {
var thing = ($("#jd-header").html().indexOf("package") != -1) ? "package" : "class";
$("#naMessage").show().html("<div><p><strong>This " + thing + " is not available with API Level " + selectedLevel + ".</strong></p>"
if (selectedLevel < minLevel) {
var thing = ($("#jd-header").html().indexOf("package") != -1) ? "package" : "class";
$("#naMessage").show().html("<div><p><strong>This " + thing + " is not available with API Level " + selectedLevel + ".</strong></p>"
+ "<p>To use this " + thing + ", your application must specify API Level " + minLevel + " or higher in its manifest "
+ "and be compiled against a version of the Android library that supports an equal or higher API Level. To reveal this "
+ "document, change the value of the API Level filter above.</p>"
+ "<p><a href='" +toRoot+ "guide/appendix/api-levels.html'>What is the API Level?</a></p></div>");
} else {
} else {
$("#naMessage").hide();
}
}
@@ -156,7 +186,7 @@ function expand_node(me, node)
node.expanded = true;
// perform api level toggling because new nodes are new to the DOM
var selectedLevel = $("#apiLevelControl option:selected").val();
var selectedLevel = $("#apiLevelSelector option:selected").val();
toggleVisisbleApis(selectedLevel, "#side-nav");
}
}
@@ -228,7 +258,7 @@ function init_default_navtree(toroot) {
init_navtree("nav-tree", toroot, NAVTREE_DATA);
// perform api level toggling because because the whole tree is new to the DOM
var selectedLevel = $("#apiLevelControl option:selected").val();
var selectedLevel = $("#apiLevelSelector option:selected").val();
toggleVisisbleApis(selectedLevel, "#side-nav");
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -168,6 +168,6 @@ function search_focus_changed(obj, focused)
function submit_search() {
var query = document.getElementById('search_autocomplete').value;
document.location = toRoot + 'search.html#q=' + query; // toRoot is initialized in android-developer-docs.js
document.location = toRoot + 'search.html#q=' + query + '&t=0';
return false;
}

View File

@@ -188,7 +188,7 @@ Summary:
<?cs # summary macros ?>
<?cs def:write_method_summary(methods) ?>
<?cs def:write_method_summary(methods, included) ?>
<?cs set:count = #1 ?>
<?cs each:method = methods ?>
<?cs # The apilevel-N class MUST BE LAST in the sequence of class names ?>
@@ -202,8 +202,7 @@ Summary:
<?cs call:type_link(method.returnType) ?></nobr>
</td>
<td class="jd-linkcol" width="100%"><nobr>
<span class="sympad"><a href="<?cs var:toroot ?><?cs var:method.href ?>">
<?cs var:method.name ?></a></span>(<?cs call:parameter_list(method.params) ?>)</nobr>
<span class="sympad"><?cs call:cond_link(method.name, toroot, method.href, included) ?></span>(<?cs call:parameter_list(method.params) ?>)</nobr>
<?cs if:subcount(method.shortDescr) || subcount(method.deprecated) ?>
<div class="jd-descrdiv"><?cs call:short_descr(method) ?></div>
<?cs /if ?>
@@ -212,7 +211,7 @@ Summary:
<?cs /each ?>
<?cs /def ?>
<?cs def:write_field_summary(fields) ?>
<?cs def:write_field_summary(fields, included) ?>
<?cs set:count = #1 ?>
<?cs each:field=fields ?>
<tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:field.since ?>" >
@@ -221,26 +220,26 @@ Summary:
<?cs var:field.static ?>
<?cs var:field.final ?>
<?cs call:type_link(field.type) ?></nobr></td>
<td class="jd-linkcol"><a href="<?cs var:toroot ?><?cs var:field.href ?>"><?cs var:field.name ?></a></td>
<td class="jd-linkcol"><?cs call:cond_link(field.name, toroot, field.href, included) ?></td>
<td class="jd-descrcol" width="100%"><?cs call:short_descr(field) ?></td>
</tr>
<?cs set:count = count + #1 ?>
<?cs /each ?>
<?cs /def ?>
<?cs def:write_constant_summary(fields) ?>
<?cs def:write_constant_summary(fields, included) ?>
<?cs set:count = #1 ?>
<?cs each:field=fields ?>
<tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:field.since ?>" >
<td class="jd-typecol"><?cs call:type_link(field.type) ?></td>
<td class="jd-linkcol"><a href="<?cs var:toroot ?><?cs var:field.href ?>"><?cs var:field.name ?></a></td>
<td class="jd-linkcol"><?cs call:cond_link(field.name, toroot, field.href, included) ?></td>
<td class="jd-descrcol" width="100%"><?cs call:short_descr(field) ?></td>
</tr>
<?cs set:count = count + #1 ?>
<?cs /each ?>
<?cs /def ?>
<?cs def:write_attr_summary(attrs) ?>
<?cs def:write_attr_summary(attrs, included) ?>
<?cs set:count = #1 ?>
<tr>
<td><nobr><em>Attribute Name</em></nobr></td>
@@ -249,9 +248,9 @@ Summary:
</tr>
<?cs each:attr=attrs ?>
<tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:attr.since ?>" >
<td class="jd-linkcol"><a href="<?cs var:toroot ?><?cs var:attr.href ?>"><?cs var:attr.name ?></a></td>
<td class="jd-linkcol"><?cs if:included ?><a href="<?cs var:toroot ?><?cs var:attr.href ?>"><?cs /if ?><?cs var:attr.name ?><?cs if:included ?></a><?cs /if ?></td>
<td class="jd-linkcol"><?cs each:m=attr.methods ?>
<a href="<?cs var:toroot ?><?cs var:m.href ?>"><?cs var:m.name ?></a>
<?cs call:cond_link(m.name, toroot, m.href, included) ?>
<?cs /each ?>
</td>
<td class="jd-descrcol" width="100%"><?cs call:short_descr(attr) ?>&nbsp;</td>
@@ -293,7 +292,7 @@ Summary:
<?cs if:subcount(class.attrs) ?>
<!-- =========== FIELD SUMMARY =========== -->
<table id="lattrs" class="jd-sumtable"><tr><th colspan="12">XML Attributes</th></tr>
<?cs call:write_attr_summary(class.attrs) ?>
<?cs call:write_attr_summary(class.attrs, 1) ?>
<?cs /if ?>
<?cs # if there are inherited attrs, write the table ?>
@@ -308,14 +307,14 @@ Summary:
<tr class="api apilevel-<?cs var:cl.since ?>" >
<td colspan="12">
<?cs call:expando_trigger("inherited-attrs-"+cl.qualified, "closed") ?>From <?cs var:cl.kind ?>
<a href="<?cs var:toroot ?><?cs var:cl.link ?>"><?cs var:cl.qualified ?></a>
<?cs call:cond_link(cl.qualified, toroot, cl.link, cl.included) ?>
<div id="inherited-attrs-<?cs var:cl.qualified ?>">
<div id="inherited-attrs-<?cs var:cl.qualified ?>-list"
class="jd-inheritedlinks">
</div>
<div id="inherited-attrs-<?cs var:cl.qualified ?>-summary" style="display: none;">
<table class="jd-sumtable-expando">
<?cs call:write_attr_summary(cl.attrs) ?></table>
<?cs call:write_attr_summary(cl.attrs, cl.included) ?></table>
</div>
</div>
</td></tr>
@@ -332,7 +331,7 @@ Summary:
<?cs each:field=class.enumConstants ?>
<tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:field.since ?>" >
<td class="jd-descrcol"><?cs call:type_link(field.type) ?>&nbsp;</td>
<td class="jd-linkcol"><a href="<?cs var:toroot ?><?cs var:field.href ?>"><?cs var:field.name ?></a>&nbsp;</td>
<td class="jd-linkcol"><?cs call:cond_link(field.name, toroot, field.href, cl.included) ?>&nbsp;</td>
<td class="jd-descrcol" width="100%"><?cs call:short_descr(field) ?>&nbsp;</td>
</tr>
<?cs set:count = count + #1 ?>
@@ -343,7 +342,7 @@ Summary:
<?cs # this next line must be exactly like this to be parsed by eclipse ?>
<!-- =========== ENUM CONSTANT SUMMARY =========== -->
<table id="constants" class="jd-sumtable"><tr><th colspan="12">Constants</th></tr>
<?cs call:write_constant_summary(class.constants) ?>
<?cs call:write_constant_summary(class.constants, 1) ?>
</table>
<?cs /if ?>
@@ -359,14 +358,14 @@ Summary:
<tr class="api apilevel-<?cs var:cl.since ?>" >
<td colspan="12">
<?cs call:expando_trigger("inherited-constants-"+cl.qualified, "closed") ?>From <?cs var:cl.kind ?>
<a href="<?cs var:toroot ?><?cs var:cl.link ?>"><?cs var:cl.qualified ?></a>
<?cs call:cond_link(cl.qualified, toroot, cl.link, cl.included) ?>
<div id="inherited-constants-<?cs var:cl.qualified ?>">
<div id="inherited-constants-<?cs var:cl.qualified ?>-list"
class="jd-inheritedlinks">
</div>
<div id="inherited-constants-<?cs var:cl.qualified ?>-summary" style="display: none;">
<table class="jd-sumtable-expando">
<?cs call:write_constant_summary(cl.constants) ?></table>
<?cs call:write_constant_summary(cl.constants, cl.included) ?></table>
</div>
</div>
</td></tr>
@@ -379,7 +378,7 @@ Summary:
<?cs # this next line must be exactly like this to be parsed by eclipse ?>
<!-- =========== FIELD SUMMARY =========== -->
<table id="lfields" class="jd-sumtable"><tr><th colspan="12">Fields</th></tr>
<?cs call:write_field_summary(class.fields) ?>
<?cs call:write_field_summary(class.fields, 1) ?>
</table>
<?cs /if ?>
@@ -395,14 +394,14 @@ Summary:
<tr class="api apilevel-<?cs var:cl.since ?>" >
<td colspan="12">
<?cs call:expando_trigger("inherited-fields-"+cl.qualified, "closed") ?>From <?cs var:cl.kind ?>
<a href="<?cs var:toroot ?><?cs var:cl.link ?>"><?cs var:cl.qualified ?></a>
<?cs call:cond_link(cl.qualified, toroot, cl.link, cl.included) ?>
<div id="inherited-fields-<?cs var:cl.qualified ?>">
<div id="inherited-fields-<?cs var:cl.qualified ?>-list"
class="jd-inheritedlinks">
</div>
<div id="inherited-fields-<?cs var:cl.qualified ?>-summary" style="display: none;">
<table class="jd-sumtable-expando">
<?cs call:write_field_summary(cl.fields) ?></table>
<?cs call:write_field_summary(cl.fields, cl.included) ?></table>
</div>
</div>
</td></tr>
@@ -415,7 +414,7 @@ Summary:
<?cs # this next line must be exactly like this to be parsed by eclipse ?>
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr>
<?cs call:write_method_summary(class.ctors.public) ?>
<?cs call:write_method_summary(class.ctors.public, 1) ?>
</table>
<?cs /if ?>
@@ -423,7 +422,7 @@ Summary:
<?cs # this next line must be exactly like this to be parsed by eclipse ?>
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
<table id="proctors" class="jd-sumtable"><tr><th colspan="12">Protected Constructors</th></tr>
<?cs call:write_method_summary(class.ctors.protected) ?>
<?cs call:write_method_summary(class.ctors.protected, 1) ?>
</table>
<?cs /if ?>
@@ -431,7 +430,7 @@ Summary:
<?cs # this next line must be exactly like this to be parsed by eclipse ?>
<!-- ========== METHOD SUMMARY =========== -->
<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr>
<?cs call:write_method_summary(class.methods.public) ?>
<?cs call:write_method_summary(class.methods.public, 1) ?>
</table>
<?cs /if ?>
@@ -439,7 +438,7 @@ Summary:
<?cs # this next line must be exactly like this to be parsed by eclipse ?>
<!-- ========== METHOD SUMMARY =========== -->
<table id="promethods" class="jd-sumtable"><tr><th colspan="12">Protected Methods</th></tr>
<?cs call:write_method_summary(class.methods.protected) ?>
<?cs call:write_method_summary(class.methods.protected, 1) ?>
</table>
<?cs /if ?>
@@ -454,14 +453,14 @@ Summary:
<?cs if:subcount(cl.methods) ?>
<tr class="api apilevel-<?cs var:cl.since ?>" >
<td colspan="12"><?cs call:expando_trigger("inherited-methods-"+cl.qualified, "closed") ?>
From <?cs var:cl.kind ?> <a href="<?cs var:toroot ?><?cs var:cl.link ?>"><?cs var:cl.qualified ?></a>
From <?cs var:cl.kind ?> <?cs call:cond_link(cl.qualified, toroot, cl.link, cl.included) ?>
<div id="inherited-methods-<?cs var:cl.qualified ?>">
<div id="inherited-methods-<?cs var:cl.qualified ?>-list"
class="jd-inheritedlinks">
</div>
<div id="inherited-methods-<?cs var:cl.qualified ?>-summary" style="display: none;">
<table class="jd-sumtable-expando">
<?cs call:write_method_summary(cl.methods) ?></table>
<?cs call:write_method_summary(cl.methods, cl.included) ?></table>
</div>
</div>
</td></tr>

View File

@@ -39,6 +39,15 @@ def:type_link_impl(type, link) ?><?cs
<?cs def:class_name(type) ?><?cs call:type_link_impl(type, "false") ?><?cs /def ?>
<?cs def:type_link(type) ?><?cs call:type_link_impl(type, "true") ?><?cs /def ?>
<?cs # a conditional link.
if the "condition" parameter evals to true then the link is displayed
otherwise only the text is displayed
?><?cs
def:cond_link(text, root, path, condition) ?><?cs
if:condition ?><a href="<?cs var:root ?><?cs var:path ?>"><?cs /if ?><?cs var:text ?><?cs if:condition ?></a><?cs /if ?><?cs
/def ?>
<?cs # A comma separated parameter list ?><?cs
def:parameter_list(params) ?><?cs
each:param = params ?><?cs
@@ -64,6 +73,15 @@ def:tag_list(tags) ?><?cs
elif:tag.kind == "@sdkCurrent" ?><?cs var:sdk.current ?><?cs
elif:tag.kind == "@sdkCurrentVersion" ?><?cs var:sdk.version ?><?cs
elif:tag.kind == "@sdkCurrentRelId" ?><?cs var:sdk.rel.id ?><?cs
elif:tag.kind == "@sdkPlatformVersion" ?><?cs var:sdk.platform.version ?><?cs
elif:tag.kind == "@sdkPlatformApiLevel" ?><?cs var:sdk.platform.apiLevel ?><?cs
elif:tag.kind == "@sdkPlatformMajorMinor" ?><?cs var:sdk.platform.majorMinor ?><?cs
elif:tag.kind == "@sdkPlatformReleaseDate" ?><?cs var:sdk.platform.releaseDate ?><?cs
elif:tag.kind == "@sdkPlatformDeployableDate" ?><?cs var:sdk.platform.deployableDate ?><?cs
elif:tag.kind == "@adtZipVersion" ?><?cs var:adt.zip.version ?><?cs
elif:tag.kind == "@adtZipDownload" ?><?cs var:adt.zip.download ?><?cs
elif:tag.kind == "@adtZipBytes" ?><?cs var:adt.zip.bytes ?><?cs
elif:tag.kind == "@adtZipChecksum" ?><?cs var:adt.zip.checksum ?><?cs
elif:tag.kind == "@inheritDoc" ?><?cs # This is the case when @inheritDoc is in something
that doesn't inherit from anything?><?cs
elif:tag.kind == "@attr" ?><?cs
@@ -89,8 +107,8 @@ def:short_descr(obj) ?><?cs
<?cs # Show the red box with the deprecated warning ?><?cs
def:deprecated_warning(obj) ?><?cs
if:subcount(obj.deprecated) ?><p>
<p class="warning jd-deprecated-warning">
<strong><?cs call:deprecated_text(obj.kind) ?></strong><?cs
<p class="caution">
<strong><?cs call:deprecated_text(obj.kind) ?></strong><br/> <?cs
call:tag_list(obj.deprecated) ?>
</p><?cs
/if ?><?cs

View File

@@ -102,7 +102,7 @@ do
$1 != "Length" ||
$2 != "Method" ||
$3 != "Size" ||
$4 != "Ratio" ||
($4 != "Ratio" && $4 != "Cmpr") ||
$5 != "Date" ||
$6 != "Time" ||
$7 != "CRC-32" ||

98
tools/findleaves.py Executable file
View File

@@ -0,0 +1,98 @@
#!/usr/bin/env python
#
# 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.
#
#
# Finds files with the specified name under a particular directory, stopping
# the search in a given subdirectory when the file is found.
#
import os
import sys
def perform_find(mindepth, prune, dirlist, filename):
result = []
pruneleaves = set(map(lambda x: os.path.split(x)[1], prune))
for rootdir in dirlist:
rootdepth = rootdir.count("/")
for root, dirs, files in os.walk(rootdir):
# prune
check_prune = False
for d in dirs:
if d in pruneleaves:
check_prune = True
break
if check_prune:
i = 0
while i < len(dirs):
if dirs[i] in prune:
del dirs[i]
else:
i += 1
# mindepth
if mindepth > 0:
depth = 1 + root.count("/") - rootdepth
if depth < mindepth:
continue
# match
if filename in files:
result.append(os.path.join(root, filename))
del dirs[:]
return result
def usage():
sys.stderr.write("""Usage: %(progName)s [<options>] <dirlist> <filename>
Options:
--mindepth=<mindepth>
Both behave in the same way as their find(1) equivalents.
--prune=<dirname>
Avoids returning results from inside any directory called <dirname>
(e.g., "*/out/*"). May be used multiple times.
""" % {
"progName": os.path.split(sys.argv[0])[1],
})
sys.exit(1)
def main(argv):
mindepth = -1
prune = []
i=1
while i<len(argv) and len(argv[i])>2 and argv[i][0:2] == "--":
arg = argv[i]
if arg.startswith("--mindepth="):
try:
mindepth = int(arg[len("--mindepth="):])
except ValueError:
usage()
elif arg.startswith("--prune="):
p = arg[len("--prune="):]
if len(p) == 0:
usage()
prune.append(p)
else:
usage()
i += 1
if len(argv)-i < 2: # need both <dirlist> and <filename>
usage()
dirlist = argv[i:-1]
filename = argv[-1]
results = perform_find(mindepth, prune, dirlist, filename)
results.sort()
for r in set(results):
print r
if __name__ == "__main__":
main(sys.argv)

View File

@@ -1,109 +0,0 @@
#!/bin/bash
#
# 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.
#
#
# Finds files with the specified name under a particular directory, stopping
# the search in a given subdirectory when the file is found.
#
set -o nounset # fail when dereferencing unset variables
set -o errexit # fail if any subcommand fails
progName=`basename $0`
function warn() {
echo "$progName: $@" >&2
}
function trace() {
echo "$progName: $@"
}
function usage() {
if [[ $# > 0 ]]
then
warn $@
fi
cat <<-EOF
Usage: $progName [<options>] <dirlist> <filename>
Options:
--mindepth=<mindepth>
--maxdepth=<maxdepth>
Both behave in the same way as their find(1) equivalents.
--prune=<glob>
Avoids returning results from any path matching the given glob-style
pattern (e.g., "*/out/*"). May be used multiple times.
EOF
exit 1
}
function fail() {
warn $@
exit 1
}
if [ $# -lt 2 ]
then
usage
fi
findargs=""
while [[ "${1:0:2}" == "--" ]]
do
arg=${1:2}
name=${arg%%=*}
value=${arg##*=}
if [[ "$name" == "mindepth" || "$name" == "maxdepth" ]]
then
# Add to beginning of findargs; these must come before the expression.
findargs="-$name $value $findargs"
elif [[ "$name" == "prune" ]]
then
# Add to end of findargs; these are part of the expression.
findargs="$findargs -path $value -prune -or"
fi
shift
done
nargs=$#
# The filename is the last argument
filename="${!nargs}"
# Print out all files that match, as long as the path isn't explicitly
# pruned. This will print out extraneous results from directories whose
# parents have a match. These are filtered out by the awk script below.
find "${@:1:$nargs-1}" $findargs -type f -name "$filename" -print |
# Only pass along the directory of each match.
sed -e 's/\/[^\/]*$/\//' |
# Sort the output, so directories appear immediately before their contents.
# If there are any duplicates, the awk script will implicitly ignore them.
# The LC_ALL=C forces sort(1) to use bytewise ordering instead of listening
# to the locale, which may do case-insensitive and/or alphanumeric-only
# sorting.
LC_ALL=C sort |
# Always print the first line, which can't possibly be covered by a
# parent directory match. After that, only print lines where the last
# line printed isn't a prefix.
awk -v "filename=$filename" '
(NR == 1) || (index($0, last) != 1) {
last = $0;
printf("%s%s\n", $0, filename);
}
'

View File

@@ -87,6 +87,10 @@ class AmendGenerator(object):
'dur' seconds."""
self.script.append("show_progress %f %d" % (frac, int(dur)))
def SetProgress(self, frac):
"""Not implemented in amend."""
pass
def PatchCheck(self, filename, *sha1):
"""Check that the given file (or MTD reference) has one of the
given *sha1 hashes."""

View File

@@ -15,6 +15,7 @@
import errno
import getopt
import getpass
import imp
import os
import re
import shutil
@@ -33,7 +34,7 @@ OPTIONS.search_path = "out/host/linux-x86"
OPTIONS.max_image_size = {}
OPTIONS.verbose = False
OPTIONS.tempfiles = []
OPTIONS.device_specific = None
class ExternalError(RuntimeError): pass
@@ -184,14 +185,20 @@ def GetKeyPasswords(keylist):
return key_passwords
def SignFile(input_name, output_name, key, password, align=None):
def SignFile(input_name, output_name, key, password, align=None,
whole_file=False):
"""Sign the input_name zip/jar/apk, producing output_name. Use the
given key and password (the latter may be None if the key does not
have a password.
If align is an integer > 1, zipalign is run to align stored files in
the output zip on 'align'-byte boundaries.
If whole_file is true, use the "-w" option to SignApk to embed a
signature that covers the whole file in the archive comment of the
zip file.
"""
if align == 0 or align == 1:
align = None
@@ -201,13 +208,14 @@ def SignFile(input_name, output_name, key, password, align=None):
else:
sign_name = output_name
p = Run(["java", "-jar",
os.path.join(OPTIONS.search_path, "framework", "signapk.jar"),
key + ".x509.pem",
key + ".pk8",
input_name, sign_name],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
cmd = ["java", "-Xmx512m", "-jar",
os.path.join(OPTIONS.search_path, "framework", "signapk.jar")]
if whole_file:
cmd.append("-w")
cmd.extend([key + ".x509.pem", key + ".pk8",
input_name, sign_name])
p = Run(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
if password is not None:
password += "\n"
p.communicate(password)
@@ -247,6 +255,10 @@ COMMON_DOCSTRING = """
Prepend <dir>/bin to the list of places to search for binaries
run by this script, and expect to find jars in <dir>/framework.
-s (--device_specific) <file>
Path to the python module containing device-specific
releasetools code.
-v (--verbose)
Show command lines being executed.
@@ -271,8 +283,9 @@ def ParseOptions(argv,
try:
opts, args = getopt.getopt(
argv, "hvp:" + extra_opts,
["help", "verbose", "path="] + list(extra_long_opts))
argv, "hvp:s:" + extra_opts,
["help", "verbose", "path=", "device_specific="] +
list(extra_long_opts))
except getopt.GetoptError, err:
Usage(docstring)
print "**", str(err), "**"
@@ -288,6 +301,8 @@ def ParseOptions(argv,
OPTIONS.verbose = True
elif o in ("-p", "--path"):
OPTIONS.search_path = a
elif o in ("-s", "--device_specific"):
OPTIONS.device_specific = a
else:
if extra_option_handler is None or not extra_option_handler(o, a):
assert False, "unknown option \"%s\"" % (o,)
@@ -412,3 +427,68 @@ def ZipWriteStr(zip, filename, data, perms=0644):
zinfo.compress_type = zip.compression
zinfo.external_attr = perms << 16
zip.writestr(zinfo, data)
class DeviceSpecificParams(object):
module = None
def __init__(self, **kwargs):
"""Keyword arguments to the constructor become attributes of this
object, which is passed to all functions in the device-specific
module."""
for k, v in kwargs.iteritems():
setattr(self, k, v)
if self.module is None:
path = OPTIONS.device_specific
if not path: return
try:
if os.path.isdir(path):
info = imp.find_module("releasetools", [path])
else:
d, f = os.path.split(path)
b, x = os.path.splitext(f)
if x == ".py":
f = b
info = imp.find_module(f, [d])
self.module = imp.load_module("device_specific", *info)
except ImportError:
print "unable to load device-specific module; assuming none"
def _DoCall(self, function_name, *args, **kwargs):
"""Call the named function in the device-specific module, passing
the given args and kwargs. The first argument to the call will be
the DeviceSpecific object itself. If there is no module, or the
module does not define the function, return the value of the
'default' kwarg (which itself defaults to None)."""
if self.module is None or not hasattr(self.module, function_name):
return kwargs.get("default", None)
return getattr(self.module, function_name)(*((self,) + args), **kwargs)
def FullOTA_Assertions(self):
"""Called after emitting the block of assertions at the top of a
full OTA package. Implementations can add whatever additional
assertions they like."""
return self._DoCall("FullOTA_Assertions")
def FullOTA_InstallEnd(self):
"""Called at the end of full OTA installation; typically this is
used to install the image for the device's baseband processor."""
return self._DoCall("FullOTA_InstallEnd")
def IncrementalOTA_Assertions(self):
"""Called after emitting the block of assertions at the top of an
incremental OTA package. Implementations can add whatever
additional assertions they like."""
return self._DoCall("IncrementalOTA_Assertions")
def IncrementalOTA_VerifyEnd(self):
"""Called at the end of the verification phase of incremental OTA
installation; additional checks can be placed here to abort the
script before any changes are made."""
return self._DoCall("IncrementalOTA_VerifyEnd")
def IncrementalOTA_InstallEnd(self):
"""Called at the end of incremental OTA installation; typically
this is used to install the image for the device's baseband
processor."""
return self._DoCall("IncrementalOTA_InstallEnd")

View File

@@ -100,9 +100,16 @@ class EdifyGenerator(object):
def ShowProgress(self, frac, dur):
"""Update the progress bar, advancing it over 'frac' over the next
'dur' seconds."""
'dur' seconds. 'dur' may be zero to advance it via SetProgress
commands instead of by time."""
self.script.append("show_progress(%f, %d);" % (frac, int(dur)))
def SetProgress(self, frac):
"""Set the position of the progress bar within the chunk defined
by the most recent ShowProgress call. 'frac' should be in
[0,1]."""
self.script.append("set_progress(%f);" % (frac,))
def PatchCheck(self, filename, *sha1):
"""Check that the given file (or MTD reference) has one of the
given *sha1 hashes."""

View File

@@ -31,6 +31,7 @@ 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
@@ -82,8 +83,16 @@ def AddSystem(output_zip):
# 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.
os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"),
os.path.join(OPTIONS.input_tmp, "system"))
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
p = common.Run(["mkyaffs2image", "-f",
os.path.join(OPTIONS.input_tmp, "system"), img.name])

View File

@@ -57,11 +57,13 @@ if sys.hexversion < 0x02040000:
sys.exit(1)
import copy
import errno
import os
import re
import sha
import subprocess
import tempfile
import threading
import time
import zipfile
@@ -80,6 +82,7 @@ OPTIONS.wipe_user_data = False
OPTIONS.omit_prereq = False
OPTIONS.extra_script = None
OPTIONS.script_mode = 'auto'
OPTIONS.worker_threads = 3
def MostPopularKey(d, default):
"""Given a dict, return the key corresponding to the largest
@@ -273,19 +276,14 @@ def SignOutput(temp_zip_name, output_zip_name):
key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
pw = key_passwords[OPTIONS.package_key]
common.SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw)
common.SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw,
whole_file=True)
def AppendAssertions(script, input_zip):
device = GetBuildProp("ro.product.device", input_zip)
script.AssertDevice(device)
info = input_zip.read("OTA/android-info.txt")
m = re.search(r"require\s+version-bootloader\s*=\s*(\S+)", info)
if m:
bootloaders = m.group(1).split("|")
script.AssertSomeBootloader(*bootloaders)
def MakeRecoveryPatch(output_zip, recovery_img, boot_img):
"""Generate a binary patch that creates the recovery image starting
@@ -302,8 +300,9 @@ def MakeRecoveryPatch(output_zip, recovery_img, boot_img):
executable.
"""
patch = Difference(recovery_img, boot_img, "imgdiff")
common.ZipWriteStr(output_zip, "system/recovery-from-boot.p", patch)
d = Difference(recovery_img, boot_img)
_, _, patch = d.ComputePatch()
common.ZipWriteStr(output_zip, "recovery/recovery-from-boot.p", patch)
Item.Get("system/recovery-from-boot.p", dir=False)
# Images with different content will have a different first page, so
@@ -324,7 +323,7 @@ fi
'header_sha1': header_sha1,
'recovery_size': recovery_img.size,
'recovery_sha1': recovery_img.sha1 }
common.ZipWriteStr(output_zip, "system/etc/install-recovery.sh", sh)
common.ZipWriteStr(output_zip, "recovery/etc/install-recovery.sh", sh)
return Item.Get("system/etc/install-recovery.sh", dir=False)
@@ -339,19 +338,18 @@ def WriteFullOTAPackage(input_zip, output_zip):
# change very often.
script = edify_generator.EdifyGenerator(2)
device_specific = common.DeviceSpecificParams(
input_zip=input_zip,
output_zip=output_zip,
script=script,
input_tmp=OPTIONS.input_tmp)
if not OPTIONS.omit_prereq:
ts = GetBuildProp("ro.build.date.utc", input_zip)
script.AssertOlderBuild(ts)
AppendAssertions(script, input_zip)
script.ShowProgress(0.1, 0)
try:
common.ZipWriteStr(output_zip, "radio.img", input_zip.read("RADIO/image"))
script.WriteFirmwareImage("radio", "radio.img")
except KeyError:
print "warning: no radio image in input target_files; not flashing radio"
device_specific.FullOTA_Assertions()
script.ShowProgress(0.5, 0)
@@ -360,6 +358,7 @@ def WriteFullOTAPackage(input_zip, output_zip):
script.FormatPartition("system")
script.Mount("MTD", "system", "/system")
script.UnpackPackageDir("recovery", "/system")
script.UnpackPackageDir("system", "/system")
symlinks = CopySystemFiles(input_zip, output_zip)
@@ -385,8 +384,11 @@ def WriteFullOTAPackage(input_zip, output_zip):
common.ZipWriteStr(output_zip, "boot.img", boot_img.data)
script.ShowProgress(0.2, 0)
script.WriteRawImage("boot", "boot.img")
script.ShowProgress(0.2, 10)
script.WriteRawImage("boot", "boot.img")
script.ShowProgress(0.1, 0)
device_specific.FullOTA_InstallEnd()
if OPTIONS.extra_script is not None:
script.AppendExtra(OPTIONS.extra_script)
@@ -423,38 +425,111 @@ def LoadSystemFiles(z):
return out
def Difference(tf, sf, diff_program):
"""Return the patch (as a string of data) needed to turn sf into tf.
diff_program is the name of an external program (or list, if
additional arguments are desired) to run to generate the diff.
"""
DIFF_PROGRAM_BY_EXT = {
".gz" : "imgdiff",
".zip" : ["imgdiff", "-z"],
".jar" : ["imgdiff", "-z"],
".apk" : ["imgdiff", "-z"],
".img" : "imgdiff",
}
ttemp = tf.WriteToTemp()
stemp = sf.WriteToTemp()
ext = os.path.splitext(tf.name)[1]
class Difference(object):
def __init__(self, tf, sf):
self.tf = tf
self.sf = sf
self.patch = None
try:
ptemp = tempfile.NamedTemporaryFile()
if isinstance(diff_program, list):
cmd = copy.copy(diff_program)
else:
cmd = [diff_program]
cmd.append(stemp.name)
cmd.append(ttemp.name)
cmd.append(ptemp.name)
p = common.Run(cmd)
_, err = p.communicate()
if err or p.returncode != 0:
print "WARNING: failure running %s:\n%s\n" % (diff_program, err)
return None
diff = ptemp.read()
finally:
ptemp.close()
stemp.close()
ttemp.close()
def ComputePatch(self):
"""Compute the patch (as a string of data) needed to turn sf into
tf. Returns the same tuple as GetPatch()."""
return diff
tf = self.tf
sf = self.sf
ext = os.path.splitext(tf.name)[1]
diff_program = DIFF_PROGRAM_BY_EXT.get(ext, "bsdiff")
ttemp = tf.WriteToTemp()
stemp = sf.WriteToTemp()
ext = os.path.splitext(tf.name)[1]
try:
ptemp = tempfile.NamedTemporaryFile()
if isinstance(diff_program, list):
cmd = copy.copy(diff_program)
else:
cmd = [diff_program]
cmd.append(stemp.name)
cmd.append(ttemp.name)
cmd.append(ptemp.name)
p = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
_, err = p.communicate()
if err or p.returncode != 0:
print "WARNING: failure running %s:\n%s\n" % (diff_program, err)
return None
diff = ptemp.read()
finally:
ptemp.close()
stemp.close()
ttemp.close()
self.patch = diff
return self.tf, self.sf, self.patch
def GetPatch(self):
"""Return a tuple (target_file, source_file, patch_data).
patch_data may be None if ComputePatch hasn't been called, or if
computing the patch failed."""
return self.tf, self.sf, self.patch
def ComputeDifferences(diffs):
"""Call ComputePatch on all the Difference objects in 'diffs'."""
print len(diffs), "diffs to compute"
# Do the largest files first, to try and reduce the long-pole effect.
by_size = [(i.tf.size, i) for i in diffs]
by_size.sort(reverse=True)
by_size = [i[1] for i in by_size]
lock = threading.Lock()
diff_iter = iter(by_size) # accessed under lock
def worker():
try:
lock.acquire()
for d in diff_iter:
lock.release()
start = time.time()
d.ComputePatch()
dur = time.time() - start
lock.acquire()
tf, sf, patch = d.GetPatch()
if sf.name == tf.name:
name = tf.name
else:
name = "%s (%s)" % (tf.name, sf.name)
if patch is None:
print "patching failed! %s" % (name,)
else:
print "%8.2f sec %8d / %8d bytes (%6.2f%%) %s" % (
dur, len(patch), tf.size, 100.0 * len(patch) / tf.size, name)
lock.release()
except Exception, e:
print e
raise
# start worker threads; wait for them all to finish.
threads = [threading.Thread(target=worker)
for i in range(OPTIONS.worker_threads)]
for th in threads:
th.start()
while threads:
threads.pop().join()
def GetBuildProp(property, z):
@@ -484,6 +559,7 @@ def GetRecoveryAPIVersion(zip):
except KeyError:
return 0
def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
source_version = GetRecoveryAPIVersion(source_zip)
@@ -502,6 +578,12 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
else:
raise ValueError('unknown script mode "%s"' % (OPTIONS.script_mode,))
device_specific = common.DeviceSpecificParams(
source_zip=source_zip,
target_zip=target_zip,
output_zip=output_zip,
script=script)
print "Loading target..."
target_data = LoadSystemFiles(target_zip)
print "Loading source..."
@@ -509,9 +591,11 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
verbatim_targets = []
patch_list = []
diffs = []
largest_source_size = 0
for fn in sorted(target_data.keys()):
tf = target_data[fn]
assert fn == tf.name
sf = source_data.get(fn, None)
if sf is None or fn in OPTIONS.require_verbatim:
@@ -523,26 +607,23 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
verbatim_targets.append((fn, tf.size))
elif tf.sha1 != sf.sha1:
# File is different; consider sending as a patch
diff_method = "bsdiff"
if tf.name.endswith(".gz"):
diff_method = "imgdiff"
d = Difference(tf, sf, diff_method)
if d is not None:
print fn, tf.size, len(d), (float(len(d)) / tf.size)
if d is None or len(d) > tf.size * OPTIONS.patch_threshold:
# patch is almost as big as the file; don't bother patching
tf.AddToZip(output_zip)
verbatim_targets.append((fn, tf.size))
else:
common.ZipWriteStr(output_zip, "patch/" + fn + ".p", d)
patch_list.append((fn, tf, sf, tf.size))
largest_source_size = max(largest_source_size, sf.size)
diffs.append(Difference(tf, sf))
else:
# Target file identical to source.
pass
total_verbatim_size = sum([i[1] for i in verbatim_targets])
total_patched_size = sum([i[3] for i in patch_list])
ComputeDifferences(diffs)
for diff in diffs:
tf, sf, d = diff.GetPatch()
if d is None or len(d) > tf.size * OPTIONS.patch_threshold:
# patch is almost as big as the file; don't bother patching
tf.AddToZip(output_zip)
verbatim_targets.append((tf.name, tf.size))
else:
common.ZipWriteStr(output_zip, "patch/" + tf.name + ".p", d)
patch_list.append((tf.name, tf, sf, tf.size))
largest_source_size = max(largest_source_size, sf.size)
source_fp = GetBuildProp("ro.build.fingerprint", source_zip)
target_fp = GetBuildProp("ro.build.fingerprint", target_zip)
@@ -566,35 +647,31 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
os.path.join(OPTIONS.target_tmp, "RECOVERY")))
updating_recovery = (source_recovery.data != target_recovery.data)
source_radio = source_zip.read("RADIO/image")
target_radio = target_zip.read("RADIO/image")
updating_radio = (source_radio != target_radio)
# The last 0.1 is reserved for creating symlinks, fixing
# permissions, and writing the boot image (if necessary).
progress_bar_total = 1.0
if updating_boot:
progress_bar_total -= 0.1
if updating_radio:
progress_bar_total -= 0.3
# Here's how we divide up the progress bar:
# 0.1 for verifying the start state (PatchCheck calls)
# 0.8 for applying patches (ApplyPatch calls)
# 0.1 for unpacking verbatim files, symlinking, and doing the
# device-specific commands.
AppendAssertions(script, target_zip)
device_specific.IncrementalOTA_Assertions()
script.Print("Verifying current system...")
pb_verify = progress_bar_total * 0.3 * \
(total_patched_size /
float(total_patched_size+total_verbatim_size+1))
for i, (fn, tf, sf, size) in enumerate(patch_list):
if i % 5 == 0:
next_sizes = sum([i[3] for i in patch_list[i:i+5]])
script.ShowProgress(next_sizes * pb_verify / (total_patched_size+1), 1)
script.ShowProgress(0.1, 0)
total_verify_size = float(sum([i[2].size for i in patch_list]) + 1)
if updating_boot:
total_verify_size += source_boot.size
so_far = 0
for fn, tf, sf, size in patch_list:
script.PatchCheck("/"+fn, tf.sha1, sf.sha1)
so_far += sf.size
script.SetProgress(so_far / total_verify_size)
if updating_boot:
d = Difference(target_boot, source_boot, "imgdiff")
d = Difference(target_boot, source_boot)
_, _, d = d.ComputePatch()
print "boot target: %d source: %d diff: %d" % (
target_boot.size, source_boot.size, len(d))
@@ -603,12 +680,16 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
script.PatchCheck("MTD:boot:%d:%s:%d:%s" %
(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)
script.Print("Unpacking patches...")
script.UnpackPackageDir("patch", "/tmp/patchtmp")
device_specific.IncrementalOTA_VerifyEnd()
script.Comment("---- start making changes here ----")
if OPTIONS.wipe_user_data:
@@ -621,6 +702,19 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
if i not in target_data] +
["/system/recovery.img"])
script.ShowProgress(0.8, 0)
total_patch_size = float(sum([i[1].size for i in patch_list]) + 1)
if updating_boot:
total_patch_size += target_boot.size
so_far = 0
script.Print("Patching system files...")
for fn, tf, sf, size in patch_list:
script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1,
sf.sha1, "/tmp/patchtmp/"+fn+".p")
so_far += tf.size
script.SetProgress(so_far / total_patch_size)
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
@@ -632,6 +726,8 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
"-",
target_boot.size, target_boot.sha1,
source_boot.sha1, "/tmp/patchtmp/boot.img.p")
so_far += target_boot.size
script.SetProgress(so_far / total_patch_size)
print "boot image changed; including."
else:
print "boot image unchanged; skipping."
@@ -650,29 +746,12 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
# as fodder for constructing the recovery image.
recovery_sh_item = MakeRecoveryPatch(output_zip,
target_recovery, target_boot)
script.UnpackPackageDir("recovery", "/system")
print "recovery image changed; including as patch from boot."
else:
print "recovery image unchanged; skipping."
if updating_radio:
script.ShowProgress(0.3, 10)
script.Print("Writing radio image...")
script.WriteFirmwareImage("radio", "radio.img")
common.ZipWriteStr(output_zip, "radio.img", target_radio)
print "radio image changed; including."
else:
print "radio image unchanged; skipping."
script.Print("Patching system files...")
pb_apply = progress_bar_total * 0.7 * \
(total_patched_size /
float(total_patched_size+total_verbatim_size+1))
for i, (fn, tf, sf, size) in enumerate(patch_list):
if i % 5 == 0:
next_sizes = sum([i[3] for i in patch_list[i:i+5]])
script.ShowProgress(next_sizes * pb_apply / (total_patched_size+1), 1)
script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1,
sf.sha1, "/tmp/patchtmp/"+fn+".p")
script.ShowProgress(0.1, 10)
target_symlinks = CopySystemFiles(target_zip, None)
@@ -700,14 +779,10 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
script.DeleteFiles(to_delete)
if verbatim_targets:
pb_verbatim = progress_bar_total * \
(total_verbatim_size /
float(total_patched_size+total_verbatim_size+1))
script.ShowProgress(pb_verbatim, 5)
script.Print("Unpacking new files...")
script.UnpackPackageDir("system", "/system")
script.Print("Finishing up...")
script.Print("Symlinks and permissions...")
# Create all the symlinks that don't already exist, or point to
# somewhere different than what we want. Delete each symlink before
@@ -726,6 +801,9 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
# permissions.
script.AppendScript(temp_script)
# Do device-specific installation (eg, write radio image).
device_specific.IncrementalOTA_InstallEnd()
if OPTIONS.extra_script is not None:
scirpt.AppendExtra(OPTIONS.extra_script)
@@ -749,6 +827,8 @@ def main(argv):
OPTIONS.extra_script = a
elif o in ("-m", "--script_mode"):
OPTIONS.script_mode = a
elif o in ("--worker_threads"):
OPTIONS.worker_threads = int(a)
else:
return False
return True
@@ -761,7 +841,8 @@ def main(argv):
"wipe_user_data",
"no_prereq",
"extra_script=",
"script_mode="],
"script_mode=",
"worker_threads="],
extra_option_handler=option_handler)
if len(args) != 2:
@@ -777,6 +858,23 @@ def main(argv):
print "unzipping target target-files..."
OPTIONS.input_tmp = common.UnzipTemp(args[0])
if OPTIONS.device_specific is None:
# look for the device-specific tools extension location in the input
try:
f = open(os.path.join(OPTIONS.input_tmp, "META", "tool-extensions.txt"))
ds = f.read().strip()
f.close()
if ds:
ds = os.path.normpath(ds)
print "using device-specific extensions in", ds
OPTIONS.device_specific = ds
except IOError, e:
if e.errno == errno.ENOENT:
# nothing specified in the file
pass
else:
raise
common.LoadMaxSizes()
if not OPTIONS.max_image_size:
print

View File

@@ -20,10 +20,6 @@ target-files zip.
Usage: sign_target_files_apks [flags] input_target_files output_target_files
-s (--signapk_jar) <path>
Path of the signapks.jar file used to sign an individual APK
file.
-e (--extra_apks) <name,name,...=key>
Add extra APK name/key pairs as though they appeared in
apkcerts.txt (so mappings specified by -k and -d are applied).
@@ -307,9 +303,7 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip):
def main(argv):
def option_handler(o, a):
if o in ("-s", "--signapk_jar"):
OPTIONS.signapk_jar = a
elif o in ("-e", "--extra_apks"):
if o in ("-e", "--extra_apks"):
names, key = a.split("=")
names = names.split(",")
for n in names:
@@ -339,9 +333,8 @@ def main(argv):
return True
args = common.ParseOptions(argv, __doc__,
extra_opts="s:e:d:k:ot:",
extra_long_opts=["signapk_jar=",
"extra_apks=",
extra_opts="e:d:k:ot:",
extra_long_opts=["extra_apks=",
"default_key_mappings=",
"key_mapping=",
"replace_ota_keys",

View File

@@ -247,7 +247,7 @@ class SignApk {
}
}
/** Write a .SF file with a digest the specified manifest. */
/** Write a .SF file with a digest of the specified manifest. */
private static void writeSignatureFile(Manifest manifest, OutputStream out)
throws IOException, GeneralSecurityException {
Manifest sf = new Manifest();
@@ -304,6 +304,75 @@ class SignApk {
pkcs7.encodeSignedData(out);
}
private static void signWholeOutputFile(byte[] zipData,
OutputStream outputStream,
X509Certificate publicKey,
PrivateKey privateKey)
throws IOException, GeneralSecurityException {
// For a zip with no archive comment, the
// end-of-central-directory record will be 22 bytes long, so
// we expect to find the EOCD marker 22 bytes from the end.
if (zipData[zipData.length-22] != 0x50 ||
zipData[zipData.length-21] != 0x4b ||
zipData[zipData.length-20] != 0x05 ||
zipData[zipData.length-19] != 0x06) {
throw new IllegalArgumentException("zip data already has an archive comment");
}
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey);
signature.update(zipData, 0, zipData.length-2);
ByteArrayOutputStream temp = new ByteArrayOutputStream();
// put a readable message and a null char at the start of the
// archive comment, so that tools that display the comment
// (hopefully) show something sensible.
// TODO: anything more useful we can put in this message?
byte[] message = "signed by SignApk".getBytes("UTF-8");
temp.write(message);
temp.write(0);
writeSignatureBlock(signature, publicKey, temp);
int total_size = temp.size() + 6;
if (total_size > 0xffff) {
throw new IllegalArgumentException("signature is too big for ZIP file comment");
}
// signature starts this many bytes from the end of the file
int signature_start = total_size - message.length - 1;
temp.write(signature_start & 0xff);
temp.write((signature_start >> 8) & 0xff);
// Why the 0xff bytes? In a zip file with no archive comment,
// bytes [-6:-2] of the file are the little-endian offset from
// the start of the file to the central directory. So for the
// two high bytes to be 0xff 0xff, the archive would have to
// be nearly 4GB in side. So it's unlikely that a real
// commentless archive would have 0xffs here, and lets us tell
// an old signed archive from a new one.
temp.write(0xff);
temp.write(0xff);
temp.write(total_size & 0xff);
temp.write((total_size >> 8) & 0xff);
temp.flush();
// Signature verification checks that the EOCD header is the
// last such sequence in the file (to avoid minzip finding a
// fake EOCD appended after the signature in its scan). The
// odds of producing this sequence by chance are very low, but
// let's catch it here if it does.
byte[] b = temp.toByteArray();
for (int i = 0; i < b.length-3; ++i) {
if (b[i] == 0x50 && b[i+1] == 0x4b && b[i+2] == 0x05 && b[i+3] == 0x06) {
throw new IllegalArgumentException("found spurious EOCD header at " + i);
}
}
outputStream.write(zipData, 0, zipData.length-2);
outputStream.write(total_size & 0xff);
outputStream.write((total_size >> 8) & 0xff);
temp.writeTo(outputStream);
}
/**
* Copy all the files in a manifest from input to output. We set
* the modification times in the output to a fixed time, so as to
@@ -340,25 +409,40 @@ class SignApk {
}
public static void main(String[] args) {
if (args.length != 4) {
System.err.println("Usage: signapk " +
if (args.length != 4 && args.length != 5) {
System.err.println("Usage: signapk [-w] " +
"publickey.x509[.pem] privatekey.pk8 " +
"input.jar output.jar");
System.exit(2);
}
boolean signWholeFile = false;
int argstart = 0;
if (args[0].equals("-w")) {
signWholeFile = true;
argstart = 1;
}
JarFile inputJar = null;
JarOutputStream outputJar = null;
FileOutputStream outputFile = null;
try {
X509Certificate publicKey = readPublicKey(new File(args[0]));
X509Certificate publicKey = readPublicKey(new File(args[argstart+0]));
// Assume the certificate is valid for at least an hour.
long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
PrivateKey privateKey = readPrivateKey(new File(args[1]));
inputJar = new JarFile(new File(args[2]), false); // Don't verify.
outputJar = new JarOutputStream(new FileOutputStream(args[3]));
PrivateKey privateKey = readPrivateKey(new File(args[argstart+1]));
inputJar = new JarFile(new File(args[argstart+2]), false); // Don't verify.
OutputStream outputStream = null;
if (signWholeFile) {
outputStream = new ByteArrayOutputStream();
} else {
outputStream = outputFile = new FileOutputStream(args[argstart+3]);
}
outputJar = new JarOutputStream(outputStream);
outputJar.setLevel(9);
JarEntry je;
@@ -387,13 +471,23 @@ class SignApk {
// Everything else
copyFiles(manifest, inputJar, outputJar, timestamp);
outputJar.close();
outputJar = null;
outputStream.flush();
if (signWholeFile) {
outputFile = new FileOutputStream(args[argstart+3]);
signWholeOutputFile(((ByteArrayOutputStream)outputStream).toByteArray(),
outputFile, publicKey, privateKey);
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
} finally {
try {
if (inputJar != null) inputJar.close();
if (outputJar != null) outputJar.close();
if (outputFile != null) outputFile.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);

523
tools/warn.py Executable file
View File

@@ -0,0 +1,523 @@
#!/usr/bin/env python
import sys
import re
if len(sys.argv) == 1:
print 'usage: ' + sys.argv[0] + ' <build.log>'
sys.exit()
# if you add another level, don't forget to give it a color below
class severity:
UNKNOWN=0
SKIP=100
FIXMENOW=1
HIGH=2
MEDIUM=3
LOW=4
HARMLESS=5
def colorforseverity(sev):
if sev == severity.FIXMENOW:
return 'fuchsia'
if sev == severity.HIGH:
return 'red'
if sev == severity.MEDIUM:
return 'orange'
if sev == severity.LOW:
return 'yellow'
if sev == severity.HARMLESS:
return 'limegreen'
if sev == severity.UNKNOWN:
return 'blue'
return 'grey'
warnpatterns = [
{ 'category':'make', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'make: overriding commands/ignoring old commands',
'patterns':[r".*: warning: overriding commands for target .+",
r".*: warning: ignoring old commands for target .+"] },
{ 'category':'C/C++', 'severity':severity.HIGH, 'members':[], 'option':'-Wimplicit-function-declaration',
'description':'Implicit function declaration',
'patterns':[r".*: warning: implicit declaration of function .+"] },
{ 'category':'C/C++', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: conflicting types for '.+'"] },
{ 'category':'C/C++', 'severity':severity.HIGH, 'members':[], 'option':'-Wtype-limits',
'description':'Expression always evaluates to true or false',
'patterns':[r".*: warning: comparison is always false due to limited range of data type",
r".*: warning: comparison of unsigned expression >= 0 is always true",
r".*: warning: comparison of unsigned expression < 0 is always false"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Incompatible pointer types',
'patterns':[r".*: warning: assignment from incompatible pointer type",
r".*: warning: passing argument [0-9]+ of '.*' from incompatible pointer type",
r".*: warning: initialization from incompatible pointer type"] },
{ 'category':'C/C++', 'severity':severity.HIGH, 'members':[], 'option':'-fno-builtin',
'description':'Incompatible declaration of built in function',
'patterns':[r".*: warning: incompatible implicit declaration of built-in function .+"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wunused-parameter',
'description':'Unused parameter',
'patterns':[r".*: warning: unused parameter '.*'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wunused',
'description':'Unused function, variable or label',
'patterns':[r".*: warning: '.+' defined but not used"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wunused-value',
'description':'Statement with no effect',
'patterns':[r".*: warning: statement with no effect"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wmissing-field-initializers',
'description':'Missing initializer',
'patterns':[r".*: warning: missing initializer"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: \(near initialization for '.+'\)"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wformat',
'description':'Format string does not match arguments',
'patterns':[r".*: warning: format '.+' expects type '.+', but argument [0-9]+ has type '.+'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wformat-extra-args',
'description':'Too many arguments for format string',
'patterns':[r".*: warning: too many arguments for format"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wsign-compare',
'description':'Comparison between signed and unsigned',
'patterns':[r".*: warning: comparison between signed and unsigned",
r".*: warning: comparison of promoted \~unsigned with unsigned",
r".*: warning: signed and unsigned type in conditional expression"] },
{ 'category':'libpng', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'libpng: zero area',
'patterns':[r".*libpng warning: Ignoring attempt to set cHRM RGB triangle with zero area"] },
{ 'category':'aapt', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'aapt: no comment for public symbol',
'patterns':[r".*: warning: No comment for public symbol .+"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wmissing-braces',
'description':'Missing braces around initializer',
'patterns':[r".*: warning: missing braces around initializer.*"] },
{ 'category':'C/C++', 'severity':severity.HARMLESS, 'members':[], 'option':'',
'description':'No newline at end of file',
'patterns':[r".*: warning: no newline at end of file"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wcast-qual',
'description':'Qualifier discarded',
'patterns':[r".*: warning: passing argument [0-9]+ of '.+' discards qualifiers from pointer target type",
r".*: warning: assignment discards qualifiers from pointer target type",
r".*: warning: return discards qualifiers from pointer target type"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wattributes',
'description':'Attribute ignored',
'patterns':[r".*: warning: '_*packed_*' attribute ignored"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wattributes',
'description':'Visibility mismatch',
'patterns':[r".*: warning: '.+' declared with greater visibility than the type of its field '.+'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Shift count greater than width of type',
'patterns':[r".*: warning: (left|right) shift count >= width of type"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'extern &lt;foo&gt; is initialized',
'patterns':[r".*: warning: '.+' initialized and declared 'extern'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wold-style-declaration',
'description':'Old style declaration',
'patterns':[r".*: warning: 'static' is not at beginning of declaration"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wuninitialized',
'description':'Variable may be used uninitialized',
'patterns':[r".*: warning: '.+' may be used uninitialized in this function"] },
{ 'category':'C/C++', 'severity':severity.HIGH, 'members':[], 'option':'-Wuninitialized',
'description':'Variable is used uninitialized',
'patterns':[r".*: warning: '.+' is used uninitialized in this function"] },
{ 'category':'ld', 'severity':severity.MEDIUM, 'members':[], 'option':'-fshort-enums',
'description':'ld: possible enum size mismatch',
'patterns':[r".*: warning: .* uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wpointer-sign',
'description':'Pointer targets differ in signedness',
'patterns':[r".*: warning: pointer targets in initialization differ in signedness",
r".*: warning: pointer targets in assignment differ in signedness",
r".*: warning: pointer targets in return differ in signedness",
r".*: warning: pointer targets in passing argument [0-9]+ of '.+' differ in signedness"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wstrict-overflow',
'description':'Assuming overflow does not occur',
'patterns':[r".*: warning: assuming signed overflow does not occur when assuming that .* is always (true|false)"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wempty-body',
'description':'Suggest adding braces around empty body',
'patterns':[r".*: warning: suggest braces around empty body in an 'if' statement",
r".*: warning: empty body in an if-statement",
r".*: warning: suggest braces around empty body in an 'else' statement",
r".*: warning: empty body in an else-statement"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wparentheses',
'description':'Suggest adding parentheses',
'patterns':[r".*: warning: suggest explicit braces to avoid ambiguous 'else'",
r".*: warning: suggest parentheses around arithmetic in operand of '.+'",
r".*: warning: suggest parentheses around comparison in operand of '.+'",
r".*: warning: suggest parentheses around '.+?' .+ '.+?'",
r".*: warning: suggest parentheses around assignment used as truth value"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Static variable used in non-static inline function',
'patterns':[r".*: warning: '.+' is static but used in inline function '.+' which is not static"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wimplicit int',
'description':'No type or storage class (will default to int)',
'patterns':[r".*: warning: data definition has no type or storage class"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: type defaults to 'int' in declaration of '.+'"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: parameter names \(without types\) in function declaration"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wstrict-aliasing',
'description':'Dereferencing &lt;foo&gt; breaks strict aliasing rules',
'patterns':[r".*: warning: dereferencing .* break strict-aliasing rules"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wpointer-to-int-cast',
'description':'Cast from pointer to integer of different size',
'patterns':[r".*: warning: cast from pointer to integer of different size"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wint-to-pointer-cast',
'description':'Cast to pointer from integer of different size',
'patterns':[r".*: warning: cast to pointer from integer of different size"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Symbol redefined',
'patterns':[r".*: warning: "".+"" redefined"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: this is the location of the previous definition"] },
{ 'category':'ld', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'ld: type and size of dynamic symbol are not defined',
'patterns':[r".*: warning: type and size of dynamic symbol `.+' are not defined"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Pointer from integer without cast',
'patterns':[r".*: warning: assignment makes pointer from integer without a cast"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Pointer from integer without cast',
'patterns':[r".*: warning: passing argument [0-9]+ of '.+' makes pointer from integer without a cast"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Integer from pointer without cast',
'patterns':[r".*: warning: assignment makes integer from pointer without a cast"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Integer from pointer without cast',
'patterns':[r".*: warning: passing argument [0-9]+ of '.+' makes integer from pointer without a cast"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Integer from pointer without cast',
'patterns':[r".*: warning: return makes integer from pointer without a cast"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wunknown-pragmas',
'description':'Ignoring pragma',
'patterns':[r".*: warning: ignoring #pragma .+"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wclobbered',
'description':'Variable might be clobbered by longjmp or vfork',
'patterns':[r".*: warning: variable '.+' might be clobbered by 'longjmp' or 'vfork'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wclobbered',
'description':'Argument might be clobbered by longjmp or vfork',
'patterns':[r".*: warning: argument '.+' might be clobbered by 'longjmp' or 'vfork'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wredundant-decls',
'description':'Redundant declaration',
'patterns':[r".*: warning: redundant redeclaration of '.+'"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: previous declaration of '.+' was here"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wswitch-enum',
'description':'Enum value not handled in switch',
'patterns':[r".*: warning: enumeration value '.+' not handled in switch"] },
{ 'category':'java', 'severity':severity.MEDIUM, 'members':[], 'option':'-encoding',
'description':'Java: Non-ascii characters used, but ascii encoding specified',
'patterns':[r".*: warning: unmappable character for encoding ascii"] },
{ 'category':'java', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Java: Non-varargs call of varargs method with inexact argument type for last parameter',
'patterns':[r".*: warning: non-varargs call of varargs method with inexact argument type for last parameter"] },
{ 'category':'aapt', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'aapt: String marked untranslatable, but translation exists',
'patterns':[r".*: warning: string '.+' in .* marked untranslatable but exists in locale '??_??'"] },
{ 'category':'aapt', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'aapt: empty span in string',
'patterns':[r".*: warning: empty '.+' span found in text '.+"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Taking address of temporary',
'patterns':[r".*: warning: taking address of temporary"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Possible broken line continuation',
'patterns':[r".*: warning: backslash and newline separated by space"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Warray-bounds',
'description':'Array subscript out of bounds',
'patterns':[r".*: warning: array subscript is above array bounds"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Decimal constant is unsigned only in ISO C90',
'patterns':[r".*: warning: this decimal constant is unsigned only in ISO C90"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wmain',
'description':'main is usually a function',
'patterns':[r".*: warning: 'main' is usually a function"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Typedef ignored',
'patterns':[r".*: warning: 'typedef' was ignored in this declaration"] },
{ 'category':'C/C++', 'severity':severity.HIGH, 'members':[], 'option':'-Waddress',
'description':'Address always evaluates to true',
'patterns':[r".*: warning: the address of '.+' will always evaluate as 'true'"] },
{ 'category':'C/C++', 'severity':severity.FIXMENOW, 'members':[], 'option':'',
'description':'Freeing a non-heap object',
'patterns':[r".*: warning: attempt to free a non-heap object '.+'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wchar-subscripts',
'description':'Array subscript has type char',
'patterns':[r".*: warning: array subscript has type 'char'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Constant too large for type',
'patterns':[r".*: warning: integer constant is too large for '.+' type"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Woverflow',
'description':'Constant too large for type, truncated',
'patterns':[r".*: warning: large integer implicitly truncated to unsigned type"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Woverflow',
'description':'Overflow in implicit constant conversion',
'patterns':[r".*: warning: overflow in implicit constant conversion"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Declaration does not declare anything',
'patterns':[r".*: warning: declaration 'class .+' does not declare anything"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wreorder',
'description':'Initialization order will be different',
'patterns':[r".*: warning: '.+' will be initialized after"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: '.+'"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: when initialized here"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wmissing-parameter-type',
'description':'Parameter type not specified',
'patterns':[r".*: warning: type of '.+' defaults to 'int'"] },
{ 'category':'gcc', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Invalid option for C file',
'patterns':[r".*: warning: command line option "".+"" is valid for C\+\+\/ObjC\+\+ but not for C"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'User warning',
'patterns':[r".*: warning: #warning "".+"""] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wextra',
'description':'Dereferencing void*',
'patterns':[r".*: warning: dereferencing 'void \*' pointer"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wextra',
'description':'Comparison of pointer to zero',
'patterns':[r".*: warning: ordered comparison of pointer with integer zero"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wwrite-strings',
'description':'Conversion of string constant to non-const char*',
'patterns':[r".*: warning: deprecated conversion from string constant to '.+'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wstrict-prototypes',
'description':'Function declaration isn''t a prototype',
'patterns':[r".*: warning: function declaration isn't a prototype"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wignored-qualifiers',
'description':'Type qualifiers ignored on function return value',
'patterns':[r".*: warning: type qualifiers ignored on function return type"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'&lt;foo&gt; declared inside parameter list, scope limited to this definition',
'patterns':[r".*: warning: '.+' declared inside parameter list"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: its scope is only this definition or declaration, which is probably not what you want"] },
{ 'category':'C/C++', 'severity':severity.LOW, 'members':[], 'option':'-Wcomment',
'description':'Line continuation inside comment',
'patterns':[r".*: warning: multi-line comment"] },
{ 'category':'C/C++', 'severity':severity.HARMLESS, 'members':[], 'option':'',
'description':'Extra tokens after #endif',
'patterns':[r".*: warning: extra tokens at end of #endif directive"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wenum-compare',
'description':'Comparison between different enums',
'patterns':[r".*: warning: comparison between 'enum .+' and 'enum .+'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wconversion',
'description':'Implicit conversion of negative number to unsigned type',
'patterns':[r".*: warning: converting negative value '.+' to '.+'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Passing NULL as non-pointer argument',
'patterns':[r".*: warning: passing NULL to non-pointer argument [0-9]+ of '.+'"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wctor-dtor-privacy',
'description':'Class seems unusable because of private ctor/dtor' ,
'patterns':[r".*: warning: all member functions in class '.+' are private"] },
# skip this next one, because it only points out some RefBase-based classes where having a private destructor is perfectly fine
{ 'category':'C/C++', 'severity':severity.SKIP, 'members':[], 'option':'-Wctor-dtor-privacy',
'description':'Class seems unusable because of private ctor/dtor' ,
'patterns':[r".*: warning: 'class .+' only defines a private destructor and has no friends"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wctor-dtor-privacy',
'description':'Class seems unusable because of private ctor/dtor' ,
'patterns':[r".*: warning: 'class .+' only defines private constructors and has no friends"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wpointer-arith',
'description':'void* used in arithmetic' ,
'patterns':[r".*: warning: pointer of type 'void \*' used in (arithmetic|subtraction)",
r".*: warning: wrong type argument to increment"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'-Wsign-promo',
'description':'Overload resolution chose to promote from unsigned or enum to signed type' ,
'patterns':[r".*: warning: passing '.+' chooses 'int' over '.* int'"] },
{ 'category':'cont.', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: in call to '.+'"] },
{ 'category':'C/C++', 'severity':severity.HIGH, 'members':[], 'option':'-Wextra',
'description':'Base should be explicitly initialized in copy constructor',
'patterns':[r".*: warning: base class '.+' should be explicitly initialized in the copy constructor"] },
{ 'category':'C/C++', 'severity':severity.MEDIUM, 'members':[], 'option':'',
'description':'Converting from <type> to <other type>',
'patterns':[r".*: warning: converting to '.+' from '.+'"] },
# these next ones are to deal with formatting problems resulting from the log being mixed up by 'make -j'
{ 'category':'C/C++', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: ,$"] },
{ 'category':'C/C++', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: $"] },
{ 'category':'C/C++', 'severity':severity.SKIP, 'members':[], 'option':'',
'description':'',
'patterns':[r".*: warning: In file included from .+,"] },
# catch-all for warnings this script doesn't know about yet
{ 'category':'C/C++', 'severity':severity.UNKNOWN, 'members':[], 'option':'',
'description':'Unclassified/unrecognized warnings',
'patterns':[r".*: warning: .+"] },
]
anchor = 0
cur_row_color = 0
row_colors = [ 'e0e0e0', 'd0d0d0' ]
def output(text):
print text,
def htmlbig(param):
return '<font size="+2">' + param + '</font>'
def dumphtmlprologue(title):
output('<html>\n<head>\n<title>' + title + '</title>\n<body>\n')
output(htmlbig(title))
output('<p>\n')
def tablerow(text):
global cur_row_color
output('<tr bgcolor="' + row_colors[cur_row_color] + '"><td colspan="2">',)
cur_row_color = 1 - cur_row_color
output(text,)
output('</td></tr>')
def begintable(text, backgroundcolor):
global anchor
output('<table border="1" rules="cols" frame="box" width="100%" bgcolor="black"><tr bgcolor="' +
backgroundcolor + '"><a name="anchor' + str(anchor) + '"><td>')
output(htmlbig(text[0]) + '<br>')
for i in text[1:]:
output(i + '<br>')
output('</td>')
output('<td width="100" bgcolor="grey"><a align="right" href="#anchor' + str(anchor-1) +
'">previous</a><br><a align="right" href="#anchor' + str(anchor+1) + '">next</a>')
output('</td></a></tr>')
anchor += 1
def endtable():
output('</table><p>')
# dump some stats about total number of warnings and such
def dumpstats():
known = 0
unknown = 0
for i in warnpatterns:
if i['severity'] == severity.UNKNOWN:
unknown += len(i['members'])
elif i['severity'] != severity.SKIP:
known += len(i['members'])
output('Number of classified warnings: <b>' + str(known) + '</b><br>' )
output('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>')
total = unknown + known
output('Total number of warnings: <b>' + str(total) + '</b>')
if total < 1000:
output('(low count may indicate incremental build)')
output('<p>')
def allpatterns(cat):
pats = ''
for i in cat['patterns']:
pats += i
pats += ' / '
return pats
def descriptionfor(cat):
if cat['description'] != '':
return cat['description']
return allpatterns(cat)
# show which warnings no longer occur
def dumpfixed():
tablestarted = False
for i in warnpatterns:
if len(i['members']) == 0 and i['severity'] != severity.SKIP:
if tablestarted == False:
tablestarted = True
begintable(['Fixed warnings', 'No more occurences. Please consider turning these in to errors if possible, before they are reintroduced in to the build'], 'blue')
tablerow(i['description'] + ' (' + allpatterns(i) + ') ' + i['option'])
if tablestarted:
endtable()
# dump a category, provided it is not marked as 'SKIP' and has more than 0 occurrences
def dumpcategory(cat):
if cat['severity'] != severity.SKIP and len(cat['members']) != 0:
header = [descriptionfor(cat),str(len(cat['members'])) + ' occurences:']
if cat['option'] != '':
header[1:1] = [' (related option: ' + cat['option'] +')']
begintable(header, colorforseverity(cat['severity']))
for i in cat['members']:
tablerow(i)
endtable()
# dump everything for a given severity
def dumpseverity(sev):
for i in warnpatterns:
if i['severity'] == sev:
dumpcategory(i)
def classifywarning(line):
for i in warnpatterns:
for cpat in i['compiledpatterns']:
if cpat.match(line):
i['members'].append(line)
return
else:
# If we end up here, there was a problem parsing the log
# probably caused by 'make -j' mixing the output from
# 2 or more concurrent compiles
pass
# precompiling every pattern speeds up parsing by about 30x
def compilepatterns():
for i in warnpatterns:
i['compiledpatterns'] = []
for pat in i['patterns']:
i['compiledpatterns'].append(re.compile(pat))
infile = open(sys.argv[1], 'r')
warnings = []
platformversion = 'unknown'
targetproduct = 'unknown'
targetvariant = 'unknown'
linecounter = 0
warningpattern = re.compile('.* warning:.*')
compilepatterns()
# read the log file and classify all the warnings
lastmatchedline = ''
for line in infile:
if warningpattern.match(line):
if line != lastmatchedline:
classifywarning(line)
lastmatchedline = line
else:
# save a little bit of time by only doing this for the first few lines
if linecounter < 50:
linecounter +=1
m = re.search('(?<=^PLATFORM_VERSION=).*', line)
if m != None:
platformversion = m.group(0)
m = re.search('(?<=^TARGET_PRODUCT=).*', line)
if m != None:
targetproduct = m.group(0)
m = re.search('(?<=^TARGET_BUILD_VARIANT=).*', line)
if m != None:
targetvariant = m.group(0)
# dump the html output to stdout
dumphtmlprologue('Warnings for ' + platformversion + ' - ' + targetproduct + ' - ' + targetvariant)
dumpstats()
dumpseverity(severity.FIXMENOW)
dumpseverity(severity.HIGH)
dumpseverity(severity.MEDIUM)
dumpseverity(severity.LOW)
dumpseverity(severity.HARMLESS)
dumpseverity(severity.UNKNOWN)
dumpfixed()

View File

@@ -8,7 +8,9 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
ZipAlign.cpp
ZipAlign.cpp \
ZipEntry.cpp \
ZipFile.cpp
LOCAL_C_INCLUDES += external/zlib

View File

@@ -1,7 +1,9 @@
zipalign -- zip archive alignment tool
usage: zipalign [-f] [-v] <align> infile.zip outfile.zip
zipalign -c [-v] <align> infile.zip
-c : check alignment only (does not modify file)
-f : overwrite existing outfile.zip
-v : verbose output
<align> is in bytes, e.g. "4" provides 32-bit alignment
@@ -29,3 +31,5 @@ entries. Files added to an "aligned" archive will not be aligned.
By default, zipalign will not overwrite an existing output file. With the
"-f" flag, an existing file will be overwritten.
You can use the "-c" flag to test whether a zip archive is properly aligned.

View File

@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Zip alignment tool
*/
#include "utils/ZipFile.h"
#include "ZipFile.h"
#include <stdlib.h>
#include <stdio.h>
@@ -29,9 +30,15 @@ using namespace android;
void usage(void)
{
fprintf(stderr, "Zip alignment utility\n");
fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
fprintf(stderr,
"Usage: zipalign [-f] [-v] <align> infile.zip outfile.zip\n"
" zipalign -c [-v] <align> infile.zip\n" );
" zipalign -c [-v] <align> infile.zip\n\n" );
fprintf(stderr,
" <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
fprintf(stderr, " -c: check alignment only (does not modify file)\n");
fprintf(stderr, " -f: overwrite existing outfile.zip\n");
fprintf(stderr, " -v: verbose output\n");
}
/*

696
tools/zipalign/ZipEntry.cpp Normal file
View File

@@ -0,0 +1,696 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//
// Access to entries in a Zip archive.
//
#define LOG_TAG "zip"
#include "ZipEntry.h"
#include <utils/Log.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
using namespace android;
/*
* Initialize a new ZipEntry structure from a FILE* positioned at a
* CentralDirectoryEntry.
*
* On exit, the file pointer will be at the start of the next CDE or
* at the EOCD.
*/
status_t ZipEntry::initFromCDE(FILE* fp)
{
status_t result;
long posn;
bool hasDD;
//LOGV("initFromCDE ---\n");
/* read the CDE */
result = mCDE.read(fp);
if (result != NO_ERROR) {
LOGD("mCDE.read failed\n");
return result;
}
//mCDE.dump();
/* using the info in the CDE, go load up the LFH */
posn = ftell(fp);
if (fseek(fp, mCDE.mLocalHeaderRelOffset, SEEK_SET) != 0) {
LOGD("local header seek failed (%ld)\n",
mCDE.mLocalHeaderRelOffset);
return UNKNOWN_ERROR;
}
result = mLFH.read(fp);
if (result != NO_ERROR) {
LOGD("mLFH.read failed\n");
return result;
}
if (fseek(fp, posn, SEEK_SET) != 0)
return UNKNOWN_ERROR;
//mLFH.dump();
/*
* We *might* need to read the Data Descriptor at this point and
* integrate it into the LFH. If this bit is set, the CRC-32,
* compressed size, and uncompressed size will be zero. In practice
* these seem to be rare.
*/
hasDD = (mLFH.mGPBitFlag & kUsesDataDescr) != 0;
if (hasDD) {
// do something clever
//LOGD("+++ has data descriptor\n");
}
/*
* Sanity-check the LFH. Note that this will fail if the "kUsesDataDescr"
* flag is set, because the LFH is incomplete. (Not a problem, since we
* prefer the CDE values.)
*/
if (!hasDD && !compareHeaders()) {
LOGW("WARNING: header mismatch\n");
// keep going?
}
/*
* If the mVersionToExtract is greater than 20, we may have an
* issue unpacking the record -- could be encrypted, compressed
* with something we don't support, or use Zip64 extensions. We
* can defer worrying about that to when we're extracting data.
*/
return NO_ERROR;
}
/*
* Initialize a new entry. Pass in the file name and an optional comment.
*
* Initializes the CDE and the LFH.
*/
void ZipEntry::initNew(const char* fileName, const char* comment)
{
assert(fileName != NULL && *fileName != '\0'); // name required
/* most fields are properly initialized by constructor */
mCDE.mVersionMadeBy = kDefaultMadeBy;
mCDE.mVersionToExtract = kDefaultVersion;
mCDE.mCompressionMethod = kCompressStored;
mCDE.mFileNameLength = strlen(fileName);
if (comment != NULL)
mCDE.mFileCommentLength = strlen(comment);
mCDE.mExternalAttrs = 0x81b60020; // matches what WinZip does
if (mCDE.mFileNameLength > 0) {
mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1];
strcpy((char*) mCDE.mFileName, fileName);
}
if (mCDE.mFileCommentLength > 0) {
/* TODO: stop assuming null-terminated ASCII here? */
mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1];
strcpy((char*) mCDE.mFileComment, comment);
}
copyCDEtoLFH();
}
/*
* Initialize a new entry, starting with the ZipEntry from a different
* archive.
*
* Initializes the CDE and the LFH.
*/
status_t ZipEntry::initFromExternal(const ZipFile* pZipFile,
const ZipEntry* pEntry)
{
/*
* Copy everything in the CDE over, then fix up the hairy bits.
*/
memcpy(&mCDE, &pEntry->mCDE, sizeof(mCDE));
if (mCDE.mFileNameLength > 0) {
mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1];
if (mCDE.mFileName == NULL)
return NO_MEMORY;
strcpy((char*) mCDE.mFileName, (char*)pEntry->mCDE.mFileName);
}
if (mCDE.mFileCommentLength > 0) {
mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1];
if (mCDE.mFileComment == NULL)
return NO_MEMORY;
strcpy((char*) mCDE.mFileComment, (char*)pEntry->mCDE.mFileComment);
}
if (mCDE.mExtraFieldLength > 0) {
/* we null-terminate this, though it may not be a string */
mCDE.mExtraField = new unsigned char[mCDE.mExtraFieldLength+1];
if (mCDE.mExtraField == NULL)
return NO_MEMORY;
memcpy(mCDE.mExtraField, pEntry->mCDE.mExtraField,
mCDE.mExtraFieldLength+1);
}
/* construct the LFH from the CDE */
copyCDEtoLFH();
/*
* The LFH "extra" field is independent of the CDE "extra", so we
* handle it here.
*/
assert(mLFH.mExtraField == NULL);
mLFH.mExtraFieldLength = pEntry->mLFH.mExtraFieldLength;
if (mLFH.mExtraFieldLength > 0) {
mLFH.mExtraField = new unsigned char[mLFH.mExtraFieldLength+1];
if (mLFH.mExtraField == NULL)
return NO_MEMORY;
memcpy(mLFH.mExtraField, pEntry->mLFH.mExtraField,
mLFH.mExtraFieldLength+1);
}
return NO_ERROR;
}
/*
* Insert pad bytes in the LFH by tweaking the "extra" field. This will
* potentially confuse something that put "extra" data in here earlier,
* but I can't find an actual problem.
*/
status_t ZipEntry::addPadding(int padding)
{
if (padding <= 0)
return INVALID_OPERATION;
//LOGI("HEY: adding %d pad bytes to existing %d in %s\n",
// padding, mLFH.mExtraFieldLength, mCDE.mFileName);
if (mLFH.mExtraFieldLength > 0) {
/* extend existing field */
unsigned char* newExtra;
newExtra = new unsigned char[mLFH.mExtraFieldLength + padding];
if (newExtra == NULL)
return NO_MEMORY;
memset(newExtra + mLFH.mExtraFieldLength, 0, padding);
memcpy(newExtra, mLFH.mExtraField, mLFH.mExtraFieldLength);
delete[] mLFH.mExtraField;
mLFH.mExtraField = newExtra;
mLFH.mExtraFieldLength += padding;
} else {
/* create new field */
mLFH.mExtraField = new unsigned char[padding];
memset(mLFH.mExtraField, 0, padding);
mLFH.mExtraFieldLength = padding;
}
return NO_ERROR;
}
/*
* Set the fields in the LFH equal to the corresponding fields in the CDE.
*
* This does not touch the LFH "extra" field.
*/
void ZipEntry::copyCDEtoLFH(void)
{
mLFH.mVersionToExtract = mCDE.mVersionToExtract;
mLFH.mGPBitFlag = mCDE.mGPBitFlag;
mLFH.mCompressionMethod = mCDE.mCompressionMethod;
mLFH.mLastModFileTime = mCDE.mLastModFileTime;
mLFH.mLastModFileDate = mCDE.mLastModFileDate;
mLFH.mCRC32 = mCDE.mCRC32;
mLFH.mCompressedSize = mCDE.mCompressedSize;
mLFH.mUncompressedSize = mCDE.mUncompressedSize;
mLFH.mFileNameLength = mCDE.mFileNameLength;
// the "extra field" is independent
delete[] mLFH.mFileName;
if (mLFH.mFileNameLength > 0) {
mLFH.mFileName = new unsigned char[mLFH.mFileNameLength+1];
strcpy((char*) mLFH.mFileName, (const char*) mCDE.mFileName);
} else {
mLFH.mFileName = NULL;
}
}
/*
* Set some information about a file after we add it.
*/
void ZipEntry::setDataInfo(long uncompLen, long compLen, unsigned long crc32,
int compressionMethod)
{
mCDE.mCompressionMethod = compressionMethod;
mCDE.mCRC32 = crc32;
mCDE.mCompressedSize = compLen;
mCDE.mUncompressedSize = uncompLen;
mCDE.mCompressionMethod = compressionMethod;
if (compressionMethod == kCompressDeflated) {
mCDE.mGPBitFlag |= 0x0002; // indicates maximum compression used
}
copyCDEtoLFH();
}
/*
* See if the data in mCDE and mLFH match up. This is mostly useful for
* debugging these classes, but it can be used to identify damaged
* archives.
*
* Returns "false" if they differ.
*/
bool ZipEntry::compareHeaders(void) const
{
if (mCDE.mVersionToExtract != mLFH.mVersionToExtract) {
LOGV("cmp: VersionToExtract\n");
return false;
}
if (mCDE.mGPBitFlag != mLFH.mGPBitFlag) {
LOGV("cmp: GPBitFlag\n");
return false;
}
if (mCDE.mCompressionMethod != mLFH.mCompressionMethod) {
LOGV("cmp: CompressionMethod\n");
return false;
}
if (mCDE.mLastModFileTime != mLFH.mLastModFileTime) {
LOGV("cmp: LastModFileTime\n");
return false;
}
if (mCDE.mLastModFileDate != mLFH.mLastModFileDate) {
LOGV("cmp: LastModFileDate\n");
return false;
}
if (mCDE.mCRC32 != mLFH.mCRC32) {
LOGV("cmp: CRC32\n");
return false;
}
if (mCDE.mCompressedSize != mLFH.mCompressedSize) {
LOGV("cmp: CompressedSize\n");
return false;
}
if (mCDE.mUncompressedSize != mLFH.mUncompressedSize) {
LOGV("cmp: UncompressedSize\n");
return false;
}
if (mCDE.mFileNameLength != mLFH.mFileNameLength) {
LOGV("cmp: FileNameLength\n");
return false;
}
#if 0 // this seems to be used for padding, not real data
if (mCDE.mExtraFieldLength != mLFH.mExtraFieldLength) {
LOGV("cmp: ExtraFieldLength\n");
return false;
}
#endif
if (mCDE.mFileName != NULL) {
if (strcmp((char*) mCDE.mFileName, (char*) mLFH.mFileName) != 0) {
LOGV("cmp: FileName\n");
return false;
}
}
return true;
}
/*
* Convert the DOS date/time stamp into a UNIX time stamp.
*/
time_t ZipEntry::getModWhen(void) const
{
struct tm parts;
parts.tm_sec = (mCDE.mLastModFileTime & 0x001f) << 1;
parts.tm_min = (mCDE.mLastModFileTime & 0x07e0) >> 5;
parts.tm_hour = (mCDE.mLastModFileTime & 0xf800) >> 11;
parts.tm_mday = (mCDE.mLastModFileDate & 0x001f);
parts.tm_mon = ((mCDE.mLastModFileDate & 0x01e0) >> 5) -1;
parts.tm_year = ((mCDE.mLastModFileDate & 0xfe00) >> 9) + 80;
parts.tm_wday = parts.tm_yday = 0;
parts.tm_isdst = -1; // DST info "not available"
return mktime(&parts);
}
/*
* Set the CDE/LFH timestamp from UNIX time.
*/
void ZipEntry::setModWhen(time_t when)
{
#ifdef HAVE_LOCALTIME_R
struct tm tmResult;
#endif
time_t even;
unsigned short zdate, ztime;
struct tm* ptm;
/* round up to an even number of seconds */
even = (time_t)(((unsigned long)(when) + 1) & (~1));
/* expand */
#ifdef HAVE_LOCALTIME_R
ptm = localtime_r(&even, &tmResult);
#else
ptm = localtime(&even);
#endif
int year;
year = ptm->tm_year;
if (year < 80)
year = 80;
zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday;
ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime;
mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate;
}
/*
* ===========================================================================
* ZipEntry::LocalFileHeader
* ===========================================================================
*/
/*
* Read a local file header.
*
* On entry, "fp" points to the signature at the start of the header.
* On exit, "fp" points to the start of data.
*/
status_t ZipEntry::LocalFileHeader::read(FILE* fp)
{
status_t result = NO_ERROR;
unsigned char buf[kLFHLen];
assert(mFileName == NULL);
assert(mExtraField == NULL);
if (fread(buf, 1, kLFHLen, fp) != kLFHLen) {
result = UNKNOWN_ERROR;
goto bail;
}
if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) {
LOGD("whoops: didn't find expected signature\n");
result = UNKNOWN_ERROR;
goto bail;
}
mVersionToExtract = ZipEntry::getShortLE(&buf[0x04]);
mGPBitFlag = ZipEntry::getShortLE(&buf[0x06]);
mCompressionMethod = ZipEntry::getShortLE(&buf[0x08]);
mLastModFileTime = ZipEntry::getShortLE(&buf[0x0a]);
mLastModFileDate = ZipEntry::getShortLE(&buf[0x0c]);
mCRC32 = ZipEntry::getLongLE(&buf[0x0e]);
mCompressedSize = ZipEntry::getLongLE(&buf[0x12]);
mUncompressedSize = ZipEntry::getLongLE(&buf[0x16]);
mFileNameLength = ZipEntry::getShortLE(&buf[0x1a]);
mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1c]);
// TODO: validate sizes
/* grab filename */
if (mFileNameLength != 0) {
mFileName = new unsigned char[mFileNameLength+1];
if (mFileName == NULL) {
result = NO_MEMORY;
goto bail;
}
if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) {
result = UNKNOWN_ERROR;
goto bail;
}
mFileName[mFileNameLength] = '\0';
}
/* grab extra field */
if (mExtraFieldLength != 0) {
mExtraField = new unsigned char[mExtraFieldLength+1];
if (mExtraField == NULL) {
result = NO_MEMORY;
goto bail;
}
if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) {
result = UNKNOWN_ERROR;
goto bail;
}
mExtraField[mExtraFieldLength] = '\0';
}
bail:
return result;
}
/*
* Write a local file header.
*/
status_t ZipEntry::LocalFileHeader::write(FILE* fp)
{
unsigned char buf[kLFHLen];
ZipEntry::putLongLE(&buf[0x00], kSignature);
ZipEntry::putShortLE(&buf[0x04], mVersionToExtract);
ZipEntry::putShortLE(&buf[0x06], mGPBitFlag);
ZipEntry::putShortLE(&buf[0x08], mCompressionMethod);
ZipEntry::putShortLE(&buf[0x0a], mLastModFileTime);
ZipEntry::putShortLE(&buf[0x0c], mLastModFileDate);
ZipEntry::putLongLE(&buf[0x0e], mCRC32);
ZipEntry::putLongLE(&buf[0x12], mCompressedSize);
ZipEntry::putLongLE(&buf[0x16], mUncompressedSize);
ZipEntry::putShortLE(&buf[0x1a], mFileNameLength);
ZipEntry::putShortLE(&buf[0x1c], mExtraFieldLength);
if (fwrite(buf, 1, kLFHLen, fp) != kLFHLen)
return UNKNOWN_ERROR;
/* write filename */
if (mFileNameLength != 0) {
if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength)
return UNKNOWN_ERROR;
}
/* write "extra field" */
if (mExtraFieldLength != 0) {
if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength)
return UNKNOWN_ERROR;
}
return NO_ERROR;
}
/*
* Dump the contents of a LocalFileHeader object.
*/
void ZipEntry::LocalFileHeader::dump(void) const
{
LOGD(" LocalFileHeader contents:\n");
LOGD(" versToExt=%u gpBits=0x%04x compression=%u\n",
mVersionToExtract, mGPBitFlag, mCompressionMethod);
LOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n",
mLastModFileTime, mLastModFileDate, mCRC32);
LOGD(" compressedSize=%lu uncompressedSize=%lu\n",
mCompressedSize, mUncompressedSize);
LOGD(" filenameLen=%u extraLen=%u\n",
mFileNameLength, mExtraFieldLength);
if (mFileName != NULL)
LOGD(" filename: '%s'\n", mFileName);
}
/*
* ===========================================================================
* ZipEntry::CentralDirEntry
* ===========================================================================
*/
/*
* Read the central dir entry that appears next in the file.
*
* On entry, "fp" should be positioned on the signature bytes for the
* entry. On exit, "fp" will point at the signature word for the next
* entry or for the EOCD.
*/
status_t ZipEntry::CentralDirEntry::read(FILE* fp)
{
status_t result = NO_ERROR;
unsigned char buf[kCDELen];
/* no re-use */
assert(mFileName == NULL);
assert(mExtraField == NULL);
assert(mFileComment == NULL);
if (fread(buf, 1, kCDELen, fp) != kCDELen) {
result = UNKNOWN_ERROR;
goto bail;
}
if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) {
LOGD("Whoops: didn't find expected signature\n");
result = UNKNOWN_ERROR;
goto bail;
}
mVersionMadeBy = ZipEntry::getShortLE(&buf[0x04]);
mVersionToExtract = ZipEntry::getShortLE(&buf[0x06]);
mGPBitFlag = ZipEntry::getShortLE(&buf[0x08]);
mCompressionMethod = ZipEntry::getShortLE(&buf[0x0a]);
mLastModFileTime = ZipEntry::getShortLE(&buf[0x0c]);
mLastModFileDate = ZipEntry::getShortLE(&buf[0x0e]);
mCRC32 = ZipEntry::getLongLE(&buf[0x10]);
mCompressedSize = ZipEntry::getLongLE(&buf[0x14]);
mUncompressedSize = ZipEntry::getLongLE(&buf[0x18]);
mFileNameLength = ZipEntry::getShortLE(&buf[0x1c]);
mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1e]);
mFileCommentLength = ZipEntry::getShortLE(&buf[0x20]);
mDiskNumberStart = ZipEntry::getShortLE(&buf[0x22]);
mInternalAttrs = ZipEntry::getShortLE(&buf[0x24]);
mExternalAttrs = ZipEntry::getLongLE(&buf[0x26]);
mLocalHeaderRelOffset = ZipEntry::getLongLE(&buf[0x2a]);
// TODO: validate sizes and offsets
/* grab filename */
if (mFileNameLength != 0) {
mFileName = new unsigned char[mFileNameLength+1];
if (mFileName == NULL) {
result = NO_MEMORY;
goto bail;
}
if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) {
result = UNKNOWN_ERROR;
goto bail;
}
mFileName[mFileNameLength] = '\0';
}
/* read "extra field" */
if (mExtraFieldLength != 0) {
mExtraField = new unsigned char[mExtraFieldLength+1];
if (mExtraField == NULL) {
result = NO_MEMORY;
goto bail;
}
if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) {
result = UNKNOWN_ERROR;
goto bail;
}
mExtraField[mExtraFieldLength] = '\0';
}
/* grab comment, if any */
if (mFileCommentLength != 0) {
mFileComment = new unsigned char[mFileCommentLength+1];
if (mFileComment == NULL) {
result = NO_MEMORY;
goto bail;
}
if (fread(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength)
{
result = UNKNOWN_ERROR;
goto bail;
}
mFileComment[mFileCommentLength] = '\0';
}
bail:
return result;
}
/*
* Write a central dir entry.
*/
status_t ZipEntry::CentralDirEntry::write(FILE* fp)
{
unsigned char buf[kCDELen];
ZipEntry::putLongLE(&buf[0x00], kSignature);
ZipEntry::putShortLE(&buf[0x04], mVersionMadeBy);
ZipEntry::putShortLE(&buf[0x06], mVersionToExtract);
ZipEntry::putShortLE(&buf[0x08], mGPBitFlag);
ZipEntry::putShortLE(&buf[0x0a], mCompressionMethod);
ZipEntry::putShortLE(&buf[0x0c], mLastModFileTime);
ZipEntry::putShortLE(&buf[0x0e], mLastModFileDate);
ZipEntry::putLongLE(&buf[0x10], mCRC32);
ZipEntry::putLongLE(&buf[0x14], mCompressedSize);
ZipEntry::putLongLE(&buf[0x18], mUncompressedSize);
ZipEntry::putShortLE(&buf[0x1c], mFileNameLength);
ZipEntry::putShortLE(&buf[0x1e], mExtraFieldLength);
ZipEntry::putShortLE(&buf[0x20], mFileCommentLength);
ZipEntry::putShortLE(&buf[0x22], mDiskNumberStart);
ZipEntry::putShortLE(&buf[0x24], mInternalAttrs);
ZipEntry::putLongLE(&buf[0x26], mExternalAttrs);
ZipEntry::putLongLE(&buf[0x2a], mLocalHeaderRelOffset);
if (fwrite(buf, 1, kCDELen, fp) != kCDELen)
return UNKNOWN_ERROR;
/* write filename */
if (mFileNameLength != 0) {
if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength)
return UNKNOWN_ERROR;
}
/* write "extra field" */
if (mExtraFieldLength != 0) {
if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength)
return UNKNOWN_ERROR;
}
/* write comment */
if (mFileCommentLength != 0) {
if (fwrite(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength)
return UNKNOWN_ERROR;
}
return NO_ERROR;
}
/*
* Dump the contents of a CentralDirEntry object.
*/
void ZipEntry::CentralDirEntry::dump(void) const
{
LOGD(" CentralDirEntry contents:\n");
LOGD(" versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n",
mVersionMadeBy, mVersionToExtract, mGPBitFlag, mCompressionMethod);
LOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n",
mLastModFileTime, mLastModFileDate, mCRC32);
LOGD(" compressedSize=%lu uncompressedSize=%lu\n",
mCompressedSize, mUncompressedSize);
LOGD(" filenameLen=%u extraLen=%u commentLen=%u\n",
mFileNameLength, mExtraFieldLength, mFileCommentLength);
LOGD(" diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n",
mDiskNumberStart, mInternalAttrs, mExternalAttrs,
mLocalHeaderRelOffset);
if (mFileName != NULL)
LOGD(" filename: '%s'\n", mFileName);
if (mFileComment != NULL)
LOGD(" comment: '%s'\n", mFileComment);
}

Some files were not shown because too many files have changed in this diff Show More