diff options
138 files changed, 10578 insertions, 2356 deletions
@@ -1 +1,2 @@ *.pyc +*.swp diff --git a/CleanSpec.mk b/CleanSpec.mk index fef406c..ab0bd2f 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -200,6 +200,12 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DMService.apk) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/SprintDM.apk) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/omadm) +# GCC 4.8 +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/*.o) + # KLP I mean KitKat now API 19. $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) @@ -211,11 +217,34 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) # 4.4.2 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +# "L" and beyond. +# Make libart the default runtime +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) + # Rename persist.sys.dalvik.vm.lib to allow new default $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +# KKWT development +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*) + +# L development +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*) + +# L development +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*) + # Add ro.product.cpu.abilist{32,64} to build.prop. $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) + +# Unset TARGET_PREFER_32_BIT_APPS for 64 bit targets. +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) # Adding dalvik.vm.dex2oat-flags to eng builds $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) @@ -236,6 +265,14 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) # Switching to 32-bit-by-default host multilib build $(call add-clean-step, rm -rf $(HOST_OUT_INTERMEDIATES)) +# KKWT has become API 20 +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*) + +# ims-common.jar added to BOOTCLASSPATH +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/ETC/init.environ.rc_intermediates) + # Change ro.zygote for core_64_bit.mk from zygote32_64 to zygote64_32 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop) @@ -245,8 +282,11 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system) + # Switch host builds to Clang by default $(call add-clean-step, rm -rf $(OUT_DIR)/host) + # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/core/Makefile b/core/Makefile index 853bd44..36d53e1 100644 --- a/core/Makefile +++ b/core/Makefile @@ -22,7 +22,7 @@ endif # src:dest pair is the first one to match the same dest" #$(1): the src:dest pair define check-product-copy-files -$(if $(filter %.apk, $(1)),$(error \ +$(if $(filter %.apk, $(call word-colon, 2, $(1))),$(error \ Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!)) endef # filter out the duplicate <source file>:<dest file> pairs. @@ -109,7 +109,7 @@ BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS))) build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER) $(BUILD_VERSION_TAGS) $(INSTALLED_BUILD_PROP_TARGET): PRIVATE_BUILD_DESC := $(build_desc) -# The string used to uniquely identify this build; used by the OTA server. +# The string used to uniquely identify the combined build and product; used by the OTA server. ifeq (,$(strip $(BUILD_FINGERPRINT))) ifneq ($(filter eng.%,$(BUILD_NUMBER)),) # Trim down BUILD_FINGERPRINT: the default BUILD_NUMBER makes it easily exceed @@ -124,6 +124,15 @@ ifneq ($(words $(BUILD_FINGERPRINT)),1) $(error BUILD_FINGERPRINT cannot contain spaces: "$(BUILD_FINGERPRINT)") endif +# The string used to uniquely identify the system build; used by the OTA server. +# This purposefully excludes any product-specific variables. +ifeq (,$(strip $(BUILD_THUMBPRINT))) + BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS) +endif +ifneq ($(words $(BUILD_THUMBPRINT)),1) + $(error BUILD_THUMBPRINT cannot contain spaces: "$(BUILD_THUMBPRINT)") +endif + # Display parameters shown under Settings -> About Phone ifeq ($(TARGET_BUILD_VARIANT),user) # User builds should show: @@ -172,10 +181,17 @@ system_prop_file := $(TARGET_SYSTEM_PROP) else system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop) endif - $(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) @echo Target buildinfo: $@ @mkdir -p $(dir $@) + $(hide) echo > $@ +ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES),) + $(hide) echo "#" >> $@; \ + echo "# PRODUCT_OEM_PROPERTIES" >> $@; \ + echo "#" >> $@; + $(hide) $(foreach prop,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES), \ + echo "import /oem/oem.prop $(prop)" >> $@;) +endif $(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \ TARGET_DEVICE="$(TARGET_DEVICE)" \ PRODUCT_NAME="$(TARGET_PRODUCT)" \ @@ -192,17 +208,21 @@ $(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $( PLATFORM_VERSION="$(PLATFORM_VERSION)" \ PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \ PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \ + PLATFORM_VERSION_ALL_CODENAMES="$(PLATFORM_VERSION_ALL_CODENAMES)" \ BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \ TARGET_BOOTLOADER_BOARD_NAME="$(TARGET_BOOTLOADER_BOARD_NAME)" \ BUILD_FINGERPRINT="$(BUILD_FINGERPRINT)" \ + BUILD_THUMBPRINT="$(BUILD_THUMBPRINT)" \ TARGET_BOARD_PLATFORM="$(TARGET_BOARD_PLATFORM)" \ TARGET_CPU_ABI_LIST="$(TARGET_CPU_ABI_LIST)" \ TARGET_CPU_ABI_LIST_32_BIT="$(TARGET_CPU_ABI_LIST_32_BIT)" \ TARGET_CPU_ABI_LIST_64_BIT="$(TARGET_CPU_ABI_LIST_64_BIT)" \ TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \ TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \ + TARGET_2ND_CPU_ABI="$(TARGET_2ND_CPU_ABI)" \ + TARGET_2ND_CPU_ABI2="$(TARGET_2ND_CPU_ABI2)" \ TARGET_AAPT_CHARACTERISTICS="$(TARGET_AAPT_CHARACTERISTICS)" \ - bash $(BUILDINFO_SH) > $@ + bash $(BUILDINFO_SH) >> $@ $(hide) $(foreach file,$(system_prop_file), \ if [ -f "$(file)" ]; then \ echo "#" >> $@; \ @@ -218,11 +238,27 @@ $(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $( echo "#" >> $@; ) $(hide) $(foreach line,$(ADDITIONAL_BUILD_PROPERTIES), \ echo "$(line)" >> $@;) - $(hide) build/tools/post_process_props.py $@ + $(hide) build/tools/post_process_props.py $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_PROPERTY_BLACKLIST) build_desc := # ----------------------------------------------------------------- +# vendor build.prop +# +# For verifying that the vendor build is what we thing it is +ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE +INSTALLED_VENDOR_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR)/build.prop +ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_VENDOR_BUILD_PROP_TARGET) +$(INSTALLED_VENDOR_BUILD_PROP_TARGET): $(INSTALLED_BUILD_PROP_TARGET) + @echo Target vendor buildinfo: $@ + @mkdir -p $(dir $@) + $(hide) echo > $@ + $(hide) echo ro.vendor.build.date=`date`>>$@ + $(hide) echo ro.vendor.build.date.utc=`date +%s`>>$@ + $(hide) echo ro.vendor.build.fingerprint="$(BUILD_FINGERPRINT)">>$@ +endif + +# ----------------------------------------------------------------- # sdk-build.prop # # There are certain things in build.prop that we don't want to @@ -459,18 +495,33 @@ bootimage-nodeps: $(MKEXT2IMG) @echo "make $@: ignoring dependencies" $(hide) $(MKEXT2BOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET) -else # TARGET_BOOTIMAGE_USE_EXT2 != true +else ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)) # TARGET_BOOTIMAGE_USE_EXT2 != true + +$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER) + $(call pretty,"Target boot image: $@") + $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@ + $(BOOT_SIGNER) /boot $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY) $@ + $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE)) + +.PHONY: bootimage-nodeps +bootimage-nodeps: $(MKBOOTIMG) $(BOOT_SIGNER) + @echo "make $@: ignoring dependencies" + $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET) + $(BOOT_SIGNER) /boot $(INSTALLED_BOOTIMAGE_TARGET) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY) $(INSTALLED_BOOTIMAGE_TARGET) + $(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE)) + +else # PRODUCT_SUPPORTS_VERITY != true $(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(call pretty,"Target boot image: $@") $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@ - $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE),raw) + $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE)) .PHONY: bootimage-nodeps bootimage-nodeps: $(MKBOOTIMG) @echo "make $@: ignoring dependencies" $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET) - $(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE),raw) + $(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE)) endif # TARGET_BOOTIMAGE_USE_EXT2 @@ -623,12 +674,21 @@ ifneq (true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED)) endif ifeq ($(INTERNAL_USERIMAGES_USE_EXT),true) -INTERNAL_USERIMAGES_DEPS := $(MKEXTUSERIMG) $(MAKE_EXT4FS) $(SIMG2IMG) $(E2FSCK) +INTERNAL_USERIMAGES_DEPS := $(SIMG2IMG) +INTERNAL_USERIMAGES_DEPS += $(MKEXTUSERIMG) $(MAKE_EXT4FS) $(E2FSCK) +ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) +INTERNAL_USERIMAGES_DEPS += $(MKF2FSUSERIMG) $(MAKE_F2FS) +endif else INTERNAL_USERIMAGES_DEPS := $(MKYAFFS2) endif + INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS))) +ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)) +INTERNAL_USERIMAGES_DEPS += $(BUILD_VERITY_TREE) $(APPEND2SIMG) $(VERITY_SIGNER) +endif + SELINUX_FC := $(TARGET_ROOT_OUT)/file_contexts INTERNAL_USERIMAGES_DEPS += $(SELINUX_FC) @@ -637,14 +697,21 @@ INTERNAL_USERIMAGES_DEPS += $(SELINUX_FC) define generate-userimage-prop-dictionary $(if $(INTERNAL_USERIMAGES_EXT_VARIANT),$(hide) echo "fs_type=$(INTERNAL_USERIMAGES_EXT_VARIANT)" >> $(1)) $(if $(BOARD_SYSTEMIMAGE_PARTITION_SIZE),$(hide) echo "system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(1)) +$(if $(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "userdata_fs_type=$(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) $(if $(BOARD_USERDATAIMAGE_PARTITION_SIZE),$(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)" >> $(1)) $(if $(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "cache_fs_type=$(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) $(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),$(hide) echo "cache_size=$(BOARD_CACHEIMAGE_PARTITION_SIZE)" >> $(1)) $(if $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_fs_type=$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) $(if $(BOARD_VENDORIMAGE_PARTITION_SIZE),$(hide) echo "vendor_size=$(BOARD_VENDORIMAGE_PARTITION_SIZE)" >> $(1)) +$(if $(BOARD_OEMIMAGE_PARTITION_SIZE),$(hide) echo "oem_size=$(BOARD_OEMIMAGE_PARTITION_SIZE)" >> $(1)) $(if $(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG),$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(1)) $(if $(mkyaffs2_extra_flags),$(hide) echo "mkyaffs2_extra_flags=$(mkyaffs2_extra_flags)" >> $(1)) $(hide) echo "selinux_fc=$(SELINUX_FC)" >> $(1) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)" >> $(1)) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)" >> $(1)) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(VERITY_SIGNER)" >> $(1)) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION)" >> $(1)) +$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1)) $(if $(2),$(hide) $(foreach kv,$(2),echo "$(kv)" >> $(1);)) endef @@ -664,11 +731,32 @@ recovery_build_prop := $(INSTALLED_BUILD_PROP_TARGET) recovery_binary := $(call intermediates-dir-for,EXECUTABLES,recovery)/recovery recovery_resources_common := $(call include-path-for, recovery)/res -# Select the 18x32 font on high-density devices; and the 12x22 font on -# other devices. Note that the font selected here can be overridden -# for a particular device by putting a font.png in its private -# recovery resources. -ifneq (,$(filter xxhdpi xhdpi,$(subst $(comma),$(space),$(PRODUCT_AAPT_CONFIG)))) +# Set recovery_density to the density bucket of the device. +recovery_density := unknown +ifneq (,$(PRODUCT_AAPT_PREF_CONFIG)) +# If PRODUCT_AAPT_PREF_CONFIG includes a dpi bucket, then use that value. +recovery_density := $(filter %dpi,$(PRODUCT_AAPT_PREF_CONFIG)) +else +# Otherwise, use the highest density that appears in PRODUCT_AAPT_CONFIG. +# Order is important here; we'll take the first one that's found. +recovery_densities := $(filter $(PRODUCT_AAPT_CONFIG_SP),xxxhdpi xxhdpi xhdpi hdpi tvdpi mdpi ldpi) +ifneq (,$(recovery_densities)) +recovery_density := $(word 1,$(recovery_densities)) +endif +endif + +ifneq (,$(wildcard $(recovery_resources_common)-$(recovery_density))) +recovery_resources_common := $(recovery_resources_common)-$(recovery_density) +else +recovery_resources_common := $(recovery_resources_common)-xhdpi +endif + +# Select the 18x32 font on high-density devices (xhdpi and up); and +# the 12x22 font on other devices. Note that the font selected here +# can be overridden for a particular device by putting a font.png in +# its private recovery resources. + +ifneq (,$(filter xxxhdpi xxhdpi xhdpi,$(recovery_density))) recovery_font := $(call include-path-for, recovery)/fonts/18x32.png else recovery_font := $(call include-path-for, recovery)/fonts/12x22.png @@ -750,7 +838,9 @@ $(INSTALLED_RECOVERYIMAGE_TARGET): $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) \ $(hide) cp -f $(recovery_sepolicy) $(TARGET_RECOVERY_ROOT_OUT)/sepolicy $(hide) -cp $(TARGET_ROOT_OUT)/init.recovery.*.rc $(TARGET_RECOVERY_ROOT_OUT)/ $(hide) cp -f $(recovery_binary) $(TARGET_RECOVERY_ROOT_OUT)/sbin/ - $(hide) cp -rf $(recovery_resources_common) $(TARGET_RECOVERY_ROOT_OUT)/ + $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/res + $(hide) rm -rf $(TARGET_RECOVERY_ROOT_OUT)/res/* + $(hide) cp -rf $(recovery_resources_common)/* $(TARGET_RECOVERY_ROOT_OUT)/res $(hide) cp -f $(recovery_font) $(TARGET_RECOVERY_ROOT_OUT)/res/images/font.png $(hide) $(foreach item,$(recovery_resources_private), \ cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/) @@ -761,7 +851,7 @@ $(INSTALLED_RECOVERYIMAGE_TARGET): $(MKBOOTFS) $(MKBOOTIMG) $(MINIGZIP) \ > $(TARGET_RECOVERY_ROOT_OUT)/default.prop $(hide) $(MKBOOTFS) $(TARGET_RECOVERY_ROOT_OUT) | $(MINIGZIP) > $(recovery_ramdisk) $(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@ - $(hide) $(call assert-max-image-size,$@,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE),raw) + $(hide) $(call assert-max-image-size,$@,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)) @echo ----- Made recovery image: $@ -------- $(RECOVERY_RESOURCE_ZIP): $(INSTALLED_RECOVERYIMAGE_TARGET) @@ -828,11 +918,28 @@ systemimage_intermediates := \ $(call intermediates-dir-for,PACKAGING,systemimage) BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img +# Create symlink /system/vendor to /vendor if necessary. +ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE +define create-system-vendor-symlink +$(hide) if [ -d $(TARGET_OUT)/vendor ] && [ ! -h $(TARGET_OUT)/vendor ]; then \ + echo 'Non-symlink $(TARGET_OUT)/vendor detected!' 1>&2; \ + echo 'You cannot install files to $(TARGET_OUT)/vendor while building a separate vendor.img!' 1>&2; \ + exit 1; \ +fi +$(hide) ln -sf /vendor $(TARGET_OUT)/vendor +endef +else +define create-system-vendor-symlink +endef +endif + # $(1): output file define build-systemimage-target @echo "Target system fs image: $(1)" + $(call create-system-vendor-symlink) @mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt - $(call generate-userimage-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt, skip_fsck=true) + $(call generate-userimage-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt, \ + skip_fsck=true) $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ ./build/tools/releasetools/build_image.py \ $(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) @@ -865,7 +972,7 @@ endif $(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH) | $(ACP) @echo "Install system fs image: $@" $(copy-file-to-target) - $(hide) $(call assert-max-image-size,$@ $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE),yaffs) + $(hide) $(call assert-max-image-size,$@ $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)) systemimage: $(INSTALLED_SYSTEMIMAGE) @@ -874,7 +981,7 @@ systemimage-nodeps snod: $(filter-out systemimage-nodeps snod,$(MAKECMDGOALS)) \ | $(INTERNAL_USERIMAGES_DEPS) @echo "make $@: ignoring dependencies" $(call build-systemimage-target,$(INSTALLED_SYSTEMIMAGE)) - $(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMIMAGE),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE),yaffs) + $(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMIMAGE),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)) ifneq (,$(filter systemimage-nodeps snod, $(MAKECMDGOALS))) ifeq (true,$(WITH_DEXPREOPT)) @@ -885,10 +992,11 @@ endif ####### ## system tarball define build-systemtarball-target - $(call pretty,"Target system fs tarball: $(INSTALLED_SYSTEMTARBALL_TARGET)") - $(MKTARBALL) $(FS_GET_STATS) \ - $(PRODUCT_OUT) system $(PRIVATE_SYSTEM_TAR) \ - $(INSTALLED_SYSTEMTARBALL_TARGET) + $(call pretty,"Target system fs tarball: $(INSTALLED_SYSTEMTARBALL_TARGET)") + $(call create-system-vendor-symlink) + $(MKTARBALL) $(FS_GET_STATS) \ + $(PRODUCT_OUT) system $(PRIVATE_SYSTEM_TAR) \ + $(INSTALLED_SYSTEMTARBALL_TARGET) endef ifndef SYSTEM_TARBALL_FORMAT @@ -909,11 +1017,6 @@ systemtarball-nodeps: $(FS_GET_STATS) \ .PHONY: stnod stnod: systemtarball-nodeps -# For platform-java goal, add platform as well -ifneq (,$(filter platform-java, $(MAKECMDGOALS))) -PLATFORM_ZIP_ADD_JAVA := true -endif - ####### ## platform.zip: system, plus other files to be used in PDK fusion build, ## in a zip file @@ -930,7 +1033,11 @@ $(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_SYSTEMIMAGE_FILES) $(TARGET_COPY_OUT_SYSTEM) \ $(patsubst $(PRODUCT_OUT)/%, %, $(TARGET_OUT_NOTICE_FILES)) \ $(addprefix symbols/,$(PDK_SYMBOL_FILES_LIST)) -ifeq (true,$(PLATFORM_ZIP_ADD_JAVA)) +ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE + $(hide) cd $(dir $@) && zip -qry $(notdir $@) \ + $(TARGET_COPY_OUT_VENDOR) +endif +ifneq ($(PDK_PLATFORM_JAVA_ZIP_CONTENTS),) $(hide) cd $(OUT_DIR) && zip -qry $(patsubst $(OUT_DIR)/%,%,$@) $(PDK_PLATFORM_JAVA_ZIP_CONTENTS) endif ifneq ($(PDK_PLATFORM_ZIP_PRODUCT_BINARIES),) @@ -1002,7 +1109,7 @@ define build-userdataimage-target $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ ./build/tools/releasetools/build_image.py \ $(TARGET_OUT_DATA) $(userdataimage_intermediates)/userdata_image_info.txt $(INSTALLED_USERDATAIMAGE_TARGET) - $(hide) $(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE),yaffs) + $(hide) $(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE)) endef # We just build this directly to the install location. @@ -1057,7 +1164,7 @@ define build-cacheimage-target $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ ./build/tools/releasetools/build_image.py \ $(TARGET_OUT_CACHE) $(cacheimage_intermediates)/cache_image_info.txt $(INSTALLED_CACHEIMAGE_TARGET) - $(hide) $(call assert-max-image-size,$(INSTALLED_CACHEIMAGE_TARGET),$(BOARD_CACHEIMAGE_PARTITION_SIZE),yaffs) + $(hide) $(call assert-max-image-size,$(INSTALLED_CACHEIMAGE_TARGET),$(BOARD_CACHEIMAGE_PARTITION_SIZE)) endef # We just build this directly to the install location. @@ -1076,7 +1183,12 @@ endif # BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE # vendor partition image ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE INTERNAL_VENDORIMAGE_FILES := \ - $(filter $(TARGET_OUT_VENDOR)/%,$(ALL_DEFAULT_INSTALLED_MODULES)) + $(filter $(TARGET_OUT_VENDOR)/%,\ + $(ALL_DEFAULT_INSTALLED_MODULES)\ + $(ALL_PDK_FUSION_FILES)) + +# platform.zip depends on $(INTERNAL_VENDORIMAGE_FILES). +$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_VENDORIMAGE_FILES) vendorimage_intermediates := \ $(call intermediates-dir-for,PACKAGING,vendor) @@ -1090,7 +1202,7 @@ define build-vendorimage-target $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ ./build/tools/releasetools/build_image.py \ $(TARGET_OUT_VENDOR) $(vendorimage_intermediates)/vendor_image_info.txt $(INSTALLED_VENDORIMAGE_TARGET) - $(hide) $(call assert-max-image-size,$(INSTALLED_VENDORIMAGE_TARGET),$(BOARD_VENDORIMAGE_PARTITION_SIZE),yaffs) + $(hide) $(call assert-max-image-size,$(INSTALLED_VENDORIMAGE_TARGET),$(BOARD_VENDORIMAGE_PARTITION_SIZE)) endef # We just build this directly to the install location. @@ -1126,7 +1238,13 @@ DISTTOOLS := $(HOST_OUT_EXECUTABLES)/minigzip \ $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \ $(HOST_OUT_EXECUTABLES)/make_ext4fs \ $(HOST_OUT_EXECUTABLES)/simg2img \ - $(HOST_OUT_EXECUTABLES)/e2fsck + $(HOST_OUT_EXECUTABLES)/e2fsck \ + $(HOST_OUT_EXECUTABLES)/xdelta3 \ + $(HOST_OUT_EXECUTABLES)/syspatch_host \ + $(HOST_OUT_EXECUTABLES)/build_verity_tree \ + $(HOST_OUT_EXECUTABLES)/verity_signer \ + $(HOST_OUT_EXECUTABLES)/append2simg \ + $(HOST_OUT_EXECUTABLES)/boot_signer OTATOOLS := $(DISTTOOLS) \ $(HOST_OUT_EXECUTABLES)/aapt @@ -1282,11 +1400,18 @@ endif $(hide) echo "use_set_metadata=1" >> $(zip_root)/META/misc_info.txt $(hide) echo "multistage_support=1" >> $(zip_root)/META/misc_info.txt $(hide) echo "update_rename_support=1" >> $(zip_root)/META/misc_info.txt +ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES),) + # OTA scripts are only interested in fingerprint related properties + $(hide) echo "oem_fingerprint_properties=$(filter ro.product.brand ro.product.name ro.product.device, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES))" >> $(zip_root)/META/misc_info.txt +endif $(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt) + $(hide) ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root) @# Zip everything up, preserving symlinks $(hide) (cd $(zip_root) && zip -qry ../$(notdir $@) .) - @# Run fs_config on all the system, boot ramdisk, and recovery ramdisk files in the zip, and save the output + @# Run fs_config on all the system, vendor, boot ramdisk, + @# and recovery ramdisk files in the zip, and save the output $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="SYSTEM/" } /^SYSTEM\// {print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/filesystem_config.txt + $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="VENDOR/" } /^VENDOR\// {print "vendor/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/vendor_filesystem_config.txt $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="BOOT/RAMDISK/" } /^BOOT\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/boot_filesystem_config.txt $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/recovery_filesystem_config.txt $(hide) (cd $(zip_root) && zip -q ../$(notdir $@) META/*filesystem_config.txt) @@ -1294,6 +1419,9 @@ endif .PHONY: target-files-package target-files-package: $(BUILT_TARGET_FILES_PACKAGE) +ifneq ($(filter $(MAKECMDGOALS),target-files-package),) +$(call dist-for-goals, target-files-package, $(BUILT_TARGET_FILES_PACKAGE)) +endif ifneq ($(TARGET_PRODUCT),sdk) ifeq ($(filter generic%,$(TARGET_DEVICE)),) @@ -1317,13 +1445,20 @@ $(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(DISTTOOLS) @echo "Package OTA: $@" $(hide) MKBOOTIMG=$(MKBOOTIMG) \ ./build/tools/releasetools/ota_from_target_files -v \ + --block \ -p $(HOST_OUT) \ -k $(KEY_CERT_PAIR) \ + $(if $(OEM_OTA_CONFIG), -o $(OEM_OTA_CONFIG)) \ $(BUILT_TARGET_FILES_PACKAGE) $@ .PHONY: otapackage otapackage: $(INTERNAL_OTA_PACKAGE_TARGET) +endif # recovery_fstab is defined +endif # TARGET_NO_KERNEL != true +endif # TARGET_DEVICE != generic* +endif # TARGET_PRODUCT != sdk + # ----------------------------------------------------------------- # The update package @@ -1335,29 +1470,16 @@ name := $(name)-img-$(FILE_NAME_TAG) INTERNAL_UPDATE_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip -ifeq ($(TARGET_RELEASETOOLS_EXTENSIONS),) -# default to common dir for device vendor -$(INTERNAL_UPDATE_PACKAGE_TARGET): extensions := $(TARGET_DEVICE_DIR)/../common -else -$(INTERNAL_UPDATE_PACKAGE_TARGET): extensions := $(TARGET_RELEASETOOLS_EXTENSIONS) -endif - $(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(DISTTOOLS) @echo "Package: $@" $(hide) MKBOOTIMG=$(MKBOOTIMG) \ ./build/tools/releasetools/img_from_target_files -v \ - -s $(extensions) \ -p $(HOST_OUT) \ $(BUILT_TARGET_FILES_PACKAGE) $@ .PHONY: updatepackage updatepackage: $(INTERNAL_UPDATE_PACKAGE_TARGET) -endif # recovery_fstab is defined -endif # TARGET_NO_KERNEL != true -endif # TARGET_DEVICE != generic* -endif # TARGET_PRODUCT != sdk - # ----------------------------------------------------------------- # A zip of the symbols directory. Keep the full paths to make it # more obvious where these files came from. @@ -1390,7 +1512,7 @@ $(APPS_ZIP): $(INSTALLED_SYSTEMIMAGE) @echo "Package apps: $@" $(hide) rm -rf $@ $(hide) mkdir -p $(dir $@) - $(hide) zip -qj $@ $(TARGET_OUT_APPS)/* $(TARGET_OUT_APPS_PRIVILEGED)/* + $(hide) zip -qj $@ $(TARGET_OUT_APPS)/*/*.apk $(TARGET_OUT_APPS_PRIVILEGED)/*/*.apk #------------------------------------------------------------------ @@ -1402,7 +1524,7 @@ EMMA_META_ZIP := $(PRODUCT_OUT)/emma_meta.zip # the dependency will be set up later in build/core/main.mk. $(EMMA_META_ZIP) : @echo "Collecting Emma coverage meta files." - $(hide) find $(TARGET_COMMON_OUT_ROOT) -name "coverage.em" | \ + $(hide) find $(TARGET_COMMON_OUT_ROOT) $(HOST_COMMON_OUT_ROOT) -name "coverage.em" | \ zip -@ -q $@ endif # EMMA_INSTRUMENT=true @@ -1418,7 +1540,8 @@ $(PROGUARD_DICT_ZIP) : @echo "Packaging Proguard obfuscation dictionary files." $(hide) dict_files=`find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary`; \ if [ -n "$$dict_files" ]; then \ - zip -q $@ $$dict_files; \ + unobfuscated_jars=$${dict_files//proguard_dictionary/classes.jar}; \ + zip -q $@ $$dict_files $$unobfuscated_jars; \ else \ touch $(dir $@)/dummy; \ (cd $(dir $@) && zip -q $(notdir $@) dummy); \ @@ -1494,7 +1617,6 @@ ifeq ($(strip $(ATREE_FILES)),) ATREE_FILES := \ $(ALL_PREBUILT) \ $(ALL_COPIED_HEADERS) \ - $(ALL_GENERATED_SOURCES) \ $(ALL_DEFAULT_INSTALLED_MODULES) \ $(INSTALLED_RAMDISK_TARGET) \ $(ALL_DOCS) \ @@ -1506,7 +1628,6 @@ atree_dir := development/build sdk_atree_files := \ $(atree_dir)/sdk.exclude.atree \ - $(atree_dir)/sdk.atree \ $(atree_dir)/sdk-$(HOST_OS)-$(SDK_HOST_ARCH).atree # development/build/sdk-android-<abi>.atree is used to differentiate @@ -1517,6 +1638,12 @@ ifneq (,$(strip $(wildcard $(atree_dir)/sdk-android-$(TARGET_CPU_ABI).atree))) sdk_atree_files += $(atree_dir)/sdk-android-$(TARGET_CPU_ABI).atree endif +ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ATREE_FILES),) +sdk_atree_files += $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ATREE_FILES) +else +sdk_atree_files += $(atree_dir)/sdk.atree +endif + deps := \ $(target_notice_file_txt) \ $(tools_notice_file_txt) \ @@ -1528,7 +1655,7 @@ deps := \ $(INSTALLED_SDK_BUILD_PROP_TARGET) \ $(INSTALLED_BUILD_PROP_TARGET) \ $(ATREE_FILES) \ - $(atree_dir)/sdk.atree \ + $(sdk_atree_files) \ $(HOST_OUT_EXECUTABLES)/atree \ $(HOST_OUT_EXECUTABLES)/line_endings @@ -1538,6 +1665,10 @@ $(INTERNAL_SDK_TARGET): PRIVATE_DIR := $(sdk_dir)/$(sdk_name) $(INTERNAL_SDK_TARGET): PRIVATE_DEP_FILE := $(sdk_dep_file) $(INTERNAL_SDK_TARGET): PRIVATE_INPUT_FILES := $(sdk_atree_files) +sdk_font_temp_dir := $(call intermediates-dir-for,PACKAGING,sdk-fonts) +sdk_font_input_list := frameworks/base/data/fonts external/noto-fonts external/google-fonts external/naver-fonts +sdk_font_rename_script := frameworks/base/tools/layoutlib/rename_font/build_font.py + # Set SDK_GNU_ERROR to non-empty to fail when a GNU target is built. # #SDK_GNU_ERROR := true @@ -1553,6 +1684,9 @@ $(INTERNAL_SDK_TARGET): $(deps) fi; \ done; \ if [ $$FAIL ]; then exit 1; fi + $(hide) mkdir -p $(sdk_font_temp_dir) + $(hide) PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib $(sdk_font_rename_script) $(sdk_font_input_list) \ + $(sdk_font_temp_dir) $(hide) ( \ ATREE_STRIP="strip -x" \ $(HOST_OUT_EXECUTABLES)/atree \ @@ -1568,6 +1702,7 @@ $(INTERNAL_SDK_TARGET): $(deps) -v "TARGET_ARCH=$(TARGET_ARCH)" \ -v "TARGET_CPU_ABI=$(TARGET_CPU_ABI)" \ -v "DLL_EXTENSION=$(HOST_SHLIB_SUFFIX)" \ + -v "FONT_OUT=$(sdk_font_temp_dir)" \ -o $(PRIVATE_DIR) && \ cp -f $(target_notice_file_txt) \ $(PRIVATE_DIR)/system-images/android-$(PLATFORM_VERSION)/$(TARGET_CPU_ABI)/NOTICE.txt && \ @@ -1594,11 +1729,11 @@ INTERNAL_FINDBUGS_XML_TARGET := $(PRODUCT_OUT)/findbugs.xml INTERNAL_FINDBUGS_HTML_TARGET := $(PRODUCT_OUT)/findbugs.html $(INTERNAL_FINDBUGS_XML_TARGET): $(ALL_FINDBUGS_FILES) @echo UnionBugs: $@ - $(hide) prebuilt/common/findbugs/bin/unionBugs $(ALL_FINDBUGS_FILES) \ + $(hide) $(FINDBUGS_DIR)/unionBugs $(ALL_FINDBUGS_FILES) \ > $@ $(INTERNAL_FINDBUGS_HTML_TARGET): $(INTERNAL_FINDBUGS_XML_TARGET) @echo ConvertXmlToText: $@ - $(hide) prebuilt/common/findbugs/bin/convertXmlToText -html:fancy.xsl \ + $(hide) $(FINDBUGS_DIR)/convertXmlToText -html:fancy.xsl \ $(INTERNAL_FINDBUGS_XML_TARGET) > $@ # ----------------------------------------------------------------- diff --git a/core/android_manifest.mk b/core/android_manifest.mk new file mode 100644 index 0000000..21b95c2 --- /dev/null +++ b/core/android_manifest.mk @@ -0,0 +1,25 @@ +# Handle AndroidManifest.xmls +# Input: LOCAL_MANIFEST_FILE, LOCAL_FULL_MANIFEST_FILE, LOCAL_FULL_LIBS_MANIFEST_FILES +# Output: full_android_manifest + +ifeq ($(strip $(LOCAL_MANIFEST_FILE)),) + LOCAL_MANIFEST_FILE := AndroidManifest.xml +endif +ifdef LOCAL_FULL_MANIFEST_FILE + full_android_manifest := $(LOCAL_FULL_MANIFEST_FILE) +else + full_android_manifest := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE) +endif + +# Set up rules to merge library manifest files +ifdef LOCAL_FULL_LIBS_MANIFEST_FILES +main_android_manifest := $(full_android_manifest) +full_android_manifest := $(intermediates.COMMON)/AndroidManifest.xml +$(full_android_manifest): PRIVATE_LIBS_MANIFESTS := $(LOCAL_FULL_LIBS_MANIFEST_FILES) +$(full_android_manifest) : $(main_android_manifest) $(LOCAL_FULL_LIBS_MANIFEST_FILES) + @echo "Merge android manifest files: $@ <-- $^" + @mkdir -p $(dir $@) + $(hide) $(ANDROID_MANIFEST_MERGER) --main $< --libs $(PRIVATE_LIBS_MANIFESTS) \ + --out $@ + +endif diff --git a/core/apicheck_msg_current.txt b/core/apicheck_msg_current.txt index 440e7f8..9abd381 100644 --- a/core/apicheck_msg_current.txt +++ b/core/apicheck_msg_current.txt @@ -7,7 +7,7 @@ To make these errors go away, you have two choices: errors above. 2) You can update current.txt by executing the following command: - make update-api + make %UPDATE_API% To submit the revised current.txt to the main Android repository, you will need approval. diff --git a/core/base_rules.mk b/core/base_rules.mk index e840047..7663ee2 100644 --- a/core/base_rules.mk +++ b/core/base_rules.mk @@ -114,6 +114,8 @@ ifeq ($(my_module_path),) else ifeq (true,$(LOCAL_PROPRIETARY_MODULE)) partition_tag := _VENDOR + else ifeq (true,$(LOCAL_OEM_MODULE)) + partition_tag := _OEM else # The definition of should-install-to-system will be different depending # on which goal (e.g., sdk or just droid) is being built. @@ -174,9 +176,15 @@ else built_module_path := $(intermediates) endif LOCAL_BUILT_MODULE := $(built_module_path)/$(my_built_module_stem) -built_module_path := ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE)) + # Apk and its attachments reside in its own subdir. + ifeq ($(LOCAL_MODULE_CLASS),APPS) + # framework-res.apk doesn't like the additional layer. + ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true) + my_module_path := $(my_module_path)/$(LOCAL_MODULE) + endif + endif LOCAL_INSTALLED_MODULE := $(my_module_path)/$(my_installed_module_stem) endif @@ -198,12 +206,12 @@ aidl_sources := $(addprefix $(TOP_DIR)$(LOCAL_PATH)/, $(aidl_sources)) aidl_preprocess_import := LOCAL_SDK_VERSION:=$(strip $(LOCAL_SDK_VERSION)) ifdef LOCAL_SDK_VERSION -ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current) +ifneq ($(filter current system_current, $(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS)),) # LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS aidl_preprocess_import := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl else aidl_preprocess_import := $(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_VERSION)/framework.aidl -endif # !current +endif # not current or system_current else # build against the platform. LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) @@ -230,7 +238,7 @@ event_log_tags := $(addprefix $(LOCAL_PATH)/,$(logtags_sources)) # Emit a java source file with constants for the tags, if # LOCAL_MODULE_CLASS is "APPS" or "JAVA_LIBRARIES". -ifneq ($(strip $(filter $(LOCAL_MODULE_CLASS),APPS JAVA_LIBRARIES)),) +ifneq ($(filter $(LOCAL_MODULE_CLASS),APPS JAVA_LIBRARIES),) logtags_java_sources := $(patsubst %.logtags,%.java,$(addprefix $(intermediates.COMMON)/src/, $(logtags_sources))) logtags_sources := $(addprefix $(TOP_DIR)$(LOCAL_PATH)/, $(logtags_sources)) @@ -386,9 +394,11 @@ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current) # LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS. $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-files,android_stubs_current) +else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current) +$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-files,android_system_stubs_current) else $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-files,sdk_v$(LOCAL_SDK_VERSION)) -endif # current +endif # current or system_current endif # LOCAL_SDK_VERSION endif # TARGET_ $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR) @@ -423,10 +433,10 @@ full_java_lib_deps += $(full_static_java_libs) $(LOCAL_CLASSPATH) # This is set by packages that are linking to other packages that export # shared libraries, allowing them to make use of the code in the linked apk. -LOCAL_APK_LIBRARIES := $(strip $(LOCAL_APK_LIBRARIES)) -ifdef LOCAL_APK_LIBRARIES +apk_libraries := $(sort $(LOCAL_APK_LIBRARIES) $(LOCAL_RES_LIBRARIES)) +ifneq ($(apk_libraries),) link_apk_libraries := \ - $(foreach lib,$(LOCAL_APK_LIBRARIES), \ + $(foreach lib,$(apk_libraries), \ $(call intermediates-dir-for, \ APPS,$(lib),,COMMON)/classes.jar) @@ -598,7 +608,7 @@ ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE)) ALL_MODULES.$(my_register_name).INSTALLED := \ $(strip $(ALL_MODULES.$(my_register_name).INSTALLED) $(LOCAL_INSTALLED_MODULE)) ALL_MODULES.$(my_register_name).BUILT_INSTALLED := \ - $(strip $(ALL_MODULES.$(my_register_name).BUILT_INSTALLED)$(LOCAL_BUILT_MODULE):$(LOCAL_INSTALLED_MODULE)) + $(strip $(ALL_MODULES.$(my_register_name).BUILT_INSTALLED) $(LOCAL_BUILT_MODULE):$(LOCAL_INSTALLED_MODULE)) endif ifdef LOCAL_PICKUP_FILES # Files or directories ready to pick up by the build system @@ -622,6 +632,9 @@ endif ifdef LOCAL_2ND_ARCH_VAR_PREFIX ALL_MODULES.$(my_register_name).FOR_2ND_ARCH := true endif +ifdef aidl_sources +ALL_MODULES.$(my_register_name).AIDL_FILES := $(aidl_sources) +endif INSTALLABLE_FILES.$(LOCAL_INSTALLED_MODULE).MODULE := $(my_register_name) diff --git a/core/binary.mk b/core/binary.mk index 3a53e48..1fdf9f5 100644 --- a/core/binary.mk +++ b/core/binary.mk @@ -164,6 +164,8 @@ endif ifeq ($(strip $(LOCAL_ADDRESS_SANITIZER)),true) my_clang := true + # Frame pointer based unwinder in ASan requires ARM frame setup. + LOCAL_ARM_MODE := arm my_cflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS) my_ldflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS) my_shared_libraries += $(ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES) @@ -474,6 +476,9 @@ proto_generated_obj_dir := $(intermediates)/proto proto_generated_objects := $(addprefix $(proto_generated_obj_dir)/, \ $(patsubst %.proto,%.pb.o,$(proto_sources_fullpath))) +# Auto-export the generated proto source dir. +LOCAL_EXPORT_C_INCLUDE_DIRS += $(proto_generated_cc_sources_dir) + # Ensure the transform-proto-to-cc rule is only defined once in multilib build. ifndef $(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined $(proto_generated_cc_sources): PRIVATE_PROTO_INCLUDES := $(TOP) @@ -954,7 +959,8 @@ $(LOCAL_INSTALLED_MODULE): | $(installed_static_library_notice_file_targets) ########################################################### export_includes := $(intermediates)/export_includes $(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDE_DIRS) -$(export_includes) : $(LOCAL_MODULE_MAKEFILE) +# Make sure .pb.h are already generated before any dependent source files get compiled. +$(export_includes) : $(LOCAL_MODULE_MAKEFILE) $(proto_generated_headers) @echo Export includes file: $< -- $@ $(hide) mkdir -p $(dir $@) && rm -f $@ ifdef LOCAL_EXPORT_C_INCLUDE_DIRS diff --git a/core/build_id.mk b/core/build_id.mk index f94b224..00a691f 100644 --- a/core/build_id.mk +++ b/core/build_id.mk @@ -18,6 +18,4 @@ # (like "CRB01"). It must be a single word, and is # capitalized by convention. -BUILD_ID := AOSP - -DISPLAY_BUILD_NUMBER := true +export BUILD_ID=LMP diff --git a/core/clang/config.mk b/core/clang/config.mk index 76293c5..59a46ef 100644 --- a/core/clang/config.mk +++ b/core/clang/config.mk @@ -93,9 +93,10 @@ CLANG_CONFIG_EXTRA_HOST_C_INCLUDES := $(LLVM_PREBUILTS_HEADER_PATH) CLANG_CONFIG_EXTRA_TARGET_C_INCLUDES := $(LLVM_PREBUILTS_HEADER_PATH) $(TARGET_OUT_HEADERS)/clang # Address sanitizer clang config -ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS := -fsanitize=address +ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan_$(TARGET_ARCH)_android +ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS := -fsanitize=address -fno-omit-frame-pointer ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS := -Wl,-u,__asan_preinit -ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES := libdl libasan_preload +ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES := libdl $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES := libasan # This allows us to use the superset of functionality that compiler-rt diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk index 8731457..1bada38 100644 --- a/core/cleanbuild.mk +++ b/core/cleanbuild.mk @@ -214,13 +214,16 @@ installclean_files := \ $(PRODUCT_OUT)/recovery \ $(PRODUCT_OUT)/root \ $(PRODUCT_OUT)/system \ + $(PRODUCT_OUT)/vendor \ + $(PRODUCT_OUT)/oem \ $(PRODUCT_OUT)/dex_bootjars \ $(PRODUCT_OUT)/obj/JAVA_LIBRARIES \ $(PRODUCT_OUT)/obj/FAKE \ $(PRODUCT_OUT)/obj/EXECUTABLES/adbd_intermediates \ $(PRODUCT_OUT)/obj/EXECUTABLES/init_intermediates \ $(PRODUCT_OUT)/obj/ETC/mac_permissions.xml_intermediates \ - $(PRODUCT_OUT)/obj/ETC/sepolicy_intermediates + $(PRODUCT_OUT)/obj/ETC/sepolicy_intermediates \ + $(PRODUCT_OUT)/obj/ETC/init.environ.rc_intermediates # The files/dirs to delete during a dataclean, which removes any files # in the staging and emulator data partitions. diff --git a/core/clear_vars.mk b/core/clear_vars.mk index 93ec226..f23c4a6 100644 --- a/core/clear_vars.mk +++ b/core/clear_vars.mk @@ -23,6 +23,7 @@ LOCAL_PACKAGE_NAME:= LOCAL_OVERRIDES_PACKAGES:= LOCAL_EXPORT_PACKAGE_RESOURCES:= LOCAL_MANIFEST_PACKAGE_NAME:= +LOCAL_PACKAGE_SPLITS:= LOCAL_REQUIRED_MODULES:= LOCAL_ACP_UNAVAILABLE:= LOCAL_MODULE_TAGS:= @@ -92,6 +93,7 @@ LOCAL_PREBUILT_JNI_LIBS:= LOCAL_JAR_MANIFEST:= LOCAL_INSTRUMENTATION_FOR:= LOCAL_APK_LIBRARIES:= +LOCAL_RES_LIBRARIES:= LOCAL_MANIFEST_INSTRUMENTATION_FOR:= LOCAL_AIDL_INCLUDES:= LOCAL_JARJAR_RULES:= @@ -111,6 +113,7 @@ LOCAL_EMMA_COVERAGE_FILTER:= LOCAL_WARNINGS_ENABLE:= LOCAL_FULL_MANIFEST_FILE:= LOCAL_MANIFEST_FILE:= +LOCAL_FULL_LIBS_MANIFEST_FILES:= LOCAL_RENDERSCRIPT_INCLUDES:= LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE:= LOCAL_RENDERSCRIPT_CC:= @@ -125,6 +128,7 @@ LOCAL_PROTOC_FLAGS:= LOCAL_PROTO_JAVA_OUTPUT_PARAMS:= LOCAL_NO_CRT:= LOCAL_PROPRIETARY_MODULE:= +LOCAL_OEM_MODULE:= LOCAL_PRIVILEGED_MODULE:= LOCAL_MODULE_OWNER:= LOCAL_CTS_TEST_PACKAGE:= @@ -133,6 +137,7 @@ LOCAL_CLANG:= LOCAL_ADDRESS_SANITIZER:= LOCAL_JAR_EXCLUDE_FILES:= LOCAL_JAR_PACKAGES:= +LOCAL_JAR_EXCLUDE_PACKAGES:= LOCAL_LINT_FLAGS:= LOCAL_SOURCE_FILES_ALL_GENERATED:= # '',true # Don't delete the META_INF dir when merging static Java libraries. @@ -142,6 +147,7 @@ LOCAL_PREBUILT_MODULE_FILE:= LOCAL_POST_INSTALL_CMD:= LOCAL_DIST_BUNDLED_BINARIES:= LOCAL_HAL_STATIC_LIBRARIES:= +LOCAL_RMTYPEDEFS:= LOCAL_NO_SYNTAX_CHECK:= LOCAL_NO_STATIC_ANALYZER:= LOCAL_32_BIT_ONLY:= # '',true diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk index a06f2dd..702a366 100644 --- a/core/combo/TARGET_linux-arm.mk +++ b/core/combo/TARGET_linux-arm.mk @@ -115,7 +115,7 @@ $(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += \ # into no-op in some builds while mesg is defined earlier. So we explicitly # disable "-Wunused-but-set-variable" here. ifneq ($(filter 4.6 4.6.% 4.7 4.7.% 4.8, $($(combo_2nd_arch_prefix)TARGET_GCC_VERSION)),) -$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -Wno-unused-but-set-variable -fno-builtin-sin \ +$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -fno-builtin-sin \ -fno-strict-volatile-bitfields endif @@ -165,8 +165,6 @@ $(combo_2nd_arch_prefix)TARGET_LIBGCC := $(shell $($(combo_2nd_arch_prefix)TARGE $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) -print-libgcc-file-name) $(combo_2nd_arch_prefix)TARGET_LIBATOMIC := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) \ $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) -print-file-name=libatomic.a) -target_libgcov := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \ - -print-file-name=libgcov.a) endif KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi @@ -209,7 +207,6 @@ $(hide) $(PRIVATE_CXX) \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_TARGET_GLOBAL_LDFLAGS) \ @@ -236,7 +233,6 @@ $(hide) $(PRIVATE_CXX) -nostdlib -Bdynamic -fPIE -pie \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_TARGET_GLOBAL_LDFLAGS) \ @@ -263,7 +259,6 @@ $(hide) $(PRIVATE_CXX) -nostdlib -Bstatic \ -Wl,--start-group \ $(call normalize-target-libraries,$(filter %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \ $(call normalize-target-libraries,$(filter %libc_nomalloc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(PRIVATE_TARGET_LIBATOMIC) \ $(if $(PRIVATE_LIBCXX),,$(PRIVATE_TARGET_LIBGCC)) \ -Wl,--end-group \ diff --git a/core/combo/TARGET_linux-arm64.mk b/core/combo/TARGET_linux-arm64.mk index f57f695..e04329e 100644 --- a/core/combo/TARGET_linux-arm64.mk +++ b/core/combo/TARGET_linux-arm64.mk @@ -35,7 +35,7 @@ TARGET_ARCH_VARIANT := armv8 endif # Decouple NDK library selection with platform compiler version -TARGET_NDK_GCC_VERSION := 4.8 +TARGET_NDK_GCC_VERSION := 4.9 ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),) TARGET_GCC_VERSION := 4.9 @@ -174,7 +174,6 @@ $(hide) $(PRIVATE_CXX) \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_TARGET_GLOBAL_LDFLAGS) \ @@ -201,7 +200,6 @@ $(hide) $(PRIVATE_CXX) -nostdlib -Bdynamic -fPIE -pie \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_TARGET_GLOBAL_LDFLAGS) \ @@ -228,7 +226,6 @@ $(hide) $(PRIVATE_CXX) -nostdlib -Bstatic \ -Wl,--start-group \ $(call normalize-target-libraries,$(filter %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \ $(call normalize-target-libraries,$(filter %libc_nomalloc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(PRIVATE_TARGET_LIBATOMIC) \ $(if $(PRIVATE_LIBCXX),,$(PRIVATE_TARGET_LIBGCC)) \ -Wl,--end-group \ diff --git a/core/combo/TARGET_linux-mips.mk b/core/combo/TARGET_linux-mips.mk index 0069bd0..8930f0e 100644 --- a/core/combo/TARGET_linux-mips.mk +++ b/core/combo/TARGET_linux-mips.mk @@ -138,8 +138,6 @@ LIBGCC_EH := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) $($(combo_2nd_arch_pre ifneq ($(LIBGCC_EH),libgcc_eh.a) $(combo_2nd_arch_prefix)TARGET_LIBGCC += $(LIBGCC_EH) endif -target_libgcov := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \ - --print-file-name=libgcov.a) endif KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi @@ -182,7 +180,6 @@ $(hide) $(PRIVATE_CXX) \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_TARGET_GLOBAL_LDFLAGS) \ @@ -209,7 +206,6 @@ $(hide) $(PRIVATE_CXX) -nostdlib -Bdynamic -fPIE -pie \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_TARGET_GLOBAL_LDFLAGS) \ @@ -236,7 +232,6 @@ $(hide) $(PRIVATE_CXX) -nostdlib -Bstatic \ -Wl,--start-group \ $(call normalize-target-libraries,$(filter %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \ $(call normalize-target-libraries,$(filter %libc_nomalloc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(PRIVATE_TARGET_LIBATOMIC) \ $(if $(PRIVATE_LIBCXX),,$(PRIVATE_TARGET_LIBGCC)) \ -Wl,--end-group \ diff --git a/core/combo/TARGET_linux-mips64.mk b/core/combo/TARGET_linux-mips64.mk index 463c7a4..e23978f 100644 --- a/core/combo/TARGET_linux-mips64.mk +++ b/core/combo/TARGET_linux-mips64.mk @@ -139,8 +139,6 @@ LIBGCC_EH := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) -print-file-name=libgc ifneq ($(LIBGCC_EH),libgcc_eh.a) TARGET_LIBGCC += $(LIBGCC_EH) endif -target_libgcov := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) \ - --print-file-name=libgcov.a) endif KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi @@ -186,7 +184,6 @@ $(hide) $(PRIVATE_CXX) \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_TARGET_GLOBAL_LDFLAGS) \ @@ -213,7 +210,6 @@ $(hide) $(PRIVATE_CXX) -nostdlib -Bdynamic -fPIE -pie \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_TARGET_GLOBAL_LDFLAGS) \ @@ -240,7 +236,6 @@ $(hide) $(PRIVATE_CXX) -nostdlib -Bstatic \ -Wl,--start-group \ $(call normalize-target-libraries,$(filter %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \ $(call normalize-target-libraries,$(filter %libc_nomalloc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(PRIVATE_TARGET_LIBATOMIC) \ $(if $(PRIVATE_LIBCXX),,$(PRIVATE_TARGET_LIBGCC)) \ -Wl,--end-group \ diff --git a/core/combo/TARGET_linux-x86.mk b/core/combo/TARGET_linux-x86.mk index 18331d5..3956603 100644 --- a/core/combo/TARGET_linux-x86.mk +++ b/core/combo/TARGET_linux-x86.mk @@ -62,8 +62,6 @@ $(combo_2nd_arch_prefix)TARGET_LIBGCC := \ $(shell $($(combo_2nd_arch_prefix)TARGET_CC) -m32 -print-file-name=libgcc.a) $(combo_2nd_arch_prefix)TARGET_LIBATOMIC := \ $(shell $($(combo_2nd_arch_prefix)TARGET_CC) -m32 -print-file-name=libatomic.a) -target_libgcov := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \ - -print-file-name=libgcov.a) endif $(combo_2nd_arch_prefix)TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined @@ -165,7 +163,6 @@ $(hide) $(PRIVATE_CXX) \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_LDFLAGS) \ @@ -192,7 +189,6 @@ $(hide) $(PRIVATE_CXX) \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_LDFLAGS) \ @@ -216,7 +212,6 @@ $(hide) $(PRIVATE_CXX) \ -Wl,--no-whole-archive \ -Wl,--start-group \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(PRIVATE_TARGET_LIBATOMIC) \ $(if $(PRIVATE_LIBCXX),,$(PRIVATE_TARGET_LIBGCC)) \ -Wl,--end-group \ diff --git a/core/combo/TARGET_linux-x86_64.mk b/core/combo/TARGET_linux-x86_64.mk index 4482a17..4f727a2 100644 --- a/core/combo/TARGET_linux-x86_64.mk +++ b/core/combo/TARGET_linux-x86_64.mk @@ -62,8 +62,6 @@ TARGET_LIBGCC := \ $(shell $(TARGET_CC) -m64 -print-file-name=libgcc.a) TARGET_LIBATOMIC := \ $(shell $(TARGET_CC) -m64 -print-file-name=libatomic.a) -target_libgcov := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) \ - -print-file-name=libgcov.a) endif TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined @@ -169,7 +167,6 @@ $(hide) $(PRIVATE_CXX) \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_LDFLAGS) \ @@ -195,7 +192,6 @@ $(hide) $(PRIVATE_CXX) \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ $(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \ $(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \ -o $@ \ $(PRIVATE_LDFLAGS) \ @@ -219,7 +215,6 @@ $(hide) $(PRIVATE_CXX) \ -Wl,--no-whole-archive \ -Wl,--start-group \ $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \ - $(PRIVATE_TARGET_FDO_LIB) \ $(PRIVATE_TARGET_LIBATOMIC) \ $(if $(PRIVATE_LIBCXX),,$(PRIVATE_TARGET_LIBGCC)) \ -Wl,--end-group \ diff --git a/core/combo/fdo.mk b/core/combo/fdo.mk index 26e842f..93d9a9c 100644 --- a/core/combo/fdo.mk +++ b/core/combo/fdo.mk @@ -17,15 +17,13 @@ # Setup FDO related flags. $(combo_2nd_arch_prefix)TARGET_FDO_CFLAGS:= -$(combo_2nd_arch_prefix)TARGET_FDO_LIB:= -ifneq ($(strip $(BUILD_FDO_INSTRUMENT)),) +ifeq ($(strip $(BUILD_FDO_INSTRUMENT)), true) # Set BUILD_FDO_INSTRUMENT=true to turn on FDO instrumentation. - # The profile will be generated on /data/local/tmp/profile on the device. - $(combo_2nd_arch_prefix)TARGET_FDO_CFLAGS := -fprofile-generate=/data/local/tmp/fdo_profile -DANDROID_FDO - $(combo_2nd_arch_prefix)TARGET_FDO_LIB := $(target_libgcov) + # The profile will be generated on /sdcard/fdo_profile on the device. + $(combo_2nd_arch_prefix)TARGET_FDO_CFLAGS := -fprofile-generate=/sdcard/fdo_profile -DANDROID_FDO else - ifneq ($(strip $(BUILD_FDO_OPTIMIZE)),) + ifeq ($(strip $(BUILD_FDO_OPTIMIZE)), true) # Set TARGET_FDO_PROFILE_PATH to set a custom profile directory for your build. ifeq ($(strip $($(combo_2nd_arch_prefix)TARGET_FDO_PROFILE_PATH)),) $(combo_2nd_arch_prefix)TARGET_FDO_PROFILE_PATH := fdo_profiles @@ -33,7 +31,6 @@ else ifneq ($(strip $(wildcard $($(combo_2nd_arch_prefix)TARGET_FDO_PROFILE_PATH))),) $(combo_2nd_arch_prefix)TARGET_FDO_CFLAGS := -fprofile-use=$($(combo_2nd_arch_prefix)TARGET_FDO_PROFILE_PATH) -DANDROID_FDO -fprofile-correction -Wcoverage-mismatch -Wno-error - $(combo_2nd_arch_prefix)TARGET_FDO_LIB := $(target_libgcov) else $(warning Profile directory $($(combo_2nd_arch_prefix)TARGET_FDO_PROFILE_PATH) does not exist. Turn off FDO.) endif diff --git a/core/combo/include/arch/darwin-x86/AndroidConfig.h b/core/combo/include/arch/darwin-x86/AndroidConfig.h index 44de4cd..54f3750 100644 --- a/core/combo/include/arch/darwin-x86/AndroidConfig.h +++ b/core/combo/include/arch/darwin-x86/AndroidConfig.h @@ -56,13 +56,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -/* #define HAVE_OOM_ADJ */ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/linux-arm/AndroidConfig.h b/core/combo/include/arch/linux-arm/AndroidConfig.h index 0eb6c72..c06c8bc 100644 --- a/core/combo/include/arch/linux-arm/AndroidConfig.h +++ b/core/combo/include/arch/linux-arm/AndroidConfig.h @@ -63,13 +63,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/linux-mips/AndroidConfig.h b/core/combo/include/arch/linux-mips/AndroidConfig.h index 076d711..bb3dc95 100644 --- a/core/combo/include/arch/linux-mips/AndroidConfig.h +++ b/core/combo/include/arch/linux-mips/AndroidConfig.h @@ -63,13 +63,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/linux-x86/AndroidConfig.h b/core/combo/include/arch/linux-x86/AndroidConfig.h index ebb95b0..5523e49 100644 --- a/core/combo/include/arch/linux-x86/AndroidConfig.h +++ b/core/combo/include/arch/linux-x86/AndroidConfig.h @@ -56,13 +56,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/target_linux-x86/AndroidConfig.h b/core/combo/include/arch/target_linux-x86/AndroidConfig.h index 5b56b51..c267b2b 100644 --- a/core/combo/include/arch/target_linux-x86/AndroidConfig.h +++ b/core/combo/include/arch/target_linux-x86/AndroidConfig.h @@ -49,13 +49,6 @@ #define HAVE_FORKEXEC /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -#define HAVE_OOM_ADJ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/combo/include/arch/windows/AndroidConfig.h b/core/combo/include/arch/windows/AndroidConfig.h index 0a52674..204740d 100644 --- a/core/combo/include/arch/windows/AndroidConfig.h +++ b/core/combo/include/arch/windows/AndroidConfig.h @@ -83,13 +83,6 @@ #endif /* - * Process out-of-memory adjustment. Set if running on Linux, - * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory - * badness adjustment. - */ -/* #define HAVE_OOM_ADJ */ - -/* * IPC model. Choose one: * * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). diff --git a/core/config.mk b/core/config.mk index 0ecb5c5..716f88f 100644 --- a/core/config.mk +++ b/core/config.mk @@ -37,13 +37,13 @@ SRC_HEADERS := \ $(TOPDIR)frameworks/native/include \ $(TOPDIR)frameworks/native/opengl/include \ $(TOPDIR)frameworks/av/include \ - $(TOPDIR)frameworks/base/include \ - $(TOPDIR)external/skia/include + $(TOPDIR)frameworks/base/include SRC_HOST_HEADERS:=$(TOPDIR)tools/include SRC_LIBRARIES:= $(TOPDIR)libs SRC_SERVERS:= $(TOPDIR)servers SRC_TARGET_DIR := $(TOPDIR)build/target SRC_API_DIR := $(TOPDIR)prebuilts/sdk/api +SRC_SYSTEM_API_DIR := $(TOPDIR)prebuilts/sdk/system-api # Some specific paths to tools SRC_DROIDDOC_DIR := $(TOPDIR)build/tools/droiddoc @@ -387,6 +387,8 @@ FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX) MKEXT2IMG := $(HOST_OUT_EXECUTABLES)/genext2fs$(HOST_EXECUTABLE_SUFFIX) MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/make_ext4fs$(HOST_EXECUTABLE_SUFFIX) MKEXTUSERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg.sh +MAKE_F2FS := $(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX) +MKF2FSUSERIMG := $(HOST_OUT_EXECUTABLES)/mkf2fsuserimg.sh MKEXT2BOOTIMG := external/genext2fs/mkbootimg_ext2.sh SIMG2IMG := $(HOST_OUT_EXECUTABLES)/simg2img$(HOST_EXECUTABLE_SUFFIX) E2FSCK := $(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX) @@ -399,6 +401,11 @@ JAVATAGS := build/tools/java-event-log-tags.py LLVM_RS_CC := $(HOST_OUT_EXECUTABLES)/llvm-rs-cc$(HOST_EXECUTABLE_SUFFIX) BCC_COMPAT := $(HOST_OUT_EXECUTABLES)/bcc_compat$(HOST_EXECUTABLE_SUFFIX) LINT := prebuilts/sdk/tools/lint +RMTYPEDEFS := $(HOST_OUT_EXECUTABLES)/rmtypedefs +APPEND2SIMG := $(HOST_OUT_EXECUTABLES)/append2simg +VERITY_SIGNER := $(HOST_OUT_EXECUTABLES)/verity_signer +BUILD_VERITY_TREE := $(HOST_OUT_EXECUTABLES)/build_verity_tree +BOOT_SIGNER := $(HOST_OUT_EXECUTABLES)/boot_signer # ACP is always for the build OS, not for the host OS ACP := $(BUILD_OUT_EXECUTABLES)/acp$(BUILD_EXECUTABLE_SUFFIX) @@ -406,9 +413,13 @@ ACP := $(BUILD_OUT_EXECUTABLES)/acp$(BUILD_EXECUTABLE_SUFFIX) # dx is java behind a shell script; no .exe necessary. DX := $(HOST_OUT_EXECUTABLES)/dx ZIPALIGN := $(HOST_OUT_EXECUTABLES)/zipalign$(HOST_EXECUTABLE_SUFFIX) -FINDBUGS := prebuilt/common/findbugs/bin/findbugs +FINDBUGS_DIR := external/owasp/sanitizer/tools/findbugs/bin +FINDBUGS := $(FINDBUGS_DIR)/findbugs EMMA_JAR := external/emma/lib/emma$(COMMON_JAVA_PACKAGE_SUFFIX) +# Tool to merge AndroidManifest.xmls +ANDROID_MANIFEST_MERGER := java -classpath prebuilts/devtools/tools/lib/manifest-merger.jar com.android.manifmerger.Main merge + YACC_HEADER_SUFFIX:= .hpp # Don't use column under Windows, cygwin or not @@ -523,7 +534,7 @@ endif # allow overriding default Java libraries on a per-target basis ifeq ($(TARGET_DEFAULT_JAVA_LIBRARIES),) - TARGET_DEFAULT_JAVA_LIBRARIES := core-libart core-junit ext framework framework2 + TARGET_DEFAULT_JAVA_LIBRARIES := core-libart core-junit ext framework endif TARGET_CPU_SMP ?= true @@ -576,7 +587,13 @@ TARGET_AVAILABLE_SDK_VERSIONS := $(call numerically_sort,\ $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/android.jar,%, \ $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/android.jar))) +# We don't have prebuilt system_current SDK yet. +TARGET_AVAILABLE_SDK_VERSIONS := system_current $(TARGET_AVAILABLE_SDK_VERSIONS) + INTERNAL_PLATFORM_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/public_api.txt +INTERNAL_PLATFORM_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/removed.txt +INTERNAL_PLATFORM_SYSTEM_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-api.txt +INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-removed.txt # This is the standard way to name a directory containing prebuilt target # objects. E.g., prebuilt/$(TARGET_PREBUILT_TAG)/libc.so diff --git a/core/definitions.mk b/core/definitions.mk index 177dbc7..6656591 100644 --- a/core/definitions.mk +++ b/core/definitions.mk @@ -1568,7 +1568,7 @@ $(hide) mkdir -p $(PRIVATE_CLASS_INTERMEDIATES_DIR) $(call unzip-jar-files,$(PRIVATE_STATIC_JAVA_LIBRARIES),$(PRIVATE_CLASS_INTERMEDIATES_DIR)) $(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list) $(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \ - find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \ + find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \ fi $(hide) tr ' ' '\n' < $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list \ | sort -u > $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq @@ -1593,12 +1593,21 @@ $(if $(PRIVATE_JAR_EXCLUDE_FILES), $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DI -name $(word 1, $(PRIVATE_JAR_EXCLUDE_FILES)) \ $(addprefix -o -name , $(wordlist 2, 999, $(PRIVATE_JAR_EXCLUDE_FILES))) \ | xargs rm -rf) -$(if $(PRIVATE_JAR_PACKAGES), $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DIR) -mindepth 1 -type d \ - $(foreach pkg, $(PRIVATE_JAR_PACKAGES), \ - -not -path $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg))) \ - | xargs rm -rf) -$(hide) jar $(if $(strip $(PRIVATE_JAR_MANIFEST)),-cfm,-cf) \ - $@ $(PRIVATE_JAR_MANIFEST) -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) . +$(if $(PRIVATE_JAR_PACKAGES), \ + $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DIR) -mindepth 1 -type f \ + $(foreach pkg, $(PRIVATE_JAR_PACKAGES), \ + -not -path $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg))/\*) -delete ; \ + find $(PRIVATE_CLASS_INTERMEDIATES_DIR) -empty -delete) +$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) rm -rf \ + $(foreach pkg, $(PRIVATE_JAR_EXCLUDE_PACKAGES), \ + $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg)))) +$(if $(PRIVATE_RMTYPEDEFS), $(hide) $(RMTYPEDEFS) -v $(PRIVATE_CLASS_INTERMEDIATES_DIR)) +$(if $(PRIVATE_JAR_MANIFEST), \ + $(hide) sed -e 's/%BUILD_NUMBER%/$(BUILD_NUMBER)/' \ + $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf && \ + jar -cfm $@ $(dir $@)/manifest.mf \ + -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) ., \ + $(hide) jar -cf $@ -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) .) endef define transform-java-to-classes.jar @@ -1644,12 +1653,21 @@ $(if $(PRIVATE_JAR_EXCLUDE_FILES), $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DI -name $(word 1, $(PRIVATE_JAR_EXCLUDE_FILES)) \ $(addprefix -o -name , $(wordlist 2, 999, $(PRIVATE_JAR_EXCLUDE_FILES))) \ | xargs rm -rf) -$(if $(PRIVATE_JAR_PACKAGES), $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DIR) -mindepth 1 -type d \ - $(foreach pkg, $(PRIVATE_JAR_PACKAGES), \ - -not -path $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg))) \ - | xargs rm -rf) -$(hide) jar $(if $(strip $(PRIVATE_JAR_MANIFEST)),-cfm,-cf) \ - $@ $(PRIVATE_JAR_MANIFEST) -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) . +$(if $(PRIVATE_JAR_PACKAGES), \ + $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DIR) -mindepth 1 -type f \ + $(foreach pkg, $(PRIVATE_JAR_PACKAGES), \ + -not -path $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg))/\*) -delete ; \ + find $(PRIVATE_CLASS_INTERMEDIATES_DIR) -empty -delete) +$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) rm -rf \ + $(foreach pkg, $(PRIVATE_JAR_EXCLUDE_PACKAGES), \ + $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg)))) +$(if $(PRIVATE_RMTYPEDEFS), $(hide) $(RMTYPEDEFS) -v $(PRIVATE_CLASS_INTERMEDIATES_DIR)) +$(if $(PRIVATE_JAR_MANIFEST), \ + $(hide) sed -e 's/%BUILD_NUMBER%/$(BUILD_NUMBER)/' \ + $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf && \ + jar -cfm $@ $(dir $@)/manifest.mf \ + -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) ., \ + $(hide) jar -cf $@ -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) .) $(hide) mv $(PRIVATE_CLASS_INTERMEDIATES_DIR)/newstamp $(PRIVATE_CLASS_INTERMEDIATES_DIR)/stamp endef @@ -1671,7 +1689,7 @@ endef define transform-classes.jar-to-dex @echo "target Dex: $(PRIVATE_MODULE)" @mkdir -p $(dir $@) -$(hide) rm -f $(dir $@)/classes*.dex +$(hide) rm -f $(dir $@)classes*.dex $(hide) $(DX) \ $(if $(findstring windows,$(HOST_OS)),,-JXms16M -JXmx2048M) \ --dex --output=$(dir $@) \ @@ -1709,7 +1727,7 @@ endef define add-assets-to-package $(hide) $(AAPT) package -u $(PRIVATE_AAPT_FLAGS) \ $(addprefix -c , $(PRIVATE_PRODUCT_AAPT_CONFIG)) \ - $(addprefix --preferred-configurations , $(PRIVATE_PRODUCT_AAPT_PREF_CONFIG)) \ + $(addprefix --preferred-density , $(PRIVATE_PRODUCT_AAPT_PREF_CONFIG)) \ $(addprefix -M , $(PRIVATE_ANDROID_MANIFEST)) \ $(addprefix -S , $(PRIVATE_RESOURCE_DIR)) \ $(addprefix -A , $(PRIVATE_ASSET_DIR)) \ @@ -1744,7 +1762,7 @@ endef #TODO: update the manifest to point to the dex file define add-dex-to-package -$(hide) zip -qj $@ $(dir $(PRIVATE_DEX_FILE))/classes*.dex +$(hide) zip -qj $@ $(dir $(PRIVATE_DEX_FILE))classes*.dex endef # Add java resources added by the current module. @@ -1993,8 +2011,8 @@ $(eval _isfds_value :=)) endef # $(1): The file(s) to check (often $@) -# $(2): The maximum total image size, in decimal bytes -# $(3): the type of filesystem "yaffs" or "raw" +# $(2): The maximum total image size, in decimal bytes. +# Make sure to take into account any reserved space needed for the FS. # # If $(2) is empty, evaluates to "true" # @@ -2007,15 +2025,9 @@ $(if $(2), \ total=$$(( $$( echo "$$size" ) )); \ printname=$$(echo -n "$(1)" | tr " " +); \ img_blocksize=$(call image-size-from-data-size,$(BOARD_FLASH_BLOCK_SIZE)); \ - if [ "$(3)" == "yaffs" ]; then \ - reservedblocks=8; \ - else \ - reservedblocks=0; \ - fi; \ twoblocks=$$((img_blocksize * 2)); \ onepct=$$((((($(2) / 100) - 1) / img_blocksize + 1) * img_blocksize)); \ - reserve=$$(((twoblocks > onepct ? twoblocks : onepct) + \ - reservedblocks * img_blocksize)); \ + reserve=$$((twoblocks > onepct ? twoblocks : onepct)); \ maxsize=$$(($(2) - reserve)); \ echo "$$printname maxsize=$$maxsize blocksize=$$img_blocksize total=$$total reserve=$$reserve"; \ if [ "$$total" -gt "$$maxsize" ]; then \ @@ -2037,8 +2049,7 @@ endef # $(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) + $(call assert-max-file-size,$(1),$(call image-size-from-data-size,$(2)))) endef @@ -2137,17 +2148,19 @@ endef # $(1) target # $(2) stable api file # $(3) api file to be tested -# $(4) arguments for apicheck -# $(5) command to run if apicheck failed -# $(6) target dependent on this api check -# $(7) additional dependencies +# $(4) stable removed api file +# $(5) removed api file to be tested +# $(6) arguments for apicheck +# $(7) command to run if apicheck failed +# $(8) target dependent on this api check +# $(9) additional dependencies define check-api -$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp: $(2) $(3) $(APICHECK) $(7) +$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp: $(2) $(3) $(4) $(APICHECK) $(9) @echo "Checking API:" $(1) - $(hide) ( $(APICHECK_COMMAND) $(4) $(2) $(3) || ( $(5) ; exit 38 ) ) + $(hide) ( $(APICHECK_COMMAND) $(6) $(2) $(3) $(4) $(5) || ( $(7) ; exit 38 ) ) $(hide) mkdir -p $$(dir $$@) $(hide) touch $$@ -$(6): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp +$(8): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp endef ## Whether to build from source if prebuilt alternative exists diff --git a/core/droiddoc.mk b/core/droiddoc.mk index ecfe3dc..d3e61d5 100644 --- a/core/droiddoc.mk +++ b/core/droiddoc.mk @@ -64,12 +64,15 @@ ifneq ($(LOCAL_SDK_VERSION),) # Use android_stubs_current if LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS. LOCAL_JAVA_LIBRARIES := android_stubs_current $(LOCAL_JAVA_LIBRARIES) $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, android_stubs_current) + else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current) + LOCAL_JAVA_LIBRARIES := android_system_stubs_current $(LOCAL_JAVA_LIBRARIES) + $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, android_system_stubs_current) else LOCAL_JAVA_LIBRARIES := sdk_v$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES) $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, sdk_v$(LOCAL_SDK_VERSION)) endif else - LOCAL_JAVA_LIBRARIES := core-libart ext framework framework2 $(LOCAL_JAVA_LIBRARIES) + LOCAL_JAVA_LIBRARIES := core-libart ext framework $(LOCAL_JAVA_LIBRARIES) $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, core-libart) endif # LOCAL_SDK_VERSION LOCAL_JAVA_LIBRARIES := $(sort $(LOCAL_JAVA_LIBRARIES)) @@ -134,15 +137,13 @@ $(full_target): PRIVATE_CUSTOM_TEMPLATE_DIR := $(LOCAL_DROIDDOC_CUSTOM_TEMPLATE_ $(full_target): PRIVATE_IN_CUSTOM_ASSET_DIR := $(LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR)/$(LOCAL_DROIDDOC_CUSTOM_ASSET_DIR) $(full_target): PRIVATE_OUT_ASSET_DIR := $(out_dir)/$(LOCAL_DROIDDOC_ASSET_DIR) $(full_target): PRIVATE_OUT_CUSTOM_ASSET_DIR := $(out_dir)/$(LOCAL_DROIDDOC_CUSTOM_ASSET_DIR) + +html_dir_files := ifneq ($(strip $(LOCAL_DROIDDOC_HTML_DIR)),) $(full_target): PRIVATE_DROIDDOC_HTML_DIR := -htmldir $(LOCAL_PATH)/$(LOCAL_DROIDDOC_HTML_DIR) +html_dir_files := $(shell find $(LOCAL_PATH)/$(LOCAL_DROIDDOC_HTML_DIR) -type f) else -$(full_target): PRIVATE_DROIDDOC_HTML_DIR := -endif -ifneq ($(strip $(LOCAL_ADDITIONAL_HTML_DIR)),) -$(full_target): PRIVATE_ADDITIONAL_HTML_DIR := -htmldir2 $(LOCAL_PATH)/$(LOCAL_ADDITIONAL_HTML_DIR) -else -$(full_target): PRIVATE_ADDITIONAL_HTML_DIR := +$(full_target): PRIVATE_DROIDDOC_HTML_DIR := endif ifneq ($(strip $(LOCAL_ADDITIONAL_HTML_DIR)),) $(full_target): PRIVATE_ADDITIONAL_HTML_DIR := -htmldir2 $(LOCAL_PATH)/$(LOCAL_ADDITIONAL_HTML_DIR) @@ -153,8 +154,6 @@ endif # TODO: not clear if this is used any more $(full_target): PRIVATE_LOCAL_PATH := $(LOCAL_PATH) -html_dir_files := $(shell find $(LOCAL_PATH)/$(LOCAL_DROIDDOC_HTML_DIR) -type f) - $(full_target): $(full_src_files) $(droiddoc_templates) $(droiddoc) $(html_dir_files) $(full_java_lib_deps) $(LOCAL_ADDITIONAL_DEPENDENCIES) @echo Docs droiddoc: $(PRIVATE_OUT_DIR) $(hide) mkdir -p $(dir $@) diff --git a/core/envsetup.mk b/core/envsetup.mk index d0b5846..96044b3 100644 --- a/core/envsetup.mk +++ b/core/envsetup.mk @@ -119,11 +119,21 @@ endif # Define them here so they can be used in product config files. TARGET_COPY_OUT_SYSTEM := system TARGET_COPY_OUT_DATA := data -TARGET_COPY_OUT_VENDOR := system/vendor +TARGET_COPY_OUT_OEM := oem TARGET_COPY_OUT_ROOT := root TARGET_COPY_OUT_RECOVERY := recovery - -# Read the product specs so we an get TARGET_DEVICE and other +########################################### +# Define TARGET_COPY_OUT_VENDOR to a placeholder, for at this point +# we don't know if the device wants to build a separate vendor.img +# or just build vendor stuff into system.img. +# A device can set up TARGET_COPY_OUT_VENDOR to "vendor" in its +# BoardConfig.mk. +# We'll substitute with the real value after loading BoardConfig.mk. +_vendor_path_placeholder := ||VENDOR-PATH-PH|| +TARGET_COPY_OUT_VENDOR := $(_vendor_path_placeholder) +########################################### + +# Read the product specs so we can get TARGET_DEVICE and other # variables that we need in order to locate the output files. include $(BUILD_SYSTEM)/product_config.mk @@ -156,6 +166,17 @@ endif TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk))) board_config_mk := +########################################### +# Now we can substitute with the real value of TARGET_COPY_OUT_VENDOR +ifeq ($(TARGET_COPY_OUT_VENDOR),$(_vendor_path_placeholder)) +TARGET_COPY_OUT_VENDOR := system/vendor +else ifeq ($(filter vendor system/vendor,$(TARGET_COPY_OUT_VENDOR)),) +$(error TARGET_COPY_OUT_VENDOR must be either 'vendor' or 'system/vendor', seeing '$(TARGET_COPY_OUT_VENDOR)'.) +endif +PRODUCT_COPY_FILES := $(subst $(_vendor_path_placeholder),$(TARGET_COPY_OUT_VENDOR),$(PRODUCT_COPY_FILES)) +########################################### + + # --------------------------------------------------------------- # Set up configuration for target machine. # The following must be set: @@ -224,6 +245,7 @@ HOST_OUT_HEADERS := $(HOST_OUT_INTERMEDIATES)/include HOST_OUT_INTERMEDIATE_LIBRARIES := $(HOST_OUT_INTERMEDIATES)/lib HOST_OUT_NOTICE_FILES := $(HOST_OUT_INTERMEDIATES)/NOTICE_FILES HOST_OUT_COMMON_INTERMEDIATES := $(HOST_COMMON_OUT_ROOT)/obj +HOST_OUT_FAKE := $(HOST_OUT)/fake_packages HOST_OUT_GEN := $(HOST_OUT)/gen HOST_OUT_COMMON_GEN := $(HOST_COMMON_OUT_ROOT)/gen @@ -315,9 +337,26 @@ $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDO $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(TARGET_OUT_VENDOR)/lib $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR_APPS) +TARGET_OUT_OEM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_OEM) +TARGET_OUT_OEM_EXECUTABLES := $(TARGET_OUT_OEM)/bin +ifneq ($(filter %64,$(TARGET_ARCH)),) +TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib64 +else +TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib +endif +# We don't expect Java libraries in the oem.img. +# TARGET_OUT_OEM_JAVA_LIBRARIES:= $(TARGET_OUT_OEM)/framework +TARGET_OUT_OEM_APPS := $(TARGET_OUT_OEM)/app +TARGET_OUT_OEM_ETC := $(TARGET_OUT_OEM)/etc + +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_EXECUTABLES := $(TARGET_OUT_OEM_EXECUTABLES) +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_APPS := $(TARGET_OUT_OEM_APPS) + TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols TARGET_OUT_EXECUTABLES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/bin TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/lib +TARGET_OUT_VENDOR_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/$(TARGET_COPY_OUT_VENDOR)/lib TARGET_ROOT_OUT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED) TARGET_ROOT_OUT_SBIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/sbin TARGET_ROOT_OUT_BIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/bin diff --git a/core/executable_internal.mk b/core/executable_internal.mk index 2e380b6..ab4cf0e 100644 --- a/core/executable_internal.mk +++ b/core/executable_internal.mk @@ -28,7 +28,6 @@ include $(BUILD_SYSTEM)/dynamic_binary.mk # Define PRIVATE_ variables from global vars my_target_global_ld_dirs := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_LD_DIRS) -my_target_fdo_lib := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_FDO_LIB) my_target_libgcc := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCC) my_target_libatomic := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBATOMIC) my_target_crtbegin_dynamic_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CRTBEGIN_DYNAMIC_O) @@ -48,7 +47,6 @@ my_target_crtend_o := $(wildcard $(my_ndk_sysroot_lib)/crtend_android.o) endif $(linked_module): PRIVATE_TARGET_GLOBAL_LD_DIRS := $(my_target_global_ld_dirs) $(linked_module): PRIVATE_TARGET_GLOBAL_LDFLAGS := $(my_target_global_ldflags) -$(linked_module): PRIVATE_TARGET_FDO_LIB := $(my_target_fdo_lib) $(linked_module): PRIVATE_TARGET_LIBGCC := $(my_target_libgcc) $(linked_module): PRIVATE_TARGET_LIBATOMIC := $(my_target_libatomic) $(linked_module): PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O := $(my_target_crtbegin_dynamic_o) diff --git a/core/executable_prefer_symlink.mk b/core/executable_prefer_symlink.mk index f66a5f2..e4df92e 100644 --- a/core/executable_prefer_symlink.mk +++ b/core/executable_prefer_symlink.mk @@ -8,17 +8,27 @@ # configuration. Note that we require the TARGET_IS_64_BIT # check because 32 bit targets may not define TARGET_PREFER_32_BIT_APPS # et al. since those variables make no sense in that context. - ifneq ($(LOCAL_IS_HOST_MODULE),true) my_symlink := $(addprefix $(TARGET_OUT)/bin/, $(LOCAL_MODULE)) ifeq ($(TARGET_IS_64_BIT),true) - ifneq ($(TARGET_PREFER_32_BIT_APPS),true) -$(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_64) + ifeq ($(TARGET_SUPPORTS_64_BIT_APPS)|$(TARGET_SUPPORTS_32_BIT_APPS),true|true) + # We support both 32 and 64 bit apps, so we will have to + # base our decision on whether the target prefers one or the + # other. + ifneq ($(TARGET_PREFER_32_BIT_APPS),true) + $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32) + else + $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_64) + endif + else ifeq ($(TARGET_SUPPORTS_64_BIT_APPS),true) + # We support only 64 bit apps. + $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_64) else -$(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32) + # We support only 32 bit apps. + $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32) endif else -$(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32) + $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32) endif else my_symlink := $(addprefix $(HOST_OUT)/bin/, $(LOCAL_MODULE)) diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk index e15bde2..61eb3ff 100644 --- a/core/host_dalvik_java_library.mk +++ b/core/host_dalvik_java_library.mk @@ -67,6 +67,7 @@ $(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) $(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := $(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES := +$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_PACKAGES := $(full_classes_compiled_jar): PRIVATE_RMTYPEDEFS := $(full_classes_compiled_jar): $(java_sources) $(java_resource_sources) $(full_java_lib_deps) \ $(jar_manifest_file) $(proto_java_sources_file_stamp) $(LOCAL_ADDITIONAL_DEPENDENCIES) diff --git a/core/host_java_library.mk b/core/host_java_library.mk index e5ebb11..7e0e437 100644 --- a/core/host_java_library.mk +++ b/core/host_java_library.mk @@ -20,21 +20,65 @@ ####################################### include $(BUILD_SYSTEM)/host_java_library_common.mk +####################################### + +# Enable emma instrumentation only if the module asks so. +ifeq (true,$(LOCAL_EMMA_INSTRUMENT)) +ifneq (true,$(EMMA_INSTRUMENT)) +LOCAL_EMMA_INSTRUMENT := +endif +endif + +full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar +emma_intermediates_dir := $(intermediates.COMMON)/emma_out +# emma is hardcoded to use the leaf name of its input for the output file -- +# only the output directory can be changed +full_classes_emma_jar := $(emma_intermediates_dir)/lib/$(notdir $(full_classes_compiled_jar)) + +LOCAL_INTERMEDIATE_TARGETS += \ + $(full_classes_compiled_jar) \ + $(full_classes_emma_jar) + +####################################### include $(BUILD_SYSTEM)/base_rules.mk ####################################### -$(full_classes_compiled_jar): PRIVATE_JAVAC_DEBUG_FLAGS := -g +ifeq (true,$(LOCAL_EMMA_INSTRUMENT)) +$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILE := $(intermediates.COMMON)/coverage.em +$(full_classes_emma_jar): PRIVATE_EMMA_INTERMEDIATES_DIR := $(emma_intermediates_dir) +ifdef LOCAL_EMMA_COVERAGE_FILTER +$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILTER := $(LOCAL_EMMA_COVERAGE_FILTER) +else +# by default, avoid applying emma instrumentation onto emma classes itself, +# otherwise there will be exceptions thrown +$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILTER := *,-emma,-emmarun,-com.vladium.* +endif +# this rule will generate both $(PRIVATE_EMMA_COVERAGE_FILE) and +# $(full_classes_emma_jar) +$(full_classes_emma_jar) : $(full_classes_compiled_jar) | $(EMMA_JAR) + $(transform-classes.jar-to-emma) + +$(LOCAL_BUILT_MODULE) : $(full_classes_emma_jar) + @echo Copying: $@ + $(hide) $(ACP) -fp $< $@ -java_alternative_checked_module := +else # LOCAL_EMMA_INSTRUMENT +# Directly build into LOCAL_BUILT_MODULE. +full_classes_compiled_jar := $(LOCAL_BUILT_MODULE) +endif # LOCAL_EMMA_INSTRUMENT + +$(full_classes_compiled_jar): PRIVATE_JAVAC_DEBUG_FLAGS := -g # The layers file allows you to enforce a layering between java packages. # Run build/tools/java-layers.py for more details. layers_file := $(addprefix $(LOCAL_PATH)/, $(LOCAL_JAVA_LAYERS_FILE)) -$(LOCAL_BUILT_MODULE): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) -$(LOCAL_BUILT_MODULE): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) -$(LOCAL_BUILT_MODULE): PRIVATE_JAR_EXCLUDE_FILES := -$(LOCAL_BUILT_MODULE): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) -$(LOCAL_BUILT_MODULE): $(java_sources) $(java_resource_sources) $(full_java_lib_deps) \ +$(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) +$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) +$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := +$(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES := +$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_PACKAGES := +$(full_classes_compiled_jar): PRIVATE_RMTYPEDEFS := +$(full_classes_compiled_jar): $(java_sources) $(java_resource_sources) $(full_java_lib_deps) \ $(jar_manifest_file) $(proto_java_sources_file_stamp) $(LOCAL_ADDITIONAL_DEPENDENCIES) $(transform-host-java-to-package) diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk index eb90c50..944420b 100644 --- a/core/install_jni_libs_internal.mk +++ b/core/install_jni_libs_internal.mk @@ -18,7 +18,7 @@ my_jni_shared_libraries := \ $(LOCAL_JNI_SHARED_LIBRARIES))) # App-specific lib path. -my_app_lib_path := $($(my_2nd_arch_prefix)TARGET_OUT$(partition_tag)_SHARED_LIBRARIES)/$(basename $(my_installed_module_stem)) +my_app_lib_path := $(dir $(LOCAL_INSTALLED_MODULE))lib/$(TARGET_$(my_2nd_arch_prefix)ARCH) my_extracted_jni_libs := ifdef my_embed_jni @@ -54,16 +54,20 @@ ifneq ($(my_jni_shared_libraries),) # The jni libaries will be installed to the system.img. my_jni_filenames := $(notdir $(my_jni_shared_libraries)) # Make sure the JNI libraries get installed -$(LOCAL_INSTALLED_MODULE) : | $(addprefix $($(my_2nd_arch_prefix)TARGET_OUT$(partition_tag)_SHARED_LIBRARIES)/, $(my_jni_filenames)) +my_shared_library_path := $($(my_2nd_arch_prefix)TARGET_OUT$(partition_tag)_SHARED_LIBRARIES) +$(LOCAL_INSTALLED_MODULE) : | $(addprefix $(my_shared_library_path)/, $(my_jni_filenames)) # Create symlink in the app specific lib path ifdef LOCAL_POST_INSTALL_CMD # Add a shell command separator LOCAL_POST_INSTALL_CMD += ; endif + +my_symlink_target_dir := $(patsubst $(PRODUCT_OUT)%,%,\ + $(my_shared_library_path)) LOCAL_POST_INSTALL_CMD += \ mkdir -p $(my_app_lib_path) \ - $(foreach lib, $(my_jni_filenames), ;ln -sf ../$(lib) $(my_app_lib_path)/$(lib)) + $(foreach lib, $(my_jni_filenames), ;ln -sf $(my_symlink_target_dir)/$(lib) $(my_app_lib_path)/$(lib)) $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD) # Clear jni_shared_libraries to not embed it into the apk. diff --git a/core/java.mk b/core/java.mk index 049bc51..52d31d0 100644 --- a/core/java.mk +++ b/core/java.mk @@ -26,6 +26,8 @@ ifneq ($(LOCAL_SDK_VERSION),) ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current) # Use android_stubs_current if LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS. LOCAL_JAVA_LIBRARIES := android_stubs_current $(LOCAL_JAVA_LIBRARIES) + else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current) + LOCAL_JAVA_LIBRARIES := android_system_stubs_current $(LOCAL_JAVA_LIBRARIES) else LOCAL_JAVA_LIBRARIES := sdk_v$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES) endif @@ -142,7 +144,7 @@ renderscript_target_api := $(LOCAL_RENDERSCRIPT_TARGET_API) else ifneq (,$(LOCAL_SDK_VERSION)) # Set target-api for LOCAL_SDK_VERSIONs other than current. -ifneq (,$(filter-out current, $(LOCAL_SDK_VERSION))) +ifneq (,$(filter-out current system_current, $(LOCAL_SDK_VERSION))) renderscript_target_api := $(LOCAL_SDK_VERSION) endif endif # LOCAL_SDK_VERSION is set @@ -158,7 +160,7 @@ renderscript_flags := -Wall -Werror renderscript_flags += $(LOCAL_RENDERSCRIPT_FLAGS) # prepend the RenderScript system include path -ifneq ($(filter-out current,$(LOCAL_SDK_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current,$(LOCAL_SDK_VERSION))),) +ifneq ($(filter-out current system_current,$(LOCAL_SDK_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current,$(LOCAL_SDK_VERSION))),) # if a numeric LOCAL_SDK_VERSION, or current LOCAL_SDK_VERSION with TARGET_BUILD_APPS LOCAL_RENDERSCRIPT_INCLUDES := \ $(HISTORICAL_SDK_VERSIONS_ROOT)/renderscript/clang-include \ @@ -321,6 +323,10 @@ layers_file := $(addprefix $(LOCAL_PATH)/, $(LOCAL_JAVA_LAYERS_FILE)) $(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) $(full_classes_compiled_jar): PRIVATE_WARNINGS_ENABLE := $(LOCAL_WARNINGS_ENABLE) +ifdef LOCAL_RMTYPEDEFS +$(full_classes_compiled_jar): | $(RMTYPEDEFS) +endif + # Compile the java files to a .jar file. # This intentionally depends on java_sources, not all_java_sources. # Deps for generated source files must be handled separately, @@ -328,6 +334,8 @@ $(full_classes_compiled_jar): PRIVATE_WARNINGS_ENABLE := $(LOCAL_WARNINGS_ENABLE $(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := $(LOCAL_JAR_EXCLUDE_FILES) $(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES := $(LOCAL_JAR_PACKAGES) +$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_PACKAGES := $(LOCAL_JAR_EXCLUDE_PACKAGES) +$(full_classes_compiled_jar): PRIVATE_RMTYPEDEFS := $(LOCAL_RMTYPEDEFS) $(full_classes_compiled_jar): PRIVATE_DONT_DELETE_JAR_META_INF := $(LOCAL_DONT_DELETE_JAR_META_INF) $(full_classes_compiled_jar): $(java_sources) $(java_resource_sources) $(full_java_lib_deps) \ $(jar_manifest_file) $(layers_file) $(RenderScript_file_stamp) \ @@ -499,7 +507,7 @@ $(LOCAL_MODULE)-findbugs : $(findbugs_html) $(findbugs_html) : $(findbugs_xml) @mkdir -p $(dir $@) @echo ConvertXmlToText: $@ - $(hide) prebuilt/common/findbugs/bin/convertXmlToText -html:fancy.xsl $(PRIVATE_XML_FILE) \ + $(hide) $(FINDBUGS_DIR)/convertXmlToText -html:fancy.xsl $(PRIVATE_XML_FILE) \ > $@ $(LOCAL_MODULE)-findbugs : $(findbugs_html) diff --git a/core/main.mk b/core/main.mk index be2b300..05205f1 100644 --- a/core/main.mk +++ b/core/main.mk @@ -185,12 +185,8 @@ ifeq ($(requires_openjdk), true) # java version is really openjdk ifeq ($(shell echo '$(java_version_str)' | grep -i openjdk),) $(info ************************************************************) -$(info You are attempting to build with an unsupported JDK.) -$(info $(space)) -$(info This build requires OpenJDK, but you are using:) +$(info You asked for an OpenJDK 7 build but your version is) $(info $(java_version_str).) -$(info Please follow the machine setup instructions at) -$(info $(space)$(space)$(space)$(space)https://source.android.com/source/download.html) $(info ************************************************************) $(error stop) endif # java version is not OpenJdk @@ -391,7 +387,7 @@ ifdef is_sdk_build sdk_repo_goal := $(strip $(filter sdk_repo,$(MAKECMDGOALS))) MAKECMDGOALS := $(strip $(filter-out sdk_repo,$(MAKECMDGOALS))) -ifneq ($(words $(filter-out $(INTERNAL_MODIFIER_TARGETS) checkbuild,$(MAKECMDGOALS))),1) +ifneq ($(words $(filter-out $(INTERNAL_MODIFIER_TARGETS) checkbuild emulator_tests target-files-package,$(MAKECMDGOALS))),1) $(error The 'sdk' target may not be specified with any other targets) endif @@ -769,7 +765,7 @@ ifdef is_sdk_build $(if $(strip $(ALL_MODULES.$(m).INSTALLED) $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).INSTALLED)),,\ $(eval dangling_modules += $(m)))) ifneq ($(dangling_modules),) - $(warning Module names '$(dangling_modules)' in PRODUCT_PACKAGES has nothing to install!) + $(warning: Modules '$(dangling_modules)' in PRODUCT_PACKAGES have nothing to install!) endif $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_DEBUG), \ $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\ @@ -961,6 +957,7 @@ else # TARGET_BUILD_APPS $(foreach f,$(INSTALLED_RADIOIMAGE_TARGET), \ $(call dist-for-goals, droidcore, $(f))) + ifneq ($(ANDROID_BUILD_EMBEDDED),true) ifneq ($(TARGET_BUILD_PDK),true) $(call dist-for-goals, droidcore, \ $(APPS_ZIP) \ @@ -968,6 +965,7 @@ else # TARGET_BUILD_APPS $(PACKAGE_STATS_FILE) \ ) endif + endif ifeq ($(EMMA_INSTRUMENT),true) $(EMMA_META_ZIP) : $(INSTALLED_SYSTEMIMAGE) @@ -1007,6 +1005,12 @@ target-java-tests : java-target-tests target-native-tests : native-target-tests tests : host-tests target-tests +# To catch more build breakage, check build tests modules in eng and userdebug builds. +ifneq ($(TARGET_BUILD_PDK),true) +ifneq ($(filter eng userdebug,$(TARGET_BUILD_VARIANT)),) +droidcore : target-tests host-tests +endif +endif .PHONY: lintall @@ -1031,7 +1035,7 @@ findbugs: $(INTERNAL_FINDBUGS_HTML_TARGET) $(INTERNAL_FINDBUGS_XML_TARGET) .PHONY: clean clean: - @rm -rf $(OUT_DIR) + @rm -rf $(OUT_DIR)/* @echo "Entire build directory removed." .PHONY: clobber diff --git a/core/multi_prebuilt.mk b/core/multi_prebuilt.mk index be60e2f..bc85cea 100644 --- a/core/multi_prebuilt.mk +++ b/core/multi_prebuilt.mk @@ -69,7 +69,11 @@ $(foreach t,$(1), \ $(if $(7), \ $(eval LOCAL_BUILT_MODULE_STEM := $(7)) \ , \ - $(eval LOCAL_BUILT_MODULE_STEM := $(notdir $(LOCAL_SRC_FILES))) \ + $(if $(word 2,$(tw)), \ + $(eval LOCAL_BUILT_MODULE_STEM := $(LOCAL_MODULE)$(suffix $(LOCAL_SRC_FILES))) \ + , \ + $(eval LOCAL_BUILT_MODULE_STEM := $(notdir $(LOCAL_SRC_FILES))) \ + ) \ ) \ $(eval LOCAL_MODULE_SUFFIX := $(suffix $(LOCAL_SRC_FILES))) \ $(if $(filter user,$(TARGET_BUILD_VARIANT)), \ diff --git a/core/package_internal.mk b/core/package_internal.mk index 5b639ea..fd92d01 100644 --- a/core/package_internal.mk +++ b/core/package_internal.mk @@ -52,16 +52,6 @@ $(error $(LOCAL_PATH): Package modules may not define LOCAL_MODULE) endif LOCAL_MODULE := $(LOCAL_PACKAGE_NAME) -ifeq ($(strip $(LOCAL_MANIFEST_FILE)),) -LOCAL_MANIFEST_FILE := AndroidManifest.xml -endif - -# If you need to put the MANIFEST_FILE outside of LOCAL_PATH -# you can use FULL_MANIFEST_FILE -ifeq ($(strip $(LOCAL_FULL_MANIFEST_FILE)),) -LOCAL_FULL_MANIFEST_FILE := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE) -endif - ifneq ($(strip $(LOCAL_MODULE_CLASS)),) $(error $(LOCAL_PATH): Package modules may not set LOCAL_MODULE_CLASS) endif @@ -78,6 +68,10 @@ ifeq ($(filter tests, $(LOCAL_MODULE_TAGS)),) LOCAL_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) -z endif +ifdef LOCAL_PACKAGE_SPLITS +LOCAL_AAPT_FLAGS += $(addprefix --split ,$(LOCAL_PACKAGE_SPLITS)) +endif + need_compile_asset := ifeq (,$(LOCAL_ASSET_DIR)) LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets @@ -101,8 +95,14 @@ package_resource_overlays := $(strip \ LOCAL_RESOURCE_DIR := $(package_resource_overlays) $(LOCAL_RESOURCE_DIR) -all_assets := $(call find-subdir-assets,$(LOCAL_ASSET_DIR)) -all_assets := $(addprefix $(LOCAL_ASSET_DIR)/,$(patsubst assets/%,%,$(all_assets))) +all_assets := $(strip \ + $(foreach dir, $(LOCAL_ASSET_DIR), \ + $(addprefix $(dir)/, \ + $(patsubst assets/%,%, \ + $(call find-subdir-assets, $(dir)) \ + ) \ + ) \ + )) ifneq ($(all_assets),) need_compile_asset := true @@ -141,6 +141,7 @@ LOCAL_INTERMEDIATE_TARGETS += $(R_file_stamp) endif LOCAL_BUILT_MODULE_STEM := package.apk +LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk LOCAL_PROGUARD_ENABLED:=$(strip $(LOCAL_PROGUARD_ENABLED)) ifndef LOCAL_PROGUARD_ENABLED @@ -200,10 +201,11 @@ ifeq ($(LOCAL_SDK_RES_VERSION),) LOCAL_SDK_RES_VERSION:=$(LOCAL_SDK_VERSION) endif -full_android_manifest := $(LOCAL_FULL_MANIFEST_FILE) +include $(BUILD_SYSTEM)/android_manifest.mk + $(LOCAL_INTERMEDIATE_TARGETS): \ PRIVATE_ANDROID_MANIFEST := $(full_android_manifest) -ifneq (,$(filter-out current, $(LOCAL_SDK_VERSION))) +ifneq (,$(filter-out current system_current, $(LOCAL_SDK_VERSION))) $(LOCAL_INTERMEDIATE_TARGETS): \ PRIVATE_DEFAULT_APP_TARGET_SDK := $(LOCAL_SDK_VERSION) else @@ -251,6 +253,7 @@ $(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(RenderScript_file_ $(proguard_options_file): $(R_file_stamp) +resource_export_package := ifdef LOCAL_EXPORT_PACKAGE_RESOURCES # Put this module's resources into a PRODUCT-agnositc package that # other packages can use to build their own PRODUCT-agnostic R.java (etc.) @@ -290,7 +293,7 @@ else # Most packages should link against the resources defined by framework-res. # Even if they don't have their own resources, they may use framework # resources. -ifneq ($(filter-out current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current,$(LOCAL_SDK_RES_VERSION))),) +ifneq ($(filter-out current system_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current,$(LOCAL_SDK_RES_VERSION))),) # for released sdk versions, the platform resources were built into android.jar. framework_res_package_export := \ $(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar @@ -304,9 +307,19 @@ framework_res_package_export := \ framework_res_package_export_deps := \ $(dir $(framework_res_package_export))src/R.stamp endif # LOCAL_SDK_RES_VERSION -$(R_file_stamp): $(framework_res_package_export_deps) +all_library_res_package_exports := \ + $(framework_res_package_export) \ + $(foreach lib,$(LOCAL_RES_LIBRARIES),\ + $(call intermediates-dir-for,APPS,$(lib),,COMMON)/package-export.apk) + +all_library_res_package_export_deps := \ + $(framework_res_package_export_deps) \ + $(foreach lib,$(LOCAL_RES_LIBRARIES),\ + $(call intermediates-dir-for,APPS,$(lib),,COMMON)/src/R.stamp) + +$(resource_export_package) $(R_file_stamp) $(LOCAL_BUILT_MODULE): $(all_library_res_package_export_deps) $(LOCAL_INTERMEDIATE_TARGETS): \ - PRIVATE_AAPT_INCLUDES := $(framework_res_package_export) + PRIVATE_AAPT_INCLUDES := $(all_library_res_package_exports) endif # LOCAL_NO_STANDARD_LIBRARIES ifneq ($(full_classes_jar),) @@ -364,8 +377,12 @@ ifeq ($(LOCAL_AAPT_INCLUDE_ALL_RESOURCES),true) $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := else $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_CONFIG := $(PRODUCT_AAPT_CONFIG) +ifdef LOCAL_PACKAGE_SPLITS + $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := +else $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := $(PRODUCT_AAPT_PREF_CONFIG) endif +endif $(LOCAL_BUILT_MODULE): $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest) @echo "target Package: $(PRIVATE_MODULE) ($@)" $(create-empty-package) @@ -401,6 +418,42 @@ $(built_odex) : $(built_dex) $(hide) rm $@.input endif +############################### +## APK splits +ifdef LOCAL_PACKAGE_SPLITS +# LOCAL_PACKAGE_SPLITS is a list of resource labels. +built_apk_splits := $(foreach s,$(LOCAL_PACKAGE_SPLITS),$(built_module_path)/package_$(s).apk) +installed_apk_splits := $(foreach s,$(LOCAL_PACKAGE_SPLITS),$(my_module_path)/$(LOCAL_MODULE)_$(s).apk) + +# The splits should have been built in the same command building the base apk. +# This rule just runs signing and zipalign etc. +# Note that we explicily check the existence of the split apk and remove the +# built base apk if the split apk isn't there. +# That way the build system will rerun the aapt after the user changes the splitting parameters. +$(built_apk_splits): PRIVATE_PRIVATE_KEY := $(private_key) +$(built_apk_splits): PRIVATE_CERTIFICATE := $(certificate) +$(built_apk_splits) : $(built_module_path)/%.apk : $(LOCAL_BUILT_MODULE) + $(hide) if [ ! -f $@ ]; then \ + echo 'No $@ generated, check your apk splitting parameters.' 1>&2; \ + rm $<; exit 1; \ + fi + $(sign-package) + $(align-package) + +# Rules to install the splits +$(installed_apk_splits) : $(my_module_path)/$(LOCAL_MODULE)_%.apk : $(built_module_path)/package_%.apk | $(ACP) + @echo "Install: $@" + $(copy-file-to-new-target) + +# Register the additional built and installed files. +ALL_MODULES.$(my_register_name).INSTALLED += $(installed_apk_splits) +ALL_MODULES.$(my_register_name).BUILT_INSTALLED += \ + $(foreach s,$(LOCAL_PACKAGE_SPLITS),$(built_module_path)/package_$(s).apk:$(my_module_path)/$(LOCAL_MODULE)_$(s).apk) + +# Make sure to install the splits when you run "make <module_name>". +$(my_register_name): $(installed_apk_splits) +endif # LOCAL_PACKAGE_SPLITS + # Save information about this package PACKAGES.$(LOCAL_PACKAGE_NAME).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES)) PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_FILES := $(all_resources) diff --git a/core/pathmap.mk b/core/pathmap.mk index b2abc07..0e10ac1 100644 --- a/core/pathmap.mk +++ b/core/pathmap.mk @@ -29,10 +29,8 @@ pathmap_INCL := \ bootloader:bootable/bootloader/legacy/include \ camera:system/media/camera/include \ - corecg:external/skia/include/core \ frameworks-base:frameworks/base/include \ frameworks-native:frameworks/native/include \ - graphics:external/skia/include/core \ libc:bionic/libc/include \ libhardware:hardware/libhardware/include \ libhardware_legacy:hardware/libhardware_legacy/include \ @@ -51,6 +49,7 @@ pathmap_INCL := \ audio-route:system/media/audio_route/include \ wilhelm:frameworks/wilhelm/include \ wilhelm-ut:frameworks/wilhelm/src/ut \ + mediandk:frameworks/av/media/ndk/ \ speex:external/speex/include # @@ -86,7 +85,9 @@ FRAMEWORKS_BASE_SUBDIRS := \ drm \ opengl \ sax \ + telecomm \ telephony \ + phone \ wifi \ keystore \ rs \ @@ -105,12 +106,16 @@ FRAMEWORKS_BASE_JAVA_SRC_DIRS := \ # A list of all source roots under frameworks/support. # FRAMEWORKS_SUPPORT_SUBDIRS := \ + annotations \ + media/protocols \ v4 \ v7/gridlayout \ v7/appcompat \ v7/mediarouter \ + v7/recyclerview \ v8/renderscript \ - v13 + v13 \ + v17/leanback # # A list of all source roots under frameworks/multidex. diff --git a/core/pdk_config.mk b/core/pdk_config.mk index 9590d70..838754f 100644 --- a/core/pdk_config.mk +++ b/core/pdk_config.mk @@ -18,9 +18,14 @@ pdk fusion: $(DEFAULT_GOAL) # if PDK_FUSION_PLATFORM_ZIP is specified, do not override. ifndef PDK_FUSION_PLATFORM_ZIP +# Most PDK project paths should be using vendor/pdk/TARGET_DEVICE +# but some legacy ones (e.g. mini_armv7a_neon generic PDK) were setup +# with vendor/pdk/TARGET_PRODUCT. _pdk_fusion_default_platform_zip = $(wildcard \ vendor/pdk/$(TARGET_DEVICE)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)/platform/platform.zip \ -vendor/pdk/$(TARGET_DEVICE)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform/platform.zip) +vendor/pdk/$(TARGET_DEVICE)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform/platform.zip \ +vendor/pdk/$(TARGET_PRODUCT)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)/platform/platform.zip \ +vendor/pdk/$(TARGET_PRODUCT)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform/platform.zip) ifneq (,$(_pdk_fusion_default_platform_zip)) PDK_FUSION_PLATFORM_ZIP := $(word 1, $(_pdk_fusion_default_platform_zip)) TARGET_BUILD_PDK := true @@ -37,29 +42,41 @@ endif endif # fusion endif # pdk or fusion +PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR := +PDK_PLATFORM_JAVA_ZIP_JAVA_HOST_LIB_DIR := \ + host/common/obj/JAVA_LIBRARIES/bouncycastle-host_intermediates +PDK_PLATFORM_JAVA_ZIP_CONTENTS := + ifneq (,$(filter platform-java, $(MAKECMDGOALS))$(PDK_FUSION_PLATFORM_ZIP)) # additional items to add to platform.zip for platform-java build # For these dirs, add classes.jar and javalib.jar from the dir to platform.zip # all paths under out dir -PDK_PLATFORM_JAVA_ZIP_JAVA_LIB_DIR := \ +PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR += \ target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates \ - target/common/obj/JAVA_LIBRARIES/core_intermediates \ + target/common/obj/JAVA_LIBRARIES/core-libart_intermediates \ target/common/obj/JAVA_LIBRARIES/core-junit_intermediates \ target/common/obj/JAVA_LIBRARIES/ext_intermediates \ target/common/obj/JAVA_LIBRARIES/framework_intermediates \ - target/common/obj/JAVA_LIBRARIES/framework2_intermediates \ target/common/obj/JAVA_LIBRARIES/android.test.runner_intermediates \ target/common/obj/JAVA_LIBRARIES/telephony-common_intermediates \ target/common/obj/JAVA_LIBRARIES/voip-common_intermediates \ + target/common/obj/JAVA_LIBRARIES/ims-common_intermediates \ target/common/obj/JAVA_LIBRARIES/mms-common_intermediates \ - target/common/obj/JAVA_LIBRARIES/android-ex-camera2_intermediates + target/common/obj/JAVA_LIBRARIES/android-ex-camera2_intermediates \ + target/common/obj/JAVA_LIBRARIES/android-common_intermediates \ + # not java libraries -PDK_PLATFORM_JAVA_ZIP_CONTENTS := \ +PDK_PLATFORM_JAVA_ZIP_CONTENTS += \ target/common/obj/APPS/framework-res_intermediates/package-export.apk \ target/common/obj/APPS/framework-res_intermediates/src/R.stamp +endif # platform-java or FUSION build + +PDK_PLATFORM_JAVA_ZIP_JAVA_LIB_DIR := \ + $(PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR) \ + $(PDK_PLATFORM_JAVA_ZIP_JAVA_HOST_LIB_DIR) + PDK_PLATFORM_JAVA_ZIP_CONTENTS += $(foreach lib_dir,$(PDK_PLATFORM_JAVA_ZIP_JAVA_LIB_DIR),\ $(lib_dir)/classes.jar $(lib_dir)/javalib.jar) -endif # platform-java or FUSION build # check and override java support level ifneq ($(TARGET_BUILD_PDK)$(PDK_FUSION_PLATFORM_ZIP),) @@ -117,6 +134,11 @@ $(PRODUCT_OUT)/% : $(_pdk_fusion_intermediates)/% $(_pdk_fusion_stamp) $(hide) rm -rf $@ $(hide) cp -fpPR $< $@ +# implicit rules for host java files +$(HOST_COMMON_OUT_ROOT)/% : $(_pdk_fusion_intermediates)/host/common/% $(_pdk_fusion_stamp) + @mkdir -p $(dir $@) + $(hide) cp -fpPR $< $@ + ifeq (true,$(TARGET_BUILD_PDK_JAVA_PLATFORM)) PDK_FUSION_OUT_DIR := $(OUT_DIR) @@ -137,11 +159,11 @@ target/common/obj/APPS/framework-res_intermediates/src/R.stamp,\ target/common/obj/APPS/framework-res_intermediates/package-export.apk)) # javalib.jar should pull classes.jar as classes.jar is not explicitly pulled. -$(foreach lib_dir,$(PDK_PLATFORM_JAVA_ZIP_JAVA_LIB_DIR),\ +$(foreach lib_dir,$(PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR),\ $(eval $(call JAVA_dependency_template,$(lib_dir)/javalib.jar,\ $(lib_dir)/classes.jar))) -# implicit rules for all others +# implicit rules for all other target files $(TARGET_COMMON_OUT_ROOT)/% : $(_pdk_fusion_intermediates)/target/common/% $(_pdk_fusion_stamp) @mkdir -p $(dir $@) $(hide) cp -fpPR $< $@ @@ -170,12 +192,16 @@ endif # BUILD_PDK ifneq (,$(filter platform platform-java, $(MAKECMDGOALS))$(filter true,$(TARGET_BUILD_PDK))) # files under $(PRODUCT_OUT)/symbols to help debugging. # Source not included to PDK due to dependency issue, so provide symbols instead. + +# We may not be building all of them. +# The platform.zip just silently ignores the nonexistent ones. PDK_SYMBOL_FILES_LIST := \ - system/bin/app_process + system/bin/app_process32 \ + system/bin/app_process64 ifdef PDK_FUSION_PLATFORM_ZIP # symbols should be explicitly pulled for fusion build -$(foreach f,$(PDK_SYMBOL_FILES_LIST),\ +$(foreach f,$(filter $(PDK_SYMBOL_FILES_LIST), $(_pdk_fusion_file_list)),\ $(eval $(call add-dependency,$(PRODUCT_OUT)/$(f),$(PRODUCT_OUT)/symbols/$(f)))) endif # PLATFORM_ZIP endif # platform.zip build or PDK diff --git a/core/post_clean.mk b/core/post_clean.mk index 213c43c..f7e654b 100644 --- a/core/post_clean.mk +++ b/core/post_clean.mk @@ -15,6 +15,7 @@ # Clean steps that need global knowledge of individual modules. # This file must be included after all Android.mks have been loaded. +####################################################### # Checks the current build configurations against the previous build, # clean artifacts in TARGET_COMMON_OUT_ROOT if necessary. # If a package's resource overlay has been changed, its R class needs to be @@ -51,3 +52,45 @@ $(shell mv -f $(current_package_overlay_config) $(previous_package_overlay_confi previous_package_overlay_config := current_package_overlay_config := current_all_packages_config := + +####################################################### +# Check if we need to delete obsolete aidl-generated java files. +# When an aidl file gets deleted (or renamed), the generated java file is obsolete. +previous_aidl_config := $(TARGET_OUT_COMMON_INTERMEDIATES)/previous_aidl_config.mk +current_aidl_config := $(TARGET_OUT_COMMON_INTERMEDIATES)/current_aidl_config.mk + +$(shell rm -rf $(current_aidl_config) \ + && mkdir -p $(dir $(current_aidl_config))\ + && touch $(current_aidl_config)) +-include $(previous_aidl_config) + +intermediates_to_clean := +modules_with_aidl_files := +$(foreach p, $(ALL_MODULES), \ + $(if $(ALL_MODULES.$(p).AIDL_FILES),\ + $(eval modules_with_aidl_files += $(p))\ + $(shell echo 'AIDL_FILES.$(p) := $(ALL_MODULES.$(p).AIDL_FILES)' >> $(current_aidl_config)))\ + $(if $(filter-out $(ALL_MODULES.$(p).AIDL_FILES),$(AIDL_FILES.$(p))),\ + $(eval intermediates_to_clean += $(ALL_MODULES.$(p).INTERMEDIATE_SOURCE_DIR)))) +intermediates_to_clean := $(strip $(intermediates_to_clean)) +ifdef intermediates_to_clean +$(info *** Obsolete aidl-generated files detected, clean intermediate files...) +$(info *** rm -rf $(intermediates_to_clean)) +$(shell rm -rf $(intermediates_to_clean)) +intermediates_to_clean := +endif + +# For modules not loaded by the current build (e.g. you are running mm/mmm), +# we copy the info from the previous bulid. +$(foreach p, $(filter-out $(modules_with_aidl_files),$(MODULES_WITH_AIDL_FILES)),\ + $(shell echo 'AIDL_FILES.$(p) := $(AIDL_FILES.$(p))' >> $(current_aidl_config))) +MODULES_WITH_AIDL_FILES := $(sort $(MODULES_WITH_AIDL_FILES) $(modules_with_aidl_files)) +$(shell echo 'MODULES_WITH_AIDL_FILES := $(MODULES_WITH_AIDL_FILES)' >> $(current_aidl_config)) + +# Now current becomes previous. +$(shell mv -f $(current_aidl_config) $(previous_aidl_config)) + +MODULES_WITH_AIDL_FILES := +modules_with_aidl_files := +previous_aidl_config := +current_aidl_config := diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk index b5e5189..5666cfd 100644 --- a/core/prebuilt_internal.mk +++ b/core/prebuilt_internal.mk @@ -54,6 +54,11 @@ ifeq (STATIC_LIBRARIES,$(LOCAL_MODULE_CLASS)) endif endif +ifeq ($(LOCAL_MODULE_CLASS),APPS) +LOCAL_BUILT_MODULE_STEM := package.apk +LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk +endif + ifeq ($(LOCAL_STRIP_MODULE),true) ifdef LOCAL_IS_HOST_MODULE $(error Cannot strip host module LOCAL_PATH=$(LOCAL_PATH)) @@ -106,6 +111,7 @@ endif endif # LOCAL_STRIP_MODULE not true +ifeq ($(LOCAL_MODULE_CLASS),APPS) PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES)) rs_compatibility_jni_libs := @@ -125,11 +131,9 @@ ifeq ($(LOCAL_CERTIFICATE),EXTERNAL) $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem endif ifeq ($(LOCAL_CERTIFICATE),) - ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),) - # It is now a build error to add a prebuilt .apk without - # specifying a key for it. - $(error No LOCAL_CERTIFICATE specified for prebuilt "$(my_prebuilt_src_file)") - endif + # It is now a build error to add a prebuilt .apk without + # specifying a key for it. + $(error No LOCAL_CERTIFICATE specified for prebuilt "$(my_prebuilt_src_file)") else ifeq ($(LOCAL_CERTIFICATE),PRESIGNED) # The magic string "PRESIGNED" means this package is already checked # signed with its release key. @@ -153,8 +157,6 @@ else $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem endif -ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),) - # Disable dex-preopt of prebuilts to save space LOCAL_DEX_PREOPT := false @@ -185,6 +187,42 @@ $(built_odex) : $(my_prebuilt_src_file) $(call dexpreopt-one-file,$<,$@) endif +############################### +## Install split apks. +ifdef LOCAL_PACKAGE_SPLITS +# LOCAL_PACKAGE_SPLITS is a list of apks to be installed. +built_apk_splits := $(addprefix $(built_module_path)/,$(notdir $(LOCAL_PACKAGE_SPLITS))) +installed_apk_splits := $(addprefix $(my_module_path)/,$(notdir $(LOCAL_PACKAGE_SPLITS))) + +# Rules to sign and zipalign the split apks. +my_src_dir := $(sort $(dir $(LOCAL_PACKAGE_SPLITS))) +ifneq (1,$(words $(my_src_dir))) +$(error You must put all the split source apks in the same folder: $(LOCAL_PACKAGE_SPLITS)) +endif +my_src_dir := $(LOCAL_PATH)/$(my_src_dir) + +$(built_apk_splits) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8 +$(built_apk_splits) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem +$(built_apk_splits) : $(built_module_path)/%.apk : $(my_src_dir)/%.apk | $(ACP) + $(copy-file-to-new-target) + $(sign-package) + $(align-package) + +# Rules to install the split apks. +$(installed_apk_splits) : $(my_module_path)/%.apk : $(built_module_path)/%.apk | $(ACP) + @echo "Install: $@" + $(copy-file-to-new-target) + +# Register the additional built and installed files. +ALL_MODULES.$(my_register_name).INSTALLED += $(installed_apk_splits) +ALL_MODULES.$(my_register_name).BUILT_INSTALLED += \ + $(foreach s,$(LOCAL_PACKAGE_SPLITS),$(built_module_path)/$(notdir $(s)):$(my_module_path)/$(notdir $(s))) + +# Make sure to install the splits when you run "make <module_name>". +$(my_register_name): $(installed_apk_splits) + +endif # LOCAL_PACKAGE_SPLITS + else # LOCAL_MODULE_CLASS != APPS ifneq ($(LOCAL_PREBUILT_STRIP_COMMENTS),) $(built_module) : $(my_prebuilt_src_file) diff --git a/core/product.mk b/core/product.mk index fd405ad..89d5982 100644 --- a/core/product.mk +++ b/core/product.mk @@ -86,6 +86,7 @@ _product_var_list := \ PRODUCT_PACKAGE_OVERLAYS \ DEVICE_PACKAGE_OVERLAYS \ PRODUCT_TAGS \ + PRODUCT_SDK_ATREE_FILES \ PRODUCT_SDK_ADDON_NAME \ PRODUCT_SDK_ADDON_COPY_FILES \ PRODUCT_SDK_ADDON_COPY_MODULES \ @@ -99,6 +100,12 @@ _product_var_list := \ PRODUCT_RUNTIMES \ PRODUCT_BOOT_JARS \ PRODUCT_DEX_PREOPT_IMAGE_IN_DATA \ + PRODUCT_SUPPORTS_VERITY \ + PRODUCT_OEM_PROPERTIES \ + PRODUCT_SYSTEM_PROPERTY_BLACKLIST \ + PRODUCT_VERITY_SIGNING_KEY \ + PRODUCT_SYSTEM_VERITY_PARTITION \ + PRODUCT_VENDOR_VERITY_PARTITION define dump-product $(info ==== $(1) ====)\ @@ -243,11 +250,13 @@ _product_stash_var_list += \ BOARD_BOOTIMAGE_PARTITION_SIZE \ BOARD_RECOVERYIMAGE_PARTITION_SIZE \ BOARD_SYSTEMIMAGE_PARTITION_SIZE \ + BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE \ BOARD_USERDATAIMAGE_PARTITION_SIZE \ BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE \ BOARD_CACHEIMAGE_PARTITION_SIZE \ BOARD_FLASH_BLOCK_SIZE \ - BOARD_SYSTEMIMAGE_PARTITION_SIZE \ + BOARD_VENDORIMAGE_PARTITION_SIZE \ + BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE \ BOARD_INSTALLER_CMDLINE \ diff --git a/core/product_config.mk b/core/product_config.mk index 9468362..261b935 100644 --- a/core/product_config.mk +++ b/core/product_config.mk @@ -317,8 +317,10 @@ PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCT_AAPT_PREF_CONFIG)) # Everyone gets nodpi assets which are density-independent. PRODUCT_AAPT_CONFIG += nodpi +# Keep a copy of the space-separated config +PRODUCT_AAPT_CONFIG_SP := $(PRODUCT_AAPT_CONFIG) + # Convert spaces to commas. -comma := , PRODUCT_AAPT_CONFIG := \ $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG))) PRODUCT_AAPT_PREF_CONFIG := \ diff --git a/core/proguard_basic_keeps.flags b/core/proguard_basic_keeps.flags index af0e05d..4a85db0 100644 --- a/core/proguard_basic_keeps.flags +++ b/core/proguard_basic_keeps.flags @@ -49,12 +49,16 @@ # -keep class * extends android.preference.Preference # -keep class * extends android.app.BackupAgent -#-keep class * implements android.os.Parcelable { -# public static final android.os.Parcelable$Creator *; -#} +# Parcelable CREATORs must be kept for Parcelable functionality +-keep class * implements android.os.Parcelable { + public static final ** CREATOR; +} # The support library contains references to newer platform versions. # Don't warn about those in case this app is linking against an older # platform version. We know about them, and they are safe. # See proguard-android.txt in the SDK package. -dontwarn android.support.** + +# Less spammy. +-dontnote diff --git a/core/shared_library_internal.mk b/core/shared_library_internal.mk index abef11f..c01be37 100644 --- a/core/shared_library_internal.mk +++ b/core/shared_library_internal.mk @@ -40,7 +40,6 @@ include $(BUILD_SYSTEM)/dynamic_binary.mk # Define PRIVATE_ variables from global vars my_target_global_ld_dirs := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_LD_DIRS) -my_target_fdo_lib := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_FDO_LIB) my_target_libgcc := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCC) my_target_libatomic := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBATOMIC) my_target_crtbegin_so_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CRTBEGIN_SO_O) @@ -58,7 +57,6 @@ my_target_crtend_so_o := $(wildcard $(my_ndk_sysroot_lib)/crtend_so.o) endif $(linked_module): PRIVATE_TARGET_GLOBAL_LD_DIRS := $(my_target_global_ld_dirs) $(linked_module): PRIVATE_TARGET_GLOBAL_LDFLAGS := $(my_target_global_ldflags) -$(linked_module): PRIVATE_TARGET_FDO_LIB := $(my_target_fdo_lib) $(linked_module): PRIVATE_TARGET_LIBGCC := $(my_target_libgcc) $(linked_module): PRIVATE_TARGET_LIBATOMIC := $(my_target_libatomic) $(linked_module): PRIVATE_TARGET_CRTBEGIN_SO_O := $(my_target_crtbegin_so_o) diff --git a/core/static_java_library.mk b/core/static_java_library.mk index 79b7292..02078e0 100644 --- a/core/static_java_library.mk +++ b/core/static_java_library.mk @@ -67,14 +67,7 @@ include $(BUILD_SYSTEM)/java_library.mk ifeq (true,$(need_compile_res)) R_file_stamp := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/R.stamp -ifeq ($(strip $(LOCAL_MANIFEST_FILE)),) - LOCAL_MANIFEST_FILE := AndroidManifest.xml -endif -ifdef LOCAL_FULL_MANIFEST_FILE - full_android_manifest := $(LOCAL_FULL_MANIFEST_FILE) -else - full_android_manifest := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE) -endif +include $(BUILD_SYSTEM)/android_manifest.mk LOCAL_SDK_RES_VERSION:=$(strip $(LOCAL_SDK_RES_VERSION)) ifeq ($(LOCAL_SDK_RES_VERSION),) @@ -85,7 +78,7 @@ framework_res_package_export := framework_res_package_export_deps := # Please refer to package.mk ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true) -ifneq ($(filter-out current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current,$(LOCAL_SDK_RES_VERSION))),) +ifneq ($(filter-out current system_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current,$(LOCAL_SDK_RES_VERSION))),) framework_res_package_export := \ $(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar framework_res_package_export_deps := $(framework_res_package_export) @@ -105,7 +98,7 @@ $(R_file_stamp): PRIVATE_ANDROID_MANIFEST := $(full_android_manifest) $(R_file_stamp): PRIVATE_RESOURCE_PUBLICS_OUTPUT := $(intermediates.COMMON)/public_resources.xml $(R_file_stamp): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR) $(R_file_stamp): PRIVATE_AAPT_INCLUDES := $(framework_res_package_export) -ifneq (,$(filter-out current, $(LOCAL_SDK_VERSION))) +ifneq (,$(filter-out current system_current, $(LOCAL_SDK_VERSION))) $(R_file_stamp): PRIVATE_DEFAULT_APP_TARGET_SDK := $(LOCAL_SDK_VERSION) else $(R_file_stamp): PRIVATE_DEFAULT_APP_TARGET_SDK := $(DEFAULT_APP_TARGET_SDK) diff --git a/core/tasks/apicheck.mk b/core/tasks/apicheck.mk index 00b78b9..fc98f5b 100644 --- a/core/tasks/apicheck.mk +++ b/core/tasks/apicheck.mk @@ -42,6 +42,8 @@ $(eval $(call check-api, \ checkapi-last, \ $(SRC_API_DIR)/$(last_released_sdk_version).txt, \ $(INTERNAL_PLATFORM_API_FILE), \ + frameworks/base/api/removed.txt, \ + $(INTERNAL_PLATFORM_REMOVED_API_FILE), \ -hide 2 -hide 3 -hide 4 -hide 5 -hide 6 -hide 24 -hide 25 -hide 26 -hide 27 \ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -error 16 -error 17 -error 18 , \ @@ -56,11 +58,13 @@ $(eval $(call check-api, \ checkapi-current, \ frameworks/base/api/current.txt, \ $(INTERNAL_PLATFORM_API_FILE), \ + frameworks/base/api/removed.txt, \ + $(INTERNAL_PLATFORM_REMOVED_API_FILE), \ -error 2 -error 3 -error 4 -error 5 -error 6 \ -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \ -error 25 -error 26 -error 27, \ - cat $(BUILD_SYSTEM)/apicheck_msg_current.txt, \ + sed -e 's/%UPDATE_API%/update-api/g' $(BUILD_SYSTEM)/apicheck_msg_current.txt, \ checkapi, \ $(call doc-timestamp-for,api-stubs) \ )) @@ -69,5 +73,51 @@ $(eval $(call check-api, \ update-api: $(INTERNAL_PLATFORM_API_FILE) | $(ACP) @echo Copying current.txt $(hide) $(ACP) $(INTERNAL_PLATFORM_API_FILE) frameworks/base/api/current.txt + @echo Copying removed.txt + $(hide) $(ACP) $(INTERNAL_PLATFORM_REMOVED_API_FILE) frameworks/base/api/removed.txt + + +#####################Check System API##################### +.PHONY: checksystemapi + +# Check that the System API we're building hasn't broken the last-released +# SDK version. +$(eval $(call check-api, \ + checksystemapi-last, \ + $(SRC_SYSTEM_API_DIR)/$(last_released_sdk_version).txt, \ + $(INTERNAL_PLATFORM_SYSTEM_API_FILE), \ + frameworks/base/api/system-removed.txt, \ + $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE), \ + -hide 2 -hide 3 -hide 4 -hide 5 -hide 6 -hide 24 -hide 25 -hide 26 -hide 27 \ + -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ + -error 16 -error 17 -error 18 , \ + cat $(BUILD_SYSTEM)/apicheck_msg_last.txt, \ + checksystemapi, \ + $(call doc-timestamp-for,system-api-stubs) \ + )) + +# Check that the System API we're building hasn't changed from the not-yet-released +# SDK version. +$(eval $(call check-api, \ + checksystemapi-current, \ + frameworks/base/api/system-current.txt, \ + $(INTERNAL_PLATFORM_SYSTEM_API_FILE), \ + frameworks/base/api/system-removed.txt, \ + $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE), \ + -error 2 -error 3 -error 4 -error 5 -error 6 \ + -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ + -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \ + -error 25 -error 26 -error 27, \ + sed -e 's/%UPDATE_API%/update-system-api/g' $(BUILD_SYSTEM)/apicheck_msg_current.txt, \ + checksystemapi, \ + $(call doc-timestamp-for,system-api-stubs) \ + )) + +.PHONY: update-system-api +update-system-api: $(INTERNAL_PLATFORM_SYSTEM_API_FILE) | $(ACP) + @echo Copying system-current.txt + $(hide) $(ACP) $(INTERNAL_PLATFORM_SYSTEM_API_FILE) frameworks/base/api/system-current.txt + @echo Copying system-removed.txt + $(hide) $(ACP) $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE) frameworks/base/api/system-removed.txt endif diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk index c521fa3..82094b9 100644 --- a/core/tasks/cts.mk +++ b/core/tasks/cts.mk @@ -18,7 +18,7 @@ cts_tools_src_dir := cts/tools cts_name := android-cts DDMLIB_JAR := $(HOST_OUT_JAVA_LIBRARIES)/ddmlib-prebuilt.jar -junit_host_jar := $(HOST_OUT_JAVA_LIBRARIES)/junit.jar +JUNIT_HOST_JAR := $(HOST_OUT_JAVA_LIBRARIES)/junit.jar HOSTTESTLIB_JAR := $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar TF_JAR := $(HOST_OUT_JAVA_LIBRARIES)/tradefed-prebuilt.jar CTS_TF_JAR := $(HOST_OUT_JAVA_LIBRARIES)/cts-tradefed.jar @@ -48,6 +48,7 @@ CTS_CORE_CASE_LIST := \ android.core.tests.libcore.package.harmony_java_text \ android.core.tests.libcore.package.harmony_java_util \ android.core.tests.libcore.package.harmony_javax_security \ + android.core.tests.libcore.package.okhttp \ android.core.tests.runner # The list of test packages that apache-harmony-tests (external/apache-harmony/Android.mk) @@ -58,17 +59,23 @@ CTS_CORE_CASE_LIST += \ android.core.tests.libcore.package.harmony_prefs \ android.core.tests.libcore.package.harmony_sql + +CTS_TEST_JAR_LIST := \ + cts-junit \ + CtsJdwp + # Depend on the full package paths rather than the phony targets to avoid # rebuilding the packages every time. CTS_CORE_CASES := $(foreach pkg,$(CTS_CORE_CASE_LIST),$(call intermediates-dir-for,APPS,$(pkg))/package.apk) +CTS_TEST_JAR_FILES := $(foreach c,$(CTS_TEST_JAR_LIST),$(call intermediates-dir-for,JAVA_LIBRARIES,$(c))/javalib.jar) -include cts/CtsTestCaseList.mk CTS_CASE_LIST := $(CTS_CORE_CASE_LIST) $(CTS_TEST_CASE_LIST) DEFAULT_TEST_PLAN := $(cts_dir)/$(cts_name)/resource/plans CTS_TEST_CASE_LIST_FILES := $(foreach c, $(CTS_TEST_CASE_LIST), $(call intermediates-dir-for,APPS,$(c))/package.apk) -$(cts_dir)/all_cts_files_stamp: PRIVATE_JUNIT_HOST_JAR := $(junit_host_jar) -$(cts_dir)/all_cts_files_stamp: $(CTS_CORE_CASES) $(CTS_TEST_CASES) $(CTS_TEST_CASE_LIST_FILES) $(junit_host_jar) $(HOSTTESTLIB_JAR) $(CTS_HOST_LIBRARY_JARS) $(TF_JAR) $(VMTESTSTF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(CTS_TF_README_PATH) $(ACP) +$(cts_dir)/all_cts_files_stamp: PRIVATE_JUNIT_HOST_JAR := $(JUNIT_HOST_JAR) +$(cts_dir)/all_cts_files_stamp: $(CTS_CORE_CASES) $(CTS_TEST_CASES) $(CTS_TEST_CASE_LIST_FILES) $(JUNIT_HOST_JAR) $(HOSTTESTLIB_JAR) $(CTS_HOST_LIBRARY_JARS) $(TF_JAR) $(VMTESTSTF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(CTS_TF_README_PATH) $(ACP) $(CTS_TEST_JAR_FILES) # Make necessary directory for CTS $(hide) rm -rf $(PRIVATE_CTS_DIR) $(hide) mkdir -p $(TMP_DIR) @@ -80,6 +87,7 @@ $(cts_dir)/all_cts_files_stamp: $(CTS_CORE_CASES) $(CTS_TEST_CASES) $(CTS_TEST_C $(hide) $(ACP) -fp $(VMTESTSTF_JAR) $(PRIVATE_DIR)/repository/testcases $(hide) $(ACP) -fp $(DDMLIB_JAR) $(PRIVATE_JUNIT_HOST_JAR) $(HOSTTESTLIB_JAR) $(CTS_HOST_LIBRARY_JARS) $(TF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(CTS_TF_README_PATH) $(PRIVATE_DIR)/tools # Change mode of the executables + $(foreach jar,$(CTS_TEST_JAR_LIST),$(call copy-testcase-jar,$(jar))) $(foreach apk,$(CTS_CASE_LIST),$(call copy-testcase-apk,$(apk))) $(foreach testcase,$(CTS_TEST_CASES),$(call copy-testcase,$(testcase))) $(hide) touch $@ @@ -95,8 +103,8 @@ $(cts_dir)/all_cts_files_stamp: $(CTS_CORE_CASES) $(CTS_TEST_CASES) $(CTS_TEST_C define generate-core-test-description @echo "Generate core-test description ("$(notdir $(1))")" $(hide) java -Xmx256M \ - -Xbootclasspath/a:$(PRIVATE_CLASSPATH) \ - -classpath $(PRIVATE_CLASSPATH):$(HOST_OUT_JAVA_LIBRARIES)/descGen.jar:$(HOST_OUT_JAVA_LIBRARIES)/junit.jar:$(HOST_JDK_TOOLS_JAR) \ + -Xbootclasspath/a:$(PRIVATE_CLASSPATH):$(JUNIT_HOST_JAR) \ + -classpath $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar:$(HOST_JDK_TOOLS_JAR) \ $(PRIVATE_PARAMS) CollectAllTests $(1) $(2) $(3) "$(4)" $(5) $(6) endef @@ -104,15 +112,17 @@ CORE_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-libart,,CO CONSCRYPT_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,conscrypt,,COMMON) BOUNCYCASTLE_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,bouncycastle,,COMMON) APACHEXML_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,apache-xml,,COMMON) -OKHTTP_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,okhttp,,COMMON) -APACHEHARMONY_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,apache-harmony-tests,,COMMON) +OKHTTP_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,okhttp-nojarjar,,COMMON) +OKHTTPTESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,okhttp-tests-nojarjar,,COMMON) +OKHTTP_REPACKAGED_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,okhttp,,COMMON) +APACHEHARMONYTESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,apache-harmony-tests,,COMMON) SQLITEJDBC_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,sqlite-jdbc,,COMMON) JUNIT_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-junit,,COMMON) CORETESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON) JSR166TESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,jsr166-tests,,COMMON) CONSCRYPTTESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,conscrypt-tests,,COMMON) -GEN_CLASSPATH := $(CORE_INTERMEDIATES)/classes.jar:$(CONSCRYPT_INTERMEDIATES)/classes.jar:$(BOUNCYCASTLE_INTERMEDIATES)/classes.jar:$(APACHEXML_INTERMEDIATES)/classes.jar:$(APACHEHARMONY_INTERMEDIATES)/classes.jar:$(OKHTTP_INTERMEDIATES)/classes.jar:$(JUNIT_INTERMEDIATES)/classes.jar:$(SQLITEJDBC_INTERMEDIATES)/javalib.jar:$(CORETESTS_INTERMEDIATES)/javalib.jar:$(JSR166TESTS_INTERMEDIATES)/javalib.jar:$(CONSCRYPTTESTS_INTERMEDIATES)/javalib.jar +GEN_CLASSPATH := $(CORE_INTERMEDIATES)/classes.jar:$(CONSCRYPT_INTERMEDIATES)/classes.jar:$(BOUNCYCASTLE_INTERMEDIATES)/classes.jar:$(APACHEXML_INTERMEDIATES)/classes.jar:$(APACHEHARMONYTESTS_INTERMEDIATES)/classes.jar:$(OKHTTP_INTERMEDIATES)/classes.jar:$(OKHTTPTESTS_INTERMEDIATES)/classes.jar:$(OKHTTP_REPACKAGED_INTERMEDIATES)/classes.jar:$(JUNIT_INTERMEDIATES)/classes.jar:$(SQLITEJDBC_INTERMEDIATES)/javalib.jar:$(CORETESTS_INTERMEDIATES)/javalib.jar:$(JSR166TESTS_INTERMEDIATES)/javalib.jar:$(CONSCRYPTTESTS_INTERMEDIATES)/javalib.jar CTS_CORE_XMLS := \ $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.dalvik.xml \ @@ -136,6 +146,7 @@ CTS_CORE_XMLS := \ $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_logging.xml \ $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_prefs.xml \ $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_sql.xml \ + $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.okhttp.xml \ $(CTS_CORE_XMLS): PRIVATE_CLASSPATH:=$(GEN_CLASSPATH) # Why does this depend on javalib.jar instead of classes.jar? Because @@ -143,7 +154,7 @@ $(CTS_CORE_XMLS): PRIVATE_CLASSPATH:=$(GEN_CLASSPATH) # build system requires that dependencies use javalib.jar. If # javalib.jar is up-to-date, then classes.jar is as well. Depending # on classes.jar will build the files incorrectly. -CTS_CORE_XMLS_DEPS := $(CTS_CORE_CASES) $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(HOST_OUT_JAVA_LIBRARIES)/junit.jar $(CORE_INTERMEDIATES)/javalib.jar $(BOUNCYCASTLE_INTERMEDIATES)/javalib.jar $(APACHEXML_INTERMEDIATES)/javalib.jar $(APACHEHARMONY_INTERMEDIATES)/javalib.jar $(OKHTTP_INTERMEDIATES)/javalib.jar $(SQLITEJDBC_INTERMEDIATES)/javalib.jar $(JUNIT_INTERMEDIATES)/javalib.jar $(CORETESTS_INTERMEDIATES)/javalib.jar $(JSR166TESTS_INTERMEDIATES)/javalib.jar $(CONSCRYPTTESTS_INTERMEDIATES)/javalib.jar build/core/tasks/cts.mk | $(ACP) +CTS_CORE_XMLS_DEPS := $(CTS_CORE_CASES) $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(JUNIT_HOST_JAR) $(CORE_INTERMEDIATES)/javalib.jar $(BOUNCYCASTLE_INTERMEDIATES)/javalib.jar $(APACHEXML_INTERMEDIATES)/javalib.jar $(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar $(OKHTTP_INTERMEDIATES)/javalib.jar $(OKHTTPTESTS_INTERMEDIATES)/javalib.jar $(OKHTTP_REPACKAGED_INTERMEDIATES)/javalib.jar $(SQLITEJDBC_INTERMEDIATES)/javalib.jar $(JUNIT_INTERMEDIATES)/javalib.jar $(CORETESTS_INTERMEDIATES)/javalib.jar $(JSR166TESTS_INTERMEDIATES)/javalib.jar $(CONSCRYPTTESTS_INTERMEDIATES)/javalib.jar build/core/tasks/cts.mk | $(ACP) $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.dalvik.xml: $(CTS_CORE_XMLS_DEPS) $(hide) mkdir -p $(CTS_TESTCASES_OUT) @@ -268,31 +279,37 @@ $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_beans.xml: $(CTS $(hide) mkdir -p $(CTS_TESTCASES_OUT) $(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_beans,\ cts/tests/core/libcore/harmony_beans/AndroidManifest.xml,\ - $(APACHEHARMONY_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.beans,\ + $(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.beans,\ libcore/expectations external/apache-harmony/Android.mk) $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_logging.xml: $(CTS_CORE_XMLS_DEPS) $(hide) mkdir -p $(CTS_TESTCASES_OUT) $(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_logging,\ cts/tests/core/libcore/harmony_logging/AndroidManifest.xml,\ - $(APACHEHARMONY_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.logging,\ + $(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.logging,\ libcore/expectations external/apache-harmony/Android.mk) - $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_prefs.xml: $(CTS_CORE_XMLS_DEPS) $(hide) mkdir -p $(CTS_TESTCASES_OUT) $(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_prefs,\ cts/tests/core/libcore/harmony_prefs/AndroidManifest.xml,\ - $(APACHEHARMONY_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.prefs,\ + $(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.prefs,\ libcore/expectations external/apache-harmony/Android.mk) $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_sql.xml: $(CTS_CORE_XMLS_DEPS) $(hide) mkdir -p $(CTS_TESTCASES_OUT) $(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_sql,\ cts/tests/core/libcore/harmony_sql/AndroidManifest.xml,\ - $(APACHEHARMONY_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.sql,\ + $(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.sql,\ libcore/expectations external/apache-harmony/Android.mk) +$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.okhttp.xml: $(CTS_CORE_XMLS_DEPS) + $(hide) mkdir -p $(CTS_TESTCASES_OUT) + $(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.okhttp,\ + cts/tests/core/libcore/okhttp/AndroidManifest.xml,\ + $(OKHTTPTESTS_INTERMEDIATES)/javalib.jar,,\ + libcore/expectations) + # ----- Generate the test descriptions for the vm-tests-tf ----- # CORE_VM_TEST_TF_DESC := $(CTS_TESTCASES_OUT)/android.core.vm-tests-tf.xml @@ -305,7 +322,7 @@ GEN_CLASSPATH := $(CORE_INTERMEDIATES)/classes.jar:$(JUNIT_INTERMEDIATES)/classe $(CORE_VM_TEST_TF_DESC): PRIVATE_CLASSPATH:=$(GEN_CLASSPATH) # Please see big comment above on why this line depends on javalib.jar instead of classes.jar -$(CORE_VM_TEST_TF_DESC): $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(HOST_OUT_JAVA_LIBRARIES)/junit.jar $(CORE_INTERMEDIATES)/javalib.jar $(JUNIT_INTERMEDIATES)/javalib.jar $(VMTESTSTF_JAR) $(DDMLIB_JAR) | $(ACP) +$(CORE_VM_TEST_TF_DESC): $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(JUNIT_HOST_JAR) $(CORE_INTERMEDIATES)/javalib.jar $(JUNIT_INTERMEDIATES)/javalib.jar $(VMTESTSTF_JAR) $(DDMLIB_JAR) | $(ACP) $(hide) mkdir -p $(CTS_TESTCASES_OUT) $(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.vm-tests-tf,\ cts/tests/vm-tests-tf/AndroidManifest.xml,\ @@ -351,3 +368,11 @@ define copy-testcase $(hide) $(ACP) -fp $(1) $(PRIVATE_DIR)/repository/testcases/$(notdir $1) endef + +define copy-testcase-jar + +$(hide) $(ACP) -fp $(call intermediates-dir-for,JAVA_LIBRARIES,$(1))/javalib.jar \ + $(PRIVATE_DIR)/repository/testcases/$(1).jar + +endef + diff --git a/core/tasks/oem_image.mk b/core/tasks/oem_image.mk new file mode 100644 index 0000000..26b9aba --- /dev/null +++ b/core/tasks/oem_image.mk @@ -0,0 +1,46 @@ +# +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# We build oem.img only if it's asked for. +ifneq ($(filter $(MAKECMDGOALS),oem_image),) +ifndef BOARD_OEMIMAGE_PARTITION_SIZE +$(error BOARD_OEMIMAGE_PARTITION_SIZE is not set.) +endif + +INTERNAL_OEMIMAGE_FILES := \ + $(filter $(TARGET_OUT_OEM)/%,$(ALL_DEFAULT_INSTALLED_MODULES)) + +oemimage_intermediates := \ + $(call intermediates-dir-for,PACKAGING,oem) +BUILT_OEMIMAGE_TARGET := $(PRODUCT_OUT)/oem.img +# We just build this directly to the install location. +INSTALLED_OEMIMAGE_TARGET := $(BUILT_OEMIMAGE_TARGET) + +$(INSTALLED_OEMIMAGE_TARGET) : $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_OEMIMAGE_FILES) + $(call pretty,"Target oem fs image: $@") + @mkdir -p $(TARGET_OUT_OEM) + @mkdir -p $(oemimage_intermediates) && rm -rf $(oemimage_intermediates)/oem_image_info.txt + $(call generate-userimage-prop-dictionary, $(oemimage_intermediates)/oem_image_info.txt, skip_fsck=true) + $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ + ./build/tools/releasetools/build_image.py \ + $(TARGET_OUT_OEM) $(oemimage_intermediates)/oem_image_info.txt $@ + $(hide) $(call assert-max-image-size,$@,$(BOARD_OEMIMAGE_PARTITION_SIZE)) + +.PHONY: oem_image +oem_image : $(INSTALLED_OEMIMAGE_TARGET) +$(call dist-for-goals, oem_image, $(INSTALLED_OEMIMAGE_TARGET)) + +endif # oem_image in $(MAKECMDGOALS) diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk index 87d723c..793dd16 100644 --- a/core/tasks/vendor_module_check.mk +++ b/core/tasks/vendor_module_check.mk @@ -22,15 +22,20 @@ _vendor_owner_whitelist := \ csr \ elan \ google \ + htc \ imgtec \ invensense \ intel \ lge \ + moto \ nvidia \ nxp \ + nxpsw \ qcom \ + qti \ samsung \ samsung_arm \ + synaptics \ ti \ trusted_logic \ widevine diff --git a/core/version_defaults.mk b/core/version_defaults.mk index 1e172ed..31c3242 100644 --- a/core/version_defaults.mk +++ b/core/version_defaults.mk @@ -41,7 +41,7 @@ ifeq "" "$(PLATFORM_VERSION)" # which is the version that we reveal to the end user. # Update this value when the platform version changes (rather # than overriding it somewhere else). Can be an arbitrary string. - PLATFORM_VERSION := 4.4.3 + PLATFORM_VERSION := L endif ifeq "" "$(PLATFORM_SDK_VERSION)" @@ -53,13 +53,18 @@ 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 := 19 + PLATFORM_SDK_VERSION := 20 endif ifeq "" "$(PLATFORM_VERSION_CODENAME)" # This is the current development code-name, if the build is not a final # release build. If this is a final release build, it is simply "REL". - PLATFORM_VERSION_CODENAME := REL + PLATFORM_VERSION_CODENAME := L + + # This is all of the development codenames that are active. Should be either + # the same as PLATFORM_VERSION_CODENAME or a comma-separated list of additional + # codenames after PLATFORM_VERSION_CODENAME. + PLATFORM_VERSION_ALL_CODENAMES := $(PLATFORM_VERSION_CODENAME) endif ifeq "" "$(DEFAULT_APP_TARGET_SDK)" diff --git a/envsetup.sh b/envsetup.sh index 5c66a9e..ca282b6 100644 --- a/envsetup.sh +++ b/envsetup.sh @@ -2,7 +2,7 @@ function hmm() { cat <<EOF Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment: - lunch: lunch <product_name>-<build_variant> -- tapas: tapas [<App1> <App2> ...] [arm|x86|mips|armv5] [eng|userdebug|user] +- tapas: tapas [<App1> <App2> ...] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user] - croot: Changes directory to the top of the tree. - m: Makes from the top of the tree. - mm: Builds all of the modules in the current directory, but not their dependencies. @@ -11,6 +11,7 @@ Invoke ". build/envsetup.sh" from your shell to add the following functions to y - mma: Builds all of the modules in the current directory, and their dependencies. - mmma: Builds all of the modules in the supplied directories, and their dependencies. - cgrep: Greps on all local C/C++ files. +- ggrep: Greps on all local Gradle files. - jgrep: Greps on all local Java files. - resgrep: Greps on all local res/*.xml files. - godir: Go to the directory containing a file. @@ -35,7 +36,7 @@ function get_abs_build_var() return fi (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ - make --no-print-directory -f build/core/config.mk dumpvar-abs-$1) + command make --no-print-directory -f build/core/config.mk dumpvar-abs-$1) } # Get the exact value of a build variable. @@ -47,7 +48,7 @@ function get_build_var() return fi (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ - make --no-print-directory -f build/core/config.mk dumpvar-$1) + command make --no-print-directory -f build/core/config.mk dumpvar-$1) } # check to see if the supplied product is one we can build @@ -204,6 +205,24 @@ function setpaths() unset ANDROID_HOST_OUT export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT) + # If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH + # to ensure that the corresponding 'emulator' binaries are used. + case $(uname -s) in + Darwin) + ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/darwin-x86_64 + ;; + Linux) + ANDROID_EMULATOR_PREBUILTS=$T/prebuilts/android-emulator/linux-x86_64 + ;; + *) + ANDROID_EMULATOR_PREBUILTS= + ;; + esac + if [ -n "$ANDROID_EMULATOR_PREBUILTS" -a -d "$ANDROID_EMULATOR_PREBUILTS" ]; then + PATH=$ANDROID_EMULATOR_PREBUILTS:$PATH + export ANDROID_EMULATOR_PREBUILTS + fi + # needed for building linux on MacOS # TODO: fix the path #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include @@ -564,12 +583,12 @@ function _lunch() complete -F _lunch lunch # Configures the build to build unbundled apps. -# Run tapas with one ore more app names (from LOCAL_PACKAGE_NAME) +# Run tapas with one or more app names (from LOCAL_PACKAGE_NAME) function tapas() { - local arch=$(echo -n $(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|armv5)$')) - local variant=$(echo -n $(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$')) - local apps=$(echo -n $(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|mips|armv5)$')) + local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|armv5|arm64|x86_64|mips64)$' | xargs)" + local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)" + local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|mips|armv5|arm64|x86_64|mips64)$' | xargs)" if [ $(echo $arch | wc -w) -gt 1 ]; then echo "tapas: Error: Multiple build archs supplied: $arch" @@ -582,9 +601,12 @@ function tapas() local product=full case $arch in - x86) product=full_x86;; - mips) product=full_mips;; - armv5) product=generic_armv5;; + x86) product=full_x86;; + mips) product=full_mips;; + armv5) product=generic_armv5;; + arm64) product=aosp_arm64;; + x86_64) product=aosp_x86_64;; + mips64) product=aosp_mips64;; esac if [ -z "$variant" ]; then variant=eng @@ -1035,6 +1057,7 @@ function gdbclient() fi OUT_SO_SYMBOLS=$OUT_SO_SYMBOLS$USE64BIT + OUT_VENDOR_SO_SYMBOLS=$OUT_VENDOR_SO_SYMBOLS$USE64BIT echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $OUT_SYMBOLS" echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $OUT_SO_SYMBOLS:$OUT_SO_SYMBOLS/hw:$OUT_SO_SYMBOLS/ssl/engines:$OUT_SO_SYMBOLS/drm:$OUT_SO_SYMBOLS/egl:$OUT_SO_SYMBOLS/soundfx:$OUT_VENDOR_SO_SYMBOLS:$OUT_VENDOR_SO_SYMBOLS/hw:$OUT_VENDOR_SO_SYMBOLS/egl" @@ -1082,6 +1105,11 @@ function gettargetarch get_build_var TARGET_ARCH } +function ggrep() +{ + find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.gradle" -print0 | xargs -0 grep --color -n "$@" +} + function jgrep() { find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.java" -print0 | xargs -0 grep --color -n "$@" @@ -1217,9 +1245,7 @@ function runhat() fi # issue "am" command to cause the hprof dump - local sdcard=$(adb ${adbOptions} shell echo -n '$EXTERNAL_STORAGE') - local devFile=$sdcard/hprof-$targetPid - #local devFile=/data/local/hprof-$targetPid + local devFile=/data/local/tmp/hprof-$targetPid echo "Poking $targetPid and waiting for data..." echo "Storing data at $devFile" adb ${adbOptions} shell am dumpheap $targetPid $devFile @@ -1445,6 +1471,36 @@ function pez { return $retval } +function make() +{ + local start_time=$(date +"%s") + command make "$@" + local ret=$? + local end_time=$(date +"%s") + local tdiff=$(($end_time-$start_time)) + local hours=$(($tdiff / 3600 )) + local mins=$((($tdiff % 3600) / 60)) + local secs=$(($tdiff % 60)) + echo + if [ $ret -eq 0 ] ; then + echo -n -e "#### make completed successfully " + else + echo -n -e "#### make failed to build some targets " + fi + if [ $hours -gt 0 ] ; then + printf "(%02g:%02g:%02g (hh:mm:ss))" $hours $mins $secs + elif [ $mins -gt 0 ] ; then + printf "(%02g:%02g (mm:ss))" $mins $secs + elif [ $secs -gt 0 ] ; then + printf "(%s seconds)" $secs + fi + echo -e " ####" + echo + return $ret +} + + + if [ "x$SHELL" != "x/bin/bash" ]; then case `ps -o command -p $$` in *bash*) diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk index fe64bcb..06a7d8a 100644 --- a/target/board/generic/device.mk +++ b/target/board/generic/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk index 354fb2a..11a6a31 100644 --- a/target/board/generic_arm64/device.mk +++ b/target/board/generic_arm64/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml PRODUCT_PACKAGES := \ diff --git a/target/board/generic_mips/device.mk b/target/board/generic_mips/device.mk index b182c4c..590f422 100644 --- a/target/board/generic_mips/device.mk +++ b/target/board/generic_mips/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf diff --git a/target/board/generic_mips64/device.mk b/target/board/generic_mips64/device.mk index 58fe976..015686e 100644 --- a/target/board/generic_mips64/device.mk +++ b/target/board/generic_mips64/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk index 089f584..b5b0faf 100644 --- a/target/board/generic_x86/device.mk +++ b/target/board/generic_x86/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml PRODUCT_PACKAGES := \ diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk index 089f584..b5b0faf 100755 --- a/target/board/generic_x86_64/device.mk +++ b/target/board/generic_x86_64/device.mk @@ -25,6 +25,9 @@ PRODUCT_PROPERTY_OVERRIDES := \ PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml PRODUCT_PACKAGES := \ diff --git a/target/board/vbox_x86/device.mk b/target/board/vbox_x86/device.mk index a44a87f..b51f801 100644 --- a/target/board/vbox_x86/device.mk +++ b/target/board/vbox_x86/device.mk @@ -29,6 +29,9 @@ LOCAL_KERNEL := prebuilts/qemu-kernel/x86/kernel-vbox PRODUCT_COPY_FILES := \ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ build/target/board/vbox_x86/init.vbox_x86.rc:root/init.vbox_x86.rc \ $(LOCAL_KERNEL):kernel diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk index a714f1f..abb4d8c 100644 --- a/target/product/AndroidProducts.mk +++ b/target/product/AndroidProducts.mk @@ -42,7 +42,8 @@ PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/aosp_mips.mk \ $(LOCAL_DIR)/full_mips.mk \ $(LOCAL_DIR)/aosp_arm64.mk \ - $(LOCAL_DIR)/aosp_mips64.mk + $(LOCAL_DIR)/aosp_mips64.mk \ + $(LOCAL_DIR)/aosp_x86_64.mk else PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/core.mk \ @@ -60,10 +61,15 @@ PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/aosp_x86_64.mk \ $(LOCAL_DIR)/full_x86_64.mk \ $(LOCAL_DIR)/vbox_x86.mk \ + $(LOCAL_DIR)/sdk_phone_armv7.mk \ + $(LOCAL_DIR)/sdk_phone_x86.mk \ + $(LOCAL_DIR)/sdk_phone_mips.mk \ + $(LOCAL_DIR)/sdk_phone_arm64.mk \ + $(LOCAL_DIR)/sdk_phone_x86_64.mk \ + $(LOCAL_DIR)/sdk_phone_mips64.mk \ $(LOCAL_DIR)/sdk.mk \ $(LOCAL_DIR)/sdk_x86.mk \ $(LOCAL_DIR)/sdk_mips.mk \ $(LOCAL_DIR)/sdk_arm64.mk \ - $(LOCAL_DIR)/sdk_x86_64.mk \ - $(LOCAL_DIR)/sdk_mips64.mk + $(LOCAL_DIR)/sdk_x86_64.mk endif diff --git a/target/product/base.mk b/target/product/base.mk index 8aa3bc0..3609d03 100644 --- a/target/product/base.mk +++ b/target/product/base.mk @@ -18,6 +18,7 @@ PRODUCT_PACKAGES += \ 20-dns.conf \ 95-configured \ + appwidget \ am \ android.policy \ android.test.runner \ @@ -31,34 +32,38 @@ PRODUCT_PACKAGES += \ dhcpcd-run-hooks \ dnsmasq \ framework \ - framework2 \ fsck_msdos \ ime \ input \ + inputflinger \ javax.obex \ libandroid \ libandroid_runtime \ libandroid_servers \ libaudioeffect_jni \ libaudioflinger \ + libaudiopolicyservice \ + libaudiopolicymanager \ libbundlewrapper \ libcamera_client \ libcameraservice \ libdl \ + libdrmclearkeyplugin \ libeffectproxy \ libeffects \ libinput \ + libinputflinger \ libiprouteutil \ - libjni_latinime \ libjnigraphics \ libldnhncr \ libmedia \ libmedia_jni \ libmediaplayerservice \ libmtp \ + libnetd_client \ libnetlink \ libnetutils \ - libpac \ + libpdfium \ libreference-ril \ libreverbwrapper \ libril \ @@ -67,6 +72,8 @@ PRODUCT_PACKAGES += \ libskia \ libsonivox \ libsoundpool \ + libsoundtrigger \ + libsoundtriggerservice \ libsqlite \ libstagefright \ libstagefright_amrnb_common \ @@ -79,6 +86,8 @@ PRODUCT_PACKAGES += \ libutils \ libvisualizer \ libvorbisidec \ + libmediandk \ + libwifi-service \ media \ media_cmd \ mediaserver \ @@ -95,7 +104,6 @@ PRODUCT_PACKAGES += \ racoon \ run-as \ schedtest \ - screenshot \ sdcard \ services \ settings \ @@ -103,7 +111,6 @@ PRODUCT_PACKAGES += \ tc \ vdc \ vold \ - webview \ wm diff --git a/target/product/core.mk b/target/product/core.mk index c5ef2aa..c0a24d3 100644 --- a/target/product/core.mk +++ b/target/product/core.mk @@ -22,15 +22,36 @@ PRODUCT_PACKAGES += \ BasicDreams \ Browser \ + Calculator \ + Calendar \ + CalendarProvider \ + CaptivePortalLogin \ + CertInstaller \ Contacts \ + DeskClock \ DocumentsUI \ DownloadProviderUi \ + Email \ + Exchange2 \ ExternalStorageProvider \ + FusedLocation \ + InputDevices \ KeyChain \ + Keyguard \ + LatinIME \ + Launcher2 \ + ManagedProvisioning \ PicoTts \ PacProcessor \ + libpac \ + PrintSpooler \ ProxyHandler \ + QuickSearchBox \ + Settings \ SharedStorageBackup \ - VpnDialogs + Telecomm \ + TeleService \ + VpnDialogs \ + MmsService $(call inherit-product, $(SRC_TARGET_DIR)/product/core_base.mk) diff --git a/target/product/core_base.mk b/target/product/core_base.mk index 529b5f2..6c29482 100644 --- a/target/product/core_base.mk +++ b/target/product/core_base.mk @@ -30,15 +30,12 @@ PRODUCT_PACKAGES += \ libandroidfw \ libaudiopreprocessing \ libaudioutils \ - libbcc \ libfilterpack_imageproc \ libgabi++ \ - libkeystore \ libmdnssd \ libnfc_ndef \ libpowermanager \ libspeexresampler \ - libstagefright_chromium_http \ libstagefright_soft_aacdec \ libstagefright_soft_aacenc \ libstagefright_soft_amrdec \ @@ -49,9 +46,11 @@ PRODUCT_PACKAGES += \ libstagefright_soft_gsmdec \ libstagefright_soft_h264dec \ libstagefright_soft_h264enc \ + libstagefright_soft_hevcdec \ libstagefright_soft_mp3dec \ libstagefright_soft_mpeg4dec \ libstagefright_soft_mpeg4enc \ + libstagefright_soft_opusdec \ libstagefright_soft_rawdec \ libstagefright_soft_vorbisdec \ libstagefright_soft_vpxdec \ @@ -59,26 +58,7 @@ PRODUCT_PACKAGES += \ libvariablespeed \ libwebrtc_audio_preprocessing \ mdnsd \ - mms-common \ requestsync \ - telephony-common \ - voip-common + wifi-service $(call inherit-product, $(SRC_TARGET_DIR)/product/core_minimal.mk) -# Override the PRODUCT_BOOT_JARS set in core_minimal.mk. The order matters. -PRODUCT_BOOT_JARS := \ - core-libart \ - conscrypt \ - okhttp \ - core-junit \ - bouncycastle \ - ext \ - framework \ - framework2 \ - telephony-common \ - voip-common \ - mms-common \ - android.policy \ - services \ - apache-xml \ - webviewchromium diff --git a/target/product/core_minimal.mk b/target/product/core_minimal.mk index b1d6546..0c453dd 100644 --- a/target/product/core_minimal.mk +++ b/target/product/core_minimal.mk @@ -37,28 +37,43 @@ PRODUCT_PACKAGES += \ com.android.media.remotedisplay \ com.android.media.remotedisplay.xml \ drmserver \ + ethernet-service \ framework-res \ idmap \ installd \ + ims-common \ ip \ ip-up-vpn \ ip6tables \ iptables \ keystore \ keystore.default \ + libbcc \ libOpenMAXAL \ libOpenSLES \ libdownmix \ libdrmframework \ libdrmframework_jni \ libfilterfw \ + libkeystore \ libsqlite_jni \ libwilhelm \ logd \ make_ext4fs \ + e2fsck \ + resize2fs \ + mms-common \ screencap \ sensorservice \ - uiautomator + telephony-common \ + uiautomator \ + uncrypt \ + voip-common \ + webview \ + wifi-service + +PRODUCT_COPY_FILES += \ + frameworks/native/data/etc/android.software.webview.xml:system/etc/permissions/android.software.webview.xml # The order of PRODUCT_BOOT_JARS matters. PRODUCT_BOOT_JARS := \ @@ -69,11 +84,16 @@ PRODUCT_BOOT_JARS := \ bouncycastle \ ext \ framework \ - framework2 \ + telephony-common \ + voip-common \ + ims-common \ + mms-common \ android.policy \ services \ apache-xml \ - webviewchromium + ethernet-service \ + webviewchromium \ + wifi-service PRODUCT_RUNTIMES := runtime_libart_default diff --git a/target/product/core_tiny.mk b/target/product/core_tiny.mk new file mode 100644 index 0000000..d6e4dc5 --- /dev/null +++ b/target/product/core_tiny.mk @@ -0,0 +1,116 @@ +# +# Copyright (C) 2013 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. +# +# Tiny configuration for small devices such as wearables. Includes base and embedded. +# No telephony + +PRODUCT_PACKAGES := \ + Bluetooth \ + CalendarProvider \ + ContactsProvider \ + CertInstaller \ + FusedLocation \ + InputDevices + +PRODUCT_PACKAGES += \ + clatd \ + clatd.conf \ + pppd + +PRODUCT_PACKAGES += \ + audio.primary.default \ + audio_policy.default \ + local_time.default \ + power.default + +PRODUCT_PACKAGES += \ + local_time.default + +PRODUCT_PACKAGES += \ + BackupRestoreConfirmation \ + DefaultContainerService \ + SettingsProvider \ + Shell \ + bu \ + com.android.location.provider \ + com.android.location.provider.xml \ + framework-res \ + installd \ + ims-common \ + ip \ + ip-up-vpn \ + ip6tables \ + iptables \ + keystore \ + keystore.default \ + libOpenMAXAL \ + libOpenSLES \ + libdownmix \ + libfilterfw \ + libkeystore \ + libsqlite_jni \ + libwilhelm \ + libdrmframework_jni \ + libdrmframework \ + make_ext4fs \ + e2fsck \ + resize2fs \ + nullwebview \ + screencap \ + sensorservice \ + uiautomator \ + uncrypt \ + telephony-common \ + voip-common \ + logd \ + mms-common \ + wifi-service + +# The order matters +PRODUCT_BOOT_JARS := \ + core-libart \ + conscrypt \ + okhttp \ + core-junit \ + bouncycastle \ + ext \ + framework \ + telephony-common \ + voip-common \ + ims-common \ + mms-common \ + android.policy \ + services \ + apache-xml \ + nullwebview \ + wifi-service + +PRODUCT_RUNTIMES := runtime_libart_default + +PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \ + ro.zygote=zygote32 +PRODUCT_COPY_FILES += \ + system/core/rootdir/init.zygote32.rc:root/init.zygote32.rc + +PRODUCT_PROPERTY_OVERRIDES += \ + ro.carrier=unknown + +$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) +$(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk) + +# Overrides +PRODUCT_BRAND := tiny +PRODUCT_DEVICE := tiny +PRODUCT_NAME := core_tiny diff --git a/target/product/embedded.mk b/target/product/embedded.mk index 29d3ada..6575ba5 100644 --- a/target/product/embedded.mk +++ b/target/product/embedded.mk @@ -20,6 +20,7 @@ PRODUCT_PACKAGES += \ adb \ adbd \ + atrace \ bootanimation \ debuggerd \ dumpstate \ @@ -55,6 +56,7 @@ PRODUCT_PACKAGES += \ libui \ libutils \ linker \ + lmkd \ logcat \ logwrapper \ mkshrc \ diff --git a/target/product/full_base.mk b/target/product/full_base.mk index 059697e..1daa523 100644 --- a/target/product/full_base.mk +++ b/target/product/full_base.mk @@ -26,7 +26,6 @@ PRODUCT_PACKAGES := \ libWnnEngDic \ libWnnJpnDic \ libwnndict \ - VideoEditor \ WAPPushManager PRODUCT_PACKAGES += \ diff --git a/target/product/full_base_telephony.mk b/target/product/full_base_telephony.mk index f98e9a2..2fd2ce8 100644 --- a/target/product/full_base_telephony.mk +++ b/target/product/full_base_telephony.mk @@ -27,7 +27,8 @@ PRODUCT_PROPERTY_OVERRIDES := \ ro.com.android.dataroaming=true PRODUCT_COPY_FILES := \ - device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml + device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ + frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony.mk) diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk index 5d9eee3..93c7563 100644 --- a/target/product/generic_no_telephony.mk +++ b/target/product/generic_no_telephony.mk @@ -17,33 +17,15 @@ # This is a generic phone product that isn't specialized for a specific device. # It includes the base Android platform. -PRODUCT_POLICY := android.policy_phone - PRODUCT_PACKAGES := \ - DeskClock \ Bluetooth \ - Calculator \ - Calendar \ Camera2 \ - CertInstaller \ - Email \ - Exchange2 \ - FusedLocation \ Gallery2 \ - InputDevices \ - Keyguard \ - LatinIME \ - Launcher2 \ Music \ MusicFX \ OneTimeInitializer \ - PrintSpooler \ Provision \ - QuickSearchBox \ - Settings \ SystemUI \ - TeleService \ - CalendarProvider \ WallpaperCropper PRODUCT_PACKAGES += \ @@ -82,7 +64,6 @@ $(call inherit-product-if-exists, external/google-fonts/carrois-gothic-sc/fonts. $(call inherit-product-if-exists, external/google-fonts/coming-soon/fonts.mk) $(call inherit-product-if-exists, external/noto-fonts/fonts.mk) $(call inherit-product-if-exists, external/naver-fonts/fonts.mk) -$(call inherit-product-if-exists, external/sil-fonts/fonts.mk) $(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk) $(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk) diff --git a/target/product/languages_full.mk b/target/product/languages_full.mk index 4cddc06..6fb68be 100644 --- a/target/product/languages_full.mk +++ b/target/product/languages_full.mk @@ -21,4 +21,4 @@ # These are all the locales that have translations and are displayable # by TextView in this branch. -PRODUCT_LOCALES := en_US en_IN fr_FR it_IT es_ES et_EE de_DE nl_NL cs_CZ pl_PL ja_JP zh_TW zh_CN zh_HK ru_RU ko_KR nb_NO es_US da_DK el_GR tr_TR pt_PT pt_BR rm_CH sv_SE bg_BG ca_ES en_GB fi_FI hi_IN hr_HR hu_HU in_ID iw_IL lt_LT lv_LV ro_RO sk_SK sl_SI sr_RS uk_UA vi_VN tl_PH ar_EG fa_IR th_TH sw_TZ ms_MY af_ZA zu_ZA am_ET hi_IN en_XA ar_XB fr_CA km_KH lo_LA ne_NP si_LK mn_MN hy_AM az_AZ ka_GE +PRODUCT_LOCALES := en_US en_IN fr_FR it_IT es_ES et_EE de_DE nl_NL cs_CZ pl_PL ja_JP zh_TW zh_CN zh_HK ru_RU ko_KR nb_NO es_US da_DK el_GR tr_TR pt_PT pt_BR rm_CH sv_SE bg_BG ca_ES en_GB fi_FI hi_IN hr_HR hu_HU in_ID iw_IL lt_LT lv_LV ro_RO sk_SK sl_SI sr_RS uk_UA vi_VN tl_PH ar_EG fa_IR th_TH sw_TZ ms_MY af_ZA zu_ZA am_ET hi_IN en_XA ar_XB fr_CA km_KH lo_LA ne_NP si_LK mn_MN hy_AM az_AZ ka_GE my_MM mr_IN ml_IN is_IS mk_MK ky_KG eu_ES gl_ES bn_BD ta_IN kn_IN te_IN uz_UZ ur_PK kk_KZ diff --git a/target/product/sdk.mk b/target/product/sdk.mk index 04157e8..96d8cc9 100644 --- a/target/product/sdk.mk +++ b/target/product/sdk.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2007 The Android Open Source Project +# Copyright (C) 2014 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,170 +14,8 @@ # limitations under the License. # -PRODUCT_POLICY := android.policy_phone -PRODUCT_PROPERTY_OVERRIDES := +# Don't modify this file - It's just an alias! -PRODUCT_PACKAGES := \ - Calculator \ - DeskClock \ - Email \ - Exchange2 \ - FusedLocation \ - Gallery \ - Keyguard \ - Music \ - Mms \ - OpenWnn \ - PrintSpooler \ - libWnnEngDic \ - libWnnJpnDic \ - libwnndict \ - TeleService \ - PinyinIME \ - Protips \ - SoftKeyboard \ - SystemUI \ - Launcher2 \ - Development \ - DevelopmentSettings \ - Fallback \ - Settings \ - SdkSetup \ - CustomLocale \ - sqlite3 \ - InputDevices \ - LatinIME \ - CertInstaller \ - LiveWallpapersPicker \ - ApiDemos \ - GestureBuilder \ - CubeLiveWallpapers \ - QuickSearchBox \ - WidgetPreview \ - librs_jni \ - CalendarProvider \ - Calendar \ - SmokeTest \ - SmokeTestApp \ - EmulatorSmokeTests \ - rild \ - LegacyCamera \ - Dialer +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_armv7.mk) - -# Define the host tools and libs that are parts of the SDK. --include sdk/build/product_sdk.mk --include development/build/product_sdk.mk - -# audio libraries. -PRODUCT_PACKAGES += \ - audio.primary.goldfish \ - audio_policy.default \ - local_time.default - -PRODUCT_PACKAGE_OVERLAYS := development/sdk_overlay - -PRODUCT_COPY_FILES := \ - device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ - frameworks/base/data/sounds/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \ - frameworks/base/data/sounds/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \ - frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml \ - device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ - device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ - frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \ - frameworks/native/data/etc/android.hardware.camera.autofocus.xml:system/etc/permissions/android.hardware.camera.autofocus.xml \ - frameworks/av/media/libeffects/data/audio_effects.conf:system/etc/audio_effects.conf \ - hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf - -include $(SRC_TARGET_DIR)/product/emulator.mk - -$(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk) -$(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk) -$(call inherit-product-if-exists, external/google-fonts/dancing-script/fonts.mk) -$(call inherit-product-if-exists, external/google-fonts/carrois-gothic-sc/fonts.mk) -$(call inherit-product-if-exists, external/google-fonts/coming-soon/fonts.mk) -$(call inherit-product-if-exists, external/noto-fonts/fonts.mk) -$(call inherit-product-if-exists, external/naver-fonts/fonts.mk) -$(call inherit-product-if-exists, external/sil-fonts/fonts.mk) -$(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk) -$(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk) - -# Overrides -PRODUCT_BRAND := generic PRODUCT_NAME := sdk -PRODUCT_DEVICE := generic - -# locale + densities. en_US is both first and in alphabetical order to -# ensure this is the default locale. -PRODUCT_LOCALES = \ - en_US \ - ldpi \ - hdpi \ - mdpi \ - xhdpi \ - ar_EG \ - ar_IL \ - bg_BG \ - ca_ES \ - cs_CZ \ - da_DK \ - de_AT \ - de_CH \ - de_DE \ - de_LI \ - el_GR \ - en_AU \ - en_CA \ - en_GB \ - en_IE \ - en_IN \ - en_NZ \ - en_SG \ - en_US \ - en_ZA \ - es_ES \ - es_US \ - fi_FI \ - fr_BE \ - fr_CA \ - fr_CH \ - fr_FR \ - he_IL \ - hi_IN \ - hr_HR \ - hu_HU \ - id_ID \ - it_CH \ - it_IT \ - ja_JP \ - ko_KR \ - lt_LT \ - lv_LV \ - nb_NO \ - nl_BE \ - nl_NL \ - pl_PL \ - pt_BR \ - pt_PT \ - ro_RO \ - ru_RU \ - sk_SK \ - sl_SI \ - sr_RS \ - sv_SE \ - th_TH \ - tl_PH \ - tr_TR \ - uk_UA \ - vi_VN \ - zh_CN \ - zh_TW - -# include available languages for TTS in the system image --include external/svox/pico/lang/PicoLangDeDeInSystem.mk --include external/svox/pico/lang/PicoLangEnGBInSystem.mk --include external/svox/pico/lang/PicoLangEnUsInSystem.mk --include external/svox/pico/lang/PicoLangEsEsInSystem.mk --include external/svox/pico/lang/PicoLangFrFrInSystem.mk --include external/svox/pico/lang/PicoLangItItInSystem.mk diff --git a/target/product/sdk_arm64.mk b/target/product/sdk_arm64.mk index 9aa58b3..8bb38f4 100644 --- a/target/product/sdk_arm64.mk +++ b/target/product/sdk_arm64.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2009 The Android Open Source Project +# Copyright (C) 2014 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,16 +14,8 @@ # limitations under the License. # -# This is a build configuration for a full-featured build of the -# Open-Source part of the tree. It's geared toward a US-centric -# build quite specifically for the emulator, and might not be -# entirely appropriate to inherit from for on-device configurations. +# Don't modify this file - It's just an alias! -$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_arm64.mk) -# Overrides -PRODUCT_BRAND := generic_arm64 PRODUCT_NAME := sdk_arm64 -PRODUCT_DEVICE := generic_arm64 -PRODUCT_MODEL := Android SDK built for arm64 diff --git a/target/product/sdk_base.mk b/target/product/sdk_base.mk new file mode 100644 index 0000000..43fd736 --- /dev/null +++ b/target/product/sdk_base.mk @@ -0,0 +1,162 @@ +# +# Copyright (C) 2007 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +PRODUCT_PROPERTY_OVERRIDES := + +PRODUCT_PACKAGES := \ + ApiDemos \ + CubeLiveWallpapers \ + CustomLocale \ + Development \ + DevelopmentSettings \ + Dialer \ + EmulatorSmokeTests \ + Fallback \ + Gallery \ + GestureBuilder \ + LegacyCamera \ + librs_jni \ + libwnndict \ + libWnnEngDic \ + libWnnJpnDic \ + LiveWallpapersPicker \ + Mms \ + Music \ + OpenWnn \ + PinyinIME \ + Protips \ + rild \ + SdkSetup \ + SmokeTest \ + SmokeTestApp \ + SoftKeyboard \ + sqlite3 \ + SystemUI \ + WidgetPreview + +# Define the host tools and libs that are parts of the SDK. +-include sdk/build/product_sdk.mk +-include development/build/product_sdk.mk + +# audio libraries. +PRODUCT_PACKAGES += \ + audio.primary.goldfish \ + audio_policy.default \ + local_time.default + +PRODUCT_PACKAGE_OVERLAYS := development/sdk_overlay + +PRODUCT_COPY_FILES := \ + device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \ + frameworks/base/data/sounds/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \ + frameworks/base/data/sounds/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \ + frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml \ + device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ + device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \ + frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \ + frameworks/native/data/etc/android.hardware.camera.autofocus.xml:system/etc/permissions/android.hardware.camera.autofocus.xml \ + frameworks/av/media/libeffects/data/audio_effects.conf:system/etc/audio_effects.conf \ + hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf + +include $(SRC_TARGET_DIR)/product/emulator.mk + +$(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk) +$(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk) +$(call inherit-product-if-exists, external/google-fonts/dancing-script/fonts.mk) +$(call inherit-product-if-exists, external/google-fonts/carrois-gothic-sc/fonts.mk) +$(call inherit-product-if-exists, external/google-fonts/coming-soon/fonts.mk) +$(call inherit-product-if-exists, external/noto-fonts/fonts.mk) +$(call inherit-product-if-exists, external/naver-fonts/fonts.mk) +$(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk) +$(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk) + +# include available languages for TTS in the system image +-include external/svox/pico/lang/PicoLangDeDeInSystem.mk +-include external/svox/pico/lang/PicoLangEnGBInSystem.mk +-include external/svox/pico/lang/PicoLangEnUsInSystem.mk +-include external/svox/pico/lang/PicoLangEsEsInSystem.mk +-include external/svox/pico/lang/PicoLangFrFrInSystem.mk +-include external/svox/pico/lang/PicoLangItItInSystem.mk + +# locale + densities. en_US is both first and in alphabetical order to +# ensure this is the default locale. +PRODUCT_LOCALES := \ + en_US \ + ldpi \ + hdpi \ + mdpi \ + xhdpi \ + ar_EG \ + ar_IL \ + bg_BG \ + ca_ES \ + cs_CZ \ + da_DK \ + de_AT \ + de_CH \ + de_DE \ + de_LI \ + el_GR \ + en_AU \ + en_CA \ + en_GB \ + en_IE \ + en_IN \ + en_NZ \ + en_SG \ + en_US \ + en_ZA \ + es_ES \ + es_US \ + fi_FI \ + fr_BE \ + fr_CA \ + fr_CH \ + fr_FR \ + he_IL \ + hi_IN \ + hr_HR \ + hu_HU \ + id_ID \ + it_CH \ + it_IT \ + ja_JP \ + ko_KR \ + lt_LT \ + lv_LV \ + nb_NO \ + nl_BE \ + nl_NL \ + pl_PL \ + pt_BR \ + pt_PT \ + ro_RO \ + ru_RU \ + sk_SK \ + sl_SI \ + sr_RS \ + sv_SE \ + th_TH \ + tl_PH \ + tr_TR \ + uk_UA \ + vi_VN \ + zh_CN \ + zh_TW diff --git a/target/product/sdk_mips.mk b/target/product/sdk_mips.mk index 2072400..366994a 100644 --- a/target/product/sdk_mips.mk +++ b/target/product/sdk_mips.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2012 The Android Open Source Project +# Copyright (C) 2014 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,15 +14,8 @@ # limitations under the License. # -# This is a build configuration for a full-featured build of the -# Open-Source part of the tree. It's geared toward a US-centric -# build quite specifically for the emulator, and might not be -# entirely appropriate to inherit from for on-device configurations. +# Don't modify this file - It's just an alias! -$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_mips.mk) -# Overrides -PRODUCT_BRAND := generic_mips PRODUCT_NAME := sdk_mips -PRODUCT_DEVICE := generic_mips -PRODUCT_MODEL := Android SDK for Mips diff --git a/target/product/sdk_phone_arm64.mk b/target/product/sdk_phone_arm64.mk new file mode 100644 index 0000000..c501f14 --- /dev/null +++ b/target/product/sdk_phone_arm64.mk @@ -0,0 +1,29 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + +$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk) + +# Overrides +PRODUCT_BRAND := generic_arm64 +PRODUCT_NAME := sdk_phone_arm64 +PRODUCT_DEVICE := generic_arm64 +PRODUCT_MODEL := Android SDK built for arm64 diff --git a/target/product/sdk_phone_armv7.mk b/target/product/sdk_phone_armv7.mk new file mode 100644 index 0000000..aeb4940 --- /dev/null +++ b/target/product/sdk_phone_armv7.mk @@ -0,0 +1,22 @@ +# +# Copyright (C) 2007 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk) + +# Overrides +PRODUCT_BRAND := generic +PRODUCT_NAME := sdk_phone_armv7 +PRODUCT_DEVICE := generic diff --git a/target/product/sdk_phone_mips.mk b/target/product/sdk_phone_mips.mk new file mode 100644 index 0000000..818491f --- /dev/null +++ b/target/product/sdk_phone_mips.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk) + +# Overrides +PRODUCT_BRAND := generic_mips +PRODUCT_NAME := sdk_phone_mips +PRODUCT_DEVICE := generic_mips +PRODUCT_MODEL := Android SDK for Mips diff --git a/target/product/sdk_mips64.mk b/target/product/sdk_phone_mips64.mk index c46eaed..afdb2a8 100644 --- a/target/product/sdk_mips64.mk +++ b/target/product/sdk_phone_mips64.mk @@ -20,10 +20,10 @@ # entirely appropriate to inherit from for on-device configurations. $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk) # Overrides PRODUCT_BRAND := generic_mips64 -PRODUCT_NAME := sdk_mips64 +PRODUCT_NAME := sdk_phone_mips64 PRODUCT_DEVICE := generic_mips64 PRODUCT_MODEL := Android SDK built for mips64 diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk new file mode 100644 index 0000000..95c49ab --- /dev/null +++ b/target/product/sdk_phone_x86.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk) + +# Overrides +PRODUCT_BRAND := generic_x86 +PRODUCT_NAME := sdk_phone_x86 +PRODUCT_DEVICE := generic_x86 +PRODUCT_MODEL := Android SDK built for x86 diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk new file mode 100644 index 0000000..69e37af --- /dev/null +++ b/target/product/sdk_phone_x86_64.mk @@ -0,0 +1,29 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + +$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk) + +# Overrides +PRODUCT_BRAND := generic_x86_64 +PRODUCT_NAME := sdk_phone_x86_64 +PRODUCT_DEVICE := generic_x86_64 +PRODUCT_MODEL := Android SDK built for x86_64 diff --git a/target/product/sdk_x86.mk b/target/product/sdk_x86.mk index 873d0c0..13ee57d 100644 --- a/target/product/sdk_x86.mk +++ b/target/product/sdk_x86.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2009 The Android Open Source Project +# Copyright (C) 2014 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,15 +14,8 @@ # limitations under the License. # -# This is a build configuration for a full-featured build of the -# Open-Source part of the tree. It's geared toward a US-centric -# build quite specifically for the emulator, and might not be -# entirely appropriate to inherit from for on-device configurations. +# Don't modify this file - It's just an alias! -include $(SRC_TARGET_DIR)/product/sdk.mk +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_x86.mk) -# Overrides -PRODUCT_BRAND := generic_x86 PRODUCT_NAME := sdk_x86 -PRODUCT_DEVICE := generic_x86 -PRODUCT_MODEL := Android SDK built for x86 diff --git a/target/product/sdk_x86_64.mk b/target/product/sdk_x86_64.mk index 62f2dbb..5f6553e 100644 --- a/target/product/sdk_x86_64.mk +++ b/target/product/sdk_x86_64.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2009 The Android Open Source Project +# Copyright (C) 2014 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,16 +14,8 @@ # limitations under the License. # -# This is a build configuration for a full-featured build of the -# Open-Source part of the tree. It's geared toward a US-centric -# build quite specifically for the emulator, and might not be -# entirely appropriate to inherit from for on-device configurations. +# Don't modify this file - It's just an alias! -$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_x86_64.mk) -# Overrides -PRODUCT_BRAND := generic_x86_64 PRODUCT_NAME := sdk_x86_64 -PRODUCT_DEVICE := generic_x86_64 -PRODUCT_MODEL := Android SDK built for x86_64 diff --git a/target/product/security/Android.mk b/target/product/security/Android.mk new file mode 100644 index 0000000..5a40397 --- /dev/null +++ b/target/product/security/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) + +####################################### +# verity_key +include $(CLEAR_VARS) + +LOCAL_MODULE := verity_key +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) + +include $(BUILD_PREBUILT) diff --git a/target/product/security/verity_key b/target/product/security/verity_key Binary files differnew file mode 100644 index 0000000..8db965f --- /dev/null +++ b/target/product/security/verity_key diff --git a/target/product/security/verity_private_dev_key b/target/product/security/verity_private_dev_key new file mode 100644 index 0000000..92528e9 --- /dev/null +++ b/target/product/security/verity_private_dev_key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDQxdVrH2RB1eg5 +17/gBmLzW1Ds10RG6ctNZMhxppMOLnEZViKGv1VNRhxqK/JKTv2UujgZ94SJcDub +G+DwAwaGZKQqDYUa0VU2cng8TYPcnYGPdJ7Usckp6tdg64vns7e+VVf0dOyEovR+ +JyeYUz05OhUMYP9xJIhpA2XnXe5Ekb9iTFSYo9uBpoXDD4IY7aOqUxSbv9wMtyIp +dl+oTm0+kqRRi4KoxGHV0CzDseEUuWG/Kp/7aVF9Sg45NcC6KYvrGysUKA+Bt09O +feDn/HRpT9SfRElJa5DRms33UBUtnom15F4yd4vvFgubB0nkPOUuwfZhTFfgeuY4 +H2bHkjKbAgMBAAECggEAMpFYqkPGQvQO9cO+ZALoAM4Dgfp6PTrv1WUt7+lLAUpa +dqqYXk8F2Fu9EjJm03ziix237QI5Bhk7Nsy/5SK2d+L0qILx1JcTrsZ3PRQBdnRo +J1k2B4qwkQii9oTXNF4hiWaekUWo7E+ULOJLAuhWkf/xjTgJZ1xT9iuuiSYFSnIa +9ABNH0vCaKEkW/4ri6fdtXmO26C/ltJlnozl86x07PIFh4uBas7/40E8ykFP00CS +zdhMh+2DGyCb1Q0eJ1IfGILNatkLNEd2BHgQ7qNBkN9yShZfhvIPblr5gSUlZplX +diV20ZGLAfByKWgZZWKkwl9KzaisL/J/4dr2UlSVEQKBgQDxAYTsgoTkkP0TKzr3 +i3ljT8OuVOj6TwZVBJYe2MIJ3veivS3gWB53FpsKthbib7y8ifIakn15mQkNCK5R +7H7F5lvZCNnB6shY5Dz7nLJxKLALcAg+d12l3gTbFQeFDs0iQQJF7P8hs/GPF7kY +Layb7EF0uzYjyHJCKtFdaZaeZwKBgQDdwvCb7NJVeGTcE97etL+8acu9y4GlqKEF +o0Vkw8TjNKj/KuDkbkAk9hXxU1ZCmDU3y6r8CVHYl0Sqh08plEhkYB/j3sFy81zY +3xu/rLFysBwjeJHHlPjRTYkdKr9pABmm8NIEShvu9u8i+mpOhjbX72HxZL+i4Fou +gz58wEdBrQKBgG8CfyKdn+7UJe3tbLTXRquK8xxauhGJ0uXYPfmpZ/8596C7OOVs +UWQTQoj1hKb6RtolRCIfNbKL3hJl3D2aDG7Fg6r9m6fpqCzhvIE9FShwUF6EVRfI +zZb4JA5xqkwMnEpZ3V0uI/p3Mx3xFG3ho+8SLLhC/1YOHysBI/y+BQWjAoGAYiqQ +PkXYWhOAeleleeqDUdF3al3y1zVNimRbLJ7owjcmdEYz5YrUhEgXMIvWjIY6UKes +2gL6IynbMK3TIjHM1fojQ8jw04TdXfdtnizBJGbHHgCab8IHXwe2oZ2xu7ZapKbI +ITP5J5BSDabSdk49attB/Qy/NEeiRCK+/5RSNsUCgYAg6vX9VqMEkhPHeoFfdLGD +EQPPN6QLrQ4Zif0GKxH96znNSv0rXdNp9t0kyapdgzMuCwIEuOkCSiKgmfjTWnYO +qh5HMUuD2VbfWwI9jVujQMRmqiaFF7VxxA1bP5j1hJlI6cn1Fjlpi+NsNZN4nm3Q +92SEwX2vDgjrU0NAtFFL1Q== +-----END PRIVATE KEY----- diff --git a/target/product/verity.mk b/target/product/verity.mk new file mode 100644 index 0000000..4a1ca5e --- /dev/null +++ b/target/product/verity.mk @@ -0,0 +1,23 @@ +# +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Provides dependencies necessary for verified boot + +PRODUCT_SUPPORTS_VERITY := true +PRODUCT_VERITY_SIGNING_KEY := build/target/product/security/verity_private_dev_key + +PRODUCT_PACKAGES += \ + verity_key diff --git a/tools/atree/atree.cpp b/tools/atree/atree.cpp index 2ba284f..b134e01 100644 --- a/tools/atree/atree.cpp +++ b/tools/atree/atree.cpp @@ -90,6 +90,26 @@ debug_printf(const char* format, ...) } } +// Escape the filename so that it can be added to the makefile properly. +static string +escape_filename(const string name) +{ + ostringstream new_name; + for (string::const_iterator iter = name.begin(); iter != name.end(); ++iter) + { + switch (*iter) + { + case '$': + new_name << "$$"; + break; + default: + new_name << *iter; + break; + } + } + return new_name.str(); +} + int main(int argc, char* const* argv) { @@ -324,7 +344,8 @@ main(int argc, char* const* argv) for (vector<FileRecord>::iterator it=files.begin(); it!=files.end(); it++) { if (!it->sourceIsDir) { - fprintf(f, "%s \\\n", it->sourcePath.c_str()); + fprintf(f, "%s \\\n", + escape_filename(it->sourcePath).c_str()); } } fprintf(f, "\n"); diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh index 46a73f8..2767496 100755 --- a/tools/buildinfo.sh +++ b/tools/buildinfo.sh @@ -8,6 +8,7 @@ echo "ro.build.display.id=$BUILD_DISPLAY_ID" echo "ro.build.version.incremental=$BUILD_NUMBER" echo "ro.build.version.sdk=$PLATFORM_SDK_VERSION" echo "ro.build.version.codename=$PLATFORM_VERSION_CODENAME" +echo "ro.build.version.all_codenames=$PLATFORM_VERSION_ALL_CODENAMES" echo "ro.build.version.release=$PLATFORM_VERSION" echo "ro.build.date=`date`" echo "ro.build.date.utc=`date +%s`" @@ -25,9 +26,16 @@ echo "ro.product.board=$TARGET_BOOTLOADER_BOARD_NAME" # instead (see below). echo "# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete," echo "# use ro.product.cpu.abilist instead." -echo "ro.product.cpu.abi=$TARGET_CPU_ABI" -if [ -n "$TARGET_CPU_ABI2" ] ; then - echo "ro.product.cpu.abi2=$TARGET_CPU_ABI2" +if [ "$TARGET_2ND_CPU_ABI" = "armeabi-v7a" ] ; then + echo "ro.product.cpu.abi=$TARGET_2ND_CPU_ABI" + if [ -n "$TARGET_2ND_CPU_ABI2" ] ; then + echo "ro.product.cpu.abi2=$TARGET_2ND_CPU_ABI2" + fi +else + echo "ro.product.cpu.abi=$TARGET_CPU_ABI" + if [ -n "$TARGET_CPU_ABI2" ] ; then + echo "ro.product.cpu.abi2=$TARGET_CPU_ABI2" + fi fi echo "ro.product.cpu.abilist=$TARGET_CPU_ABI_LIST" echo "ro.product.cpu.abilist32=$TARGET_CPU_ABI_LIST_32_BIT" @@ -46,9 +54,10 @@ echo "ro.board.platform=$TARGET_BOARD_PLATFORM" echo "# ro.build.product is obsolete; use ro.product.device" echo "ro.build.product=$TARGET_DEVICE" -echo "# Do not try to parse ro.build.description or .fingerprint" +echo "# Do not try to parse description, fingerprint, or thumbprint" echo "ro.build.description=$PRIVATE_BUILD_DESC" echo "ro.build.fingerprint=$BUILD_FINGERPRINT" +echo "ro.build.thumbprint=$BUILD_THUMBPRINT" echo "ro.build.characteristics=$TARGET_AAPT_CHARACTERISTICS" echo "# end build properties" diff --git a/tools/droiddoc/templates-ds/package.cs b/tools/droiddoc/templates-ds/package.cs index ea3e4f4..d67d5d9 100644 --- a/tools/droiddoc/templates-ds/package.cs +++ b/tools/droiddoc/templates-ds/package.cs @@ -45,6 +45,7 @@ <?cs /if ?> <?cs /def ?> +<?cs call:class_table("Annotations", package.annotations) ?> <?cs call:class_table("Interfaces", package.interfaces) ?> <?cs call:class_table("Classes", package.classes) ?> <?cs call:class_table("Enums", package.enums) ?> diff --git a/tools/droiddoc/templates-sac/assets/images/sac_logo.png b/tools/droiddoc/templates-sac/assets/images/sac_logo.png Binary files differindex 54b9a4c..6dc126a 100644 --- a/tools/droiddoc/templates-sac/assets/images/sac_logo.png +++ b/tools/droiddoc/templates-sac/assets/images/sac_logo.png diff --git a/tools/droiddoc/templates-sac/package.cs b/tools/droiddoc/templates-sac/package.cs index 99eaff2..abd49f1 100644 --- a/tools/droiddoc/templates-sac/package.cs +++ b/tools/droiddoc/templates-sac/package.cs @@ -45,6 +45,7 @@ <?cs /if ?> <?cs /def ?> +<?cs call:class_table("Annotations", package.annotations) ?> <?cs call:class_table("Interfaces", package.interfaces) ?> <?cs call:class_table("Classes", package.classes) ?> <?cs call:class_table("Enums", package.enums) ?> diff --git a/tools/droiddoc/templates-sdk-dyn/assets/css/default.css b/tools/droiddoc/templates-sdk-dyn/assets/css/default.css index 7515360..e26aec6 100644 --- a/tools/droiddoc/templates-sdk-dyn/assets/css/default.css +++ b/tools/droiddoc/templates-sdk-dyn/assets/css/default.css @@ -98,7 +98,8 @@ body { #devdoc-nav.fixed { position: fixed; margin:0; - top: 20px; } + top: 65px; /* sticky-header height + 20px gutter */ +} #devdoc-nav span.small { font-size:12px; @@ -358,6 +359,19 @@ video.with-shadow { #nav li span.tree-list-subtitle:after { content: '—'; } + #nav li span.tree-list-subtitle.package { + padding-top:15px; + cursor:default; + } + #nav li span.tree-list-subtitle.package:before { + content: ''; + } + #nav li span.tree-list-subtitle.package:after { + content: ''; + } + #nav li ul.tree-list-children.classes { + padding-left:10px; + } #nav li ul { display:none; overflow: hidden; @@ -1365,8 +1379,7 @@ color-stop(50%, #acbc00), color-stop(50%, #bdde00), color-stop(100%, #bdde00)); .training-nav-top, .training-nav-bottom, #doc-col .content-footer, .nav-x, .nav-y, - .paging-links, - a.totop { + .paging-links { display: none !important; } @@ -1491,7 +1504,8 @@ color-stop(50%, #acbc00), color-stop(50%, #bdde00), color-stop(100%, #bdde00)); Header, Login, Nav-X, Search */ #header { - padding: 2.2em 0 0.2em 0; + margin: 0; + padding: 0; } #header:before, #header:after { content: ""; @@ -1828,8 +1842,8 @@ EndColorStr='#ececec'); #qv-wrapper { float:right; clear:right; - margin:0 0 0 20px; /* negative top-margin to counter the content-header bottom margin */ - padding:0 0 20px; + margin:0 0 0 30px; /* negative top-margin to counter the content-header bottom margin */ + padding:0 0 30px; } #tb-wrapper { @@ -2871,26 +2885,6 @@ div.design-announce p { margin:0 0 10px; } -#devdoc-nav a.totop { - display:block; - top:0; - width:inherit; - background: transparent url(../images/styles/gototop.png) no-repeat scroll 50% 50%; - text-indent:-9999em; -} -#devdoc-nav a.totop { - position:fixed; - display:none; -} -#devdoc-nav a.totop:hover { - background-color:#33B5E5; -} - -.content-footer a.totop { - text-transform:uppercase; - line-height:30px; -} - .expandable { height:34px; padding-left:20px; @@ -3955,13 +3949,174 @@ EndColorStr='#ececec'); z-index:100; } -} +/************ STICKY NAV BAR ******************/ + +#header-wrapper { + background: #f9f9f9; + margin: 0 -10px 0 -10px; + padding: 31px 10px 0px 10px; + position: relative; +} +#header-wrapper #nav-x div.wrap { + max-width: 940px; + height: 38px; +} +#header-wrapper #nav-x ul.nav-x li { + margin-right: 36px !important; + margin-top: 5px; + margin-bottom: 0px; + height: 30px; +} +#header-wrapper #nav-x > div.wrap ul.nav-x li.active { + color: #669900; + border-bottom: 3px solid #669900; +} +#header-wrapper #nav-x > div.wrap ul.nav-x li.active a { + color: #669900; +} +#header-wrapper #nav-x > div.wrap ul.nav-x a { + font-size: 14.5px; +} +#header-wrapper .developer-console-btn { + float: right; + background: #fefefe; + border-radius: 4px; + padding: 8px 14px; + box-shadow: 1px 1px 0px #7a7a7a; + font-size: 14px; + margin-top: -6px; + cursor: pointer; + color: #464646; + margin-right: 20px; +} +/* not currently used */ +#header-wrapper .shadow { + width: 1034px; + height: 4px; + position: absolute; + left: 50%; + margin-left: -517px; + bottom: -4px; + background-image: url(../images/header-shadow.png); +} + +#context { + clear: both; + padding-top: 14px; +} +#context .breadcrumb { + float: left; + margin-bottom: 10px; +} +#context .util { + float: right; + margin-right: 20px; +} + +.breadcrumb { + list-style: none; + margin: 0; + padding: 0; + position: relative; +} +.breadcrumb li { + float: left; + padding: 0 20px 0 0; + color: #000; + white-space: nowrap; +} +.breadcrumb li a { + color: #000; +} +.breadcrumb li:after { + content: url(../images/breadcrumb.png); + position: relative; + top: 1px; + left: 10px; + width: 5px; + height: 10px; +} +.breadcrumb li.current { + font-weight: 700; +} +.breadcrumb li.current:after { + display: none; +} + +/* Sticky Nav overrides */ +.sticky-menu { + position: fixed; + width: 940px; + height: 0px; + z-index: 51; + top: 12px; +} +#sticky-header { + display: none; + padding: 0 10px; + position: fixed; + background: #f9f9f9; + top: 0px; + left: 0px; + right: 0px; + height: 45px; + box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1); + border-bottom: 1px solid #a5c43a; + z-index: 50; +} +#sticky-header.design { + border-bottom: 1px solid #33b5e5; +} +#sticky-header.develop { + border-bottom: 1px solid #F80; +} +#sticky-header.distribute { + border-bottom: 1px solid #9C0; +} +#sticky-header.about { + border-bottom: 1px solid #9933CC; +} +#sticky-header > div { + overflow: hidden; + *zoom: 1; + width: 940px; + margin: 0 auto; + clear: both; + padding-top: 9px; +} +#sticky-header > div .logo { + float: left; + width: 26px; + height: 25px; + background: url(../images/dac_logo.png); + z-index: 52; + position: relative; +} +#sticky-header > div .top { + float: left; + width: 38px; + height: 38px; + position: relative; + background: url(../images/styles/gototop.png); + z-index: 52; +} +#sticky-header > div .breadcrumb { + float: left; + padding: 0 0 0 10px; + border-left: 1px solid #d2d2d2; + line-height: 24px; + font-size: 14px; + position: relative; + top: 0px; + z-index: 52; +} +} @@ -4001,7 +4156,6 @@ EndColorStr='#ececec'); } .logo a { - width:123px; float:left; } @@ -4013,6 +4167,17 @@ EndColorStr='#ececec'); padding-right:10px; } + +#header-wrap .logo.wear-logo { + width:220px; + margin:0; + padding:0; + margin-bottom:22px; +} +#header-wrap .logo.wear-logo img { + padding:0 0 0 10px; +} + .search { height:25px; margin-top: -3px; @@ -4436,11 +4601,11 @@ a.download-sdk { } #nav-x { - padding-top: 14px; + padding-top: 13px; } #nav-x .wrap { - min-height:34px; + min-height:32px; } #nav-x .wrap, @@ -4782,53 +4947,6 @@ a.download-sdk { -/************ DISTRIBUTE HOMEPAGE ***************/ - -.marquee { - width: 760px; -} -.marquee .main-img { - float: left; - margin-top: 20px; - width: 490px; -} -.marquee .copy { - width: 270px; - float: left; - margin-top: 30px; -} -.distribute-features { - margin: 0; -} -.distribute-features ul { - margin: 0; -} -.distribute-features ul li { - list-style: none; - float: left; - border-top: 1px solid #9C0; - width: 220px; - margin-right: 50px; -} -.distribute-features ul li.last { - margin-right: 0px; -} - -.distribute-features .distribute-link li a { - color:red !important; -} - -.distribute-features .distribute-link li a, -.distribute-features .distribute-link li a:active { - color:#555 !important; -} - -.distribute-features .distribute-link li a:hover, -.distribute-features .distribute-link li a:hover * { - color:#7AA1B0 !important; -} - - /************ DEVELOP TOPIC CONTAINERS ************/ .landing-banner, @@ -5006,3 +5124,1263 @@ a.download-sdk { .fullpage #footer { margin-top: -40px; } + +/************ DISTRIBUTE PAGES ******************/ + +/* Article page header line fix */ +.headerLine { + overflow: hidden; +} +.headerLine h1 { + float: left; + padding-right: 20px; + margin-bottom: 0px; + font-size: 20px; + color: #363636; +} +.headerLine hr { + overflow: hidden; + margin: 42px 0 0 0; +} + +.article-detail #body-content { + padding-top: 10px; +} + +/* A container for grid sets with uppercase h3 and rule */ +.dynamic-grid h3 { + font-size:14px; + line-height:21px; + color:#555; + text-transform:uppercase; + border-bottom:1px solid #CCC; + padding:8px 0 0 1px; + margin-bottom:10px; + clear:both; +} + +.top-right-float { + float: right; +} + +.clearfloat { + float: none; + clear: both; +} + +.border-img { + border: 1px solid #CCC; +} + +.center-img { + margin: auto; + text-align: center; +} +.center-img img { + margin-bottom: 15px; +} + +.figure img, .border-img { + margin-bottom: 15px; +} + +/************ RESOURCE CARDS ******************/ + +/* Resource cards, 12, 13, 16-col */ + +/* Basic card-styling with shadow */ +.resource-card { + border-radius: 1px; + box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.14); + background: #fefefe; +} + +/* Styling for background image including tinting and section icons in stacks */ +.card-bg { + display: block; + position: absolute; + vertical-align: top; + width: 100%; + left: 0; + top: 0; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + background-image: url(../images/resource-card-default-android.jpg); +} +.card-bg:after { + content: ""; + display: block; + height: 100%; + width: 100%; + opacity: 1; + background: rgba(0, 0, 0, 0.2); + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; +} +.card-bg .card-section-icon { + position: absolute; + top: 50%; + width: 100%; + margin-top: -35px; + text-align: center; + padding-top: 65px; + z-index: 100; +} +.card-bg .card-section-icon .icon { + position: absolute; + left: 50%; + margin-left: -28px; + top: 0px; + width: 56px; + height: 56px; + background-repeat: no-repeat; + background-position: 50% 50%; + background-image: url(../images/stack-icon.png); +} +.card-bg .card-section-icon .section { + text-transform: uppercase; + color: white; + font-size: 14px; +} + +.card-info { + position: absolute; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + background: #fefefe; + padding: 4px 12px 6px 12px; +} +.card-info .section { + text-transform: uppercase; + color: #898989; + font-size: 12px; + margin-bottom: 1px; +} +.card-info .title { + color: #363636; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding-bottom: 5px; + margin-bottom: -2px; + font-size: 16px; +} +.card-info .description { + overflow: hidden; +} +.card-info .description .text { + color: #464646; + font: 13px/15px Roboto Condensed; + overflow: hidden; + width:100%; +} +.card-info .description .util { + position: absolute; + right: 5px; + bottom: 70px; /*-2px;*/ + opacity: 0; + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; +} +.card-info.empty-desc .title { + white-space: normal; + overflow: visible; +} +.card-info.empty-desc .description { + display: none; +} +/* Truncate card summaries at bounding box and + * and apply ellipsis at lower right */ +.ellipsis { + overflow: hidden; + float:right; + line-height: 15px; + width:100%; +} +.resource-card-6x6 .card-info .description .teddddddxt { + float:left; + position:relative; + margin-left:0; +} +.ellipsis:before { + content:""; + float: left; + width: 5px; + height:100%; +} +.ellipsis > *:first-child.text { + float: right; + width: 100% !important; + margin-left: -5px; +} +.ellipsis:after { + content: "\02026"; + height:17px; + padding-bottom:4px; + + box-sizing: content-box; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + + float: right; position: relative; + top: -16px; left: 100%; + width: 4em; margin-left: -4em; + padding-right: 5px; + + background: -webkit-gradient(linear, left top, right top, + from(rgba(255, 255, 255, 0)), to(white), color-stop(65%, white)); + background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); + background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); + background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); + background: linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); +} +.ellipsis:after { + font-style: normal; color: #aaa; + font-size:13px; + text-align: right; +} + +/* Flow Layout */ +.resource-flow-layout { + display: inline-block; +} +.resource-flow-layout .resource-card, .resource-flow-layout .resource-card-stack { + float: left; + position: relative; +} +.resource-flow-layout .resource-card-stack > .resource-card { + margin-right: 0px !important; +} +.resource-flow-layout:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +.resource-card:hover { + cursor: pointer; +} +.resource-card:hover .card-bg:after { + opacity: 0; +} +/* disabled to make way for fade/ellipsis truncation, + and the plusone moves up. +.resource-card:hover .card-info .description .text { + padding-right: 70px; +} */ +.resource-card:hover .card-info .description .util { + opacity: 1; +} + +/* Carousel Layout */ +/* Carousel styles for landing page */ +.resource-carousel-layout { + margin: 20px 0 20px 0; + position: relative; + overflow: hidden; +} +.resource-carousel-layout .slideshow-prev, .resource-carousel-layout .slideshow-next { + display: none; +} +.resource-carousel-layout .pagination { + bottom: 0px; +} +.resource-carousel-layout .frame li { + position: relative; +} +.resource-carousel-layout .frame li .card-bg { + height: 300px; +} +.resource-carousel-layout .frame li .card-info { + padding: 7px 15px 0px 15px; + top: 300px; +} +.resource-carousel-layout .frame li .card-info .section { + font-size: 13px; + margin-bottom: 7px; +} +.resource-carousel-layout .frame li .card-info .title { + font-size: 25px; + margin-bottom: 2px; +} +.resource-carousel-layout .frame li .card-info .description { + font-family: 15px/16px Roboto Condensed, sans-serif; +} +.resource-carousel-layout .frame li .card-info .description .text { + height: 40px; +} +.resource-carousel-layout .frame li .card-info .description .util { + bottom:97px; + right:4px; +} + +/* Stack Layout */ +.resource-stack-layout { + display: inline-block; +} +.resource-stack-layout .resource-card-stack { + float: left; + position: relative; +} +.resource-stack-layout .resource-card { + margin-bottom: 20px; + display: block; + position: relative; +} +.resource-stack-layout .section-card-menu > .card-info .section, .resource-stack-layout .section-card > .card-info .title { + /*text-transform: uppercase;*/ + color: #898989; + font-size: 17px; + line-height: 24px; + margin-bottom: 6px; +} +.resource-stack-layout .section-card { + height: 284px; +} +.resource-stack-layout .section-card > .card-bg { + height: 192px; +} +.resource-stack-layout .section-card > .card-info { + padding: 4px 12px 6px 12px; + top: 192px; +} +.resource-stack-layout .section-card > .card-info .section { + display: none; +} +.resource-stack-layout .section-card > .card-info .title { + font-size: 17px; + border-bottom: 1px solid #959595; + padding-bottom: 0px; +} +.resource-stack-layout .section-card > .card-info .description { + font-size: 13px; + line-height: 15px; +} +.resource-stack-layout .section-card > .card-info .description .text { + height: 30px; +} +.resource-stack-layout .related-card { + height: 90px; +} +.resource-stack-layout .related-card > .card-bg { + left: 0; + top: 0; + width: 90px; + height: 100%; + position: absolute; + display: block; +} +.resource-stack-layout .related-card > .card-info { + left: 90px; + padding: 4px 12px 4px 12px; +} +.resource-stack-layout .related-card > .card-info .section { + font-size: 12px; + margin-bottom: 1px; + display: none; +} +.resource-stack-layout .related-card > .card-info .title { + font-size: 16px; + margin-bottom: -2px; + white-space: normal; + overflow: visible; + text-overflow: ellipsis; +} +.resource-stack-layout .related-card > .card-info .title:after { + content: url(../images/link-out.png); + display: block; +} +.resource-stack-layout .related-card > .card-info .description { + display: none; +} +.resource-stack-layout .section-card-menu { + /* Flexible height */ + display: block; + height: auto; + width: auto; +} +.resource-stack-layout .section-card-menu .card-bg { + height: 155px; + /* Flexible height */ + position: relative; + display: inline-block; + vertical-align: top; +} +.resource-stack-layout .section-card-menu .card-info { + padding: 4px 12px 0px 12px; + /* Flexible height */ + position: relative; + left: auto; + top: auto; + right: auto; + bottom: auto; +} +.resource-stack-layout .section-card-menu .card-info ul { + list-style: none; + margin: 0; +} +.resource-stack-layout .section-card-menu .card-info ul li { + list-style: none; + margin: 0; + padding: 15px 0; + border-top-width: 1px; + border-top-style: solid; + border-top-color: #959595; +} +.resource-stack-layout .section-card-menu .card-info ul li a, .resource-stack-layout .section-card-menu .card-info ul li a:focus, .resource-stack-layout .section-card-menu .card-info ul li a:link, .resource-stack-layout .section-card-menu .card-info ul li a:visited, .resource-stack-layout .section-card-menu .card-info ul li a:active, .resource-stack-layout .section-card-menu .card-info ul li a:hover { + color: #363636 !important; +} +.resource-stack-layout .section-card-menu .card-info ul li:first-child { + border-top: none; +} +.resource-stack-layout .section-card-menu .card-info ul li:hover .title:after { + opacity: 1; + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; +} +.resource-stack-layout .section-card-menu .card-info ul li:hover .description { + max-height: 30px; + opacity: 1; + -webkit-transition: max-height 0.5s, opacity 1s; + -moz-transition: max-height 0.5s, opacity 1s; + -o-transition: max-height 0.5s, opacity 1s; + transition: max-height 0.5s, opacity 1s; +} +.resource-stack-layout .section-card-menu .card-info .title { + font-size: 16px; + margin-bottom: -2px; + position: relative; +} +.resource-stack-layout .section-card-menu .card-info .title:after { + background: url(../images/stack-arrow-right.png); + content: ''; + opacity: 0; + -webkit-transition: opacity 0.25s; + -moz-transition: opacity 0.25s; + -o-transition: opacity 0.25s; + transition: opacity 0.25s; + position: absolute; + right: 0px; + top: 3px; + width: 10px; + height: 15px; +} +.resource-stack-layout .section-card-menu .card-info .title.more { + text-transform: uppercase; + color: #898989; + display: inline-block; +} +.resource-stack-layout .section-card-menu .card-info .title.more:after { + background: url(../images/stack-arrow-right.png); + content: ''; + display: block; + position: absolute; + right: -20px; + top: 3px; + width: 10px; + height: 15px; +} +.resource-stack-layout .section-card-menu .card-info .description { + max-height: 0px; + opacity: 0; + overflow: hidden; + font-size: 13px; + line-height: 15px; + /* Hover off */ + -webkit-transition: max-height 0.5s, opacity 0.5s; + -moz-transition: max-height 0.5s, opacity 0.5s; + -o-transition: max-height 0.5s, opacity 0.5s; + transition: max-height 0.5s, opacity 0.5s; +} +.resource-stack-layout .section-card-menu .card-info .description .text { + height: 30px; +} +.resource-stack-layout:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +/* Generate the flow layout styles for a 3-column 16-col span */ +.resource-flow-layout.col-16 { + margin: 0 -14px 0 0; + width: 954px; +} +.resource-flow-layout.col-16 .resource-card, .resource-flow-layout.col-16 .resource-card-stack { + margin: 0 14px 20px 0; +} +.resource-flow-layout.col-16 .resource-card-row-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-16 .resource-card-col-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-16 .resource-card-3x6 { + width: 145px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-3x12 { + width: 145px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-3x18 { + width: 145px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-6x6 { + width: 304px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-6x12 { + width: 304px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-6x18 { + width: 304px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-9x6 { + width: 463px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-9x12 { + width: 463px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-9x18 { + width: 463px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-12x6 { + width: 622px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-12x12 { + width: 622px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-12x18 { + width: 622px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-15x6 { + width: 781px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-15x12 { + width: 781px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-15x18 { + width: 781px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-18x6 { + width: 940px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-18x12 { + width: 940px; + height: 420px; +} +.resource-flow-layout.col-16 .resource-card-18x18 { + width: 940px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-3x2 { + width: 145px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-3x2x3 { + width: 145px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-3x3 { + width: 145px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-3x3x2 { + width: 145px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-6x2 { + width: 304px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-6x2x3 { + width: 304px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-6x3 { + width: 304px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-6x3x2 { + width: 304px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-9x2 { + width: 463px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-9x2x3 { + width: 463px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-9x3 { + width: 463px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-9x3x2 { + width: 463px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-12x2 { + width: 622px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-12x2x3 { + width: 622px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-12x3 { + width: 622px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-12x3x2 { + width: 622px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-15x2 { + width: 781px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-15x2x3 { + width: 781px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-15x3 { + width: 781px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-15x3x2 { + width: 781px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-18x2 { + width: 940px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-18x2x3 { + width: 940px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-18x3 { + width: 940px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-18x3x2 { + width: 940px; + height: 138px; + margin-bottom: 8px; +} + +/* Generate the flow layout styles for a 3-column 16-col span */ +.resource-flow-layout.col-12 { + margin: 0 -14px 0 0; + width: 714px; +} + +.resource-flow-layout.col-12 .resource-card, .resource-flow-layout.col-12 .resource-card-stack { + margin: 0 14px 20px 0; +} +.resource-flow-layout.col-12 .resource-card-row-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-12 .resource-card-col-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-12 .resource-card-3x6 { + width: 105px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-3x12 { + width: 105px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-3x18 { + width: 105px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-6x6 { + width: 224px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-6x12 { + width: 224px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-6x18 { + width: 224px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-9x6 { + width: 343px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-9x12 { + width: 343px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-9x18 { + width: 343px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-12x6 { + width: 462px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-12x12 { + width: 462px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-12x18 { + width: 462px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-15x6 { + width: 581px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-15x12 { + width: 581px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-15x18 { + width: 581px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-18x6 { + width: 700px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-18x12 { + width: 700px; + height: 420px; +} +.resource-flow-layout.col-12 .resource-card-18x18 { + width: 700px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-3x2 { + width: 105px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-3x2x3 { + width: 105px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-3x3 { + width: 105px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-3x3x2 { + width: 105px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-6x2 { + width: 224px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-6x2x3 { + width: 224px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-6x3 { + width: 224px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-6x3x2 { + width: 224px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-9x2 { + width: 343px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-9x2x3 { + width: 343px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-9x3 { + width: 343px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-9x3x2 { + width: 343px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-12x2 { + width: 462px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-12x2x3 { + width: 462px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-12x3 { + width: 462px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-12x3x2 { + width: 462px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-15x2 { + width: 581px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-15x2x3 { + width: 581px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-15x3 { + width: 581px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-15x3x2 { + width: 581px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-18x2 { + width: 700px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-18x2x3 { + width: 700px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-18x3 { + width: 700px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-18x3x2 { + width: 700px; + height: 138px; + margin-bottom: 8px; +} + +/* Generate the flow layout styles for a 3-column 13-col span */ + +.resource-flow-layout.col-13 { + margin: 0 -14px 0 0; + width: 774px; +} +.resource-flow-layout.col-13 .resource-card, .resource-flow-layout.col-13 .resource-card-stack { + margin: 0 14px 20px 0; +} +.resource-flow-layout.col-13 .resource-card-row-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-13 .resource-card-col-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-13 .resource-card-3x6 { + width: 115px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-3x12 { + width: 115px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-3x18 { + width: 115px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-6x6 { + width: 244px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-6x12 { + width: 244px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-6x18 { + width: 244px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-9x6 { + width: 373px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-9x12 { + width: 373px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-9x18 { + width: 373px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-12x6 { + width: 502px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-12x12 { + width: 502px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-12x18 { + width: 502px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-15x6 { + width: 631px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-15x12 { + width: 631px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-15x18 { + width: 631px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-18x6 { + width: 760px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-18x12 { + width: 760px; + height: 420px; +} +.resource-flow-layout.col-13 .resource-card-18x18 { + width: 760px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-3x2 { + width: 115px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-3x2x3 { + width: 115px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-3x3 { + width: 115px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-3x3x2 { + width: 115px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-6x2 { + width: 244px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-6x2x3 { + width: 244px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-6x3 { + width: 244px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-6x3x2 { + width: 244px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-9x2 { + width: 373px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-9x2x3 { + width: 373px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-9x3 { + width: 373px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-9x3x2 { + width: 373px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-12x2 { + width: 502px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-12x2x3 { + width: 502px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-12x3 { + width: 502px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-12x3x2 { + width: 502px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-15x2 { + width: 631px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-15x2x3 { + width: 631px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-15x3 { + width: 631px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-15x3x2 { + width: 631px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-18x2 { + width: 760px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-18x2x3 { + width: 760px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-18x3 { + width: 760px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-18x3x2 { + width: 760px; + height: 138px; + margin-bottom: 8px; +} + +/* + The following are styles for cards in the flowlayout above, styled by the number of rows they span +*/ +/* Single row items, might be simpler to just apply a class */ +.resource-card-3x6 > .card-bg, .resource-card-6x6 > .card-bg, .resource-card-9x6 > .card-bg, .resource-card-12x6 > .card-bg, .resource-card-15x6 > .card-bg, .resource-card-18x6 > .card-bg { + height: 192px; +} +.resource-card-3x6 > .card-info, .resource-card-6x6 > .card-info, .resource-card-9x6 > .card-info, .resource-card-12x6 > .card-info, .resource-card-15x6 > .card-info, .resource-card-18x6 > .card-info { + padding: 4px 12px 6px 12px; + top: 192px; +} +.resource-card-3x6 > .card-info .section, .resource-card-6x6 > .card-info .section, .resource-card-9x6 > .card-info .section, .resource-card-12x6 > .card-info .section, .resource-card-15x6 > .card-info .section, .resource-card-18x6 > .card-info .section { + font-size: 12px; + margin-bottom: 1px; +} +.resource-card-3x6 > .card-info .title, .resource-card-6x6 > .card-info .title, .resource-card-9x6 > .card-info .title, .resource-card-12x6 > .card-info .title, .resource-card-15x6 > .card-info .title, .resource-card-18x6 > .card-info .title { + font-size: 16px; + margin-bottom: -2px; +} +.resource-card-3x6 > .card-info .description, .resource-card-6x6 > .card-info .description, .resource-card-9x6 > .card-info .description, .resource-card-12x6 > .card-info .description, .resource-card-15x6 > .card-info .description, .resource-card-18x6 > .card-info .description { + font-size: 13px; + line-height: 15px; +} +.resource-card-3x6 > .card-info .description .text, .resource-card-6x6 > .card-info .description .text, .resource-card-9x6 > .card-info .description .text, .resource-card-12x6 > .card-info .description .text, .resource-card-15x6 > .card-info .description .text, .resource-card-18x6 > .card-info .description .text { + height: 30px; +} + +/* Double row items */ +.resource-card-3x12 > .card-bg, .resource-card-6x12 > .card-bg, .resource-card-9x12 > .card-bg, .resource-card-12x12 > .card-bg, .resource-card-15x12 > .card-bg, .resource-card-18x12 > .card-bg { + height: 320px; +} +.resource-card-3x12 > .card-info, .resource-card-6x12 > .card-info, .resource-card-9x12 > .card-info, .resource-card-12x12 > .card-info, .resource-card-15x12 > .card-info, .resource-card-18x12 > .card-info { + padding: 4px 12px 6px 12px; + top: 320px; +} +.resource-card-3x12 > .card-info .section, .resource-card-6x12 > .card-info .section, .resource-card-9x12 > .card-info .section, .resource-card-12x12 > .card-info .section, .resource-card-15x12 > .card-info .section, .resource-card-18x12 > .card-info .section { + font-size: 12px; + margin-bottom: 1px; +} +.resource-card-3x12 > .card-info .title, .resource-card-6x12 > .card-info .title, .resource-card-9x12 > .card-info .title, .resource-card-12x12 > .card-info .title, .resource-card-15x12 > .card-info .title, .resource-card-18x12 > .card-info .title { + font-size: 16px; + margin-bottom: -2px; + white-space: normal; +} +.resource-card-3x12 > .card-info .description, .resource-card-6x12 > .card-info .description, .resource-card-9x12 > .card-info .description, .resource-card-12x12 > .card-info .description, .resource-card-15x12 > .card-info .description, .resource-card-18x12 > .card-info .description { + font-size: 13px; + line-height: 15px; +} + +/* 1/3 row items */ +.resource-card-3x2 > .card-bg, .resource-card-6x2 > .card-bg, .resource-card-9x2 > .card-bg, .resource-card-12x2 > .card-bg, .resource-card-15x2 > .card-bg, .resource-card-18x2 > .card-bg { + left: 0; + top: 0; + width: 90px; + height: 100%; + position: absolute; + display: block; +} +.resource-card-3x2 > .card-info, .resource-card-6x2 > .card-info, .resource-card-9x2 > .card-info, .resource-card-12x2 > .card-info, .resource-card-15x2 > .card-info, .resource-card-18x2 > .card-info { + left: 90px; + padding: 4px 12px 4px 12px; + height: 80px; + overflow: hidden; +} +.resource-card-3x2 > .card-info .section, .resource-card-6x2 > .card-info .section, .resource-card-6x3 > .card-info .section, .resource-card-9x2 > .card-info .section, .resource-card-12x2 > .card-info .section, .resource-card-15x2 > .card-info .section, .resource-card-18x2 > .card-info .section { + font-size: 12px; + margin-bottom: 1px; + /* display: none; */ +} +.resource-card-3x2 > .card-info .title, .resource-card-6x2 > .card-info .title, .resource-card-9x2 > .card-info .title, .resource-card-12x2 > .card-info .title, .resource-card-15x2 > .card-info .title, .resource-card-18x2 > .card-info .title { + font-size: 16px; + margin-bottom: -2px; + white-space: normal; + overflow: visible; + text-overflow: ellipsis; +} +.resource-card-3x2 > .card-info .title:after, .resource-card-6x2 > .card-info .title:after, .resource-card-9x2 > .card-info .title:after, .resource-card-12x2 > .card-info .title:after, .resource-card-15x2 > .card-info .title:after, .resource-card-18x2 > .card-info .title:after { + /* content: url(../images/link-out.png); */ + display: block; +} +.resource-card-3x2 > .card-info .description, .resource-card-6x2 > .card-info .description, .resource-card-9x2 > .card-info .description, .resource-card-12x2 > .card-info .description, .resource-card-15x2 > .card-info .description, .resource-card-18x2 > .card-info .description { + display: none; +} + +/* 1/2 row items */ +.resource-card-3x3 > .card-bg, .resource-card-6x3 > .card-bg, .resource-card-9x3 > .card-bg, .resource-card-12x3 > .card-bg, .resource-card-15x3 > .card-bg, .resource-card-18x3 > .card-bg { + left: 0; + top: 0; + width: 90px; + height: 100%; + position: absolute; + display: block; +} +.resource-card-3x3 > .card-info, .resource-card-6x3 > .card-info, .resource-card-9x3 > .card-info, .resource-card-12x3 > .card-info, .resource-card-15x3 > .card-info, .resource-card-18x3 > .card-info { + left: 90px; + padding: 4px 12px 0px 12px; +} +.resource-card-3x3 > .card-info .section, .resource-card-6x3 > .card-info .section, .resource-card-9x3 > .card-info .section, .resource-card-12x3 > .card-info .section, .resource-card-15x3 > .card-info .section, .resource-card-18x3 > .card-info .section { + font-size: 12px; + margin-bottom: 1px; + display: none; +} +.resource-card-3x3 > .card-info .title, .resource-card-6x3 > .card-info .title, .resource-card-9x3 > .card-info .title, .resource-card-12x3 > .card-info .title, .resource-card-15x3 > .card-info .title, .resource-card-18x3 > .card-info .title { + font-size: 16px; + margin-bottom: -2px; + white-space: normal; + overflow: visible; +} +.resource-card-3x3 > .card-info .description .text, .resource-card-6x3 > .card-info .description .text, .resource-card-9x3 > .card-info .description .text, .resource-card-12x3 > .card-info .description .text, .resource-card-15x3 > .card-info .description .text, .resource-card-18x3 > .card-info .description .text { + font-size: 12px; + line-height: 15px; + padding-right: 0px !important; + height: 80px; +} +.resource-card-3x3 > .card-info .description .util, .resource-card-6x3 > .card-info .description .util, .resource-card-9x3 > .card-info .description .util, .resource-card-12x3 > .card-info .description .util, .resource-card-15x3 > .card-info .description .util, .resource-card-18x3 > .card-info .description .util { + display: none; +} +/* placement of plusone */ +.resource-card-6x12 > .card-info .description .util, .resource-card-9x12 > .card-info .description .util, .resource-card-12x12 > .card-info .description .util, .resource-card-15x12 > .card-info .description .util { + bottom:2px; +} +.resource-card-18x12 > .card-info .description .util { + bottom:2px; +} +/* Overrides for col-16 6x6 cards linking to local content on landing pages. + Suppresses "section" and puts the title above a hairline rule. */ +.landing .card-info .section, .resource-flow-layout.col-16.landing .resource-card-9x6 .card-info .section { + display:none; +} +.landing .card-info .title { + color: #898989; + font-size: 17px; + line-height: 24px; + margin-bottom: 6px; + border-bottom: 1px solid #959595; + padding-bottom: 0px; +} +.landing .card-info .description { + font-size: 13px; + line-height: 15px; +} +.landing .card-info .description .text { +height:30px; +} +.landing .resource-card-6x6 > .card-info .description .util, .landing .resource-card-9x6 > .card-info .description .util { + bottom:2px; +} +/* + Generate a resource stack layout for a 3 column widget spanning 16 grid cols +*/ +.resource-stack-layout.col-16 { + margin: 0 -14px 0 0; + width: 954px; +} +.resource-stack-layout.col-16 .resource-card-stack { + margin: 0 14px 0 0; + width: 304px; +} + +/* Example of card menu tinting */ +.resource-widget[data-section=distribute\/tools] .section-card-menu +.card-bg:after { + background: rgba(126, 55, 148, 0.4) !important; +} +.resource-widget[data-section=distribute\/tools] .section-card-menu +.card-section-icon .icon { + background-color: #7e3794 !important; +} +.resource-widget[data-section=distribute\/tools] .section-card-menu +.card-info ul li { + border-top-color: #7e3794 !important; +} + +/* tinting for stacks */ + +div.jd-descr > .resource-widget[data-section=distribute\/tools] +.section-card-menu .card-info ul li { + border-top-color: #7e3794 !important; +}
\ No newline at end of file diff --git a/tools/droiddoc/templates-sdk-dyn/assets/css/fullscreen.css b/tools/droiddoc/templates-sdk-dyn/assets/css/fullscreen.css index 71cf65b..53d9a64 100644 --- a/tools/droiddoc/templates-sdk-dyn/assets/css/fullscreen.css +++ b/tools/droiddoc/templates-sdk-dyn/assets/css/fullscreen.css @@ -170,7 +170,7 @@ body { max-width: 100%; } -#nav-x .wrap, +#header-wrapper #nav-x div.wrap, #searchResults.wrap { max-width:100%; } @@ -184,7 +184,18 @@ body { left:20px; /* !important ... for IE i think */ } +#sticky-header { + padding: 0 20px; +} + +#sticky-header > div { + width: 100%; +} +.sticky-menu { + width:100%; + left:-20px; +} } diff --git a/tools/droiddoc/templates-sdk-dyn/assets/images/breadcrumb.png b/tools/droiddoc/templates-sdk-dyn/assets/images/breadcrumb.png Binary files differnew file mode 100644 index 0000000..407a318 --- /dev/null +++ b/tools/droiddoc/templates-sdk-dyn/assets/images/breadcrumb.png diff --git a/tools/droiddoc/templates-sdk-dyn/assets/images/dac_logo@2x.png b/tools/droiddoc/templates-sdk-dyn/assets/images/dac_logo@2x.png Binary files differnew file mode 100644 index 0000000..0f2784d --- /dev/null +++ b/tools/droiddoc/templates-sdk-dyn/assets/images/dac_logo@2x.png diff --git a/tools/droiddoc/templates-sdk-dyn/assets/images/link-out.png b/tools/droiddoc/templates-sdk-dyn/assets/images/link-out.png Binary files differnew file mode 100644 index 0000000..aa55f9a --- /dev/null +++ b/tools/droiddoc/templates-sdk-dyn/assets/images/link-out.png diff --git a/tools/droiddoc/templates-sdk-dyn/assets/images/resource-card-default-android.jpg b/tools/droiddoc/templates-sdk-dyn/assets/images/resource-card-default-android.jpg Binary files differnew file mode 100644 index 0000000..8050744 --- /dev/null +++ b/tools/droiddoc/templates-sdk-dyn/assets/images/resource-card-default-android.jpg diff --git a/tools/droiddoc/templates-sdk-dyn/assets/images/stack-arrow-right.png b/tools/droiddoc/templates-sdk-dyn/assets/images/stack-arrow-right.png Binary files differnew file mode 100644 index 0000000..46d6a50 --- /dev/null +++ b/tools/droiddoc/templates-sdk-dyn/assets/images/stack-arrow-right.png diff --git a/tools/droiddoc/templates-sdk-dyn/assets/js/docs.js b/tools/droiddoc/templates-sdk-dyn/assets/js/docs.js index 6630bf9..e6befe3 100644 --- a/tools/droiddoc/templates-sdk-dyn/assets/js/docs.js +++ b/tools/droiddoc/templates-sdk-dyn/assets/js/docs.js @@ -167,10 +167,12 @@ $(document).ready(function() { // highlight Design tab if ($("body").hasClass("design")) { $("#header li.design a").addClass("selected"); + $("#sticky-header").addClass("design"); // highlight Develop tab } else if ($("body").hasClass("develop") || $("body").hasClass("google")) { $("#header li.develop a").addClass("selected"); + $("#sticky-header").addClass("develop"); // In Develop docs, also highlight appropriate sub-tab var rootDir = pagePathOriginal.substring(1,pagePathOriginal.indexOf('/', 1)); if (rootDir == "training") { @@ -195,12 +197,34 @@ $(document).ready(function() { // highlight Distribute tab } else if ($("body").hasClass("distribute")) { $("#header li.distribute a").addClass("selected"); - } + $("#sticky-header").addClass("distribute"); + + var baseFrag = pagePathOriginal.indexOf('/', 1) + 1; + var secondFrag = pagePathOriginal.substring(baseFrag, pagePathOriginal.indexOf('/', baseFrag)); + if (secondFrag == "users") { + $("#nav-x li.users a").addClass("selected"); + } else if (secondFrag == "engage") { + $("#nav-x li.engage a").addClass("selected"); + } else if (secondFrag == "monetize") { + $("#nav-x li.monetize a").addClass("selected"); + } else if (secondFrag == "tools") { + $("#nav-x li.disttools a").addClass("selected"); + } else if (secondFrag == "stories") { + $("#nav-x li.stories a").addClass("selected"); + } else if (secondFrag == "essentials") { + $("#nav-x li.essentials a").addClass("selected"); + } else if (secondFrag == "googleplay") { + $("#nav-x li.googleplay a").addClass("selected"); + } + } else if ($("body").hasClass("about")) { + $("#sticky-header").addClass("about"); + } // set global variable so we can highlight the sidenav a bit later (such as for google reference) // and highlight the sidenav mPagePath = pagePath; highlightSidenav(); + buildBreadcrumbs(); // set up prev/next links if they exist var $selNavLink = $('#nav').find('a[href="' + pagePath + '"]'); @@ -385,70 +409,6 @@ false; // navigate across topic boundaries only in design docs }); - // Set up fixed navbar - var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll - $(window).scroll(function(event) { - if ($('#side-nav').length == 0) return; - if (event.target.nodeName == "DIV") { - // Dump scroll event if the target is a DIV, because that means the event is coming - // from a scrollable div and so there's no need to make adjustments to our layout - return; - } - var scrollTop = $(window).scrollTop(); - var headerHeight = $('#header').outerHeight(); - var subheaderHeight = $('#nav-x').outerHeight(); - var searchResultHeight = $('#searchResults').is(":visible") ? - $('#searchResults').outerHeight() : 0; - var totalHeaderHeight = headerHeight + subheaderHeight + searchResultHeight; - // we set the navbar fixed when the scroll position is beyond the height of the site header... - var navBarShouldBeFixed = scrollTop > totalHeaderHeight; - // ... except if the document content is shorter than the sidenav height. - // (this is necessary to avoid crazy behavior on OSX Lion due to overscroll bouncing) - if ($("#doc-col").height() < $("#side-nav").height()) { - navBarShouldBeFixed = false; - } - - var scrollLeft = $(window).scrollLeft(); - // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match - if (navBarIsFixed && (scrollLeft != prevScrollLeft)) { - updateSideNavPosition(); - prevScrollLeft = scrollLeft; - } - - // Don't continue if the header is sufficently far away - // (to avoid intensive resizing that slows scrolling) - if (navBarIsFixed && navBarShouldBeFixed) { - return; - } - - if (navBarIsFixed != navBarShouldBeFixed) { - if (navBarShouldBeFixed) { - // make it fixed - var width = $('#devdoc-nav').width(); - $('#devdoc-nav') - .addClass('fixed') - .css({'width':width+'px'}) - .prependTo('#body-content'); - // add neato "back to top" button - $('#devdoc-nav a.totop').css({'display':'block','width':$("#nav").innerWidth()+'px'}); - - // update the sidenaav position for side scrolling - updateSideNavPosition(); - } else { - // make it static again - $('#devdoc-nav') - .removeClass('fixed') - .css({'width':'auto','margin':''}) - .prependTo('#side-nav'); - $('#devdoc-nav a.totop').hide(); - } - navBarIsFixed = navBarShouldBeFixed; - } - - resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance - }); - - var navBarLeftPos; if ($('#devdoc-nav').length) { setNavBarLeftPos(); @@ -593,6 +553,28 @@ function initExpandableNavItems(rootTag) { }); } + +/** Create the list of breadcrumb links in the sticky header */ +function buildBreadcrumbs() { + var $breadcrumbUl = $("#sticky-header ul.breadcrumb"); + // Add the secondary horizontal nav item, if provided + var $selectedSecondNav = $("div#nav-x ul.nav-x a.selected").clone().removeClass("selected"); + if ($selectedSecondNav.length) { + $breadcrumbUl.prepend($("<li>").append($selectedSecondNav)) + } + // Add the primary horizontal nav + var $selectedFirstNav = $("div#header-wrap ul.nav-x a.selected").clone().removeClass("selected"); + // If there's no header nav item, use the logo link and title from alt text + if ($selectedFirstNav.length < 1) { + $selectedFirstNav = $("<a>") + .attr('href', $("div#header .logo a").attr('href')) + .text($("div#header .logo img").attr('alt')); + } + $breadcrumbUl.prepend($("<li>").append($selectedFirstNav)); +} + + + /** Highlight the current page in sidenav, expanding children as appropriate */ function highlightSidenav() { // if something is already highlighted, undo it. This is for dynamic navigation (Samples index) @@ -705,9 +687,8 @@ function resizeNav(delay) { // Then figure out based on scroll position whether the header is visible var windowHeight = $window.height(); var scrollTop = $window.scrollTop(); - var headerHeight = $('#header').outerHeight(); - var subheaderHeight = $('#nav-x').outerHeight(); - var headerVisible = (scrollTop < (headerHeight + subheaderHeight)); + var headerHeight = $('#header-wrapper').outerHeight(); + var headerVisible = scrollTop < stickyTop; // get the height of space between nav and top of window. // Could be either margin or top position, depending on whether the nav is fixed. @@ -717,7 +698,7 @@ function resizeNav(delay) { // Depending on whether the header is visible, set the side nav's height. if (headerVisible) { // The sidenav height grows as the header goes off screen - navHeight = windowHeight - (headerHeight + subheaderHeight - scrollTop) - topMargin; + navHeight = windowHeight - (headerHeight - scrollTop) - topMargin; } else { // Once header is off screen, the nav height is almost full window height navHeight = windowHeight - topMargin; @@ -905,8 +886,115 @@ function writeCookie(cookie, val, section, expiration) { +var stickyTop; +/* Sets the vertical scoll position at which the sticky bar should appear. + This method is called to reset the position when search results appear or hide */ +function setStickyTop() { + stickyTop = $('#header-wrapper').outerHeight() - $('#sticky-header').outerHeight(); +} +/* + * Displays sticky nav bar on pages when dac header scrolls out of view + */ +(function() { + $(document).ready(function() { + + setStickyTop(); + var sticky = false; + var hiding = false; + var $stickyEl = $('#sticky-header'); + var $menuEl = $('.menu-container'); + + var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll + + $(window).scroll(function() { + // Exit if there's no sidenav + if ($('#side-nav').length == 0) return; + // Exit if the mouse target is a DIV, because that means the event is coming + // from a scrollable div and so there's no need to make adjustments to our layout + if (event.target.nodeName == "DIV") { + return; + } + + + var top = $(window).scrollTop(); + // we set the navbar fixed when the scroll position is beyond the height of the site header... + var shouldBeSticky = top >= stickyTop; + // ... except if the document content is shorter than the sidenav height. + // (this is necessary to avoid crazy behavior on OSX Lion due to overscroll bouncing) + if ($("#doc-col").height() < $("#side-nav").height()) { + shouldBeSticky = false; + } + + // Don't continue if the header is sufficently far away + // (to avoid intensive resizing that slows scrolling) + if (sticky && shouldBeSticky) { + return; + } + + // Account for horizontal scroll + var scrollLeft = $(window).scrollLeft(); + // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match + if (navBarIsFixed && (scrollLeft != prevScrollLeft)) { + updateSideNavPosition(); + prevScrollLeft = scrollLeft; + } + + // If sticky header visible and position is now near top, hide sticky + if (sticky && !shouldBeSticky) { + sticky = false; + hiding = true; + // make the sidenav static again + $('#devdoc-nav') + .removeClass('fixed') + .css({'width':'auto','margin':''}) + .prependTo('#side-nav'); + // delay hide the sticky + $menuEl.removeClass('sticky-menu'); + $stickyEl.fadeOut(250); + hiding = false; + + // update the sidenaav position for side scrolling + updateSideNavPosition(); + } else if (!sticky && shouldBeSticky) { + sticky = true; + $stickyEl.fadeIn(10); + $menuEl.addClass('sticky-menu'); + + // make the sidenav fixed + var width = $('#devdoc-nav').width(); + $('#devdoc-nav') + .addClass('fixed') + .css({'width':width+'px'}) + .prependTo('#body-content'); + + // update the sidenaav position for side scrolling + updateSideNavPosition(); + + } else if (hiding && top < 15) { + $menuEl.removeClass('sticky-menu'); + $stickyEl.hide(); + hiding = false; + } + + resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance + }); + + // Stack hover states + $('.section-card-menu').each(function(index, el) { + var height = $(el).height(); + $(el).css({height:height+'px', position:'relative'}); + var $cardInfo = $(el).find('.card-info'); + + $cardInfo.css({position: 'absolute', bottom:'0px', left:'0px', right:'0px', overflow:'visible'}); + }); + + resizeNav(); // must resize once loading is finished + }); + +})(); + @@ -1724,6 +1812,7 @@ function search_changed(e, kd, toroot) $('.suggest-card').hide(); if ($("#searchResults").is(":hidden") && (search.value != "")) { // if results aren't showing (and text not empty), return true to allow search to execute + $('body,html').animate({scrollTop:0}, '500', 'swing'); return true; } else { // otherwise, results are already showing, so allow ajax to auto refresh the results @@ -2278,13 +2367,13 @@ function submit_search() { var query = document.getElementById('search_autocomplete').value; location.hash = 'q=' + query; loadSearchResults(); - $("#searchResults").slideDown('slow'); + $("#searchResults").slideDown('slow', setStickyTop); return false; } function hideResults() { - $("#searchResults").slideUp(); + $("#searchResults").slideUp('fast', setStickyTop); $(".search .close").addClass("hide"); location.hash = ''; @@ -2401,7 +2490,7 @@ google.setOnLoadCallback(function(){ return; } else { // first time loading search results for this page - $('#searchResults').slideDown('slow'); + $('#searchResults').slideDown('slow', setStickyTop); $(".search .close").removeClass("hide"); loadSearchResults(); } @@ -2409,19 +2498,22 @@ google.setOnLoadCallback(function(){ // when an event on the browser history occurs (back, forward, load) requery hash and do search $(window).hashchange( function(){ - // Exit if the hash isn't a search query or there's an error in the query + // If the hash isn't a search query or there's an error in the query, + // then adjust the scroll position to account for sticky header, then exit. if ((location.hash.indexOf("q=") == -1) || (query == "undefined")) { // If the results pane is open, close it. if (!$("#searchResults").is(":hidden")) { hideResults(); } + // Adjust the scroll position to account for sticky header + $(window).scrollTop($(window).scrollTop() - 60); return; } // Otherwise, we have a search to do var query = decodeURI(getQuery(location.hash)); searchControl.execute(query); - $('#searchResults').slideDown('slow'); + $('#searchResults').slideDown('slow', setStickyTop); $("#search_autocomplete").focus(); $(".search .close").removeClass("hide"); @@ -3233,3 +3325,560 @@ function showSamples() { $("#samples").append($ul); } + + + +/* ########################################################## */ +/* ################### RESOURCE CARDS ##################### */ +/* ########################################################## */ + +/** Handle resource queries, collections, and grids (sections). Requires + jd_tag_helpers.js and the *_unified_data.js to be loaded. */ + +(function() { + // Prevent the same resource from being loaded more than once per page. + var addedPageResources = {}; + + $(document).ready(function() { + $('.resource-widget').each(function() { + initResourceWidget(this); + }); + + /* Pass the line height to ellipsisfade() to adjust the height of the + text container to show the max number of lines possible, without + showing lines that are cut off. This works with the css ellipsis + classes to fade last text line and apply an ellipsis char. */ + + //card text currently uses 15px line height. + var lineHeight = 15; + $('.card-info .text').ellipsisfade(lineHeight); + }); + + /* + Three types of resource layouts: + Flow - Uses a fixed row-height flow using float left style. + Carousel - Single card slideshow all same dimension absolute. + Stack - Uses fixed columns and flexible element height. + */ + function initResourceWidget(widget) { + var $widget = $(widget); + var isFlow = $widget.hasClass('resource-flow-layout'), + isCarousel = $widget.hasClass('resource-carousel-layout'), + isStack = $widget.hasClass('resource-stack-layout'); + + // find size of widget by pulling out its class name + var sizeCols = 1; + var m = $widget.get(0).className.match(/\bcol-(\d+)\b/); + if (m) { + sizeCols = parseInt(m[1], 10); + } + + var opts = { + cardSizes: ($widget.data('cardsizes') || '').split(','), + maxResults: parseInt($widget.data('maxresults') || '100', 10), + itemsPerPage: $widget.data('itemsperpage'), + sortOrder: $widget.data('sortorder'), + query: $widget.data('query'), + section: $widget.data('section'), + sizeCols: sizeCols + }; + + // run the search for the set of resources to show + + var resources = buildResourceList(opts); + + if (isFlow) { + drawResourcesFlowWidget($widget, opts, resources); + } else if (isCarousel) { + drawResourcesCarouselWidget($widget, opts, resources); + } else if (isStack) { + var sections = buildSectionList(opts); + opts['numStacks'] = $widget.data('numstacks'); + drawResourcesStackWidget($widget, opts, resources, sections); + } + } + + /* Initializes a Resource Carousel Widget */ + function drawResourcesCarouselWidget($widget, opts, resources) { + $widget.empty(); + var plusone = true; //always show plusone on carousel + + $widget.addClass('resource-card slideshow-container') + .append($('<a>').addClass('slideshow-prev').text('Prev')) + .append($('<a>').addClass('slideshow-next').text('Next')); + + var css = { 'width': $widget.width() + 'px', + 'height': $widget.height() + 'px' }; + + var $ul = $('<ul>'); + + for (var i = 0; i < resources.length; ++i) { + //keep url clean for matching and offline mode handling + var urlPrefix = resources[i].url.indexOf("//") > -1 ? "" : toRoot; + var $card = $('<a>') + .attr('href', urlPrefix + resources[i].url) + .decorateResourceCard(resources[i],plusone); + + $('<li>').css(css) + .append($card) + .appendTo($ul); + } + + $('<div>').addClass('frame') + .append($ul) + .appendTo($widget); + + $widget.dacSlideshow({ + auto: true, + btnPrev: '.slideshow-prev', + btnNext: '.slideshow-next' + }); + }; + + /* Initializes a Resource Card Stack Widget (column-based layout) */ + function drawResourcesStackWidget($widget, opts, resources, sections) { + // Don't empty widget, grab all items inside since they will be the first + // items stacked, followed by the resource query + var plusone = true; //by default show plusone on section cards + var cards = $widget.find('.resource-card').detach().toArray(); + var numStacks = opts.numStacks || 1; + var $stacks = []; + var urlString; + + for (var i = 0; i < numStacks; ++i) { + $stacks[i] = $('<div>').addClass('resource-card-stack') + .appendTo($widget); + } + + var sectionResources = []; + + // Extract any subsections that are actually resource cards + for (var i = 0; i < sections.length; ++i) { + if (!sections[i].sections || !sections[i].sections.length) { + //keep url clean for matching and offline mode handling + urlPrefix = sections[i].url.indexOf("//") > -1 ? "" : toRoot; + // Render it as a resource card + + sectionResources.push( + $('<a>') + .addClass('resource-card section-card') + .attr('href', urlPrefix + sections[i].resource.url) + .decorateResourceCard(sections[i].resource,plusone)[0] + ); + + } else { + cards.push( + $('<div>') + .addClass('resource-card section-card-menu') + .decorateResourceSection(sections[i],plusone)[0] + ); + } + } + + cards = cards.concat(sectionResources); + + for (var i = 0; i < resources.length; ++i) { + //keep url clean for matching and offline mode handling + urlPrefix = resources[i].url.indexOf("//") > -1 ? "" : toRoot; + var $card = $('<a>') + .addClass('resource-card related-card') + .attr('href', urlPrefix + resources[i].url) + .decorateResourceCard(resources[i],plusone); + + cards.push($card[0]); + } + + for (var i = 0; i < cards.length; ++i) { + // Find the stack with the shortest height, but give preference to + // left to right order. + var minHeight = $stacks[0].height(); + var minIndex = 0; + + for (var j = 1; j < numStacks; ++j) { + var height = $stacks[j].height(); + if (height < minHeight - 45) { + minHeight = height; + minIndex = j; + } + } + + $stacks[minIndex].append($(cards[i])); + } + + }; + + /* Initializes a flow widget, see distribute.scss for generating accompanying css */ + function drawResourcesFlowWidget($widget, opts, resources) { + $widget.empty(); + var cardSizes = opts.cardSizes || ['6x6']; + var i = 0, j = 0; + var plusone = true; // by default show plusone on resource cards + + while (i < resources.length) { + var cardSize = cardSizes[j++ % cardSizes.length]; + cardSize = cardSize.replace(/^\s+|\s+$/,''); + console.log("cardsize is " + cardSize); + // Some card sizes do not get a plusone button, such as where space is constrained + // or for cards commonly embedded in docs (to improve overall page speed). + plusone = !((cardSize == "6x2") || (cardSize == "6x3") || + (cardSize == "9x2") || (cardSize == "9x3") || + (cardSize == "12x2") || (cardSize == "12x3")); + + // A stack has a third dimension which is the number of stacked items + var isStack = cardSize.match(/(\d+)x(\d+)x(\d+)/); + var stackCount = 0; + var $stackDiv = null; + + if (isStack) { + // Create a stack container which should have the dimensions defined + // by the product of the items inside. + $stackDiv = $('<div>').addClass('resource-card-stack resource-card-' + isStack[1] + + 'x' + isStack[2] * isStack[3]) .appendTo($widget); + } + + // Build each stack item or just a single item + do { + var resource = resources[i]; + //keep url clean for matching and offline mode handling + urlPrefix = resource.url.indexOf("//") > -1 ? "" : toRoot; + var $card = $('<a>') + .addClass('resource-card resource-card-' + cardSize + ' resource-card-' + resource.type) + .attr('href', urlPrefix + resource.url); + + if (isStack) { + $card.addClass('resource-card-' + isStack[1] + 'x' + isStack[2]); + if (++stackCount == parseInt(isStack[3])) { + $card.addClass('resource-card-row-stack-last'); + stackCount = 0; + } + } else { + stackCount = 0; + } + + $card.decorateResourceCard(resource,plusone) + .appendTo($stackDiv || $widget); + + } while (++i < resources.length && stackCount > 0); + } + } + + /* Build a site map of resources using a section as a root. */ + function buildSectionList(opts) { + if (opts.section && SECTION_BY_ID[opts.section]) { + return SECTION_BY_ID[opts.section].sections || []; + } + return []; + } + + function buildResourceList(opts) { + var maxResults = opts.maxResults || 100; + + var query = opts.query || ''; + var expressions = parseResourceQuery(query); + var addedResourceIndices = {}; + var results = []; + + for (var i = 0; i < expressions.length; i++) { + var clauses = expressions[i]; + + // build initial set of resources from first clause + var firstClause = clauses[0]; + var resources = []; + switch (firstClause.attr) { + case 'type': + resources = ALL_RESOURCES_BY_TYPE[firstClause.value]; + break; + case 'lang': + resources = ALL_RESOURCES_BY_LANG[firstClause.value]; + break; + case 'tag': + resources = ALL_RESOURCES_BY_TAG[firstClause.value]; + break; + case 'collection': + var urls = RESOURCE_COLLECTIONS[firstClause.value].resources || []; + resources = urls.map(function(url){ return ALL_RESOURCES_BY_URL[url]; }); + break; + case 'section': + var urls = SITE_MAP[firstClause.value].sections || []; + resources = urls.map(function(url){ return ALL_RESOURCES_BY_URL[url]; }); + break; + } + // console.log(firstClause.attr + ':' + firstClause.value); + resources = resources || []; + + // use additional clauses to filter corpus + if (clauses.length > 1) { + var otherClauses = clauses.slice(1); + resources = resources.filter(getResourceMatchesClausesFilter(otherClauses)); + } + + // filter out resources already added + if (i > 1) { + resources = resources.filter(getResourceNotAlreadyAddedFilter(addedResourceIndices)); + } + + // add to list of already added indices + for (var j = 0; j < resources.length; j++) { + // console.log(resources[j].title); + addedResourceIndices[resources[j].index] = 1; + } + + // concat to final results list + results = results.concat(resources); + } + + if (opts.sortOrder && results.length) { + var attr = opts.sortOrder; + + if (opts.sortOrder == 'random') { + var i = results.length, j, temp; + while (--i) { + j = Math.floor(Math.random() * (i + 1)); + temp = results[i]; + results[i] = results[j]; + results[j] = temp; + } + } else { + var desc = attr.charAt(0) == '-'; + if (desc) { + attr = attr.substring(1); + } + results = results.sort(function(x,y) { + return (desc ? -1 : 1) * (parseInt(x[attr], 10) - parseInt(y[attr], 10)); + }); + } + } + + results = results.filter(getResourceNotAlreadyAddedFilter(addedPageResources)); + results = results.slice(0, maxResults); + + for (var j = 0; j < results.length; ++j) { + addedPageResources[results[j].index] = 1; + } + + return results; + } + + + function getResourceNotAlreadyAddedFilter(addedResourceIndices) { + return function(resource) { + return !addedResourceIndices[resource.index]; + }; + } + + + function getResourceMatchesClausesFilter(clauses) { + return function(resource) { + return doesResourceMatchClauses(resource, clauses); + }; + } + + + function doesResourceMatchClauses(resource, clauses) { + for (var i = 0; i < clauses.length; i++) { + var map; + switch (clauses[i].attr) { + case 'type': + map = IS_RESOURCE_OF_TYPE[clauses[i].value]; + break; + case 'lang': + map = IS_RESOURCE_IN_LANG[clauses[i].value]; + break; + case 'tag': + map = IS_RESOURCE_TAGGED[clauses[i].value]; + break; + } + + if (!map || (!!clauses[i].negative ? map[resource.index] : !map[resource.index])) { + return clauses[i].negative; + } + } + return true; + } + + + function parseResourceQuery(query) { + // Parse query into array of expressions (expression e.g. 'tag:foo + type:video') + var expressions = []; + var expressionStrs = query.split(',') || []; + for (var i = 0; i < expressionStrs.length; i++) { + var expr = expressionStrs[i] || ''; + + // Break expression into clauses (clause e.g. 'tag:foo') + var clauses = []; + var clauseStrs = expr.split(/(?=[\+\-])/); + for (var j = 0; j < clauseStrs.length; j++) { + var clauseStr = clauseStrs[j] || ''; + + // Get attribute and value from clause (e.g. attribute='tag', value='foo') + var parts = clauseStr.split(':'); + var clause = {}; + + clause.attr = parts[0].replace(/^\s+|\s+$/g,''); + if (clause.attr) { + if (clause.attr.charAt(0) == '+') { + clause.attr = clause.attr.substring(1); + } else if (clause.attr.charAt(0) == '-') { + clause.negative = true; + clause.attr = clause.attr.substring(1); + } + } + + if (parts.length > 1) { + clause.value = parts[1].replace(/^\s+|\s+$/g,''); + } + + clauses.push(clause); + } + + if (!clauses.length) { + continue; + } + + expressions.push(clauses); + } + + return expressions; + } +})(); + +(function($) { + /* Simple jquery function to create dom for a standard resource card */ + $.fn.decorateResourceCard = function(resource,plusone) { + var section = resource.group || resource.type; + var imgUrl; + if (resource.image) { + //keep url clean for matching and offline mode handling + var urlPrefix = resource.image.indexOf("//") > -1 ? "" : toRoot; + imgUrl = urlPrefix + resource.image; + } + //add linkout logic here. check url or type, assign a class, map to css :after + $('<div>') + .addClass('card-bg') + .css('background-image', 'url(' + (imgUrl || toRoot + 'assets/images/resource-card-default-android.jpg') + ')') + .appendTo(this); + if (!plusone) { + $('<div>').addClass('card-info' + (!resource.summary ? ' empty-desc' : '')) + .append($('<div>').addClass('section').text(section)) + .append($('<div>').addClass('title').html(resource.title)) + .append($('<div>').addClass('description ellipsis') + .append($('<div>').addClass('text').html(resource.summary)) + .append($('<div>').addClass('util'))) + .appendTo(this); + } else { + $('<div>').addClass('card-info' + (!resource.summary ? ' empty-desc' : '')) + .append($('<div>').addClass('section').text(section)) + .append($('<div>').addClass('title').html(resource.title)) + .append($('<div>').addClass('description ellipsis') + .append($('<div>').addClass('text').html(resource.summary)) + .append($('<div>').addClass('util') + .append($('<div>').addClass('g-plusone') + .attr('data-size', 'small') + .attr('data-align', 'right') + .attr('data-href', resource.url)))) + .appendTo(this); + } + + return this; + }; + + /* Simple jquery function to create dom for a resource section card (menu) */ + $.fn.decorateResourceSection = function(section,plusone) { + var resource = section.resource; + //keep url clean for matching and offline mode handling + var urlPrefix = resource.image.indexOf("//") > -1 ? "" : toRoot; + var $base = $('<a>') + .addClass('card-bg') + .attr('href', resource.url) + .append($('<div>').addClass('card-section-icon') + .append($('<div>').addClass('icon')) + .append($('<div>').addClass('section').html(resource.title))) + .appendTo(this); + + var $cardInfo = $('<div>').addClass('card-info').appendTo(this); + + if (section.sections && section.sections.length) { + // Recurse the section sub-tree to find a resource image. + var stack = [section]; + + while (stack.length) { + if (stack[0].resource.image) { + $base.css('background-image', 'url(' + urlPrefix + stack[0].resource.image + ')'); + break; + } + + if (stack[0].sections) { + stack = stack.concat(stack[0].sections); + } + + stack.shift(); + } + + var $ul = $('<ul>') + .appendTo($cardInfo); + + var max = section.sections.length > 3 ? 3 : section.sections.length; + + for (var i = 0; i < max; ++i) { + + var subResource = section.sections[i]; + if (!plusone) { + $('<li>') + .append($('<a>').attr('href', subResource.url) + .append($('<div>').addClass('title').html(subResource.title)) + .append($('<div>').addClass('description ellipsis') + .append($('<div>').addClass('text').html(subResource.summary)) + .append($('<div>').addClass('util')))) + .appendTo($ul); + } else { + $('<li>') + .append($('<a>').attr('href', subResource.url) + .append($('<div>').addClass('title').html(subResource.title)) + .append($('<div>').addClass('description ellipsis') + .append($('<div>').addClass('text').html(subResource.summary)) + .append($('<div>').addClass('util') + .append($('<div>').addClass('g-plusone') + .attr('data-size', 'small') + .attr('data-align', 'right') + .attr('data-href', resource.url))))) + .appendTo($ul); + } + } + + // Add a more row + if (max < section.sections.length) { + $('<li>') + .append($('<a>').attr('href', resource.url) + .append($('<div>') + .addClass('title') + .text('More'))) + .appendTo($ul); + } + } else { + // No sub-resources, just render description? + } + + return this; + }; +})(jQuery); +/* Calculate the vertical area remaining */ +(function($) { + $.fn.ellipsisfade= function(lineHeight) { + this.each(function() { + // get element text + var $this = $(this); + var remainingHeight = $this.parent().parent().height(); + $this.parent().siblings().each(function () + { + var h = $(this).height(); + remainingHeight = remainingHeight - h; + }); + + adjustedRemainingHeight = ((remainingHeight)/lineHeight>>0)*lineHeight + $this.parent().css({'height': adjustedRemainingHeight}); + $this.css({'height': "auto"}); + }); + + return this; + }; +}) (jQuery); diff --git a/tools/droiddoc/templates-sdk-dyn/components/masthead.cs b/tools/droiddoc/templates-sdk-dyn/components/masthead.cs index 47639bb..d0ff64d 100644 --- a/tools/droiddoc/templates-sdk-dyn/components/masthead.cs +++ b/tools/droiddoc/templates-sdk-dyn/components/masthead.cs @@ -1,225 +1,131 @@ <?cs def:custom_masthead() ?> +<?cs if:wear ?> + <?cs call:wear_masthead() ?> +<?cs else ?> <a name="top"></a> -<?cs if:!devsite ?><?cs # leave out the global header for devsite; it's in devsite template ?> - <!-- Header --> +<?cs if:!devsite ?><?cs # leave out the global header for devsite; it is in devsite template ?> + <!-- Header --> + <div id="header-wrapper"> <div id="header"> - <div class="wrap" id="header-wrap"> - <div class="col-3 logo"> + <div class="wrap" id="header-wrap"> + <div class="col-3 logo"> <a href="<?cs var:toroot ?>index.html"> - <img src="<?cs var:toroot ?>assets/images/dac_logo.png" width="123" height="25" alt="Android Developers" /> + <img src="<?cs var:toroot ?>assets/images/dac_logo.png" + srcset="<?cs var:toroot ?>assets/images/dac_logo@2x.png 2x" + width="123" height="25" alt="Android Developers" /> </a> <div class="btn-quicknav" id="btn-quicknav"> - <a href="#" class="arrow-inactive">Quicknav</a> - <a href="#" class="arrow-active">Quicknav</a> + <a href="#" class="arrow-inactive">Quicknav</a> + <a href="#" class="arrow-active">Quicknav</a> </div> - </div> - <ul class="nav-x col-9"> - <li class="design"> - <a href="<?cs var:toroot ?>design/index.html" - zh-tw-lang="設計" - zh-cn-lang="设计" - ru-lang="Проектирование" - ko-lang="디자인" - ja-lang="設計" - es-lang="Diseñar" - >Design</a></li> - <li class="develop"><a href="<?cs var:toroot ?>develop/index.html" - zh-tw-lang="開發" - zh-cn-lang="开发" - ru-lang="Разработка" - ko-lang="개발" - ja-lang="開発" - es-lang="Desarrollar" - >Develop</a></li> - <li class="distribute last"><a href="<?cs var:toroot ?>distribute/index.html" - zh-tw-lang="發佈" - zh-cn-lang="分发" - ru-lang="Распространение" - ko-lang="배포" - ja-lang="配布" - es-lang="Distribuir" - >Distribute</a></li> - </ul> - - <!-- New Search --> - <div class="menu-container"> - <div class="moremenu"> - <div id="more-btn"></div> - </div> - <div class="morehover" id="moremenu"> - <div class="top"></div> - <div class="mid"> - <div class="header">Links</div> - <ul> - <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li> - <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li> - <li><a href="<?cs var:toroot ?>about/index.html">About Android</a></li> - </ul> - <div class="header">Android Sites</div> - <ul> - <li><a href="http://www.android.com">Android.com</a></li> - <li class="active"><a>Android Developers</a></li> - <li><a href="http://source.android.com">Android Open Source Project</a></li> - </ul> - - <?cs # Include language switcher only in online docs ?> - <?cs if:android.whichdoc == "online" ?> - <div class="header">Language</div> - <div id="language" class="locales"> - <select name="language" onChange="changeLangPref(this.value, true)"> - <option value="en">English</option> - <option value="es">Español</option> - <option value="ja">日本語</option> - <option value="ko">한국어</option> - <option value="ru">Русский</option> - <option value="zh-cn">中文 (中国)</option> - <option value="zh-tw">中文 (台灣)</option> - </select> - </div> - <script type="text/javascript"> - <!-- - loadLangPref(); - //--> - </script> - <?cs /if ?> - <?cs # End of lang switcher ?> + </div> + <ul class="nav-x col-9"> + <li class="design"> + <a href="<?cs var:toroot ?>design/index.html" + zh-tw-lang="設計" + zh-cn-lang="设计" + ru-lang="Проектирование" + ko-lang="디자인" + ja-lang="設計" + es-lang="Diseñar" + >Design</a></li> + <li class="develop"><a href="<?cs var:toroot ?>develop/index.html" + zh-tw-lang="開發" + zh-cn-lang="开发" + ru-lang="Разработка" + ko-lang="개발" + ja-lang="開発" + es-lang="Desarrollar" + >Develop</a></li> + <li class="distribute last"><a href="<?cs var:toroot ?>distribute/<?cs + if:android.whichdoc == "offline" ?>googleplay/<?cs /if ?>index.html" + zh-tw-lang="發佈" + zh-cn-lang="分发" + ru-lang="Распространение" + ko-lang="배포" + ja-lang="配布" + es-lang="Distribuir" + >Distribute</a></li> + </ul> - <br class="clearfix" /> - </div> - <div class="bottom"></div> - </div> - <div class="search" id="search-container"> - <div class="search-inner"> - <div id="search-btn"></div> - <div class="left"></div> - <form onsubmit="return submit_search()"> - <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q" -onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)" -onkeydown="return search_changed(event, true, '<?cs var:toroot ?>')" -onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> - </form> - <div class="right"></div> - <a class="close hide">close</a> - <div class="left"></div> - <div class="right"></div> - </div> - </div> + <?cs # ADD SEARCH AND MENU ?> + <?cs call:header_search_widget() ?> - <div class="search_filtered_wrapper reference"> - <div class="suggest-card reference no-display"> - <ul class="search_filtered"> - </ul> - </div> - </div> - <div class="search_filtered_wrapper docs"> - <div class="suggest-card dummy no-display"> </div> - <div class="suggest-card develop no-display"> - <ul class="search_filtered"> - </ul> - <div class="child-card guides no-display"> - </div> - <div class="child-card training no-display"> - </div> - <div class="child-card samples no-display"> - </div> - </div> - <div class="suggest-card design no-display"> - <ul class="search_filtered"> - </ul> - </div> - <div class="suggest-card distribute no-display"> - <ul class="search_filtered"> - </ul> - </div> - </div> + <!-- Expanded quicknav --> + <div id="quicknav" class="col-9"> + <ul> + <li class="design"> + <ul> + <li><a href="<?cs var:toroot ?>design/index.html">Get Started</a></li> + <li><a href="<?cs var:toroot ?>design/style/index.html">Style</a></li> + <li><a href="<?cs var:toroot ?>design/patterns/index.html">Patterns</a></li> + <li><a href="<?cs var:toroot ?>design/building-blocks/index.html">Building Blocks</a></li> + <li><a href="<?cs var:toroot ?>design/downloads/index.html">Downloads</a></li> + <li><a href="<?cs var:toroot ?>design/videos/index.html">Videos</a></li> + </ul> + </li> + <li class="develop"> + <ul> + <li><a href="<?cs var:toroot ?>training/index.html" + zh-tw-lang="訓練課程" + zh-cn-lang="培训" + ru-lang="Курсы" + ko-lang="교육" + ja-lang="トレーニング" + es-lang="Capacitación" + >Training</a></li> + <li><a href="<?cs var:toroot ?>guide/index.html" + zh-tw-lang="API 指南" + zh-cn-lang="API 指南" + ru-lang="Руководства по API" + ko-lang="API 가이드" + ja-lang="API ガイド" + es-lang="Guías de la API" + >API Guides</a></li> + <li><a href="<?cs var:toroot ?>reference/packages.html" + zh-tw-lang="參考資源" + zh-cn-lang="参考" + ru-lang="Справочник" + ko-lang="참조문서" + ja-lang="リファレンス" + es-lang="Referencia" + >Reference</a></li> + <li><a href="<?cs var:toroot ?>tools/index.html" + zh-tw-lang="相關工具" + zh-cn-lang="工具" + ru-lang="Инструменты" + ko-lang="도구" + ja-lang="ツール" + es-lang="Herramientas" + >Tools</a> + <ul><li><a href="<?cs var:toroot ?>sdk/index.html">Get the SDK</a></li></ul> + </li> + <li><a href="<?cs var:toroot ?>google/index.html">Google Services</a> + </li> + <?cs if:android.hasSamples ?> + <li><a href="<?cs var:toroot ?>samples/index.html">Samples</a> + </li> + <?cs /if ?> + </ul> + </li> + <li class="distribute last"> + <ul> + <li><a href="<?cs var:toroot ?>distribute/googleplay/index.html">Google Play</a></li> + <li><a href="<?cs var:toroot ?>distribute/essentials/index.html">Essentials</a></li> + <li><a href="<?cs var:toroot ?>distribute/users/index.html">Get Users</a></li> + <li><a href="<?cs var:toroot ?>distribute/engage/index.html">Engage & Retain</a></li> + <li><a href="<?cs var:toroot ?>distribute/monetize/index.html">Monetize</a></li> + <li><a href="<?cs var:toroot ?>distribute/tools/index.html">Tools & Reference</a></li> + <li><a href="<?cs var:toroot ?>distribute/stories/index.html">Developer Stories</a></li> + </ul> + </li> + </ul> + </div><!-- /Expanded quicknav --> + </div><!-- end header-wrap.wrap --> + </div><!-- end header --> - </div> - <!-- /New Search> - - - <!-- Expanded quicknav --> - <div id="quicknav" class="col-9"> - <ul> - <li class="design"> - <ul> - <li><a href="<?cs var:toroot ?>design/index.html">Get Started</a></li> - <li><a href="<?cs var:toroot ?>design/style/index.html">Style</a></li> - <li><a href="<?cs var:toroot ?>design/patterns/index.html">Patterns</a></li> - <li><a href="<?cs var:toroot ?>design/building-blocks/index.html">Building Blocks</a></li> - <li><a href="<?cs var:toroot ?>design/downloads/index.html">Downloads</a></li> - <li><a href="<?cs var:toroot ?>design/videos/index.html">Videos</a></li> - </ul> - </li> - <li class="develop"> - <ul> - <li><a href="<?cs var:toroot ?>training/index.html" - zh-tw-lang="訓練課程" - zh-cn-lang="培训" - ru-lang="Курсы" - ko-lang="교육" - ja-lang="トレーニング" - es-lang="Capacitación" - >Training</a></li> - <li><a href="<?cs var:toroot ?>guide/index.html" - zh-tw-lang="API 指南" - zh-cn-lang="API 指南" - ru-lang="Руководства по API" - ko-lang="API 가이드" - ja-lang="API ガイド" - es-lang="Guías de la API" - >API Guides</a></li> - <li><a href="<?cs var:toroot ?>reference/packages.html" - zh-tw-lang="參考資源" - zh-cn-lang="参考" - ru-lang="Справочник" - ko-lang="참조문서" - ja-lang="リファレンス" - es-lang="Referencia" - >Reference</a></li> - <li><a href="<?cs var:toroot ?>tools/index.html" - zh-tw-lang="相關工具" - zh-cn-lang="工具" - ru-lang="Инструменты" - ko-lang="도구" - ja-lang="ツール" - es-lang="Herramientas" - >Tools</a> - <ul><li><a href="<?cs var:toroot ?>sdk/index.html">Get the SDK</a></li></ul> - </li> - <li><a href="<?cs var:toroot ?>google/index.html">Google Services</a> - </li> - <?cs if:android.hasSamples ?> - <li><a href="<?cs var:toroot ?>samples/index.html">Samples</a> - </li> - <?cs /if ?> - </ul> - </li> - <li class="distribute last"> - <ul> - <li><a href="<?cs var:toroot ?>distribute/index.html">Google Play</a></li> - <li><a href="<?cs var:toroot ?>distribute/googleplay/publish/index.html">Publishing</a></li> - <li><a href="<?cs var:toroot ?>distribute/googleplay/promote/index.html">Promoting</a></li> - <li><a href="<?cs var:toroot ?>distribute/googleplay/quality/index.html">App Quality</a></li> - <li><a href="<?cs var:toroot ?>distribute/googleplay/spotlight/index.html">Spotlight</a></li> - <li><a href="<?cs var:toroot ?>distribute/open.html">Open Distribution</a></li> - </ul> - </li> - </ul> - </div> - <!-- /Expanded quicknav --> - </div> - </div> - <!-- /Header --> - - - <div id="searchResults" class="wrap" style="display:none;"> - <h2 id="searchTitle">Results</h2> - <div id="leftSearchControl" class="search-control">Loading...</div> - </div> - - <?cs if:training || guide || reference || tools || develop || google || samples ?> <!-- Secondary x-nav --> <div id="nav-x"> @@ -231,7 +137,7 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> ru-lang="Курсы" ko-lang="교육" ja-lang="トレーニング" - es-lang="Capacitación" + es-lang="Capacitación" >Training</a></li> <li class="guide"><a href="<?cs var:toroot ?>guide/index.html" zh-tw-lang="API 指南" @@ -239,7 +145,7 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> ru-lang="Руководства по API" ko-lang="API 가이드" ja-lang="API ガイド" - es-lang="Guías de la API" + es-lang="Guías de la API" >API Guides</a></li> <li class="reference"><a href="<?cs var:toroot ?>reference/packages.html" zh-tw-lang="參考資源" @@ -247,7 +153,7 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> ru-lang="Справочник" ko-lang="참조문서" ja-lang="リファレンス" - es-lang="Referencia" + es-lang="Referencia" >Reference</a></li> <li class="tools"><a href="<?cs var:toroot ?>tools/index.html" zh-tw-lang="相關工具" @@ -267,13 +173,98 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> <?cs /if ?> </ul> </div> - </div> <!-- /Sendondary x-nav --> + + <?cs elif:distribute || googleplay || essentials || users || engage || monetize || disttools || stories ?> + <!-- Secondary distribute x-nav --> + <div id="nav-x"> + <div class="wrap"> + <ul class="nav-x distribute"> + <li class="googleplay"><a href="<?cs var:toroot ?>distribute/googleplay/index.html" + >Google Play</a></li> + <li class="essentials"><a href="<?cs var:toroot ?>distribute/essentials/index.html" + >Essentials</a></li> + <li class="users"><a href="<?cs var:toroot ?>distribute/users/index.html" + >Get Users</a></li> + <li class="engage"><a href="<?cs var:toroot ?>distribute/engage/index.html" + >Engage & Retain</a></li> + <li class="monetize"><a href="<?cs var:toroot ?>distribute/monetize/index.html" + >Monetize</a> + </li> + <li class="disttools"><a href="<?cs var:toroot ?>distribute/tools/index.html" + >Tools</a> + </li> + <li class="stories"><a href="<?cs var:toroot ?>distribute/stories/index.html" + >Stories</a> + </li> + </ul> + <a href="https://play.google.com/apps/publish/" class="developer-console-btn">Developer Console</a> + </div> <!-- /Secondary distribute x-nav --> + </div> <?cs /if ?> -<?cs /if ?> -<?cs # end if/else !devsite ?> + <div id="searchResults" class="wrap" style="display:none;"> + <h2 id="searchTitle">Results</h2> + <div id="leftSearchControl" class="search-control">Loading...</div> + </div> + </div> <!--end header-wrapper --> + + <div id="sticky-header"> + <div> + <a class="logo" href="#top"></a> + <a class="top" href="#top"></a> + <ul class="breadcrumb"> + <?cs # More <li> elements added here with javascript ?> + <?cs if:!section.landing ?><li class="current"><?cs var:page.title ?></li><?cs + /if ?> + </ul> + </div> + </div> + +<?cs /if ?><?cs # end if/else !devsite ?> +<?cs /if ?><?cs # end if/else wear ?><?cs +/def ?> + +<?cs def:wear_masthead() ?> +<a name="top"></a> + +<!-- Header --> +<div id="header-wrapper"> + <div id="header"> + <div class="wrap" id="header-wrap"> + <div class="col_3 logo wear-logo"> + <a href="<?cs var:toroot ?>wear/index.html"> + <img src="<?cs var:toroot ?>wear/images/android-wear.png" height="16" alt="Android Wear" /> + </a> + </div> + <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px; +color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div> + + <?cs # ADD SEARCH AND MENU ?> + <?cs call:header_search_widget() ?> + + </div><!-- end header-wrap --> + </div><!-- /Header --> + + + <div id="searchResults" class="wrap" style="display:none;"> + <h2 id="searchTitle">Results</h2> + <div id="leftSearchControl" class="search-control">Loading...</div> + </div> +</div> <!--end header-wrapper --> + +<div id="sticky-header"> + <div> + <a class="logo" href="#top"></a> + <a class="top" href="#top"></a> + <ul class="breadcrumb"> + <?cs # More <li> elements added here with javascript ?> + <?cs if:!section.landing ?><li class="current"><?cs var:page.title ?></li><?cs + /if ?> + </ul> + </div> +</div> - <?cs + <?cs /def ?> diff --git a/tools/droiddoc/templates-sdk-dyn/customizations.cs b/tools/droiddoc/templates-sdk-dyn/customizations.cs index ed57f1c..27822d5 100644 --- a/tools/droiddoc/templates-sdk-dyn/customizations.cs +++ b/tools/droiddoc/templates-sdk-dyn/customizations.cs @@ -7,7 +7,6 @@ def:sdk_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/sdk/sdk_toc.cs" ?> @@ -15,19 +14,53 @@ def:sdk_nav() ?> </div> </div> <!-- end side-nav --> -<?cs /def ?> +<?cs /def ?><?cs + +def:no_nav() ?> + <div class="wrap clearfix" id="body-content"> +<?cs /def ?><?cs + +def:tools_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> <?cs -def:resources_tab_nav() ?> + include:"../../../../frameworks/base/docs/html/tools/tools_toc.cs" ?> + + + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?> +<?cs +def:training_nav() ?> <div class="wrap clearfix" id="body-content"> - <a <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> + <?cs - include:"../../../../frameworks/base/docs/html/resources/resources_toc.cs" ?> + include:"../../../../frameworks/base/docs/html/training/training_toc.cs" ?> + + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs +def:googleplay_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/googleplay/googleplay_toc.cs" ?> </div> </div> <!-- end side-nav --> <script> @@ -35,17 +68,13 @@ def:resources_tab_nav() ?> scrollIntoView("devdoc-nav"); }); </script> -<?cs /def ?> -<?cs -def:tools_nav() ?> +<?cs /def ?><?cs + +def:essentials_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> -<?cs - include:"../../../../frameworks/base/docs/html/tools/tools_toc.cs" ?> - - +<?cs include:"../../../../frameworks/base/docs/html/distribute/essentials/essentials_toc.cs" ?> </div> </div> <!-- end side-nav --> <script> @@ -53,19 +82,69 @@ def:tools_nav() ?> scrollIntoView("devdoc-nav"); }); </script> -<?cs /def ?> -<?cs -def:training_nav() ?> +<?cs /def ?><?cs + +def:users_nav() ?> <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> +<?cs include:"../../../../frameworks/base/docs/html/distribute/users/users_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs + +def:engage_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/engage/engage_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs +def:monetize_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/monetize/monetize_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs -<?cs - include:"../../../../frameworks/base/docs/html/training/training_toc.cs" ?> - +def:disttools_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/tools/disttools_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs +def:stories_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/stories/stories_toc.cs" ?> </div> </div> <!-- end side-nav --> <script> @@ -73,14 +152,12 @@ def:training_nav() ?> scrollIntoView("devdoc-nav"); }); </script> -<?cs /def ?> -<?cs +<?cs /def ?><?cs + def:guide_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> - <?cs include:"../../../../frameworks/base/docs/html/guide/guide_toc.cs" ?> @@ -99,7 +176,6 @@ def:design_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs @@ -119,7 +195,6 @@ def:distribute_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/distribute/distribute_toc.cs" ?> @@ -139,7 +214,6 @@ def:samples_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/samples/samples_toc.cs" ?> @@ -159,7 +233,6 @@ def:google_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/google/google_toc.cs" ?> @@ -183,7 +256,6 @@ def:about_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/about/about_toc.cs" ?> @@ -198,6 +270,26 @@ def:about_nav() ?> </script> <?cs /def ?> + +<?cs +def:wear_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> + +<?cs + include:"../../../../frameworks/base/docs/html/wear/wear_toc.cs" ?> + + + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?> + <?cs # The default side navigation for the reference docs ?><?cs def:default_left_nav() ?> <?cs if:reference.gcm || reference.gms ?> @@ -206,8 +298,6 @@ def:default_left_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav"> - -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <div id="api-nav-header"> <div id="api-level-toggle"> <label for="apiLevelCheckbox" class="disabled" @@ -308,10 +398,111 @@ def:default_left_nav() ?> <?cs /def ?> + +<?cs +def:header_search_widget() ?> +<div class="menu-container"> + <div class="moremenu"> + <div id="more-btn"></div> + </div> + <div class="morehover" id="moremenu"> + <div class="top"></div> + <div class="mid"> + <div class="header">Links</div> + <ul> + <li><a href="https://play.google.com/apps/publish/" target="_googleplay">Google Play Developer Console</a></li> + <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li> + <li><a href="<?cs var:toroot ?>about/index.html">About Android</a></li> + </ul> + <div class="header">Android Sites</div> + <ul> + <li><a href="http://www.android.com">Android.com</a></li> + <li class="active"><a>Android Developers</a></li> + <li><a href="http://source.android.com">Android Open Source Project</a></li> + </ul> + + <?cs # Include language switcher only in online docs ?> + <?cs if:android.whichdoc == "online" ?> + <div class="header">Language</div> + <div id="language" class="locales"> + <select name="language" onChange="changeLangPref(this.value, true)"> + <option value="en">English</option> + <option value="es">Español</option> + <option value="ja">日本語</option> + <option value="ko">한국어</option> + <option value="ru">Русский</option> + <option value="zh-cn">中文 (中国)</option> + <option value="zh-tw">中文 (台灣)</option> + </select> + </div> + <script type="text/javascript"> + <!-- + loadLangPref(); + //--> + </script> + <?cs /if ?> + <?cs # End of lang switcher ?> + <br class="clearfix" /> + </div><!-- end 'mid' --> + <div class="bottom"></div> + </div><!-- end 'moremenu' --> + + <div class="search" id="search-container"> + <div class="search-inner"> + <div id="search-btn"></div> + <div class="left"></div> + <form onsubmit="return submit_search()"> + <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q" + onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)" + onkeydown="return search_changed(event, true, '<?cs var:toroot ?>')" + onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> + </form> + <div class="right"></div> + <a class="close hide">close</a> + <div class="left"></div> + <div class="right"></div> + </div><!-- end search-inner --> + </div><!-- end search-container --> + + <div class="search_filtered_wrapper reference"> + <div class="suggest-card reference no-display"> + <ul class="search_filtered"> + </ul> + </div> + </div> + + <div class="search_filtered_wrapper docs"> + <div class="suggest-card dummy no-display"> </div> + <div class="suggest-card develop no-display"> + <ul class="search_filtered"> + </ul> + <div class="child-card guides no-display"> + </div> + <div class="child-card training no-display"> + </div> + <div class="child-card samples no-display"> + </div> + </div> + <div class="suggest-card design no-display"> + <ul class="search_filtered"> + </ul> + </div> + <div class="suggest-card distribute no-display"> + <ul class="search_filtered"> + </ul> + </div> + </div> +</div><!-- end menu-container (search and menu widget) --> +<?cs /def ?> + + + <?cs def:custom_left_nav() ?><?cs - if:fullpage ?><?cs - call:fullpage() ?><?cs + if:fullpage ?><?cs + call:fullpage() ?><?cs + elif:nonavpage ?><?cs + call:no_nav() ?><?cs elif:guide ?><?cs call:guide_nav() ?><?cs elif:design ?><?cs @@ -324,15 +515,31 @@ def:custom_left_nav() ?><?cs call:google_nav() ?><?cs elif:samples ?><?cs call:samples_nav() ?><?cs - elif:more ?><?cs - call:dist_more_nav() ?><?cs elif:distribute ?><?cs - call:distribute_nav() ?><?cs - elif:about ?><?cs - call:about_nav() ?><?cs - else ?><?cs - call:default_left_nav() ?> <?cs - /if ?><?cs + if:googleplay ?><?cs + call:googleplay_nav() ?><?cs + elif:essentials ?><?cs + call:essentials_nav() ?><?cs + elif:users ?><?cs + call:users_nav() ?><?cs + elif:engage ?><?cs + call:engage_nav() ?><?cs + elif:monetize ?><?cs + call:monetize_nav() ?><?cs + elif:disttools ?><?cs + call:disttools_nav() ?><?cs + elif:stories ?><?cs + call:stories_nav() ?><?cs + /if ?><?cs + elif:about ?><?cs + call:about_nav() ?><?cs + elif:distribute ?><?cs + call:distribute_nav() ?><?cs + elif:wear ?><?cs + call:wear_nav() ?><?cs + else ?><?cs + call:default_left_nav() ?> <?cs + /if ?><?cs /def ?> <?cs # appears at the bottom of every page ?><?cs diff --git a/tools/droiddoc/templates-sdk-dyn/docpage.cs b/tools/droiddoc/templates-sdk-dyn/docpage.cs index ea462c9..7eae405 100644 --- a/tools/droiddoc/templates-sdk-dyn/docpage.cs +++ b/tools/droiddoc/templates-sdk-dyn/docpage.cs @@ -2,19 +2,36 @@ <?cs include:"macros.cs" ?> <html<?cs if:devsite ?> devsite<?cs /if ?>> <?cs include:"head_tag.cs" ?> -<body class="gc-documentation <?cs if:(google || reference.gms || reference.gcm) ?>google<?cs /if ?> - <?cs if:(guide||develop||training||reference||tools||sdk||samples) ?>develop<?cs if:guide ?> guide<?cs /if ?><?cs if:samples ?> samples<?cs /if ?><?cs +<body class="gc-documentation + +<?cs +if:(google || reference.gms || reference.gcm) ?>google<?cs /if ?><?cs + if:(guide||develop||training||reference||tools||sdk||samples) ?>develop<?cs + if:guide ?> guide<?cs /if ?><?cs + if:samples ?> samples<?cs /if ?><?cs + elif:(distribute||googleplay||essentials||users||engage||monetize||disttools||stories) + ?>distribute<?cs + if:googleplay ?> googleplay<?cs /if ?><?cs + if:essentials ?> essentials<?cs /if ?><?cs + if:users ?> users<?cs /if ?><?cs + if:engage ?> engage<?cs /if ?><?cs + if:monetize ?> monetize<?cs /if ?><?cs + if:disttools ?> disttools<?cs /if ?><?cs + if:stories ?> stories<?cs /if ?><?cs elif:about ?>about<?cs elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?><?cs - if:page.trainingcourse ?> trainingcourse<?cs /if ?>" itemscope itemtype="http://schema.org/Article"> -<?cs include:"header.cs" ?> +/if ?><?cs +if:page.trainingcourse ?> trainingcourse<?cs +/if ?>" itemscope itemtype="http://schema.org/Article"><?cs +include:"header.cs" ?> -<div <?cs if:fullpage -?>class="fullpage"<?cs elif:design||tools||about||sdk||distribute -?>class="col-13" id="doc-col"<?cs else -?>class="col-12" id="doc-col"<?cs /if ?> > +<div <?cs + if:fullpage + ?>class="fullpage"<?cs + elif:(design||tools||about||sdk||googleplay||essentials||users||monetize||disttools) && !nonavpage + ?>class="col-13" id="doc-col"<?cs + elif:!nonavpage + ?>class="col-12" id="doc-col"<?cs /if ?> > <?cs if:(design||training||walkthru) && !page.trainingcourse && !page.article ?><?cs # header logic for docs that provide previous/next buttons ?> <?cs if:header.hide ?> @@ -74,6 +91,7 @@ <?cs /if ?><?cs # end if training ?> </div> <?cs /if ?> + <?cs elif:samplesProjectIndex ?> <div id="api-info-block"> <div class="sum-details-links"> @@ -83,7 +101,10 @@ </div><!-- end sum-details-links --> </div><!-- end breadcurmb block --> <h1 itemprop="name"><?cs var:projectDir ?></h1> + <?cs else ?> + + <?cs if:(!fullpage && !header.hide) ?> <?cs if:page.landing ?><?cs # header logic for docs that are landing pages ?> <div class="landing-banner"> @@ -181,8 +202,6 @@ <?cs include:"footer.cs" ?> </div><!-- end doc-content --> -<?cs include:"trailer.cs" ?> - <!-- Start of Tag --> <script type="text/javascript"> var axel = Math.random() + ""; @@ -193,6 +212,15 @@ document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2 <iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe> </noscript> <!-- End of Tag --> + + +<?cs include:"trailer.cs" ?> + <script src="https://developer.android.com/ytblogger_lists_unified.js" type="text/javascript"></script> + <script src="<?cs var:toroot ?>jd_lists_unified.js" type="text/javascript"></script> + <script src="<?cs var:toroot ?>jd_extras.js" type="text/javascript"></script> + <script src="<?cs var:toroot ?>jd_collections.js" type="text/javascript"></script> + <script src="<?cs var:toroot ?>jd_tag_helpers.js" type="text/javascript"></script> + </body> </html> diff --git a/tools/droiddoc/templates-sdk-dyn/head_tag.cs b/tools/droiddoc/templates-sdk-dyn/head_tag.cs index 54de169..732118f 100644 --- a/tools/droiddoc/templates-sdk-dyn/head_tag.cs +++ b/tools/droiddoc/templates-sdk-dyn/head_tag.cs @@ -15,13 +15,13 @@ ?><?cs # END if/else devsite ?> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="viewport" content="width=device-width" /> +<meta name="viewport" content="width=<?cs + if:page.viewport_width ?><?cs + var:page.viewport_width ?><?cs + else ?>device-width<?cs /if ?>" /> <?cs if:page.metaDescription ?> <meta name="Description" content="<?cs var:page.metaDescription ?>"><?cs - /if ?><?cs - if:page.customHeadTag ?> -<?cs var:page.customHeadTag ?><?cs /if ?> <link rel="shortcut icon" type="image/x-icon" href="<?cs var:toroot ?>favicon.ico" /> <title><?cs @@ -31,10 +31,16 @@ <!-- STYLESHEETS --> <link rel="stylesheet" -href="<?cs if:android.whichdoc != 'online' ?>http:<?cs /if ?>//fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic,bold" title="roboto"> +href="<?cs +if:android.whichdoc != 'online' ?>http:<?cs +/if ?>//fonts.googleapis.com/css?family=Roboto+Condensed"> +<link rel="stylesheet" href="<?cs +if:android.whichdoc != 'online' ?>http:<?cs +/if ?>//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" + title="roboto"> <link href="<?cs var:toroot ?>assets/css/default.css" rel="stylesheet" type="text/css"> -<?cs if:reference && !(reference.gms || reference.gcm) ?> +<?cs if:reference && !(reference.gms || reference.gcm || wear) ?> <!-- FULLSCREEN STYLESHEET --> <link href="<?cs var:toroot ?>assets/css/fullscreen.css" rel="stylesheet" class="fullscreen" type="text/css"> @@ -47,7 +53,10 @@ if:devsite ?><script src="<?cs var:toroot ?>_static/js/android_3p-bundle.js" type="text/javascript"></script><?cs else ?><script src="<?cs var:toroot ?>assets/js/android_3p-bundle.js" type="text/javascript"></script><?cs -/if ?> +/if ?><?cs + if:page.customHeadTag ?> +<?cs var:page.customHeadTag ?><?cs + /if ?> <script type="text/javascript"> var toRoot = "<?cs var:toroot ?>"; var metaTags = [<?cs var:meta.tags ?>]; @@ -66,4 +75,4 @@ else var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> -</head>
\ No newline at end of file +</head> diff --git a/tools/droiddoc/templates-sdk-dyn/sample.cs b/tools/droiddoc/templates-sdk-dyn/sample.cs index 684e284..c6f28f8 100644 --- a/tools/droiddoc/templates-sdk-dyn/sample.cs +++ b/tools/droiddoc/templates-sdk-dyn/sample.cs @@ -7,7 +7,7 @@ <div <?cs if:fullpage ?>class="fullpage"<?cs elif:design||tools||about||sdk||distribute -?>class="col-13" id="doc-col"<?cs else +?>class="col-13" id="doc-col"<?cs else ?>class="col-12" id="doc-col"<?cs /if ?> > <!-- start breadcrumb block --> diff --git a/tools/droiddoc/templates-sdk-dyn/sdkpage.cs b/tools/droiddoc/templates-sdk-dyn/sdkpage.cs index d98146a..95f6596 100644 --- a/tools/droiddoc/templates-sdk-dyn/sdkpage.cs +++ b/tools/droiddoc/templates-sdk-dyn/sdkpage.cs @@ -11,7 +11,7 @@ <?cs else ?> <?cs include:"head_tag.cs" ?> <?cs /if ?> -<body class="gc-documentation +<body class="gc-documentation <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs elif:design ?>design<?cs elif:distribute ?>distribute<?cs @@ -107,7 +107,7 @@ </td> <td><?cs var:ndk.win64_bytes ?></td> <td><?cs var:ndk.win64_checksum ?></td> - </tr> + </tr> <!-- <tr> <td> <a onClick="return onDownload(this)" @@ -199,12 +199,12 @@ <td><?cs var:ndk.debug_info_checksum ?></td> </tr> </table> - + <?cs ######## HERE IS THE JD DOC CONTENT ######### ?> <?cs call:tag_list(root.descr) ?> - + <script> function onDownload(link) { @@ -229,13 +229,13 @@ function onDownloadNdkForRealz(link) { if ($("input#agree").is(':checked')) { $("#tos").fadeOut('slow'); - + $('html, body').animate({ scrollTop: $("#Installing").offset().top }, 800, function() { $("#Installing").click(); }); - + return true; } else { $("label#agreeLabel").parent().stop().animate({color: "#258AAF"}, 200, @@ -254,7 +254,7 @@ </script> <?cs else ?> -<?cs # end if NDK ... +<?cs # end if NDK ... # # # @@ -281,11 +281,11 @@ <h4><a href='' class="expandable" onclick="toggleExpandable(this,'.pax');hideExpandable('.myide,.reqs');return false;" >DOWNLOAD FOR OTHER PLATFORMS</a></h4> - - + + <div class="pax col-13 online" style="display:none;margin:0;"> - + <p class="table-caption"><strong>ADT Bundle</strong></p> <table class="download"> <tr> @@ -298,7 +298,7 @@ <td>Windows 32-bit</td> <td> <a onClick="return onDownload(this)" id="win-bundle32" - href="http://dl.google.com/android/adt/<?cs var:sdk.win32_bundle_download ?>"><?cs var:sdk.win32_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.win32_bundle_download ?>"><?cs var:sdk.win32_bundle_download ?></a> </td> <td><?cs var:sdk.win32_bundle_bytes ?> bytes</td> <td><?cs var:sdk.win32_bundle_checksum ?></td> @@ -307,7 +307,7 @@ <td>Windows 64-bit</td> <td> <a onClick="return onDownload(this)" id="win-bundle64" - href="http://dl.google.com/android/adt/<?cs var:sdk.win64_bundle_download ?>"><?cs var:sdk.win64_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.win64_bundle_download ?>"><?cs var:sdk.win64_bundle_download ?></a> </td> <td><?cs var:sdk.win64_bundle_bytes ?> bytes</td> <td><?cs var:sdk.win64_bundle_checksum ?></td> @@ -316,7 +316,7 @@ <td><nobr>Mac OS X 64-bit</nobr></td> <td> <a onClick="return onDownload(this)" id="mac-bundle64" - href="http://dl.google.com/android/adt/<?cs var:sdk.mac64_bundle_download ?>"><?cs var:sdk.mac64_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.mac64_bundle_download ?>"><?cs var:sdk.mac64_bundle_download ?></a> </td> <td><?cs var:sdk.mac64_bundle_bytes ?> bytes</td> <td><?cs var:sdk.mac64_bundle_checksum ?></td> @@ -325,7 +325,7 @@ <td>Linux 32-bit</td> <td> <a onClick="return onDownload(this)" id="linux-bundle32" - href="http://dl.google.com/android/adt/<?cs var:sdk.linux32_bundle_download ?>"><?cs var:sdk.linux32_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.linux32_bundle_download ?>"><?cs var:sdk.linux32_bundle_download ?></a> </td> <td><?cs var:sdk.linux32_bundle_bytes ?> bytes</td> <td><?cs var:sdk.linux32_bundle_checksum ?></td> @@ -334,7 +334,7 @@ <td>Linux 64-bit</td> <td> <a onClick="return onDownload(this)" id="linux-bundle64" - href="http://dl.google.com/android/adt/<?cs var:sdk.linux64_bundle_download ?>"><?cs var:sdk.linux64_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.linux64_bundle_download ?>"><?cs var:sdk.linux64_bundle_download ?></a> </td> <td><?cs var:sdk.linux64_bundle_bytes ?> bytes</td> <td><?cs var:sdk.linux64_bundle_checksum ?></td> @@ -396,10 +396,10 @@ var:sdk.linux_download </div><!-- end col-13 for lower-half content --> - - - - + + + + <script> if (location.hash == "#Requirements") { $('.reqs').show(); @@ -440,17 +440,17 @@ var:sdk.linux_download } else { $('.pax').show(); } - - + + function onDownload(link, button, bundle) { - + /* set text for download button */ if (button) { $("#downloadForRealz").html($(link).text()); } else { $("#downloadForRealz").html("Download " + $(link).text()); } - + /* if it's a bundle, show the 32/64-bit picker */ if (bundle) { $("#downloadForRealz").attr('bundle','true'); @@ -482,7 +482,7 @@ var:sdk.linux_download function onAgreeChecked() { /* verify that the TOS is agreed and a bit version is chosen */ if ($("input#agree").is(":checked") && $("#bitpicker input:checked").length) { - + /* if downloading the bundle */ if ($("#downloadForRealz").attr('bundle')) { /* construct the name of the link we want based on the bit version */ @@ -490,7 +490,7 @@ var:sdk.linux_download /* set the real url for download */ $("a#downloadForRealz").attr("href", $(linkId).attr("href")); } - + /* reveal the download button */ $("a#downloadForRealz").removeClass('disabled'); } else { @@ -536,29 +536,29 @@ var:sdk.linux_download <p>Welcome developers! We are pleased to provide you with a preview SDK for the upcoming Android 3.0 release, to give you a head-start on developing applications for it. </p> - + <p>See the <a href="<?cs var:toroot ?>sdk/preview/start.html">Getting Started</a> document for more information about how to set up the preview SDK and get started.</p> <style type="text/css"> .non-preview { display:none; } </style> - + <?cs else ?><?cs # it's normal offline docs ?> - + <?cs ######## HERE IS THE JD DOC CONTENT FOR OFFLINE ######### ?> <?cs call:tag_list(root.descr) ?> <style type="text/css"> body .offline { display:block; } body .online { display:none; } - </style> + </style> <script> $('.reqs').show(); </script> <?cs /if ?> - + <?cs /if ?> <?cs # end if/else online ?> - + <?cs /if ?> <?cs # end if/else NDK ?> <?cs /if ?> <?cs # end if/else redirect ?> diff --git a/tools/droiddoc/templates-sdk/assets/css/default.css b/tools/droiddoc/templates-sdk/assets/css/default.css index aa30c8a..3b647c2 100644 --- a/tools/droiddoc/templates-sdk/assets/css/default.css +++ b/tools/droiddoc/templates-sdk/assets/css/default.css @@ -98,7 +98,8 @@ body { #devdoc-nav.fixed { position: fixed; margin:0; - top: 20px; } + top: 65px; /* sticky-header height + 20px gutter */ +} #devdoc-nav span.small { font-size:12px; @@ -157,12 +158,6 @@ video.with-shadow { .layout-content-row { display: inline-block; margin-bottom: 10px; } - .layout-content-row:after { - content: "."; - display: block; - height: 0; - clear: both; - visibility: hidden; } * html .layout-content-row { height: 1px; } @@ -429,20 +424,19 @@ video.with-shadow { /* content header */ .content-header { height: 30px; - margin:20px 0 25px; - padding:0 0 10px;} + margin:36px 0 23px; /* same as h1 */ + padding:0 0 10px;} /* same as h1 */ .content-header.just-links { margin-bottom:0; padding-bottom:0;} .content-header h1 { - color:#000; margin:0; - border-bottom:0; padding:0; + width: 700px; } .content-header > div:first-child { - height:55px; /* set fixed height for the header div to ensure the + height:1px; /* set fixed height for the header div to ensure the next/prev links align with toc on training classes */ } @@ -450,7 +444,7 @@ video.with-shadow { border-top: 1px solid #ccc; margin-top: 10px; padding-top:10px; - height: 30px; } + width:100%; } .content-footer .col-9 { margin-left:0; @@ -461,20 +455,30 @@ video.with-shadow { .content-footer.wrap { width:940px; } +.content-footer .plus-container { + margin:5px 0 0; + text-align:right; + float:right; +} + +a.back-link { + text-decoration: none; + text-transform: uppercase; +} .paging-links { - position: relative; } + position: relative; + height:30px; } .paging-links a { position: absolute; } .paging-links a, .training-nav-top a { - font-size: 14px; - line-height: 30px; color: #555555; text-decoration: none; text-transform: uppercase; } .paging-links .prev-page-link:before, - .training-nav-top .prev-page-link:before { + .training-nav-top .prev-page-link:before, + a.back-link:before { content: ''; background: transparent url(../images/styles/disclosure_left.png) no-repeat scroll 50% 50%; width: 10px; @@ -488,7 +492,7 @@ video.with-shadow { .paging-links .prev-page-link { left: -15px; } .paging-links .next-page-link { - right: 0px; } + right: 0; } .next-page-link:after, .start-class-link:after, .start-course-link:after, @@ -505,6 +509,9 @@ video.with-shadow { .next-page-link.inline:after { content: none; } + .content-footer .paging-links .next-page-link { + left:0; + } .training-nav-top a { display:block; @@ -543,7 +550,6 @@ video.with-shadow { .paging-links a.start-class-link { width:100%; - text-align:right; } /* list of classes on course landing page */ @@ -622,19 +628,6 @@ video.with-shadow { display:none !important; } - .content-footer.next-class { - display:block; - border:0; - margin-top:0; - padding-top:0; - } - - .content-footer.next-class a.next-class-link { - display:block; - float:right; - text-transform:uppercase; - } - /* inner-doc tabs w/ title */ @@ -712,6 +705,7 @@ ul#title-tabs li a:active { color: #33b5e5; border-bottom-color: #33b5e5; } } +h1:target, h2:target, h3:target { -webkit-animation-name: glowheader; @@ -893,7 +887,7 @@ scroll top left; .framed-nexus4-port-216 img { width: 216px; height: 360px; } - + .framed-nexus5-port-span-5 { background: transparent url(../images/styles/device_nexus5_blank_port_span5.png) no-repeat scroll top left; @@ -928,6 +922,47 @@ scroll top left; height: 384px; } +/* wear device frames */ + +.framed-wear-square { + background: transparent url(../images/styles/device_wear_square.png) no-repeat scroll top left; + background-size: 302px 302px; + height:222px; + width:222px; + padding:40px; + overflow:hidden; +} + +.framed-wear-square-small { + background: transparent url(../images/styles/device_wear_square_small.png) no-repeat scroll top left; + background-size: 169px 200px; + height:147px; + width:147px; + padding:27px 11px; + overflow:hidden; +} + +#jd-content +.framed-wear-square img { + height:222px; + width: 222px; + padding:0; + margin:0; +} + +#jd-content +.framed-wear-square-small img { + height:147px; + width: 147px; + padding:0; + margin:0; +} + + + + + + /* landing page disclosures */ .landing-page-link { text-decoration: none; @@ -1101,12 +1136,13 @@ table, fieldset { } h1 { color:#333; - font-size: 22px; - margin: 20px 0 20px; + font-size: 34px; + margin: 36px 0 27px; padding:0 0 10px; + font-weight:300; } h1, h2 { - line-height: 32px; + line-height: 30px; } h1.short { margin-right:320px; @@ -1119,21 +1155,24 @@ h1.super { } h2 { color:#333; - font-size: 20px; - margin: 20px 0 20px; + font-size: 26px; + margin: 32px 0 20px; padding:0; + font-weight:300; } h3 { color:#333; - font-size: 18px; + font-size: 21px; + font-weight:400; + margin:21px 0 14px 0; } h3, h4 { - color:#333; - line-height: 20px; - margin: 10px 0; + line-height: 21px; } h4 { - font-size: 16px; + font-size: 18px; + margin: 12px 0; + font-weight:500; } h5 { font-size: 14px; @@ -1146,7 +1185,7 @@ h6 { } hr { /* applied to the bottom of h2 elements */ height: 1px; - margin: 5px 0 20px; + margin: 3px 0 12px; border: 0; background: #ccc; } @@ -1215,6 +1254,13 @@ a:focus, a:hover, a:active { color: #33B5E5; text-decoration: none; } +a.white { + color: #fff; + text-decoration:underline; +} +a.white:hover, a.white:active { + color: #ccc !important; +} strong, b { font-weight:bold; color: #222; @@ -1248,6 +1294,7 @@ th { tr:first-of-type th:first-of-type:empty { visibility: hidden; } + /* -------------------------------------------------------------------------- Footer */ @@ -1378,8 +1425,7 @@ color-stop(50%, #acbc00), color-stop(50%, #bdde00), color-stop(100%, #bdde00)); .training-nav-top, .training-nav-bottom, #doc-col .content-footer, .nav-x, .nav-y, - .paging-links, - a.totop { + .paging-links { display: none !important; } @@ -1504,7 +1550,8 @@ color-stop(50%, #acbc00), color-stop(50%, #bdde00), color-stop(100%, #bdde00)); Header, Login, Nav-X, Search */ #header { - padding: 2.2em 0 0.2em 0; + margin: 0; + padding: 0; } #header:before, #header:after { content: ""; @@ -1522,6 +1569,9 @@ Header, Login, Nav-X, Search color: #333; font-size: 16px; } +.about a.selected { + color: #9933CC; +} .design a.selected { color: #33b5e5; } @@ -1833,6 +1883,11 @@ EndColorStr='#ececec'); margin:0 0 0 20px; } +.training-nav-top { + position:relative; + top:73px; +} + .training-nav-bottom { padding:0 0 20px; } @@ -1841,12 +1896,12 @@ EndColorStr='#ececec'); #qv-wrapper { float:right; clear:right; - margin:0 0 0 20px; /* negative top-margin to counter the content-header bottom margin */ - padding:0 0 20px; + margin:6px 0 0 30px; /* negative top-margin to counter the content-header bottom margin */ + padding:0 0 30px; } #tb-wrapper { - margin:-29px 0 0 20px; /* negative top-margin to counter the content-header bottom margin */ + margin:51px 0 0 20px; /* negative top-margin to counter the content-header bottom margin */ } #tb, @@ -1930,6 +1985,10 @@ EndColorStr='#ececec'); margin:0 15px 10px 35px; } +#tb p { + margin:0 15px 10px; +} + #qv ol { list-style:none; margin:0 15px 15px; @@ -1958,28 +2017,12 @@ EndColorStr='#ececec'); /* related resources blocks in checklists */ -.rel-resources { - margin:10px 0px; - border:1px solid #ccc; - background-color:rgba(0, 0, 0, 0.027451); - border:1px solid #ccc; - font-size:13px; - color:#6f6f6f; -} +/* related resources sections that have dynamic content */ -.rel-resources ul { -padding: .5em 1em 0 1em; -} -.rel-resources a { -font-weight:500; -} -.rel-resources h3 { - margin:4px 15px 0px 15px; - font-size:13px; - font-weight:600; - text-transform:uppercase; +h3.rel-resources { +margin:1.25em auto; } /* -------------------------------------------------------------------------- @@ -2359,6 +2402,13 @@ a:visited, #doc-col { margin-right:0; } + +/* Uncomment this for preview release watermark +#doc-col { + background: url('../images/preview.png') repeat; +} +*/ + #doc-content-container { margin-left: 291px } @@ -2760,7 +2810,7 @@ table.blank th, table.blank td { .caption { margin: 0.5em 0 2em 0; color: #000; - font-size: 11.5px; + font-size: 11.5px; } .nolist, .nolist ul, .nolist ol { @@ -2884,26 +2934,6 @@ div.design-announce p { margin:0 0 10px; } -#devdoc-nav a.totop { - display:block; - top:0; - width:inherit; - background: transparent url(../images/styles/gototop.png) no-repeat scroll 50% 50%; - text-indent:-9999em; -} -#devdoc-nav a.totop { - position:fixed; - display:none; -} -#devdoc-nav a.totop:hover { - background-color:#33B5E5; -} - -.content-footer a.totop { - text-transform:uppercase; - line-height:30px; -} - .expandable { height:34px; padding-left:20px; @@ -3013,6 +3043,34 @@ a.header-toggle { } +/* for IDE instruction toggle (Studio/Eclipse/Other) */ +select.ide { + background: transparent; + border: 1px solid #bbb; + border-left: 0; + border-right: 0; + margin: 10px 0; + padding: 10px 0; + color:#666; +} +select.ide, +select.ide option { + font-family: inherit; + font-size:16px; + font-weight:500; +} +/* hide all except eclipse by default */ +.select-ide.studio, +.select-ide.other { + display:none; +} +/* ... unless eclipse also includes one of the others */ +.select-ide.eclipse.studio, +.select-ide.eclipse.other { + display:block; +} + + /* ----------------------------------------------- good/bad example containers */ @@ -3365,28 +3423,37 @@ Page-Specific Styles } #jd-header { - padding: 0 0 5px; - margin: 20px 0 10px; - font-size:13px; + padding: 0 0 12px; + margin: 20px 0 12px; + font-size:12px; + padding-bottom:12px; border-bottom:solid 1px #ccc; } #jd-header h1 { margin:0; - padding:0; + padding:0 0 6px 0; } +/* not sure if this is needed in the ref docs, disabling for now +.jd-descr h2 { + margin:16px 0; +} +*/ + /* page-top-right container for reference pages (holds links to summary tables) */ #api-info-block { - font-size:13px; + font-size:12px; margin:20px 0 0; padding:0 10px 6px; font-weight:normal; float:right; text-align:right; color:#999; - max-width:70%; + max-width:80%; + font-size: 12px; + line-height:14px; } #api-info-block div.api-level { @@ -3403,7 +3470,8 @@ links to summary tables) */ border-spacing:0; margin:0; padding:0; - font-size:13px; + font-size:12px; + line-height:14px; background-color:transparent; } .jd-inheritance-table tr td { @@ -3968,13 +4036,175 @@ EndColorStr='#ececec'); z-index:100; } -} +/************ STICKY NAV BAR ******************/ + +#header-wrapper { + background: #f9f9f9; + margin: 0 -10px 0 -10px; + padding: 31px 10px 0px 10px; + position: relative; +} +#header-wrapper #nav-x div.wrap { + max-width: 940px; + height: 38px; +} +#header-wrapper #nav-x ul.nav-x li { + margin-right: 36px !important; + margin-top: 5px; + margin-bottom: 0px; + height: 30px; +} +#header-wrapper #nav-x > div.wrap ul.nav-x li.active { + color: #669900; + border-bottom: 3px solid #669900; +} +#header-wrapper #nav-x > div.wrap ul.nav-x li.active a { + color: #669900; +} +#header-wrapper #nav-x > div.wrap ul.nav-x a { + font-size: 14.5px; +} +#header-wrapper .developer-console-btn { + float: right; + background: #fefefe; + border-radius: 4px; + padding: 8px 14px; + box-shadow: 1px 1px 0px #7a7a7a; + font-size: 14px; + margin-top: -6px; + cursor: pointer; + color: #464646; + margin-right: 20px; +} +/* not currently used */ +#header-wrapper .shadow { + width: 1034px; + height: 4px; + position: absolute; + left: 50%; + margin-left: -517px; + bottom: -4px; + background-image: url(../images/header-shadow.png); +} + +#context { + clear: both; + padding-top: 14px; +} +#context .breadcrumb { + float: left; + margin-bottom: 10px; +} +#context .util { + float: right; + margin-right: 20px; +} + +.breadcrumb { + list-style: none; + margin: 0; + padding: 0; + position: relative; +} +.breadcrumb li { + float: left; + padding: 0 20px 0 0; + color: #000; + white-space: nowrap; +} +.breadcrumb li a { + color: #000; +} +.breadcrumb li:after { + content: url(../images/breadcrumb.png); + position: relative; + top: 1px; + left: 10px; + width: 5px; + height: 10px; +} +.breadcrumb li.current { + font-weight: 700; +} +.breadcrumb li.current:after { + display: none; +} + +/* Sticky Nav overrides */ +.sticky-menu { + position: fixed; + width: 940px; + height: 0px; + z-index: 51; + top: 12px; +} +#sticky-header { + display: none; + padding: 0 10px; + position: fixed; + background: #f9f9f9; + top: 0px; + left: 0px; + right: 0px; + height: 45px; + box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1); + border-bottom: 1px solid #a5c43a; + z-index: 50; +} +#sticky-header.design { + border-bottom: 1px solid #33b5e5; +} +#sticky-header.develop { + border-bottom: 1px solid #F80; +} +#sticky-header.distribute { + border-bottom: 1px solid #9C0; +} +#sticky-header.about { + border-bottom: 1px solid #9933CC; +} +#sticky-header > div { + overflow: hidden; + *zoom: 1; + width: 940px; + margin: 0 auto; + clear: both; + padding-top: 9px; +} +#sticky-header > div .logo { + float: left; + width: 26px; + height: 25px; + background: url(../images/dac_logo.png); + background-image: -webkit-image-set(url(../images/dac_logo.png) 1x, url(../images/dac_logo@2x.png) 2x); + z-index: 52; + position: relative; +} +#sticky-header > div .top { + float: left; + width: 38px; + height: 38px; + position: relative; + background: url(../images/styles/gototop.png); + z-index: 52; +} +#sticky-header > div .breadcrumb { + float: left; + padding: 0 0 0 10px; + border-left: 1px solid #d2d2d2; + line-height: 24px; + font-size: 14px; + position: relative; + top: 0px; + z-index: 52; +} +} @@ -4014,7 +4244,6 @@ EndColorStr='#ececec'); } .logo a { - width:123px; float:left; } @@ -4027,11 +4256,13 @@ EndColorStr='#ececec'); } -#header .logo-wear { +#header-wrap .logo.landing-logo { width:220px; margin:0; + padding:0; + margin-bottom:22px; } -#header .logo-wear img { +#header-wrap .logo.landing-logo img { padding:0 0 0 10px; } @@ -4103,7 +4334,7 @@ EndColorStr='#ececec'); #quicknav { float:none; clear:both; - margin-left:180px; + margin-left:0; margin-top:-30px; display:none; overflow:hidden; @@ -4118,6 +4349,10 @@ EndColorStr='#ececec'); padding:0; } +#quicknav ul li.about { + border-top:1px solid #9933CC; +} + #quicknav ul li.design { border-top:1px solid #33b5e5; } @@ -4447,7 +4682,9 @@ EndColorStr='#ececec'); } - +#landing h1 { + margin:17px 0 20px 0 !important; +} a.download-sdk { float:right; @@ -4458,11 +4695,11 @@ a.download-sdk { } #nav-x { - padding-top: 14px; + padding-top: 13px; } #nav-x .wrap { - min-height:34px; + min-height:32px; } #nav-x .wrap, @@ -4618,14 +4855,14 @@ a.download-sdk { /* Slideshow */ .slideshow-develop { - height: 300px; + height: 316px; width: 940px; position: relative; overflow:hidden; } .slideshow-develop .frame { width: 940px; - height: 300px; + height: 316px; } .slideshow-develop img.play { max-width:350px; @@ -4657,6 +4894,7 @@ a.download-sdk { padding:0; margin-bottom:10px; border:none; + font-size:24px; } .slideshow-develop .item { height: 300px; @@ -4804,53 +5042,6 @@ a.download-sdk { -/************ DISTRIBUTE HOMEPAGE ***************/ - -.marquee { - width: 760px; -} -.marquee .main-img { - float: left; - margin-top: 20px; - width: 490px; -} -.marquee .copy { - width: 270px; - float: left; - margin-top: 30px; -} -.distribute-features { - margin: 0; -} -.distribute-features ul { - margin: 0; -} -.distribute-features ul li { - list-style: none; - float: left; - border-top: 1px solid #9C0; - width: 220px; - margin-right: 50px; -} -.distribute-features ul li.last { - margin-right: 0px; -} - -.distribute-features .distribute-link li a { - color:red !important; -} - -.distribute-features .distribute-link li a, -.distribute-features .distribute-link li a:active { - color:#555 !important; -} - -.distribute-features .distribute-link li a:hover, -.distribute-features .distribute-link li a:hover * { - color:#7AA1B0 !important; -} - - /************ DEVELOP TOPIC CONTAINERS ************/ .landing-banner, @@ -4876,7 +5067,8 @@ a.download-sdk { margin-bottom:0; } .landing-banner h1 { - margin-top:0; + margin-top:16px; + padding-bottom:24px; } .landing-docs, .landing-banner { @@ -5028,3 +5220,2113 @@ a.download-sdk { .fullpage #footer { margin-top: -40px; } + +/************ DISTRIBUTE PAGES ******************/ + +.article-detail #body-content { + padding-top: 10px; +} + +/* A container for grid sets with uppercase h3 and rule */ +.dynamic-grid h3 { + font-size:14px; + line-height:21px; + color:#555; + text-transform:uppercase; + border-bottom:1px solid #CCC; + padding:8px 0 0 1px; + margin-bottom:14px; + clear:both; +} + +.top-right-float { + float: right; +} + +.clearfloat { + float: none; + clear: both; +} + +.border-img { + border: 1px solid #CCC; +} + +.center-img { + margin: auto; + text-align: center; +} +.center-img img { + margin-bottom: 15px; +} + +.figure img, .border-img { + margin-bottom: 15px; +} + +/************ RESOURCE CARDS ******************/ + +/* Resource cards, 12, 13, 16-col */ + +/* Basic card-styling with shadow */ +.resource-card { + border-radius: 1px; + box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.12); + background: #fefefe; +} + +/* Styling for background image including tinting and section icons in stacks */ +.card-bg { + display: block; + position: absolute; + vertical-align: top; + width: 100%; + left: 0; + top: 0; + background-size: cover; + background-repeat: no-repeat; + background-position: center; + background-image: url(../images/resource-card-default-android.jpg); +} +.card-bg:after { + content: ""; + display: block; + height: 100%; + width: 100%; + opacity: 1; + background: rgba(0, 0, 0, 0.2); + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; +} +.static .card-bg:after { + display:none; +} +.card-bg .card-section-icon { + position: absolute; + top: 50%; + width: 100%; + margin-top: -35px; + text-align: center; + padding-top: 65px; + z-index: 100; +} +.card-bg .card-section-icon .icon { + position: absolute; + left: 50%; + margin-left: -28px; + top: 0px; + width: 56px; + height: 56px; + background-repeat: no-repeat; + background-position: 50% 50%; + background-image: url(../images/stack-icon.png); +} +.card-bg .card-section-icon .section { + text-transform: uppercase; + color: white; + font-size: 14px; +} + +.card-info { + position: absolute; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + background: #fefefe; + padding: 4px 12px 6px 12px; +} +.card-info .section { + text-transform: uppercase; + color: #898989; + font-size: 12px; + margin-bottom: 1px; +} +.card-info .title { + color: #363636; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding-bottom: 5px; + margin-bottom: -2px; + font-size: 16px; +} +.card-info .description { + overflow: hidden; +} +.card-info .description .text { + color: #464646; + font: 13px/15px Roboto Condensed; + overflow: hidden; + width:100%; +} +.card-info .description .util { + position: absolute; + right: 5px; + bottom: 70px; /*-2px;*/ + opacity: 0; + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; +} +.card-info.empty-desc .title { + white-space: normal; + overflow: visible; +} +.card-info.empty-desc .description { + display: none; +} +/* Truncate card summaries at bounding box and + * and apply ellipsis at lower right */ +.ellipsis { + overflow: hidden; + float:right; + line-height: 15px; + width:100%; +} +.resource-card-6x6 .card-info .description .teddddddxt { + float:left; + position:relative; + margin-left:0; +} +.ellipsis:before { + content:""; + float: left; + width: 5px; + height:100%; +} +.ellipsis > *:first-child.text { + float: right; + width: 100% !important; + margin-left: -5px; +} +.ellipsis:after { + content: "\02026"; + height:17px; + padding-bottom:4px; + + box-sizing: content-box; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + + float: right; position: relative; + top: -16px; left: 100%; + width: 4em; margin-left: -4em; + padding-right: 5px; + + background: -webkit-gradient(linear, left top, right top, + from(rgba(255, 255, 255, 0)), to(white), color-stop(65%, white)); + background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); + background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); + background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); + background: linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); +} +.ellipsis:after { + font-style: normal; color: #aaa; + font-size:13px; + text-align: right; +} + +/* Flow Layout */ +.resource-flow-layout { + display: inline-block; +} +.resource-flow-layout .resource-card, .resource-flow-layout .resource-card-stack { + float: left; + position: relative; +} +.resource-flow-layout .resource-card-stack > .resource-card { + margin-right: 0px !important; +} +.resource-flow-layout:after { + content: "."; + display: block; + height: 0; + position:relative; + clear: both; + visibility: hidden; +} +.resource-card:hover { + cursor: pointer; +} +.static .resource-card:hover { + cursor: auto; +} +.resource-card:hover .card-bg:after { + opacity: 0; +} +/* disabled to make way for fade/ellipsis truncation, + and the plusone moves up. +.resource-card:hover .card-info .description .text { + padding-right: 70px; +} */ +.resource-card:hover .card-info .description .util { + opacity: 1; +} + +/* Carousel Layout */ +/* Carousel styles for landing page */ +.resource-carousel-layout { + margin: 20px 0 20px 0; + position: relative; + overflow: hidden; +} +.resource-carousel-layout .slideshow-prev, .resource-carousel-layout .slideshow-next { + display: none; +} +.resource-carousel-layout .pagination { + bottom: 0px; +} +.resource-carousel-layout .frame li { + position: relative; +} +.resource-carousel-layout .frame li .card-bg { + height: 300px; +} +.resource-carousel-layout .frame li .card-info { + padding: 7px 15px 0px 15px; + top: 300px; +} +.resource-carousel-layout .frame li .card-info .section { + font-size: 13px; + margin-bottom: 7px; +} +.resource-carousel-layout .frame li .card-info .title { + font-size: 25px; + margin-bottom: 2px; +} +.resource-carousel-layout .frame li .card-info .description { + font-family: 15px/16px Roboto Condensed, sans-serif; +} +.resource-carousel-layout .frame li .card-info .description .text { + height: 40px; +} +.resource-carousel-layout .frame li .card-info .description .util { + bottom:97px; + right:4px; +} + +/* Stack Layout */ +.resource-stack-layout { + display: inline-block; +} +.resource-stack-layout .resource-card-stack { + float: left; + position: relative; +} +.resource-stack-layout .resource-card { + margin-bottom: 20px; + display: block; + position: relative; +} +.resource-stack-layout .section-card-menu > .card-info .section, .resource-stack-layout .section-card > .card-info .title { + /*text-transform: uppercase;*/ + color: #898989; + font-size: 17px; + line-height: 24px; + margin-bottom: 6px; +} +.resource-stack-layout .section-card { + height: 284px; +} +.resource-stack-layout .section-card > .card-bg { + height: 192px; +} +.resource-stack-layout .section-card > .card-info { + padding: 4px 12px 6px 12px; + top: 192px; +} +.resource-stack-layout .section-card > .card-info .section { + display: none; +} +.resource-stack-layout .section-card > .card-info .title { + font-size: 17px; + border-bottom: 1px solid #959595; + padding-bottom: 0px; +} +.resource-stack-layout .section-card > .card-info .description { + font-size: 13px; + line-height: 15px; +} +.resource-stack-layout .section-card > .card-info .description .text { + height: 30px; +} +.resource-stack-layout .related-card { + height: 90px; +} +.resource-stack-layout .related-card > .card-bg { + left: 0; + top: 0; + width: 90px; + height: 100%; + position: absolute; + display: block; +} +.resource-stack-layout .related-card > .card-info { + left: 90px; + padding: 4px 12px 4px 12px; +} +.resource-stack-layout .related-card > .card-info .section { + font-size: 12px; + margin-bottom: 1px; + display: none; +} +.resource-stack-layout .related-card > .card-info .title { + font-size: 16px; + margin-bottom: -2px; + white-space: normal; + overflow: visible; + text-overflow: ellipsis; +} +.resource-stack-layout .related-card > .card-info .title:after { + content: url(../images/link-out.png); + display: block; +} +.resource-stack-layout .related-card > .card-info .description { + display: none; +} +.resource-stack-layout .section-card-menu { + /* Flexible height */ + display: block; + height: auto; + width: auto; +} +.resource-stack-layout .section-card-menu .card-bg { + height: 155px; + /* Flexible height */ + position: relative; + display: inline-block; + vertical-align: top; +} +.resource-stack-layout .section-card-menu .card-info { + padding: 4px 12px 0px 12px; + /* Flexible height */ + position: relative; + left: auto; + top: auto; + right: auto; + bottom: auto; +} +.resource-stack-layout .section-card-menu .card-info ul { + list-style: none; + margin: 0; +} +.resource-stack-layout .section-card-menu .card-info ul li { + list-style: none; + margin: 0; + padding: 15px 0; + border-top-width: 1px; + border-top-style: solid; + border-top-color: #959595; +} +.resource-stack-layout .section-card-menu .card-info ul li a, .resource-stack-layout .section-card-menu .card-info ul li a:focus, .resource-stack-layout .section-card-menu .card-info ul li a:link, .resource-stack-layout .section-card-menu .card-info ul li a:visited, .resource-stack-layout .section-card-menu .card-info ul li a:active, .resource-stack-layout .section-card-menu .card-info ul li a:hover { + color: #363636 !important; +} +.resource-stack-layout .section-card-menu .card-info ul li:first-child { + border-top: none; +} +.resource-stack-layout .section-card-menu .card-info ul li:hover .title:after { + opacity: 1; + -webkit-transition: opacity 0.5s; + -moz-transition: opacity 0.5s; + -o-transition: opacity 0.5s; + transition: opacity 0.5s; +} +.resource-stack-layout .section-card-menu .card-info ul li:hover .description { + max-height: 30px; + opacity: 1; + -webkit-transition: max-height 0.5s, opacity 1s; + -moz-transition: max-height 0.5s, opacity 1s; + -o-transition: max-height 0.5s, opacity 1s; + transition: max-height 0.5s, opacity 1s; +} +.resource-stack-layout .section-card-menu .card-info .title { + font-size: 16px; + margin-bottom: -2px; + position: relative; +} +.resource-stack-layout .section-card-menu .card-info .title:after { + background: url(../images/stack-arrow-right.png); + content: ''; + opacity: 0; + -webkit-transition: opacity 0.25s; + -moz-transition: opacity 0.25s; + -o-transition: opacity 0.25s; + transition: opacity 0.25s; + position: absolute; + right: 0px; + top: 3px; + width: 10px; + height: 15px; +} +.resource-stack-layout .section-card-menu .card-info .title.more { + text-transform: uppercase; + color: #898989; + display: inline-block; +} +.resource-stack-layout .section-card-menu .card-info .title.more:after { + background: url(../images/stack-arrow-right.png); + content: ''; + display: block; + position: absolute; + right: -20px; + top: 3px; + width: 10px; + height: 15px; +} +.resource-stack-layout .section-card-menu .card-info .description { + max-height: 0px; + opacity: 0; + overflow: hidden; + font-size: 13px; + line-height: 15px; + /* Hover off */ + -webkit-transition: max-height 0.5s, opacity 0.5s; + -moz-transition: max-height 0.5s, opacity 0.5s; + -o-transition: max-height 0.5s, opacity 0.5s; + transition: max-height 0.5s, opacity 0.5s; +} +.resource-stack-layout .section-card-menu .card-info .description .text { + height: 30px; +} +.resource-stack-layout:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +/* Generate the flow layout styles for a 3-column 16-col span */ +.resource-flow-layout.col-16 { + margin: 0 -14px 0 0; + width: 954px; +} +.resource-flow-layout.col-16 .resource-card, .resource-flow-layout.col-16 .resource-card-stack { + margin: 0 14px 20px 0; +} +.resource-flow-layout.col-16 .resource-card-row-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-16 .resource-card-col-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-16 .resource-card-3x6 { + width: 145px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-3x12 { + width: 145px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-3x18 { + width: 145px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-6x6 { + width: 304px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-6x12 { + width: 304px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-6x18 { + width: 304px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-9x6 { + width: 463px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-9x12 { + width: 463px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-9x18 { + width: 463px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-12x6 { + width: 622px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-12x12 { + width: 622px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-12x18 { + width: 622px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-15x6 { + width: 781px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-15x12 { + width: 781px; + height: 588px; +} +.resource-flow-layout.col-16 .resource-card-15x18 { + width: 781px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-18x6 { + width: 940px; + height: 284px; +} +.resource-flow-layout.col-16 .resource-card-18x12 { + width: 940px; + height: 420px; +} +.resource-flow-layout.col-16 .resource-card-18x18 { + width: 940px; + height: 892px; +} +.resource-flow-layout.col-16 .resource-card-3x2 { + width: 145px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-3x2x3 { + width: 145px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-3x3 { + width: 145px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-3x3x2 { + width: 145px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-6x2 { + width: 304px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-6x2x3 { + width: 304px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-6x3 { + width: 304px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-6x3x2 { + width: 304px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-9x2 { + width: 463px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-9x2x3 { + width: 463px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-9x3 { + width: 463px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-9x3x2 { + width: 463px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-12x2 { + width: 622px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-12x2x3 { + width: 622px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-12x3 { + width: 622px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-12x3x2 { + width: 622px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-15x2 { + width: 781px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-15x2x3 { + width: 781px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-15x3 { + width: 781px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-15x3x2 { + width: 781px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-16 .resource-card-18x2 { + width: 940px; + height: 95px; +} +.resource-flow-layout.col-16 .resource-card-18x2x3 { + width: 940px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-16 .resource-card-18x3 { + width: 940px; + height: 142px; +} +.resource-flow-layout.col-16 .resource-card-18x3x2 { + width: 940px; + height: 138px; + margin-bottom: 8px; +} + +/* Generate the flow layout styles for a 3-column 16-col span */ +.resource-flow-layout.col-12 { + margin: 0 -14px 0 0; + width: 714px; +} + +.resource-flow-layout.col-12 .resource-card, .resource-flow-layout.col-12 .resource-card-stack { + margin: 0 14px 20px 0; +} +.resource-flow-layout.col-12 .resource-card-row-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-12 .resource-card-col-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-12 .resource-card-3x6 { + width: 105px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-3x12 { + width: 105px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-3x18 { + width: 105px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-6x6 { + width: 224px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-6x12 { + width: 224px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-6x18 { + width: 224px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-9x6 { + width: 343px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-9x12 { + width: 343px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-9x18 { + width: 343px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-12x6 { + width: 462px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-12x12 { + width: 462px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-12x18 { + width: 462px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-15x6 { + width: 581px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-15x12 { + width: 581px; + height: 588px; +} +.resource-flow-layout.col-12 .resource-card-15x18 { + width: 581px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-18x6 { + width: 700px; + height: 284px; +} +.resource-flow-layout.col-12 .resource-card-18x12 { + width: 700px; + height: 420px; +} +.resource-flow-layout.col-12 .resource-card-18x18 { + width: 700px; + height: 892px; +} +.resource-flow-layout.col-12 .resource-card-3x2 { + width: 105px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-3x2x3 { + width: 105px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-3x3 { + width: 105px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-3x3x2 { + width: 105px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-6x2 { + width: 224px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-6x2x3 { + width: 224px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-6x3 { + width: 224px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-6x3x2 { + width: 224px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-9x2 { + width: 343px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-9x2x3 { + width: 343px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-9x3 { + width: 343px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-9x3x2 { + width: 343px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-12x2 { + width: 462px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-12x2x3 { + width: 462px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-12x3 { + width: 462px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-12x3x2 { + width: 462px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-15x2 { + width: 581px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-15x2x3 { + width: 581px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-15x3 { + width: 581px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-15x3x2 { + width: 581px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-12 .resource-card-18x2 { + width: 700px; + height: 95px; +} +.resource-flow-layout.col-12 .resource-card-18x2x3 { + width: 700px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-12 .resource-card-18x3 { + width: 700px; + height: 142px; +} +.resource-flow-layout.col-12 .resource-card-18x3x2 { + width: 700px; + height: 138px; + margin-bottom: 8px; +} + +/* Generate the flow layout styles for a 3-column 13-col span */ + +.resource-flow-layout.col-13 { + margin: 0 -14px 0 0; + width: 774px; +} +.resource-flow-layout.col-13 .resource-card, .resource-flow-layout.col-13 .resource-card-stack { + margin: 0 14px 20px 0; +} +.resource-flow-layout.col-13 .resource-card-row-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-13 .resource-card-col-stack-last { + margin-bottom: 0px !important; +} +.resource-flow-layout.col-13 .resource-card-3x6 { + width: 115px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-3x12 { + width: 115px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-3x18 { + width: 115px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-6x6 { + width: 244px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-6x12 { + width: 244px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-6x18 { + width: 244px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-9x6 { + width: 373px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-9x12 { + width: 373px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-9x18 { + width: 373px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-12x6 { + width: 502px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-12x12 { + width: 502px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-12x18 { + width: 502px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-15x6 { + width: 631px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-15x12 { + width: 631px; + height: 588px; +} +.resource-flow-layout.col-13 .resource-card-15x18 { + width: 631px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-18x6 { + width: 760px; + height: 284px; +} +.resource-flow-layout.col-13 .resource-card-18x12 { + width: 760px; + height: 420px; +} +.resource-flow-layout.col-13 .resource-card-18x18 { + width: 760px; + height: 892px; +} +.resource-flow-layout.col-13 .resource-card-3x2 { + width: 115px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-3x2x3 { + width: 115px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-3x3 { + width: 115px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-3x3x2 { + width: 115px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-6x2 { + width: 244px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-6x2x3 { + width: 244px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-6x3 { + width: 244px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-6x3x2 { + width: 244px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-9x2 { + width: 373px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-9x2x3 { + width: 373px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-9x3 { + width: 373px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-9x3x2 { + width: 373px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-12x2 { + width: 502px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-12x2x3 { + width: 502px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-12x3 { + width: 502px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-12x3x2 { + width: 502px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-15x2 { + width: 631px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-15x2x3 { + width: 631px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-15x3 { + width: 631px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-15x3x2 { + width: 631px; + height: 138px; + margin-bottom: 8px; +} +.resource-flow-layout.col-13 .resource-card-18x2 { + width: 760px; + height: 95px; +} +.resource-flow-layout.col-13 .resource-card-18x2x3 { + width: 760px; + height: 90px; + margin-bottom: 7px; +} +.resource-flow-layout.col-13 .resource-card-18x3 { + width: 760px; + height: 142px; +} +.resource-flow-layout.col-13 .resource-card-18x3x2 { + width: 760px; + height: 138px; + margin-bottom: 8px; +} + +/* + The following are styles for cards in the flowlayout above, styled by the number of rows they span +*/ +/* Single row items, might be simpler to just apply a class */ +.resource-card-3x6 > .card-bg, .resource-card-6x6 > .card-bg, .resource-card-9x6 > .card-bg, .resource-card-12x6 > .card-bg, .resource-card-15x6 > .card-bg, .resource-card-18x6 > .card-bg { + height: 192px; +} +.resource-card-3x6 > .card-info, .resource-card-6x6 > .card-info, .resource-card-9x6 > .card-info, .resource-card-12x6 > .card-info, .resource-card-15x6 > .card-info, .resource-card-18x6 > .card-info { + padding: 4px 12px 6px 12px; + top: 192px; +} +.resource-card-3x6 > .card-info .section, .resource-card-6x6 > .card-info .section, .resource-card-9x6 > .card-info .section, .resource-card-12x6 > .card-info .section, .resource-card-15x6 > .card-info .section, .resource-card-18x6 > .card-info .section { + font-size: 12px; + margin-bottom: 1px; +} +.resource-card-3x6 > .card-info .title, .resource-card-6x6 > .card-info .title, .resource-card-9x6 > .card-info .title, .resource-card-12x6 > .card-info .title, .resource-card-15x6 > .card-info .title, .resource-card-18x6 > .card-info .title { + font-size: 16px; + margin-bottom: -2px; +} +.resource-card-3x6 > .card-info .description, .resource-card-6x6 > .card-info .description, .resource-card-9x6 > .card-info .description, .resource-card-12x6 > .card-info .description, .resource-card-15x6 > .card-info .description, .resource-card-18x6 > .card-info .description { + font-size: 13px; + line-height: 15px; +} +.resource-card-3x6 > .card-info .description .text, .resource-card-6x6 > .card-info .description .text, .resource-card-9x6 > .card-info .description .text, .resource-card-12x6 > .card-info .description .text, .resource-card-15x6 > .card-info .description .text, .resource-card-18x6 > .card-info .description .text { + height: 30px; +} + +/* Double row items */ +.resource-card-3x12 > .card-bg, .resource-card-6x12 > .card-bg, .resource-card-9x12 > .card-bg, .resource-card-12x12 > .card-bg, .resource-card-15x12 > .card-bg, .resource-card-18x12 > .card-bg { + height: 320px; +} +.resource-card-3x12 > .card-info, .resource-card-6x12 > .card-info, .resource-card-9x12 > .card-info, .resource-card-12x12 > .card-info, .resource-card-15x12 > .card-info, .resource-card-18x12 > .card-info { + padding: 4px 12px 6px 12px; + top: 320px; +} +.resource-card-3x12 > .card-info .section, .resource-card-6x12 > .card-info .section, .resource-card-9x12 > .card-info .section, .resource-card-12x12 > .card-info .section, .resource-card-15x12 > .card-info .section, .resource-card-18x12 > .card-info .section { + font-size: 12px; + margin-bottom: 1px; +} +.resource-card-3x12 > .card-info .title, .resource-card-6x12 > .card-info .title, .resource-card-9x12 > .card-info .title, .resource-card-12x12 > .card-info .title, .resource-card-15x12 > .card-info .title, .resource-card-18x12 > .card-info .title { + font-size: 16px; + margin-bottom: -2px; + white-space: normal; +} +.resource-card-3x12 > .card-info .description, .resource-card-6x12 > .card-info .description, .resource-card-9x12 > .card-info .description, .resource-card-12x12 > .card-info .description, .resource-card-15x12 > .card-info .description, .resource-card-18x12 > .card-info .description { + font-size: 13px; + line-height: 15px; +} + +/* 1/3 row items */ +.resource-card-3x2 > .card-bg, .resource-card-6x2 > .card-bg, .resource-card-9x2 > .card-bg, .resource-card-12x2 > .card-bg, .resource-card-15x2 > .card-bg, .resource-card-18x2 > .card-bg { + left: 0; + top: 0; + width: 90px; + height: 100%; + position: absolute; + display: block; +} +.resource-card-3x2 > .card-info, .resource-card-6x2 > .card-info, .resource-card-9x2 > .card-info, .resource-card-12x2 > .card-info, .resource-card-15x2 > .card-info, .resource-card-18x2 > .card-info { + left: 90px; + padding: 4px 12px 4px 12px; + height: 80px; + overflow: hidden; +} +.resource-card-3x2 > .card-info .section, .resource-card-6x2 > .card-info .section, .resource-card-6x3 > .card-info .section, .resource-card-9x2 > .card-info .section, .resource-card-12x2 > .card-info .section, .resource-card-15x2 > .card-info .section, .resource-card-18x2 > .card-info .section { + font-size: 12px; + margin-bottom: 1px; + /* display: none; */ +} +.resource-card-3x2 > .card-info .title, .resource-card-6x2 > .card-info .title, .resource-card-9x2 > .card-info .title, .resource-card-12x2 > .card-info .title, .resource-card-15x2 > .card-info .title, .resource-card-18x2 > .card-info .title { + font-size: 16px; + margin-bottom: -2px; + white-space: normal; + overflow: visible; + text-overflow: ellipsis; +} +.resource-card-3x2 > .card-info .title:after, .resource-card-6x2 > .card-info .title:after, .resource-card-9x2 > .card-info .title:after, .resource-card-12x2 > .card-info .title:after, .resource-card-15x2 > .card-info .title:after, .resource-card-18x2 > .card-info .title:after { + /* content: url(../images/link-out.png); */ + display: block; +} +.resource-card-3x2 > .card-info .description, .resource-card-6x2 > .card-info .description, .resource-card-9x2 > .card-info .description, .resource-card-12x2 > .card-info .description, .resource-card-15x2 > .card-info .description, .resource-card-18x2 > .card-info .description { + display: none; +} + + +/* Override to show the description instead of the content section */ +.no-section .resource-card-3x2 > .card-info .section, +.no-section .resource-card-6x2 > .card-info .section { + display: none; +} +.no-section .resource-card-3x2 > .card-info .description, +.no-section .resource-card-6x2 > .card-info .description { + display: block; +} + +/* 1/2 row items */ +.resource-card-3x3 > .card-bg, .resource-card-6x3 > .card-bg, .resource-card-9x3 > .card-bg, .resource-card-12x3 > .card-bg, .resource-card-15x3 > .card-bg, .resource-card-18x3 > .card-bg { + left: 0; + top: 0; + width: 90px; + height: 100%; + position: absolute; + display: block; +} +.resource-card-3x3 > .card-info, .resource-card-6x3 > .card-info, .resource-card-9x3 > .card-info, .resource-card-12x3 > .card-info, .resource-card-15x3 > .card-info, .resource-card-18x3 > .card-info { + left: 90px; + padding: 4px 12px 0px 12px; +} +.resource-card-3x3 > .card-info .section, .resource-card-6x3 > .card-info .section, .resource-card-9x3 > .card-info .section, .resource-card-12x3 > .card-info .section, .resource-card-15x3 > .card-info .section, .resource-card-18x3 > .card-info .section { + font-size: 12px; + margin-bottom: 1px; + display: none; +} +.resource-card-3x3 > .card-info .title, .resource-card-6x3 > .card-info .title, .resource-card-9x3 > .card-info .title, .resource-card-12x3 > .card-info .title, .resource-card-15x3 > .card-info .title, .resource-card-18x3 > .card-info .title { + font-size: 16px; + margin-bottom: -2px; + white-space: normal; + overflow: visible; +} +.resource-card-3x3 > .card-info .description .text, .resource-card-6x3 > .card-info .description .text, .resource-card-9x3 > .card-info .description .text, .resource-card-12x3 > .card-info .description .text, .resource-card-15x3 > .card-info .description .text, .resource-card-18x3 > .card-info .description .text { + font-size: 12px; + line-height: 15px; + padding-right: 0px !important; + height: 80px; +} +.resource-card-3x3 > .card-info .description .util, .resource-card-6x3 > .card-info .description .util, .resource-card-9x3 > .card-info .description .util, .resource-card-12x3 > .card-info .description .util, .resource-card-15x3 > .card-info .description .util, .resource-card-18x3 > .card-info .description .util { + display: none; +} +/* placement of plusone */ +.resource-card-6x12 > .card-info .description .util, .resource-card-9x12 > .card-info .description .util, .resource-card-12x12 > .card-info .description .util, .resource-card-15x12 > .card-info .description .util { + bottom:2px; +} +.resource-card-18x12 > .card-info .description .util { + bottom:2px; +} +/* Overrides for col-16 6x6 cards linking to local content on landing pages. + Suppresses "section" and puts the title above a hairline rule. */ +.landing .card-info .section, .resource-flow-layout.col-16.landing .resource-card-9x6 .card-info .section { + display:none; +} +.landing .card-info .title { + color: #898989; + font-size: 17px; + line-height: 24px; + margin-bottom: 6px; + border-bottom: 1px solid #959595; + padding-bottom: 0px; +} +.landing .card-info .description { + font-size: 13px; + line-height: 15px; +} +.landing .card-info .description .text { +height:30px; +} +.landing .resource-card-6x6 > .card-info .description .util, .landing .resource-card-9x6 > .card-info .description .util { + bottom:2px; +} +/* + Generate a resource stack layout for a 3 column widget spanning 16 grid cols +*/ +.resource-stack-layout.col-16 { + margin: 0 -14px 0 0; + width: 954px; +} +.resource-stack-layout.col-16 .resource-card-stack { + margin: 0 14px 0 0; + width: 304px; +} + +/* Example of card menu tinting */ +.resource-widget[data-section=distribute\/tools] .section-card-menu +.card-bg:after { + background: rgba(126, 55, 148, 0.4) !important; +} +.resource-widget[data-section=distribute\/tools] .section-card-menu +.card-section-icon .icon { + background-color: #7e3794 !important; +} +.resource-widget[data-section=distribute\/tools] .section-card-menu +.card-info ul li { + border-top-color: #7e3794 !important; +} + +/* tinting for stacks */ + +div.jd-descr > .resource-widget[data-section=distribute\/tools] +.section-card-menu .card-info ul li { + border-top-color: #7e3794 !important; +} + + + +/** + * UTILITIES + */ + + +.border-box { + box-sizing: border-box; +} + +.vertical-center-outer { + display: table; + height: 100%; + width: 100%; +} + +.vertical-center-inner { + display: table-cell; + vertical-align: middle; +} + +/** + * TYPE STYLES + */ + +.landing-h1 { + font-weight: 100; + font-size: 60px; + line-height: 78px; + text-align: center; + letter-spacing: -1px; +} + +.landing-pre-h1 { + font-weight: 400; + font-size: 28px; + color: #93B73F; + line-height: 36px; + text-align: center; + letter-spacing: -1px; + text-transform: uppercase; + +} + +.landing-h1.hero { + text-align: left; +} + +.landing-h2 { + font-weight: 300; + font-size: 42px; + line-height: 64px; + text-align: center; +} + +.landing-subhead { + color: #999999; + font-size: 20px; + line-height: 28px; + font-weight:300; + text-align: center; +} +.landing-subhead.hero { + text-align: left; + color: white; +} + +.landing-hero-description { + text-align: left; + margin: 1em 0; +} + +.landing-hero-description p { + font-weight: 300; + margin: 0; + font-size: 18px; + line-height: 24px; +} + +.landing-body .landing-small { + font-size: 14px; + line-height: 19px; +} + +.landing-body.landing-align-center { + text-align: center; +} + +.landing-align-left { + text-align: left; +} + +/** + * LAYOUT + */ + +#body-content, +.fullpage, +#jd-content, +.jd-descr, +.landing-body-content { + height: 100%; +} + +.landing-section { + padding: 80px 10px 80px; + width: 100%; + margin-left: -10px; + text-rendering: optimizeLegibility; +} + +#extending-android-to-wearables { + padding-top: 30px; +} + +.landing-short-section { + padding: 40px 10px 28px; +} + +.landing-gray-background { + background-color: #e9e9e9; +} + +.landing-white-background { + background-color: white; +} + +.landing-red-background { + color: white; + background-color: hsl(8, 70%, 54%); +} + +.landing-subhead-red { + color: hsl(8, 71%, 84%); + text-align: left; +} + +.landing-subhead-red p { + margin-top: 20px; +} + +.landing-hero-container { + height: 100%; +} + + +.preview-hero { + height: calc(100% - 110px); + min-height: 504px; + margin-top: -5px; + padding-top: 0; + padding-bottom: 0; + background-image: url(../../preview/images/hero.jpg); + background-size: cover; + background-position: right center; + color: white; + position: relative; + overflow: hidden; +} + +.wear-hero { + height: calc(100% - 110px); + min-height: 504px; + margin-top: -5px; + padding-top: 0; + padding-bottom: 0; + background-image: url(../../wear/images/hero.jpg); + background-size: cover; + background-position: top center; + color: white; + position: relative; + overflow: hidden; +} + +.tv-hero { + height: calc(100% - 110px); + min-height: 504px; + margin-top: -5px; + padding-top: 0; + padding-bottom: 0; + background-image: url(../../tv/images/hero.jpg); + background-size: cover; + background-position: right center; + color: white; + position: relative; + overflow: hidden; +} + +.auto-hero { + height: calc(100% - 110px); + min-height: 504px; + margin-top: -5px; + padding-top: 0; + padding-bottom: 0; + background-image: url(../../auto/images/hero.jpg); + background-size: cover; + background-position: right center; + color: white; + position: relative; + overflow: hidden; +} + +.landing-hero-scrim { + background: black; + opacity: .2; + position: absolute; + width: 100%; + height: 100%; + margin-left: -10px; +} + +.landing-hero-wrap { + margin: 0 auto; + width: 940px; + clear: both; + height: 100%; + position: relative; +} + +.landing-section-header { + margin-bottom: 40px; +} + +.landing-hero-wrap .landing-section-header { + margin-bottom: 16px; +} + +.landing-body { + font-size: 18px; + line-height: 24px; +} + +.landing-button { + white-space: nowrap; + display: inline-block; + padding: 16px 32px; + font-size: 18px; + font-weight: 500; + line-height: 24px; + cursor: pointer; + color: white; + -webkit-user-select: none; + -moz-user-select: none; + -o-user-select: none; + user-select: none; + -webkit-transition: .2s background-color ease-in-out; + -moz-transition: .2s background-color ease-in-out; + -o-transition: .2s background-color ease-in-out; + transition: .2s background-color ease-in-out; +} + +.landing-primary { + background-color: hsl(8, 70%, 44%); + color: #f8f8f8; +} + +.landing-button.landing-primary:hover { + background-color: hsl(8, 70%, 36%); +} + +.landing-button.landing-primary:active { + background-color: hsl(8, 70%, 30%); +} + +.landing-button.landing-secondary { + background-color: #2faddb; +} + +.landing-button.landing-secondary:hover { + background-color: #09c; +} + +.landing-button.landing-secondary:active { + background-color: #3990ab; +} + +a.landing-button, +a.landing-button:hover, +a.landing-button:visited { + color: white !important; +} + +.landing-video-link { + white-space: nowrap; + display: inline-block; + padding: 16px 32px 16px 82px; + font-size: 18px; + font-weight: 400; + line-height: 24px; + cursor: pointer; + color: hsla(0, 0%, 100%, .8); + -webkit-user-select: none; + -moz-user-select: none; + -o-user-select: none; + user-select: none; + -webkit-transition: .2s color ease-in-out; + -moz-transition: .2s color ease-in-out; + -o-transition: .2s color ease-in-out; + transition: .2s color ease-in-out; +} + +.landing-video-link:before { + height: 64px; + width: 64px; + display: inline-block; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAFuklEQVR42u2dXWgcVRSAV9LWtBBTTZVWUhNqEQtq1QeroDRKFRFsROqTYPuo+JCiIoJKFC0USqlUfCiowRcfrBgVUUElefAPkW5T8aeaGn9aRbFsjP0x2cx8PuRMvFxmdjeb2Z17Z8+B85DsZPbO+eaec3/OPSkABdXsVI2gABSAqgJQAKoKQAGoKgAFoKoAFICqAlAAqgpAAai6DqDRAiwDeoFtwB7gPaAInABKwKToCWAMeB/YDdwJrAWWNLh9+QMAXABsBQ4A3wFTwAxQBmaBAAhjNJDPy3L938BXwAvArUCHAkh+kCXAVcA+YBw4bRg7MngtkgTlDPA98CywHmhTAP8/xCbgVeAvMZZpwDQllN7xB/AysKGlAQAXAvuBkzW85UVgCBgENlfQQbmuWAXELPAnsAvoaikAQBtwh/j3coLhS2LIfqCzzu/plL8fkvvFgZiR4L2lHrfkHQBgpQTFUwmGnwC212v0KjC2y/3jQPwDPA+05xYAcBHwubx1YZzhC02QBBBRbxgBzssdAOBy4JgRZE0ZTPuNr7FHDCbEhqNAd24AAN0yUbID7QSwsZChABut3hANXY8Bq70HIMb/Ocb4w81+66v0hmGrN0QQ1ngLQJYRvpWHMWWo4KDIaMnuCcVKgdlZAGL8t2J8vpPGrwChDLyWBMFlAA8D0z4ZvwKEs8D93gCQEc9Jy/jFgkdizaRDGUSs8wXAu1bQLQE9ngHosWbPAXDQeQAypT9rBd3+gociyxi2K9riLABZUj5iuZ6RgsciM2OzFxw2A7JrAO6VwGtKTwpG+Anoy9AVmb3gDHCPcwCAFcChRox6jPu9CazMeFQUAKNRL3AJwE2yopjq228BQPZ/d2bcCyaBTa4BeNGa8Q6naIA4GQWubiKEYWvBbp8zAGQt5VfL/fQ3GEAkTzXDLVkjokA2k5a7AuA2GaLNj/tTfvhq0pQgbcwLQtlQusYVALtlzSR191MjADNI9zbJDZWBR10BMGr5/4GMADQ0SAMDlht62xUAxy0AmzMEEMnhtIO0ZF2YAH5wITd0hQw/5wE04M1bjDyXZpC2hqMlYGnWAHqBf40APOEYgChI35VSWyasWfGqrAH0WVkOIw4CSC1IG2tDoSy7XJE1gPs8ArDoIG0BmJGk30wBDHgGYFFBOgbAtqwB7GxxAHerC8rOBU0Dt2gQzjYIb8gawDor+6HVhqFdrkzEwhabiAVOTMSkUb+06FLEUVfWgj5q0cW4g64AeNo66ZLlcnTDNmesBN4y8KArAG6QU42ttCEzBVzpCoAO4EfLDeV5SzIEvgHaXdqUP2BlQud1Ux55zj2uZUX02cPRnKalRLmu17qYmPWF5YbymJgVAh8Ay5wCII3ZEZOYm6fURGT2u9X43Mnk3CDHybmfmRVYXExPv9nKEcpLejqSC3SjdY2TBzTesHqB7wc0onTEV2KucxLApXKkJy9HlAI5anuJFwCkYQ/EuCJfD+mdBnYkXOssgHY53un7MdVZ4CVgqVcADAhjMafkfTioHc14P04yvvMApIEXy5F/+7S8y6UKolPyR4BVVf7Wi2IdawwIPhTrmAW+rmZ8bwBIQ7vloXwoVzNWS6UUrwAYy9YfOlqwKZDkgneA5Qu4l3cly84F9sqGhislywLmaozuYoGFXr0DII1ukxP1hxJ6QzR7HqLxRfumZaRzXZ3f4XXZyi7gCeB3kqsnzs+kSb9s5XHgMeD8RTxDLgq3rmeuYuFvNYCoR8wqujNi+L3UWBcu9wAMt3QZ8LiMlk5RuU50teq6kcEDgTolveIRYHUQBOek1O5cFu/ukLz7/ZJgNSm+OirebWpgaPS7slxfAr4EngGuX8jopqUBxGzyrAVuB54EXgc+lV4yLhO8cfn5E+ZqUD8kBu9sQvv0Hzj4rmoEBaAAVBWAAlBVAApAVQEoAFUFoABUFYACUFUACkC1CfofXVRJocowZVYAAAAASUVORK5CYII=); + background-size: contain; + position: absolute; + content: ""; + opacity: .7; + margin-top: -19px; + margin-left: -64px; + -webkit-transition: .2s opacity ease-in-out; + -moz-transition: .2s opacity ease-in-out; + -o-transition: .2s opacity ease-in-out; + transition: .2s opacity ease-in-out; +} + +.landing-video-link:hover { + color: hsla(0, 0%, 100%, 1); +} + +.landing-video-link:hover:before { + opacity: 1; +} + +.landing-social-image { + float: left; + margin-right: 14px; + height: 64px; + width: 64px; +} + +.landing-social-copy { + padding-left: 78px; +} + +.landing-scroll-down-affordance { + position: absolute; + bottom: 0; + width: 100%; + text-align: center; + z-index: 10; +} + +.landing-down-arrow { + padding: 24px; + display: inline-block; + opacity: .5; + -webkit-transition: .2s opacity ease-in-out; + -moz-transition: .2s opacity ease-in-out; + -o-transition: .2s opacity ease-in-out; + transition: .2s opacity ease-in-out; + + -webkit-animation-name: pulse-opacity; + -webkit-animation-duration: 4s; +} + +.landing-down-arrow:hover { + opacity: 1; +} + +.landing-down-arrow img { + height: 28px; + width: 28px; + margin: 0 auto; + display: block; +} + +.landing-divider { + display: inline-block; + height: 2px; + background-color: white; + position: relative; + margin: 10px 0; +} + +/* 3 CLOLUMN LAYOUT */ + +.landing-breakout { + margin-top: 40px; + margin-bottom: 40px; +} + +.landing-breakout img { + margin-bottom: 20px; +} + +.landing-partners img { + margin-bottom: 20px; +} + +.landing-breakout p { + padding: 0 23px; +} + +.landing-breakout.landing-partners img { + margin-bottom: 20px; +} + +.col-3-wide { + display: inline; + float: left; + margin-left: 10px; + margin-right: 10px; +} + +.col-3-wide { + width: 302px; +} + +/** + * ANIMATION + */ + +@-webkit-keyframes pulse-opacity { + 0% { + opacity: .5; + } + 20% { + opacity: .5; + } + 40% { + opacity: 1; + } + 60% { + opacity: .5; + } + 80% { + opacity: 1; + } + 100% { + opacity: .5; + } +} + + + +/** + * VIDEO + */ + +#video-container { + display:none; + position:fixed; + top:0; + left:-10px; + width:102%; + height:100%; + background-color:rgba(0,0,0,0.7); + z-index:99; +} + +#video-frame { + width:940px; + height:526.4px; + margin:80px auto 0; + display:none; +} + +.video-close { +cursor: pointer; +position: relative; +left: 940px; +top: 0; +pointer-events: all; +} + +#icon-video-close { +background-image: url("../images/close.png"); +background-position: 0 0; +height: 36px; +width: 36px; +display:block; +} + + + + +/****************** +Styles for d.a.c/index: +*******************/ + + + +/* Generic full screen carousel styling to be used across pages. */ +.fullscreen-carousel { + margin: 0 -10px; + width: 100%; + overflow: hidden; + position: relative; +} + +.fullscreen-carousel-content { + width: 100%; + height: 100%; + position: relative; + display: table; /* For vertical centering */ +} + +.fullscreen-carousel .vcenter { + display: table-cell; + vertical-align: middle; + position: relative; +} + +.fullscreen-carousel .vcenter > div { + margin: 10px auto; +} + +/* Styles for the full-bleed hero image type. */ +.fullscreen-carousel .hero, .fullscreen-carousel .hero h1 { + color: #fff; +} + +.fullscreen-carousel .hero h1 { + font-weight: 300; + font-size: 60px; + line-height: 68px; + letter-spacing: -1px; + margin-top: 0; +} + +.fullscreen-carousel .hero p { + font-weight: 300; + font-size: 18px; + line-height: 24px; + -webkit-font-smoothing: antialiased; +} + +.fullscreen-carousel .hero .hero-bg { + background-size: cover; + width: 100%; + height: 100%; + position: absolute; + left: 0px; + top: 0px; +} + + +/* Full screen carousel styling for the resource flow layout type of content */ +.fullscreen-carousel .resource-flow-layout:after { + height: 0; /* Dont know why this is set at 10 in default.css */ +} + +.fullscreen-carousel .resource-flow-layout { + margin-bottom: 20px; +} + + + +/* Generic Tab carousel styling to be used across multiple pages. */ + +.tab-carousel .tab-nav { + list-style: none; + position: relative; + text-align: center; +} + +.tab-carousel .tab-nav li { + display: inline-block; + font-size: 22px; + font-weight: 400; + line-height: 50px; + list-style: none; + margin: 0; + padding: 0 25px; + position: relative; +} + +.tab-carousel .tab-nav li a, +.tab-carousel .tab-nav li a:hover { + color: #333 !important; + padding: 10px 10px 13px 10px; + position: relative; + z-index: 1000; +} + +.tab-carousel .tab-nav li:after { + background: #ddd; + bottom: 0; + content: ''; + height: 4px; + left: 0; + position: absolute; + width: 100%; + z-index: 0; +} + +.tab-carousel .tab-nav .highlight { + position: absolute; + height: 4px; + width: 100px; + bottom: 0; + background: #33b5e5; +} + +.tab-carousel .tab-carousel-content { + position: relative; + overflow: hidden; + white-space: nowrap; +} + +.tab-carousel .tab-carousel-content [data-tab] { + display: inline-block; + white-space: normal; +} + + + +/* + Resource styling for the tab carousel. The tab carousel contains either + a 3 column layout of resources or a single full-width resource. The + latter has the 18x12 class applied to it and can be styled differently + that way. +*/ + +.tab-carousel .resource .image { + width: 100%; + height: 250px; + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; +} + +.tab-carousel .resource .info .title { + font-size: 18px; + line-height: 24px; +} + +.tab-carousel .resource .info .summary, +.tab-carousel .resource .info .cta { + line-height: 24px; + font-size: 16px; +} + +.tab-carousel .resource-card-18x12 { + position: relative; + padding-left: 450px; + box-sizing: border-box; + display: table-cell; + vertical-align: middle; +} + +.tab-carousel .resource-card-18x12 .image { + position: absolute; + width: 420px; + height: 100%; + left: 0; + top: 0; +} + +.tab-carousel .resource-card-18x12 .info { + display: inline-block; +} + +.tab-carousel .resource-card-18x12 .info .title { + margin-bottom: 26px; +} + + + + + +/* + Styles for the entity link used in the actions bar and in the cta of + the resources that appear in the tab carousel. +*/ +.actions-bar a:after, +.resource .cta:after { + content: '›'; + font-weight: 400; + font-size: 22px; + left: 5px; + line-height: 1; + position: relative; + top: 1px; + transition: left 190ms ease-out; +} + +.actions-bar a:hover:after, +.resource .cta:hover:after { + left: 10px; +} + + + + +/* + Styles for the actions bar. +*/ +.actions-bar { + background: #9acd00; + margin: 0 -10px; + text-align: center; +} + +.actions-bar .actions { + padding: 30px 0 30px; + text-align: justify; + font-size: 0.1px; + line-height: 0.1px; + margin: 0 10px 0 0; +} + +.actions-bar .actions:after { + content: ''; + width: 100%; + display: inline-block; +} + +.actions-bar .actions > div { + display: inline-block; +} + +.actions-bar a { + font-size: 21px; + line-height: 27px; + color: #fff; + font-weight: 300; + -webkit-font-smoothing: antialiased; +} + +.actions-bar a:after { + top: 0px; + font-size: 22px; +} + +.actions-bar a:hover { + color: #fff !important; +} + + + + + +/* + Specific styles for new home page layout of the carousels. +*/ + +/* Big blue button */ +a.home-new-cta-btn, +.home-new-carousel-1 .resource-card-18x6 .cta { + white-space: nowrap; + display: inline-block; + padding: 14px 32px; + font-size: 18px; + font-weight: 500; + line-height: 24px; + cursor: pointer; + background: #33b5e6; + border-radius: 4px; + margin-top: 20px; + color: #fff; + transition: 0.2s background-color ease-in-out; +} + +.home-new-carousel-1 .resource-card-18x6 .cta:after { + display: none; /* Hide the entity for this button */ +} + +a.home-new-cta-btn:hover, +.home-new-carousel-1 .resource-card-18x6 .cta:hover { + color: #fff !important; + background: #2d9fca; +} + +.home-new-carousel-1 .resource-card-18x6 .cta { + position: absolute; + bottom: 20px; + left: 16px; +} + +/* Fullscreen carousel. */ +.home-new-carousel-1 { + max-height: 700px; /* Set max height so doesn't get too long */ +} + +.home-new-carousel-1 .fullscreen-carousel-content { + min-height: 450px; /* Set min height for all content */ +} + +.home-new-carousel-1 .hero { + background: #000; +} + +.home-new-carousel-1 .hero-bg { + background-image: url(/home-new/images/hero.jpg); + background-position: right center; + opacity: 0.85; +} + +/* + Styling for special top card of full screen layout resource layout. + We need to specifically style the 18x6 card to adjust its size and layout, + since it's not a standard card, not sure if this is unique to the home page + layout or should be namespaced within the fullscreen-carousel container. +*/ +.home-new-carousel-1 .resource-flow-layout.col-16 .resource-card-18x6 { + height: 320px; + background-color:#F9F9F9; + border-radius: 0px; + box-shadow: 0px 0px 0px rgba(0, 0, 0, 0); + +} + +.home-new-carousel-1 .resource-card-18x6 .card-bg { + width: 636px; + height: 100%; +} + +.home-new-carousel-1 .resource-card-18x6 .card-info { + right: 0px; + left: 636px; + height: 100%; + top: 0px; + padding: 15px 22px; +} + +.home-new-carousel-1 .resource-card-18x6 .card-info .util { + display: none; +} + +.home-new-carousel-1 .resource-card-18x6 .card-info .title { + font-size: 20px; + font-weight: 500; + margin-top: 15px; + margin-bottom: 15px; +} + +.home-new-carousel-1 .resource-card-18x6 .card-info .text { + font-size: 15px; + line-height: 21px; +} + + +/* Tabbed carousel. */ +.home-new-carousel-2 { + margin: 35px auto 100px auto; +} + +.home-new-carousel-2 h1 { + font-size: 47px; + font-weight: 100; + line-height: 54px; + text-align: center; +} diff --git a/tools/droiddoc/templates-sdk/assets/css/fullscreen.css b/tools/droiddoc/templates-sdk/assets/css/fullscreen.css index 71cf65b..7912e34 100644 --- a/tools/droiddoc/templates-sdk/assets/css/fullscreen.css +++ b/tools/droiddoc/templates-sdk/assets/css/fullscreen.css @@ -170,7 +170,7 @@ body { max-width: 100%; } -#nav-x .wrap, +#header-wrapper #nav-x div.wrap, #searchResults.wrap { max-width:100%; } @@ -184,9 +184,17 @@ body { left:20px; /* !important ... for IE i think */ } +#sticky-header { + padding: 0 20px; +} +#sticky-header > div { + width: 100%; +} - +.sticky-menu { + width:100%; + left:-20px; } .col-right { diff --git a/tools/droiddoc/templates-sdk/assets/images/android.png b/tools/droiddoc/templates-sdk/assets/images/android.png Binary files differnew file mode 100644 index 0000000..4040f3f --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/android.png diff --git a/tools/droiddoc/templates-sdk/assets/images/breadcrumb.png b/tools/droiddoc/templates-sdk/assets/images/breadcrumb.png Binary files differnew file mode 100644 index 0000000..407a318 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/breadcrumb.png diff --git a/tools/droiddoc/templates-sdk/assets/images/dac_logo@2x.png b/tools/droiddoc/templates-sdk/assets/images/dac_logo@2x.png Binary files differnew file mode 100644 index 0000000..0f2784d --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/dac_logo@2x.png diff --git a/tools/droiddoc/templates-sdk/assets/images/link-out.png b/tools/droiddoc/templates-sdk/assets/images/link-out.png Binary files differnew file mode 100644 index 0000000..aa55f9a --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/link-out.png diff --git a/tools/droiddoc/templates-sdk/assets/images/preview.png b/tools/droiddoc/templates-sdk/assets/images/preview.png Binary files differnew file mode 100644 index 0000000..e5856db --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/preview.png diff --git a/tools/droiddoc/templates-sdk/assets/images/resource-card-default-android.jpg b/tools/droiddoc/templates-sdk/assets/images/resource-card-default-android.jpg Binary files differnew file mode 100644 index 0000000..8050744 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/resource-card-default-android.jpg diff --git a/tools/droiddoc/templates-sdk/assets/images/stack-arrow-right.png b/tools/droiddoc/templates-sdk/assets/images/stack-arrow-right.png Binary files differnew file mode 100644 index 0000000..46d6a50 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/stack-arrow-right.png diff --git a/tools/droiddoc/templates-sdk/assets/images/styles/device_wear_square.png b/tools/droiddoc/templates-sdk/assets/images/styles/device_wear_square.png Binary files differnew file mode 100644 index 0000000..077a7e6 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/styles/device_wear_square.png diff --git a/tools/droiddoc/templates-sdk/assets/images/styles/device_wear_square_small.png b/tools/droiddoc/templates-sdk/assets/images/styles/device_wear_square_small.png Binary files differnew file mode 100644 index 0000000..e7e1540 --- /dev/null +++ b/tools/droiddoc/templates-sdk/assets/images/styles/device_wear_square_small.png diff --git a/tools/droiddoc/templates-sdk/assets/js/docs.js b/tools/droiddoc/templates-sdk/assets/js/docs.js index 6630bf9..f03fb88 100644 --- a/tools/droiddoc/templates-sdk/assets/js/docs.js +++ b/tools/droiddoc/templates-sdk/assets/js/docs.js @@ -19,7 +19,6 @@ $.ajaxSetup({ /****** ON LOAD SET UP STUFF *********/ -var navBarIsFixed = false; $(document).ready(function() { // load json file for JD doc search suggestions @@ -64,7 +63,12 @@ $(document).ready(function() { $('.scroll-pane').jScrollPane( {verticalGutter:0} ); // add HRs below all H2s (except for a few other h2 variants) - $('h2').not('#qv h2').not('#tb h2').not('.sidebox h2').not('#devdoc-nav h2').not('h2.norule').css({marginBottom:0}).after('<hr/>'); + $('h2').not('#qv h2') + .not('#tb h2') + .not('.sidebox h2') + .not('#devdoc-nav h2') + .not('h2.norule').css({marginBottom:0}) + .after('<hr/>'); // set up the search close button $('.search .close').click(function() { @@ -167,10 +171,24 @@ $(document).ready(function() { // highlight Design tab if ($("body").hasClass("design")) { $("#header li.design a").addClass("selected"); + $("#sticky-header").addClass("design"); + // highlight About tabs + } else if ($("body").hasClass("about")) { + var rootDir = pagePathOriginal.substring(1,pagePathOriginal.indexOf('/', 1)); + if (rootDir == "about") { + $("#nav-x li.about a").addClass("selected"); + } else if (rootDir == "wear") { + $("#nav-x li.wear a").addClass("selected"); + } else if (rootDir == "tv") { + $("#nav-x li.tv a").addClass("selected"); + } else if (rootDir == "auto") { + $("#nav-x li.auto a").addClass("selected"); + } // highlight Develop tab } else if ($("body").hasClass("develop") || $("body").hasClass("google")) { $("#header li.develop a").addClass("selected"); + $("#sticky-header").addClass("develop"); // In Develop docs, also highlight appropriate sub-tab var rootDir = pagePathOriginal.substring(1,pagePathOriginal.indexOf('/', 1)); if (rootDir == "training") { @@ -195,12 +213,34 @@ $(document).ready(function() { // highlight Distribute tab } else if ($("body").hasClass("distribute")) { $("#header li.distribute a").addClass("selected"); + $("#sticky-header").addClass("distribute"); + + var baseFrag = pagePathOriginal.indexOf('/', 1) + 1; + var secondFrag = pagePathOriginal.substring(baseFrag, pagePathOriginal.indexOf('/', baseFrag)); + if (secondFrag == "users") { + $("#nav-x li.users a").addClass("selected"); + } else if (secondFrag == "engage") { + $("#nav-x li.engage a").addClass("selected"); + } else if (secondFrag == "monetize") { + $("#nav-x li.monetize a").addClass("selected"); + } else if (secondFrag == "tools") { + $("#nav-x li.disttools a").addClass("selected"); + } else if (secondFrag == "stories") { + $("#nav-x li.stories a").addClass("selected"); + } else if (secondFrag == "essentials") { + $("#nav-x li.essentials a").addClass("selected"); + } else if (secondFrag == "googleplay") { + $("#nav-x li.googleplay a").addClass("selected"); + } + } else if ($("body").hasClass("about")) { + $("#sticky-header").addClass("about"); } // set global variable so we can highlight the sidenav a bit later (such as for google reference) // and highlight the sidenav mPagePath = pagePath; highlightSidenav(); + buildBreadcrumbs(); // set up prev/next links if they exist var $selNavLink = $('#nav').find('a[href="' + pagePath + '"]'); @@ -215,7 +255,7 @@ $(document).ready(function() { var crossBoundaries = ($("body.design").length > 0) || ($("body.guide").length > 0) ? true : false; // navigate across topic boundaries only in design docs if ($prevListItem.length) { - if ($prevListItem.hasClass('nav-section')) { + if ($prevListItem.hasClass('nav-section') || crossBoundaries) { // jump to last topic of previous section $prevLink = $prevListItem.find('a:last'); } else if (!$selListItem.hasClass('nav-section')) { @@ -238,7 +278,6 @@ false; // navigate across topic boundaries only in design docs // set up next links var $nextLink = []; var startClass = false; - var training = $(".next-class-link").length; // decides whether to provide "next class" link var isCrossingBoundary = false; if ($selListItem.hasClass('nav-section') && $selListItem.children('div.empty').length == 0) { @@ -265,13 +304,15 @@ false; // navigate across topic boundaries only in design docs if ($nextLink.length == 0) { isCrossingBoundary = true; // no more topics in this section, jump to the first topic in the next section - $nextLink = $selListItem.parents('li:eq(0)').next('li.nav-section').find('a:eq(0)'); + $nextLink = $selListItem.parents('li:eq(0)').next('li').find('a:eq(0)'); if (!$nextLink.length) { // Go up another layer to look for next page (lesson > class > course) $nextLink = $selListItem.parents('li:eq(1)').next('li.nav-section').find('a:eq(0)'); if ($nextLink.length == 0) { // if that doesn't work, we're at the end of the list, so disable NEXT link $('.next-page-link').attr('href','').addClass("disabled") .click(function() { return false; }); + // and completely hide the one in the footer + $('.content-footer .next-page-link').hide(); } } } @@ -290,13 +331,19 @@ false; // navigate across topic boundaries only in design docs $('.next-page-link').attr('href','') .removeClass("hide").addClass("disabled") .click(function() { return false; }); + // and completely hide the one in the footer + $('.content-footer .next-page-link').hide(); if ($nextLink.length) { $('.next-class-link').attr('href',$nextLink.attr('href')) - .removeClass("hide").append($nextLink.html()); + .removeClass("hide") + .append(": " + $nextLink.html()); $('.next-class-link').find('.new').empty(); } } else { - $('.next-page-link').attr('href', $nextLink.attr('href')).removeClass("hide"); + $('.next-page-link').attr('href', $nextLink.attr('href')) + .removeClass("hide"); + // for the footer link, also add the next page title + $('.content-footer .next-page-link').append(": " + $nextLink.html()); } if (!startClass && $prevLink.length) { @@ -308,14 +355,6 @@ false; // navigate across topic boundaries only in design docs } } - // If this is a training 'article', there should be no prev/next nav - // ... if the grandparent is the "nav" ... and it has no child list items... - if (training && $selListItem.parents('ul').eq(1).is('[id="nav"]') && - !$selListItem.find('li').length) { - $('.next-page-link,.prev-page-link').attr('href','').addClass("disabled") - .click(function() { return false; }); - } - } @@ -323,7 +362,20 @@ false; // navigate across topic boundaries only in design docs // Set up the course landing pages for Training with class names and descriptions if ($('body.trainingcourse').length) { var $classLinks = $selListItem.find('ul li a').not('#nav .nav-section .nav-section ul a'); - var $classDescriptions = $classLinks.attr('description'); + + // create an array for all the class descriptions + var $classDescriptions = new Array($classLinks.length); + var lang = getLangPref(); + $classLinks.each(function(index) { + var langDescr = $(this).attr(lang + "-description"); + if (typeof langDescr !== 'undefined' && langDescr !== false) { + // if there's a class description in the selected language, use that + $classDescriptions[index] = langDescr; + } else { + // otherwise, use the default english description + $classDescriptions[index] = $(this).attr("description"); + } + }); var $olClasses = $('<ol class="class-list"></ol>'); var $liClass; @@ -335,7 +387,7 @@ false; // navigate across topic boundaries only in design docs $classLinks.each(function(index) { $liClass = $('<li></li>'); $h2Title = $('<a class="title" href="'+$(this).attr('href')+'"><h2>' + $(this).html()+'</h2><span></span></a>'); - $pSummary = $('<p class="description">' + $(this).attr('description') + '</p>'); + $pSummary = $('<p class="description">' + $classDescriptions[index] + '</p>'); $olLessons = $('<ol class="lesson-list"></ol>'); @@ -374,7 +426,7 @@ false; // navigate across topic boundaries only in design docs var stylesheet = $('link[rel="stylesheet"][class="fullscreen"]'); setNavBarLeftPos(); // do this even if sidenav isn't fixed because it could become fixed // make sidenav behave when resizing the window and side-scolling is a concern - if (navBarIsFixed) { + if (sticky) { if ((stylesheet.attr("disabled") == "disabled") || stylesheet.length == 0) { updateSideNavPosition(); } else { @@ -385,70 +437,6 @@ false; // navigate across topic boundaries only in design docs }); - // Set up fixed navbar - var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll - $(window).scroll(function(event) { - if ($('#side-nav').length == 0) return; - if (event.target.nodeName == "DIV") { - // Dump scroll event if the target is a DIV, because that means the event is coming - // from a scrollable div and so there's no need to make adjustments to our layout - return; - } - var scrollTop = $(window).scrollTop(); - var headerHeight = $('#header').outerHeight(); - var subheaderHeight = $('#nav-x').outerHeight(); - var searchResultHeight = $('#searchResults').is(":visible") ? - $('#searchResults').outerHeight() : 0; - var totalHeaderHeight = headerHeight + subheaderHeight + searchResultHeight; - // we set the navbar fixed when the scroll position is beyond the height of the site header... - var navBarShouldBeFixed = scrollTop > totalHeaderHeight; - // ... except if the document content is shorter than the sidenav height. - // (this is necessary to avoid crazy behavior on OSX Lion due to overscroll bouncing) - if ($("#doc-col").height() < $("#side-nav").height()) { - navBarShouldBeFixed = false; - } - - var scrollLeft = $(window).scrollLeft(); - // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match - if (navBarIsFixed && (scrollLeft != prevScrollLeft)) { - updateSideNavPosition(); - prevScrollLeft = scrollLeft; - } - - // Don't continue if the header is sufficently far away - // (to avoid intensive resizing that slows scrolling) - if (navBarIsFixed && navBarShouldBeFixed) { - return; - } - - if (navBarIsFixed != navBarShouldBeFixed) { - if (navBarShouldBeFixed) { - // make it fixed - var width = $('#devdoc-nav').width(); - $('#devdoc-nav') - .addClass('fixed') - .css({'width':width+'px'}) - .prependTo('#body-content'); - // add neato "back to top" button - $('#devdoc-nav a.totop').css({'display':'block','width':$("#nav").innerWidth()+'px'}); - - // update the sidenaav position for side scrolling - updateSideNavPosition(); - } else { - // make it static again - $('#devdoc-nav') - .removeClass('fixed') - .css({'width':'auto','margin':''}) - .prependTo('#side-nav'); - $('#devdoc-nav a.totop').hide(); - } - navBarIsFixed = navBarShouldBeFixed; - } - - resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance - }); - - var navBarLeftPos; if ($('#devdoc-nav').length) { setNavBarLeftPos(); @@ -522,7 +510,11 @@ false; // navigate across topic boundaries only in design docs } } + // Resize once loading is finished resizeNav(); + // Check if there's an anchor that we need to scroll into view. + // A delay is needed, because some browsers do not immediately scroll down to the anchor + window.setTimeout(offsetScrollForSticky, 100); /* init the language selector based on user cookie for lang */ loadLangPref(); @@ -593,6 +585,28 @@ function initExpandableNavItems(rootTag) { }); } + +/** Create the list of breadcrumb links in the sticky header */ +function buildBreadcrumbs() { + var $breadcrumbUl = $("#sticky-header ul.breadcrumb"); + // Add the secondary horizontal nav item, if provided + var $selectedSecondNav = $("div#nav-x ul.nav-x a.selected").clone().removeClass("selected"); + if ($selectedSecondNav.length) { + $breadcrumbUl.prepend($("<li>").append($selectedSecondNav)) + } + // Add the primary horizontal nav + var $selectedFirstNav = $("div#header-wrap ul.nav-x a.selected").clone().removeClass("selected"); + // If there's no header nav item, use the logo link and title from alt text + if ($selectedFirstNav.length < 1) { + $selectedFirstNav = $("<a>") + .attr('href', $("div#header .logo a").attr('href')) + .text($("div#header .logo img").attr('alt')); + } + $breadcrumbUl.prepend($("<li>").append($selectedFirstNav)); +} + + + /** Highlight the current page in sidenav, expanding children as appropriate */ function highlightSidenav() { // if something is already highlighted, undo it. This is for dynamic navigation (Samples index) @@ -705,9 +719,8 @@ function resizeNav(delay) { // Then figure out based on scroll position whether the header is visible var windowHeight = $window.height(); var scrollTop = $window.scrollTop(); - var headerHeight = $('#header').outerHeight(); - var subheaderHeight = $('#nav-x').outerHeight(); - var headerVisible = (scrollTop < (headerHeight + subheaderHeight)); + var headerHeight = $('#header-wrapper').outerHeight(); + var headerVisible = scrollTop < stickyTop; // get the height of space between nav and top of window. // Could be either margin or top position, depending on whether the nav is fixed. @@ -717,7 +730,7 @@ function resizeNav(delay) { // Depending on whether the header is visible, set the side nav's height. if (headerVisible) { // The sidenav height grows as the header goes off screen - navHeight = windowHeight - (headerHeight + subheaderHeight - scrollTop) - topMargin; + navHeight = windowHeight - (headerHeight - scrollTop) - topMargin; } else { // Once header is off screen, the nav height is almost full window height navHeight = windowHeight - topMargin; @@ -903,9 +916,111 @@ function writeCookie(cookie, val, section, expiration) { /* ######### END COOKIES! ########## */ +var sticky = false; +var stickyTop; +var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll +/* Sets the vertical scoll position at which the sticky bar should appear. + This method is called to reset the position when search results appear or hide */ +function setStickyTop() { + stickyTop = $('#header-wrapper').outerHeight() - $('#sticky-header').outerHeight(); +} + +/* + * Displays sticky nav bar on pages when dac header scrolls out of view + */ +$(window).scroll(function(event) { + + setStickyTop(); + var hiding = false; + var $stickyEl = $('#sticky-header'); + var $menuEl = $('.menu-container'); + // Exit if there's no sidenav + if ($('#side-nav').length == 0) return; + // Exit if the mouse target is a DIV, because that means the event is coming + // from a scrollable div and so there's no need to make adjustments to our layout + if ($(event.target).nodeName == "DIV") { + return; + } + + var top = $(window).scrollTop(); + // we set the navbar fixed when the scroll position is beyond the height of the site header... + var shouldBeSticky = top >= stickyTop; + // ... except if the document content is shorter than the sidenav height. + // (this is necessary to avoid crazy behavior on OSX Lion due to overscroll bouncing) + if ($("#doc-col").height() < $("#side-nav").height()) { + shouldBeSticky = false; + } + // Account for horizontal scroll + var scrollLeft = $(window).scrollLeft(); + // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match + if (sticky && (scrollLeft != prevScrollLeft)) { + updateSideNavPosition(); + prevScrollLeft = scrollLeft; + } + + // Don't continue if the header is sufficently far away + // (to avoid intensive resizing that slows scrolling) + if (sticky == shouldBeSticky) { + return; + } + // If sticky header visible and position is now near top, hide sticky + if (sticky && !shouldBeSticky) { + sticky = false; + hiding = true; + // make the sidenav static again + $('#devdoc-nav') + .removeClass('fixed') + .css({'width':'auto','margin':''}) + .prependTo('#side-nav'); + // delay hide the sticky + $menuEl.removeClass('sticky-menu'); + $stickyEl.fadeOut(250); + hiding = false; + + // update the sidenaav position for side scrolling + updateSideNavPosition(); + } else if (!sticky && shouldBeSticky) { + sticky = true; + $stickyEl.fadeIn(10); + $menuEl.addClass('sticky-menu'); + + // make the sidenav fixed + var width = $('#devdoc-nav').width(); + $('#devdoc-nav') + .addClass('fixed') + .css({'width':width+'px'}) + .prependTo('#body-content'); + + // update the sidenaav position for side scrolling + updateSideNavPosition(); + + } else if (hiding && top < 15) { + $menuEl.removeClass('sticky-menu'); + $stickyEl.hide(); + hiding = false; + } + resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance +}); +/* + * Manages secion card states and nav resize to conclude loading + */ +(function() { + $(document).ready(function() { + // Stack hover states + $('.section-card-menu').each(function(index, el) { + var height = $(el).height(); + $(el).css({height:height+'px', position:'relative'}); + var $cardInfo = $(el).find('.card-info'); + + $cardInfo.css({position: 'absolute', bottom:'0px', left:'0px', right:'0px', overflow:'visible'}); + }); + + }); + +})(); @@ -972,8 +1087,16 @@ function hideNestedItems(list, toggle) { } +/* Call this to add listeners to a <select> element for Studio/Eclipse/Other docs */ +function setupIdeDocToggle() { + $( "select.ide" ).change(function() { + var selected = $(this).find("option:selected").attr("value"); + $(".select-ide").hide(); + $(".select-ide."+selected).show(); - + $("select.ide").val(selected); + }); +} @@ -1724,6 +1847,7 @@ function search_changed(e, kd, toroot) $('.suggest-card').hide(); if ($("#searchResults").is(":hidden") && (search.value != "")) { // if results aren't showing (and text not empty), return true to allow search to execute + $('body,html').animate({scrollTop:0}, '500', 'swing'); return true; } else { // otherwise, results are already showing, so allow ajax to auto refresh the results @@ -1736,8 +1860,12 @@ function search_changed(e, kd, toroot) return false; } } - // Stop here if Google results are showing + // If Google results are showing, return true to allow ajax search to execute else if ($("#searchResults").is(":visible")) { + // Also, if search_results is scrolled out of view, scroll to top to make results visible + if ((sticky ) && (search.value != "")) { + $('body,html').animate({scrollTop:0}, '500', 'swing'); + } return true; } // 38 UP ARROW @@ -2278,13 +2406,13 @@ function submit_search() { var query = document.getElementById('search_autocomplete').value; location.hash = 'q=' + query; loadSearchResults(); - $("#searchResults").slideDown('slow'); + $("#searchResults").slideDown('slow', setStickyTop); return false; } function hideResults() { - $("#searchResults").slideUp(); + $("#searchResults").slideUp('fast', setStickyTop); $(".search .close").addClass("hide"); location.hash = ''; @@ -2401,27 +2529,47 @@ google.setOnLoadCallback(function(){ return; } else { // first time loading search results for this page - $('#searchResults').slideDown('slow'); + $('#searchResults').slideDown('slow', setStickyTop); $(".search .close").removeClass("hide"); loadSearchResults(); } }, true); +/* Adjust the scroll position to account for sticky header, only if the hash matches an id */ +function offsetScrollForSticky() { + var hash = escape(location.hash.substr(1)); + var $matchingElement = $("#"+hash); + // If there's no element with the hash as an ID, then look for an <a name=''> with it. + if ($matchingElement.length < 1) { + $matchingElement = $('a[name="' + hash + '"]'); + } + // Sanity check that there's an element with that ID on the page + if ($matchingElement.length) { + // If the position of the target element is near the top of the page (<20px, where we expect it + // to be because we need to move it down 60px to become in view), then move it down 60px + if (Math.abs($matchingElement.offset().top - $(window).scrollTop()) < 20) { + $(window).scrollTop($(window).scrollTop() - 60); + } + } +} + // when an event on the browser history occurs (back, forward, load) requery hash and do search $(window).hashchange( function(){ - // Exit if the hash isn't a search query or there's an error in the query + // If the hash isn't a search query or there's an error in the query, + // then adjust the scroll position to account for sticky header, then exit. if ((location.hash.indexOf("q=") == -1) || (query == "undefined")) { // If the results pane is open, close it. if (!$("#searchResults").is(":hidden")) { hideResults(); } + offsetScrollForSticky(); return; } // Otherwise, we have a search to do var query = decodeURI(getQuery(location.hash)); searchControl.execute(query); - $('#searchResults').slideDown('slow'); + $('#searchResults').slideDown('slow', setStickyTop); $("#search_autocomplete").focus(); $(".search .close").removeClass("hide"); @@ -2529,7 +2677,7 @@ var maxLevel = 1; } function updateSidenavFixedWidth() { - if (!navBarIsFixed) return; + if (!sticky) return; $('#devdoc-nav').css({ 'width' : $('#side-nav').css('width'), 'margin' : $('#side-nav').css('margin') @@ -2540,7 +2688,7 @@ function updateSidenavFixedWidth() { } function updateSidenavFullscreenWidth() { - if (!navBarIsFixed) return; + if (!sticky) return; $('#devdoc-nav').css({ 'width' : $('#side-nav').css('width'), 'margin' : $('#side-nav').css('margin') @@ -3233,3 +3381,836 @@ function showSamples() { $("#samples").append($ul); } + + + +/* ########################################################## */ +/* ################### RESOURCE CARDS ##################### */ +/* ########################################################## */ + +/** Handle resource queries, collections, and grids (sections). Requires + jd_tag_helpers.js and the *_unified_data.js to be loaded. */ + +(function() { + // Prevent the same resource from being loaded more than once per page. + var addedPageResources = {}; + + $(document).ready(function() { + $('.resource-widget').each(function() { + initResourceWidget(this); + }); + + /* Pass the line height to ellipsisfade() to adjust the height of the + text container to show the max number of lines possible, without + showing lines that are cut off. This works with the css ellipsis + classes to fade last text line and apply an ellipsis char. */ + + //card text currently uses 15px line height. + var lineHeight = 15; + $('.card-info .text').ellipsisfade(lineHeight); + }); + + /* + Three types of resource layouts: + Flow - Uses a fixed row-height flow using float left style. + Carousel - Single card slideshow all same dimension absolute. + Stack - Uses fixed columns and flexible element height. + */ + function initResourceWidget(widget) { + var $widget = $(widget); + var isFlow = $widget.hasClass('resource-flow-layout'), + isCarousel = $widget.hasClass('resource-carousel-layout'), + isStack = $widget.hasClass('resource-stack-layout'); + + // find size of widget by pulling out its class name + var sizeCols = 1; + var m = $widget.get(0).className.match(/\bcol-(\d+)\b/); + if (m) { + sizeCols = parseInt(m[1], 10); + } + + var opts = { + cardSizes: ($widget.data('cardsizes') || '').split(','), + maxResults: parseInt($widget.data('maxresults') || '100', 10), + itemsPerPage: $widget.data('itemsperpage'), + sortOrder: $widget.data('sortorder'), + query: $widget.data('query'), + section: $widget.data('section'), + sizeCols: sizeCols, + /* Added by LFL 6/6/14 */ + resourceStyle: $widget.data('resourcestyle') || 'card', + stackSort: $widget.data('stacksort') || 'true' + }; + + // run the search for the set of resources to show + + var resources = buildResourceList(opts); + + if (isFlow) { + drawResourcesFlowWidget($widget, opts, resources); + } else if (isCarousel) { + drawResourcesCarouselWidget($widget, opts, resources); + } else if (isStack) { + /* Looks like this got removed and is not used, so repurposing for the + homepage style layout. + Modified by LFL 6/6/14 + */ + //var sections = buildSectionList(opts); + opts['numStacks'] = $widget.data('numstacks'); + drawResourcesStackWidget($widget, opts, resources/*, sections*/); + } + } + + /* Initializes a Resource Carousel Widget */ + function drawResourcesCarouselWidget($widget, opts, resources) { + $widget.empty(); + var plusone = true; //always show plusone on carousel + + $widget.addClass('resource-card slideshow-container') + .append($('<a>').addClass('slideshow-prev').text('Prev')) + .append($('<a>').addClass('slideshow-next').text('Next')); + + var css = { 'width': $widget.width() + 'px', + 'height': $widget.height() + 'px' }; + + var $ul = $('<ul>'); + + for (var i = 0; i < resources.length; ++i) { + var $card = $('<a>') + .attr('href', cleanUrl(resources[i].url)) + .decorateResourceCard(resources[i],plusone); + + $('<li>').css(css) + .append($card) + .appendTo($ul); + } + + $('<div>').addClass('frame') + .append($ul) + .appendTo($widget); + + $widget.dacSlideshow({ + auto: true, + btnPrev: '.slideshow-prev', + btnNext: '.slideshow-next' + }); + }; + + /* Initializes a Resource Card Stack Widget (column-based layout) + Modified by LFL 6/6/14 + */ + function drawResourcesStackWidget($widget, opts, resources, sections) { + // Don't empty widget, grab all items inside since they will be the first + // items stacked, followed by the resource query + var plusone = true; //by default show plusone on section cards + var cards = $widget.find('.resource-card').detach().toArray(); + var numStacks = opts.numStacks || 1; + var $stacks = []; + var urlString; + + for (var i = 0; i < numStacks; ++i) { + $stacks[i] = $('<div>').addClass('resource-card-stack') + .appendTo($widget); + } + + var sectionResources = []; + + // Extract any subsections that are actually resource cards + if (sections) { + for (var i = 0; i < sections.length; ++i) { + if (!sections[i].sections || !sections[i].sections.length) { + // Render it as a resource card + sectionResources.push( + $('<a>') + .addClass('resource-card section-card') + .attr('href', cleanUrl(sections[i].resource.url)) + .decorateResourceCard(sections[i].resource,plusone)[0] + ); + + } else { + cards.push( + $('<div>') + .addClass('resource-card section-card-menu') + .decorateResourceSection(sections[i],plusone)[0] + ); + } + } + } + + cards = cards.concat(sectionResources); + + for (var i = 0; i < resources.length; ++i) { + var $card = createResourceElement(resources[i], opts); + + if (opts.resourceStyle.indexOf('related') > -1) { + $card.addClass('related-card'); + } + + cards.push($card[0]); + } + + if (opts.stackSort != 'false') { + for (var i = 0; i < cards.length; ++i) { + // Find the stack with the shortest height, but give preference to + // left to right order. + var minHeight = $stacks[0].height(); + var minIndex = 0; + + for (var j = 1; j < numStacks; ++j) { + var height = $stacks[j].height(); + if (height < minHeight - 45) { + minHeight = height; + minIndex = j; + } + } + + $stacks[minIndex].append($(cards[i])); + } + } + + }; + + /* + Create a resource card using the given resource object and a list of html + configured options. Returns a jquery object containing the element. + */ + function createResourceElement(resource, opts, plusone) { + var $el; + + // The difference here is that generic cards are not entirely clickable + // so its a div instead of an a tag, also the generic one is not given + // the resource-card class so it appears with a transparent background + // and can be styled in whatever way the css setup. + if (opts.resourceStyle == 'generic') { + $el = $('<div>') + .addClass('resource') + .attr('href', cleanUrl(resource.url)) + .decorateResource(resource, opts); + } else { + var cls = 'resource resource-card'; + + $el = $('<a>') + .addClass(cls) + .attr('href', cleanUrl(resource.url)) + .decorateResourceCard(resource, plusone); + } + + return $el; + } + + /* Initializes a flow widget, see distribute.scss for generating accompanying css */ + function drawResourcesFlowWidget($widget, opts, resources) { + $widget.empty(); + var cardSizes = opts.cardSizes || ['6x6']; + var i = 0, j = 0; + var plusone = true; // by default show plusone on resource cards + + while (i < resources.length) { + var cardSize = cardSizes[j++ % cardSizes.length]; + cardSize = cardSize.replace(/^\s+|\s+$/,''); + // Some card sizes do not get a plusone button, such as where space is constrained + // or for cards commonly embedded in docs (to improve overall page speed). + plusone = !((cardSize == "6x2") || (cardSize == "6x3") || + (cardSize == "9x2") || (cardSize == "9x3") || + (cardSize == "12x2") || (cardSize == "12x3")); + + // A stack has a third dimension which is the number of stacked items + var isStack = cardSize.match(/(\d+)x(\d+)x(\d+)/); + var stackCount = 0; + var $stackDiv = null; + + if (isStack) { + // Create a stack container which should have the dimensions defined + // by the product of the items inside. + $stackDiv = $('<div>').addClass('resource-card-stack resource-card-' + isStack[1] + + 'x' + isStack[2] * isStack[3]) .appendTo($widget); + } + + // Build each stack item or just a single item + do { + var resource = resources[i]; + + var $card = createResourceElement(resources[i], opts, plusone); + + $card.addClass('resource-card-' + cardSize + + ' resource-card-' + resource.type); + + if (isStack) { + $card.addClass('resource-card-' + isStack[1] + 'x' + isStack[2]); + if (++stackCount == parseInt(isStack[3])) { + $card.addClass('resource-card-row-stack-last'); + stackCount = 0; + } + } else { + stackCount = 0; + } + + $card.appendTo($stackDiv || $widget); + + } while (++i < resources.length && stackCount > 0); + } + } + + /* Build a site map of resources using a section as a root. */ + function buildSectionList(opts) { + if (opts.section && SECTION_BY_ID[opts.section]) { + return SECTION_BY_ID[opts.section].sections || []; + } + return []; + } + + function buildResourceList(opts) { + var maxResults = opts.maxResults || 100; + + var query = opts.query || ''; + var expressions = parseResourceQuery(query); + var addedResourceIndices = {}; + var results = []; + + for (var i = 0; i < expressions.length; i++) { + var clauses = expressions[i]; + + // build initial set of resources from first clause + var firstClause = clauses[0]; + var resources = []; + switch (firstClause.attr) { + case 'type': + resources = ALL_RESOURCES_BY_TYPE[firstClause.value]; + break; + case 'lang': + resources = ALL_RESOURCES_BY_LANG[firstClause.value]; + break; + case 'tag': + resources = ALL_RESOURCES_BY_TAG[firstClause.value]; + break; + case 'collection': + var urls = RESOURCE_COLLECTIONS[firstClause.value].resources || []; + resources = urls.map(function(url){ return ALL_RESOURCES_BY_URL[url]; }); + break; + case 'section': + var urls = SITE_MAP[firstClause.value].sections || []; + resources = urls.map(function(url){ return ALL_RESOURCES_BY_URL[url]; }); + break; + } + // console.log(firstClause.attr + ':' + firstClause.value); + resources = resources || []; + + // use additional clauses to filter corpus + if (clauses.length > 1) { + var otherClauses = clauses.slice(1); + resources = resources.filter(getResourceMatchesClausesFilter(otherClauses)); + } + + // filter out resources already added + if (i > 1) { + resources = resources.filter(getResourceNotAlreadyAddedFilter(addedResourceIndices)); + } + + // add to list of already added indices + for (var j = 0; j < resources.length; j++) { + // console.log(resources[j].title); + addedResourceIndices[resources[j].index] = 1; + } + + // concat to final results list + results = results.concat(resources); + } + + if (opts.sortOrder && results.length) { + var attr = opts.sortOrder; + + if (opts.sortOrder == 'random') { + var i = results.length, j, temp; + while (--i) { + j = Math.floor(Math.random() * (i + 1)); + temp = results[i]; + results[i] = results[j]; + results[j] = temp; + } + } else { + var desc = attr.charAt(0) == '-'; + if (desc) { + attr = attr.substring(1); + } + results = results.sort(function(x,y) { + return (desc ? -1 : 1) * (parseInt(x[attr], 10) - parseInt(y[attr], 10)); + }); + } + } + + results = results.filter(getResourceNotAlreadyAddedFilter(addedPageResources)); + results = results.slice(0, maxResults); + + for (var j = 0; j < results.length; ++j) { + addedPageResources[results[j].index] = 1; + } + + return results; + } + + + function getResourceNotAlreadyAddedFilter(addedResourceIndices) { + return function(resource) { + return !addedResourceIndices[resource.index]; + }; + } + + + function getResourceMatchesClausesFilter(clauses) { + return function(resource) { + return doesResourceMatchClauses(resource, clauses); + }; + } + + + function doesResourceMatchClauses(resource, clauses) { + for (var i = 0; i < clauses.length; i++) { + var map; + switch (clauses[i].attr) { + case 'type': + map = IS_RESOURCE_OF_TYPE[clauses[i].value]; + break; + case 'lang': + map = IS_RESOURCE_IN_LANG[clauses[i].value]; + break; + case 'tag': + map = IS_RESOURCE_TAGGED[clauses[i].value]; + break; + } + + if (!map || (!!clauses[i].negative ? map[resource.index] : !map[resource.index])) { + return clauses[i].negative; + } + } + return true; + } + + function cleanUrl(url) + { + if (url && url.indexOf('//') === -1) { + url = toRoot + url; + } + + return url; + } + + + function parseResourceQuery(query) { + // Parse query into array of expressions (expression e.g. 'tag:foo + type:video') + var expressions = []; + var expressionStrs = query.split(',') || []; + for (var i = 0; i < expressionStrs.length; i++) { + var expr = expressionStrs[i] || ''; + + // Break expression into clauses (clause e.g. 'tag:foo') + var clauses = []; + var clauseStrs = expr.split(/(?=[\+\-])/); + for (var j = 0; j < clauseStrs.length; j++) { + var clauseStr = clauseStrs[j] || ''; + + // Get attribute and value from clause (e.g. attribute='tag', value='foo') + var parts = clauseStr.split(':'); + var clause = {}; + + clause.attr = parts[0].replace(/^\s+|\s+$/g,''); + if (clause.attr) { + if (clause.attr.charAt(0) == '+') { + clause.attr = clause.attr.substring(1); + } else if (clause.attr.charAt(0) == '-') { + clause.negative = true; + clause.attr = clause.attr.substring(1); + } + } + + if (parts.length > 1) { + clause.value = parts[1].replace(/^\s+|\s+$/g,''); + } + + clauses.push(clause); + } + + if (!clauses.length) { + continue; + } + + expressions.push(clauses); + } + + return expressions; + } +})(); + +(function($) { + + /* + Utility method for creating dom for the description area of a card. + Used in decorateResourceCard and decorateResource. + */ + function buildResourceCardDescription(resource, plusone) { + var $description = $('<div>').addClass('description ellipsis'); + + $description.append($('<div>').addClass('text').html(resource.summary)); + + if (resource.cta) { + $description.append($('<a>').addClass('cta').html(resource.cta)); + } + + if (plusone) { + var plusurl = resource.url.indexOf("//") > -1 ? resource.url : + "//developer.android.com/" + resource.url; + + $description.append($('<div>').addClass('util') + .append($('<div>').addClass('g-plusone') + .attr('data-size', 'small') + .attr('data-align', 'right') + .attr('data-href', plusurl))); + } + + return $description; + } + + + /* Simple jquery function to create dom for a standard resource card */ + $.fn.decorateResourceCard = function(resource,plusone) { + var section = resource.group || resource.type; + var imgUrl = resource.image || + 'assets/images/resource-card-default-android.jpg'; + + if (imgUrl.indexOf('//') === -1) { + imgUrl = toRoot + imgUrl; + } + + $('<div>').addClass('card-bg') + .css('background-image', 'url(' + (imgUrl || toRoot + + 'assets/images/resource-card-default-android.jpg') + ')') + .appendTo(this); + + $('<div>').addClass('card-info' + (!resource.summary ? ' empty-desc' : '')) + .append($('<div>').addClass('section').text(section)) + .append($('<div>').addClass('title').html(resource.title)) + .append(buildResourceCardDescription(resource, plusone)) + .appendTo(this); + + return this; + }; + + /* Simple jquery function to create dom for a resource section card (menu) */ + $.fn.decorateResourceSection = function(section,plusone) { + var resource = section.resource; + //keep url clean for matching and offline mode handling + var urlPrefix = resource.image.indexOf("//") > -1 ? "" : toRoot; + var $base = $('<a>') + .addClass('card-bg') + .attr('href', resource.url) + .append($('<div>').addClass('card-section-icon') + .append($('<div>').addClass('icon')) + .append($('<div>').addClass('section').html(resource.title))) + .appendTo(this); + + var $cardInfo = $('<div>').addClass('card-info').appendTo(this); + + if (section.sections && section.sections.length) { + // Recurse the section sub-tree to find a resource image. + var stack = [section]; + + while (stack.length) { + if (stack[0].resource.image) { + $base.css('background-image', 'url(' + urlPrefix + stack[0].resource.image + ')'); + break; + } + + if (stack[0].sections) { + stack = stack.concat(stack[0].sections); + } + + stack.shift(); + } + + var $ul = $('<ul>') + .appendTo($cardInfo); + + var max = section.sections.length > 3 ? 3 : section.sections.length; + + for (var i = 0; i < max; ++i) { + + var subResource = section.sections[i]; + if (!plusone) { + $('<li>') + .append($('<a>').attr('href', subResource.url) + .append($('<div>').addClass('title').html(subResource.title)) + .append($('<div>').addClass('description ellipsis') + .append($('<div>').addClass('text').html(subResource.summary)) + .append($('<div>').addClass('util')))) + .appendTo($ul); + } else { + $('<li>') + .append($('<a>').attr('href', subResource.url) + .append($('<div>').addClass('title').html(subResource.title)) + .append($('<div>').addClass('description ellipsis') + .append($('<div>').addClass('text').html(subResource.summary)) + .append($('<div>').addClass('util') + .append($('<div>').addClass('g-plusone') + .attr('data-size', 'small') + .attr('data-align', 'right') + .attr('data-href', resource.url))))) + .appendTo($ul); + } + } + + // Add a more row + if (max < section.sections.length) { + $('<li>') + .append($('<a>').attr('href', resource.url) + .append($('<div>') + .addClass('title') + .text('More'))) + .appendTo($ul); + } + } else { + // No sub-resources, just render description? + } + + return this; + }; + + + + + /* Render other types of resource styles that are not cards. */ + $.fn.decorateResource = function(resource, opts) { + var imgUrl = resource.image || + 'assets/images/resource-card-default-android.jpg'; + var linkUrl = resource.url; + + if (imgUrl.indexOf('//') === -1) { + imgUrl = toRoot + imgUrl; + } + + if (linkUrl && linkUrl.indexOf('//') === -1) { + linkUrl = toRoot + linkUrl; + } + + $(this).append( + $('<div>').addClass('image') + .css('background-image', 'url(' + imgUrl + ')'), + $('<div>').addClass('info').append( + $('<h4>').addClass('title').html(resource.title), + $('<p>').addClass('summary').html(resource.summary), + $('<a>').attr('href', linkUrl).addClass('cta').html('Learn More') + ) + ); + + return this; + }; +})(jQuery); + + +/* Calculate the vertical area remaining */ +(function($) { + $.fn.ellipsisfade= function(lineHeight) { + this.each(function() { + // get element text + var $this = $(this); + var remainingHeight = $this.parent().parent().height(); + $this.parent().siblings().each(function () + { + if ($(this).is(":visible")) { + var h = $(this).height(); + remainingHeight = remainingHeight - h; + } + }); + + adjustedRemainingHeight = ((remainingHeight)/lineHeight>>0)*lineHeight + $this.parent().css({'height': adjustedRemainingHeight}); + $this.css({'height': "auto"}); + }); + + return this; + }; +}) (jQuery); + +/* + Fullscreen Carousel + + The following allows for an area at the top of the page that takes over the + entire browser height except for its top offset and an optional bottom + padding specified as a data attribute. + + HTML: + + <div class="fullscreen-carousel"> + <div class="fullscreen-carousel-content"> + <!-- content here --> + </div> + <div class="fullscreen-carousel-content"> + <!-- content here --> + </div> + + etc ... + + </div> + + Control over how the carousel takes over the screen can mostly be defined in + a css file. Setting min-height on the .fullscreen-carousel-content elements + will prevent them from shrinking to far vertically when the browser is very + short, and setting max-height on the .fullscreen-carousel itself will prevent + the area from becoming to long in the case that the browser is stretched very + tall. + + There is limited functionality for having multiple sections since that request + was removed, but it is possible to add .next-arrow and .prev-arrow elements to + scroll between multiple content areas. +*/ + +(function() { + $(document).ready(function() { + $('.fullscreen-carousel').each(function() { + initWidget(this); + }); + }); + + function initWidget(widget) { + var $widget = $(widget); + + var topOffset = $widget.offset().top; + var padBottom = parseInt($widget.data('paddingbottom')) || 0; + var maxHeight = 0; + var minHeight = 0; + var $content = $widget.find('.fullscreen-carousel-content'); + var $nextArrow = $widget.find('.next-arrow'); + var $prevArrow = $widget.find('.prev-arrow'); + var $curSection = $($content[0]); + + if ($content.length <= 1) { + $nextArrow.hide(); + $prevArrow.hide(); + } else { + $nextArrow.click(function() { + var index = ($content.index($curSection) + 1); + $curSection.hide(); + $curSection = $($content[index >= $content.length ? 0 : index]); + $curSection.show(); + }); + + $prevArrow.click(function() { + var index = ($content.index($curSection) - 1); + $curSection.hide(); + $curSection = $($content[index < 0 ? $content.length - 1 : 0]); + $curSection.show(); + }); + } + + // Just hide all content sections except first. + $content.each(function(index) { + if ($(this).height() > minHeight) minHeight = $(this).height(); + $(this).css({position: 'absolute', display: index > 0 ? 'none' : ''}); + }); + + // Register for changes to window size, and trigger. + $(window).resize(resizeWidget); + resizeWidget(); + + function resizeWidget() { + var height = $(window).height() - topOffset - padBottom; + $widget.width($(window).width()); + $widget.height(height < minHeight ? minHeight : + (maxHeight && height > maxHeight ? maxHeight : height)); + } + } +})(); + + + + + +/* + Tab Carousel + + The following allows tab widgets to be installed via the html below. Each + tab content section should have a data-tab attribute matching one of the + nav items'. Also each tab content section should have a width matching the + tab carousel. + + HTML: + + <div class="tab-carousel"> + <ul class="tab-nav"> + <li><a href="#" data-tab="handsets">Handsets</a> + <li><a href="#" data-tab="wearable">Wearable</a> + <li><a href="#" data-tab="tv">TV</a> + </ul> + + <div class="tab-carousel-content"> + <div data-tab="handsets"> + <!--Full width content here--> + </div> + + <div data-tab="wearable"> + <!--Full width content here--> + </div> + + <div data-tab="tv"> + <!--Full width content here--> + </div> + </div> + </div> + +*/ +(function() { + $(document).ready(function() { + $('.tab-carousel').each(function() { + initWidget(this); + }); + }); + + function initWidget(widget) { + var $widget = $(widget); + var $nav = $widget.find('.tab-nav'); + var $anchors = $nav.find('[data-tab]'); + var $li = $nav.find('li'); + var $contentContainer = $widget.find('.tab-carousel-content'); + var $tabs = $contentContainer.find('[data-tab]'); + var $curTab = $($tabs[0]); // Current tab is first tab. + var width = $widget.width(); + + // Setup nav interactivity. + $anchors.click(function(evt) { + evt.preventDefault(); + var query = '[data-tab=' + $(this).data('tab') + ']'; + transitionWidget($tabs.filter(query)); + }); + + // Add highlight for navigation on first item. + var $highlight = $('<div>').addClass('highlight') + .css({left:$li.position().left + 'px', width:$li.outerWidth() + 'px'}) + .appendTo($nav); + + // Store height since we will change contents to absolute. + $contentContainer.height($contentContainer.height()); + + // Absolutely position tabs so they're ready for transition. + $tabs.each(function(index) { + $(this).css({position: 'absolute', left: index > 0 ? width + 'px' : '0'}); + }); + + function transitionWidget($toTab) { + if (!$curTab.is($toTab)) { + var curIndex = $tabs.index($curTab[0]); + var toIndex = $tabs.index($toTab[0]); + var dir = toIndex > curIndex ? 1 : -1; + + // Animate content sections. + $toTab.css({left:(width * dir) + 'px'}); + $curTab.animate({left:(width * -dir) + 'px'}); + $toTab.animate({left:'0'}); + + // Animate navigation highlight. + $highlight.animate({left:$($li[toIndex]).position().left + 'px', + width:$($li[toIndex]).outerWidth() + 'px'}) + + // Store new current section. + $curTab = $toTab; + } + } + } +})();
\ No newline at end of file diff --git a/tools/droiddoc/templates-sdk/components/masthead.cs b/tools/droiddoc/templates-sdk/components/masthead.cs index 47639bb..c880eee 100644 --- a/tools/droiddoc/templates-sdk/components/masthead.cs +++ b/tools/droiddoc/templates-sdk/components/masthead.cs @@ -1,226 +1,160 @@ <?cs def:custom_masthead() ?> +<?cs if:preview ?> + <?cs call:preview_masthead() ?> +<?cs else ?> <a name="top"></a> -<?cs if:!devsite ?><?cs # leave out the global header for devsite; it's in devsite template ?> - <!-- Header --> +<?cs if:!devsite ?><?cs # leave out the global header for devsite; it is in devsite template ?> + <!-- Header --> + <div id="header-wrapper"> <div id="header"> - <div class="wrap" id="header-wrap"> - <div class="col-3 logo"> + <div class="wrap" id="header-wrap"> + <div class="col-3 logo"> <a href="<?cs var:toroot ?>index.html"> - <img src="<?cs var:toroot ?>assets/images/dac_logo.png" width="123" height="25" alt="Android Developers" /> + <img src="<?cs var:toroot ?>assets/images/dac_logo.png" + srcset="<?cs var:toroot ?>assets/images/dac_logo@2x.png 2x" + width="123" height="25" alt="Android Developers" /> </a> <div class="btn-quicknav" id="btn-quicknav"> - <a href="#" class="arrow-inactive">Quicknav</a> - <a href="#" class="arrow-active">Quicknav</a> + <a href="#" class="arrow-inactive">Quicknav</a> + <a href="#" class="arrow-active">Quicknav</a> </div> - </div> - <ul class="nav-x col-9"> - <li class="design"> - <a href="<?cs var:toroot ?>design/index.html" - zh-tw-lang="設計" - zh-cn-lang="设计" - ru-lang="Проектирование" - ko-lang="디자인" - ja-lang="設計" - es-lang="Diseñar" - >Design</a></li> - <li class="develop"><a href="<?cs var:toroot ?>develop/index.html" - zh-tw-lang="開發" - zh-cn-lang="开发" - ru-lang="Разработка" - ko-lang="개발" - ja-lang="開発" - es-lang="Desarrollar" - >Develop</a></li> - <li class="distribute last"><a href="<?cs var:toroot ?>distribute/index.html" - zh-tw-lang="發佈" - zh-cn-lang="分发" - ru-lang="Распространение" - ko-lang="배포" - ja-lang="配布" - es-lang="Distribuir" - >Distribute</a></li> - </ul> - - <!-- New Search --> - <div class="menu-container"> - <div class="moremenu"> - <div id="more-btn"></div> - </div> - <div class="morehover" id="moremenu"> - <div class="top"></div> - <div class="mid"> - <div class="header">Links</div> - <ul> - <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li> - <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li> - <li><a href="<?cs var:toroot ?>about/index.html">About Android</a></li> - </ul> - <div class="header">Android Sites</div> - <ul> - <li><a href="http://www.android.com">Android.com</a></li> - <li class="active"><a>Android Developers</a></li> - <li><a href="http://source.android.com">Android Open Source Project</a></li> - </ul> - - <?cs # Include language switcher only in online docs ?> - <?cs if:android.whichdoc == "online" ?> - <div class="header">Language</div> - <div id="language" class="locales"> - <select name="language" onChange="changeLangPref(this.value, true)"> - <option value="en">English</option> - <option value="es">Español</option> - <option value="ja">日本語</option> - <option value="ko">한국어</option> - <option value="ru">Русский</option> - <option value="zh-cn">中文 (中国)</option> - <option value="zh-tw">中文 (台灣)</option> - </select> - </div> - <script type="text/javascript"> - <!-- - loadLangPref(); - //--> - </script> - <?cs /if ?> - <?cs # End of lang switcher ?> + </div> + <ul class="nav-x col-9"> + <li class="design"> + <a href="<?cs var:toroot ?>design/index.html" + zh-tw-lang="設計" + zh-cn-lang="设计" + ru-lang="Проектирование" + ko-lang="디자인" + ja-lang="設計" + es-lang="Diseñar" + >Design</a></li> + <li class="develop"><a href="<?cs var:toroot ?>develop/index.html" + zh-tw-lang="開發" + zh-cn-lang="开发" + ru-lang="Разработка" + ko-lang="개발" + ja-lang="開発" + es-lang="Desarrollar" + >Develop</a></li> + <li class="distribute last"><a href="<?cs var:toroot ?>distribute/<?cs + if:android.whichdoc == "offline" ?>googleplay/<?cs /if ?>index.html" + zh-tw-lang="發佈" + zh-cn-lang="分发" + ru-lang="Распространение" + ko-lang="배포" + ja-lang="配布" + es-lang="Distribuir" + >Distribute</a></li> + </ul> - <br class="clearfix" /> - </div> - <div class="bottom"></div> - </div> - <div class="search" id="search-container"> - <div class="search-inner"> - <div id="search-btn"></div> - <div class="left"></div> - <form onsubmit="return submit_search()"> - <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q" -onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)" -onkeydown="return search_changed(event, true, '<?cs var:toroot ?>')" -onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> - </form> - <div class="right"></div> - <a class="close hide">close</a> - <div class="left"></div> - <div class="right"></div> - </div> - </div> + <?cs # ADD SEARCH AND MENU ?> + <?cs call:header_search_widget() ?> - <div class="search_filtered_wrapper reference"> - <div class="suggest-card reference no-display"> - <ul class="search_filtered"> - </ul> - </div> - </div> - <div class="search_filtered_wrapper docs"> - <div class="suggest-card dummy no-display"> </div> - <div class="suggest-card develop no-display"> - <ul class="search_filtered"> - </ul> - <div class="child-card guides no-display"> - </div> - <div class="child-card training no-display"> - </div> - <div class="child-card samples no-display"> - </div> - </div> - <div class="suggest-card design no-display"> - <ul class="search_filtered"> - </ul> - </div> - <div class="suggest-card distribute no-display"> - <ul class="search_filtered"> - </ul> - </div> - </div> + <!-- Expanded quicknav --> + <div id="quicknav" class="col-13"> + <ul> + <li class="about"> + <ul> + <li><a href="<?cs var:toroot ?>about/index.html">About</a></li> + <li><a href="<?cs var:toroot ?>wear/index.html">Wear</a></li> + <li><a href="<?cs var:toroot ?>tv/index.html">TV</a></li> + <li><a href="<?cs var:toroot ?>auto/index.html">Auto</a></li> + </ul> + </li> + <li class="design"> + <ul> + <li><a href="<?cs var:toroot ?>design/index.html">Get Started</a></li> + <li><a href="<?cs var:toroot ?>design/devices.html">Devices</a></li> + <li><a href="<?cs var:toroot ?>design/style/index.html">Style</a></li> + <li><a href="<?cs var:toroot ?>design/patterns/index.html">Patterns</a></li> + <li><a href="<?cs var:toroot ?>design/building-blocks/index.html">Building Blocks</a></li> + <li><a href="<?cs var:toroot ?>design/downloads/index.html">Downloads</a></li> + <li><a href="<?cs var:toroot ?>design/videos/index.html">Videos</a></li> + </ul> + </li> + <li class="develop"> + <ul> + <li><a href="<?cs var:toroot ?>training/index.html" + zh-tw-lang="訓練課程" + zh-cn-lang="培训" + ru-lang="Курсы" + ko-lang="교육" + ja-lang="トレーニング" + es-lang="Capacitación" + >Training</a></li> + <li><a href="<?cs var:toroot ?>guide/index.html" + zh-tw-lang="API 指南" + zh-cn-lang="API 指南" + ru-lang="Руководства по API" + ko-lang="API 가이드" + ja-lang="API ガイド" + es-lang="Guías de la API" + >API Guides</a></li> + <li><a href="<?cs var:toroot ?>reference/packages.html" + zh-tw-lang="參考資源" + zh-cn-lang="参考" + ru-lang="Справочник" + ko-lang="참조문서" + ja-lang="リファレンス" + es-lang="Referencia" + >Reference</a></li> + <li><a href="<?cs var:toroot ?>sdk/index.html" + zh-tw-lang="相關工具" + zh-cn-lang="工具" + ru-lang="Инструменты" + ko-lang="도구" + ja-lang="ツール" + es-lang="Herramientas" + >Tools</a> + </li> + <li><a href="<?cs var:toroot ?>google/index.html">Google Services</a> + </li> + <?cs if:android.hasSamples ?> + <li><a href="<?cs var:toroot ?>samples/index.html">Samples</a> + </li> + <?cs /if ?> + </ul> + </li> + <li class="distribute last"> + <ul> + <li><a href="<?cs var:toroot ?>distribute/googleplay/index.html">Google Play</a></li> + <li><a href="<?cs var:toroot ?>distribute/essentials/index.html">Essentials</a></li> + <li><a href="<?cs var:toroot ?>distribute/users/index.html">Get Users</a></li> + <li><a href="<?cs var:toroot ?>distribute/engage/index.html">Engage & Retain</a></li> + <li><a href="<?cs var:toroot ?>distribute/monetize/index.html">Monetize</a></li> + <li><a href="<?cs var:toroot ?>distribute/tools/index.html">Tools & Reference</a></li> + <li><a href="<?cs var:toroot ?>distribute/stories/index.html">Developer Stories</a></li> + </ul> + </li> + </ul> + </div><!-- /Expanded quicknav --> + </div><!-- end header-wrap.wrap --> + </div><!-- end header --> - </div> - <!-- /New Search> - - - <!-- Expanded quicknav --> - <div id="quicknav" class="col-9"> - <ul> - <li class="design"> - <ul> - <li><a href="<?cs var:toroot ?>design/index.html">Get Started</a></li> - <li><a href="<?cs var:toroot ?>design/style/index.html">Style</a></li> - <li><a href="<?cs var:toroot ?>design/patterns/index.html">Patterns</a></li> - <li><a href="<?cs var:toroot ?>design/building-blocks/index.html">Building Blocks</a></li> - <li><a href="<?cs var:toroot ?>design/downloads/index.html">Downloads</a></li> - <li><a href="<?cs var:toroot ?>design/videos/index.html">Videos</a></li> - </ul> - </li> - <li class="develop"> - <ul> - <li><a href="<?cs var:toroot ?>training/index.html" - zh-tw-lang="訓練課程" - zh-cn-lang="培训" - ru-lang="Курсы" - ko-lang="교육" - ja-lang="トレーニング" - es-lang="Capacitación" - >Training</a></li> - <li><a href="<?cs var:toroot ?>guide/index.html" - zh-tw-lang="API 指南" - zh-cn-lang="API 指南" - ru-lang="Руководства по API" - ko-lang="API 가이드" - ja-lang="API ガイド" - es-lang="Guías de la API" - >API Guides</a></li> - <li><a href="<?cs var:toroot ?>reference/packages.html" - zh-tw-lang="參考資源" - zh-cn-lang="参考" - ru-lang="Справочник" - ko-lang="참조문서" - ja-lang="リファレンス" - es-lang="Referencia" - >Reference</a></li> - <li><a href="<?cs var:toroot ?>tools/index.html" - zh-tw-lang="相關工具" - zh-cn-lang="工具" - ru-lang="Инструменты" - ko-lang="도구" - ja-lang="ツール" - es-lang="Herramientas" - >Tools</a> - <ul><li><a href="<?cs var:toroot ?>sdk/index.html">Get the SDK</a></li></ul> - </li> - <li><a href="<?cs var:toroot ?>google/index.html">Google Services</a> - </li> - <?cs if:android.hasSamples ?> - <li><a href="<?cs var:toroot ?>samples/index.html">Samples</a> - </li> - <?cs /if ?> - </ul> - </li> - <li class="distribute last"> - <ul> - <li><a href="<?cs var:toroot ?>distribute/index.html">Google Play</a></li> - <li><a href="<?cs var:toroot ?>distribute/googleplay/publish/index.html">Publishing</a></li> - <li><a href="<?cs var:toroot ?>distribute/googleplay/promote/index.html">Promoting</a></li> - <li><a href="<?cs var:toroot ?>distribute/googleplay/quality/index.html">App Quality</a></li> - <li><a href="<?cs var:toroot ?>distribute/googleplay/spotlight/index.html">Spotlight</a></li> - <li><a href="<?cs var:toroot ?>distribute/open.html">Open Distribution</a></li> - </ul> - </li> - </ul> - </div> - <!-- /Expanded quicknav --> + <?cs if:about || wear || tv || auto ?> + <!-- Secondary x-nav --> + <div id="nav-x"> + <div class="wrap"> + <ul class="nav-x col-9 about" style="width:100%"> + <li class="about"><a href="<?cs var:toroot ?>about/index.html" + >About</a></li> + <li class="wear"><a href="<?cs var:toroot ?>wear/index.html" + >Wear</a></li> + <li class="tv"><a href="<?cs var:toroot ?>tv/index.html" + >TV</a></li> + <li class="auto"><a href="<?cs var:toroot ?>auto/index.html" + >Auto</a></li> + </ul> </div> </div> - <!-- /Header --> - - - <div id="searchResults" class="wrap" style="display:none;"> - <h2 id="searchTitle">Results</h2> - <div id="leftSearchControl" class="search-control">Loading...</div> - </div> - - - <?cs if:training || guide || reference || tools || develop || google || samples ?> + <!-- /Sendondary x-nav ABOUT --> + + + + <?cs elif:training || guide || reference || tools || develop || google || samples ?> <!-- Secondary x-nav --> <div id="nav-x"> <div class="wrap"> @@ -231,7 +165,7 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> ru-lang="Курсы" ko-lang="교육" ja-lang="トレーニング" - es-lang="Capacitación" + es-lang="Capacitación" >Training</a></li> <li class="guide"><a href="<?cs var:toroot ?>guide/index.html" zh-tw-lang="API 指南" @@ -239,7 +173,7 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> ru-lang="Руководства по API" ko-lang="API 가이드" ja-lang="API ガイド" - es-lang="Guías de la API" + es-lang="Guías de la API" >API Guides</a></li> <li class="reference"><a href="<?cs var:toroot ?>reference/packages.html" zh-tw-lang="參考資源" @@ -247,9 +181,9 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> ru-lang="Справочник" ko-lang="참조문서" ja-lang="リファレンス" - es-lang="Referencia" + es-lang="Referencia" >Reference</a></li> - <li class="tools"><a href="<?cs var:toroot ?>tools/index.html" + <li class="tools"><a href="<?cs var:toroot ?>sdk/index.html" zh-tw-lang="相關工具" zh-cn-lang="工具" ru-lang="Инструменты" @@ -267,13 +201,101 @@ onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> <?cs /if ?> </ul> </div> - </div> - <!-- /Sendondary x-nav --> + <!-- /Sendondary x-nav DEVELOP --> + + <?cs elif:distribute || googleplay || essentials || users || engage || monetize || disttools || stories ?> + <!-- Secondary distribute x-nav --> + <div id="nav-x"> + <div class="wrap"> + <ul class="nav-x distribute"> + <li class="googleplay"><a href="<?cs var:toroot ?>distribute/googleplay/index.html" + >Google Play</a></li> + <li class="essentials"><a href="<?cs var:toroot ?>distribute/essentials/index.html" + >Essentials</a></li> + <li class="users"><a href="<?cs var:toroot ?>distribute/users/index.html" + >Get Users</a></li> + <li class="engage"><a href="<?cs var:toroot ?>distribute/engage/index.html" + >Engage & Retain</a></li> + <li class="monetize"><a href="<?cs var:toroot ?>distribute/monetize/index.html" + >Monetize</a> + </li> + <li class="disttools"><a href="<?cs var:toroot ?>distribute/tools/index.html" + >Tools</a> + </li> + <li class="stories"><a href="<?cs var:toroot ?>distribute/stories/index.html" + >Stories</a> + </li> + </ul> + <a href="https://play.google.com/apps/publish/" class="developer-console-btn">Developer Console</a> + </div> <!-- /Secondary distribute x-nav --> + </div> + <!-- /Sendondary x-nav DISTRIBUTE --> <?cs /if ?> -<?cs /if ?> -<?cs # end if/else !devsite ?> + <div id="searchResults" class="wrap" style="display:none;"> + <h2 id="searchTitle">Results</h2> + <div id="leftSearchControl" class="search-control">Loading...</div> + </div> + </div> <!--end header-wrapper --> + + <div id="sticky-header"> + <div> + <a class="logo" href="#top"></a> + <a class="top" href="#top"></a> + <ul class="breadcrumb"> + <?cs # More <li> elements added here with javascript ?> + <?cs if:!section.landing ?><li class="current"><?cs var:page.title ?></li><?cs + /if ?> + </ul> + </div> + </div> + +<?cs /if ?><?cs # end if/else !devsite ?> +<?cs /if ?><?cs # end if/else preview ?><?cs +/def ?> + +<?cs def:preview_masthead() ?> +<a name="top"></a> + + +<!-- Header --> +<div id="header-wrapper"> + <div id="header"> + <div class="wrap" id="header-wrap"> + <div class="col_3 logo landing-logo" style="width:240px"> + <a href="<?cs var:toroot ?>preview/index.html"> + <img src="<?cs var:toroot ?>assets/images/android.png" height="25" alt="Android" + style="margin:-3px 0 0" /> + </a> + </div> + <div class="col-8" style="margin:0"><h1 style="margin: 4px 0 0 0px;padding:0;line-height:16px; +color:#666;font-weight:100;font-size:27px;">L Developer Preview</h1></div> + + <?cs # ADD SEARCH AND MENU ?> + <?cs call:header_search_widget() ?> + + </div><!-- end header-wrap --> + </div><!-- /Header --> + + + <div id="searchResults" class="wrap" style="display:none;"> + <h2 id="searchTitle">Results</h2> + <div id="leftSearchControl" class="search-control">Loading...</div> + </div> +</div> <!--end header-wrapper --> + +<div id="sticky-header"> + <div> + <a class="logo" href="#top"></a> + <a class="top" href="#top"></a> + <ul class="breadcrumb"> + <?cs # More <li> elements added here with javascript ?> + <?cs if:!section.landing ?><li class="current"><?cs var:page.title ?></li><?cs + /if ?> + </ul> + </div> +</div> - <?cs + <?cs /def ?> diff --git a/tools/droiddoc/templates-sdk/customizations.cs b/tools/droiddoc/templates-sdk/customizations.cs index ed57f1c..e0e3ca1 100644 --- a/tools/droiddoc/templates-sdk/customizations.cs +++ b/tools/droiddoc/templates-sdk/customizations.cs @@ -7,7 +7,6 @@ def:sdk_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/sdk/sdk_toc.cs" ?> @@ -15,19 +14,53 @@ def:sdk_nav() ?> </div> </div> <!-- end side-nav --> -<?cs /def ?> +<?cs /def ?><?cs + +def:no_nav() ?> + <div class="wrap clearfix" id="body-content"> +<?cs /def ?><?cs + +def:tools_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> <?cs -def:resources_tab_nav() ?> + include:"../../../../frameworks/base/docs/html/tools/tools_toc.cs" ?> + + + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?> +<?cs +def:training_nav() ?> <div class="wrap clearfix" id="body-content"> - <a <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> + <?cs - include:"../../../../frameworks/base/docs/html/resources/resources_toc.cs" ?> + include:"../../../../frameworks/base/docs/html/training/training_toc.cs" ?> + + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs +def:googleplay_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/googleplay/googleplay_toc.cs" ?> </div> </div> <!-- end side-nav --> <script> @@ -35,17 +68,13 @@ def:resources_tab_nav() ?> scrollIntoView("devdoc-nav"); }); </script> -<?cs /def ?> -<?cs -def:tools_nav() ?> +<?cs /def ?><?cs + +def:essentials_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> -<?cs - include:"../../../../frameworks/base/docs/html/tools/tools_toc.cs" ?> - - +<?cs include:"../../../../frameworks/base/docs/html/distribute/essentials/essentials_toc.cs" ?> </div> </div> <!-- end side-nav --> <script> @@ -53,19 +82,55 @@ def:tools_nav() ?> scrollIntoView("devdoc-nav"); }); </script> -<?cs /def ?> -<?cs -def:training_nav() ?> +<?cs /def ?><?cs + +def:users_nav() ?> <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> +<?cs include:"../../../../frameworks/base/docs/html/distribute/users/users_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs +def:engage_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/engage/engage_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs -<?cs - include:"../../../../frameworks/base/docs/html/training/training_toc.cs" ?> - +def:monetize_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/monetize/monetize_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs +def:disttools_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/tools/disttools_toc.cs" ?> </div> </div> <!-- end side-nav --> <script> @@ -73,14 +138,26 @@ def:training_nav() ?> scrollIntoView("devdoc-nav"); }); </script> -<?cs /def ?> -<?cs +<?cs /def ?><?cs + +def:stories_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> +<?cs include:"../../../../frameworks/base/docs/html/distribute/stories/stories_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?><?cs + def:guide_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> - <?cs include:"../../../../frameworks/base/docs/html/guide/guide_toc.cs" ?> @@ -99,7 +176,6 @@ def:design_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs @@ -119,7 +195,6 @@ def:distribute_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/distribute/distribute_toc.cs" ?> @@ -139,7 +214,6 @@ def:samples_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/samples/samples_toc.cs" ?> @@ -159,7 +233,6 @@ def:google_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/google/google_toc.cs" ?> @@ -183,7 +256,6 @@ def:about_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav" class="scroll-pane"> -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <?cs include:"../../../../frameworks/base/docs/html/about/about_toc.cs" ?> @@ -198,6 +270,42 @@ def:about_nav() ?> </script> <?cs /def ?> + +<?cs +def:wear_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> + +<?cs + include:"../../../../frameworks/base/docs/html/wear/wear_toc.cs" ?> + + + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?> + +<?cs +def:preview_nav() ?> + <div class="wrap clearfix" id="body-content"> + <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> + <div id="devdoc-nav" class="scroll-pane"> + <?cs + include:"../../../../frameworks/base/docs/html/preview/preview_toc.cs" ?> + </div> + </div> <!-- end side-nav --> + <script> + $(document).ready(function() { + scrollIntoView("devdoc-nav"); + }); + </script> +<?cs /def ?> + <?cs # The default side navigation for the reference docs ?><?cs def:default_left_nav() ?> <?cs if:reference.gcm || reference.gms ?> @@ -206,8 +314,6 @@ def:default_left_nav() ?> <div class="wrap clearfix" id="body-content"> <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> <div id="devdoc-nav"> - -<a class="totop" href="#top" data-g-event="left-nav-top">to top</a> <div id="api-nav-header"> <div id="api-level-toggle"> <label for="apiLevelCheckbox" class="disabled" @@ -247,6 +353,7 @@ def:default_left_nav() ?> <?cs if:subcount(class.package) ?> <ul> + <?cs call:list("Annotations", class.package.annotations) ?> <?cs call:list("Interfaces", class.package.interfaces) ?> <?cs call:list("Classes", class.package.classes) ?> <?cs call:list("Enums", class.package.enums) ?> @@ -255,6 +362,7 @@ def:default_left_nav() ?> </ul><?cs elif:subcount(package) ?> <ul> + <?cs call:class_link_list("Annotations", package.annotations) ?> <?cs call:class_link_list("Interfaces", package.interfaces) ?> <?cs call:class_link_list("Classes", package.classes) ?> <?cs call:class_link_list("Enums", package.enums) ?> @@ -308,10 +416,111 @@ def:default_left_nav() ?> <?cs /def ?> + +<?cs +def:header_search_widget() ?> +<div class="menu-container"> + <div class="moremenu"> + <div id="more-btn"></div> + </div> + <div class="morehover" id="moremenu"> + <div class="top"></div> + <div class="mid"> + <div class="header">Links</div> + <ul> + <li><a href="https://play.google.com/apps/publish/" target="_googleplay">Google Play Developer Console</a></li> + <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li> + <li><a href="<?cs var:toroot ?>about/index.html">About Android</a></li> + </ul> + <div class="header">Android Sites</div> + <ul> + <li><a href="http://www.android.com">Android.com</a></li> + <li class="active"><a>Android Developers</a></li> + <li><a href="http://source.android.com">Android Open Source Project</a></li> + </ul> + + <?cs # Include language switcher only in online docs ?> + <?cs if:android.whichdoc == "online" ?> + <div class="header">Language</div> + <div id="language" class="locales"> + <select name="language" onChange="changeLangPref(this.value, true)"> + <option value="en">English</option> + <option value="es">Español</option> + <option value="ja">日本語</option> + <option value="ko">한국어</option> + <option value="ru">Русский</option> + <option value="zh-cn">中文 (中国)</option> + <option value="zh-tw">中文 (台灣)</option> + </select> + </div> + <script type="text/javascript"> + <!-- + loadLangPref(); + //--> + </script> + <?cs /if ?> + <?cs # End of lang switcher ?> + <br class="clearfix" /> + </div><!-- end 'mid' --> + <div class="bottom"></div> + </div><!-- end 'moremenu' --> + + <div class="search" id="search-container"> + <div class="search-inner"> + <div id="search-btn"></div> + <div class="left"></div> + <form onsubmit="return submit_search()"> + <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q" + onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)" + onkeydown="return search_changed(event, true, '<?cs var:toroot ?>')" + onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> + </form> + <div class="right"></div> + <a class="close hide">close</a> + <div class="left"></div> + <div class="right"></div> + </div><!-- end search-inner --> + </div><!-- end search-container --> + + <div class="search_filtered_wrapper reference"> + <div class="suggest-card reference no-display"> + <ul class="search_filtered"> + </ul> + </div> + </div> + + <div class="search_filtered_wrapper docs"> + <div class="suggest-card dummy no-display"> </div> + <div class="suggest-card develop no-display"> + <ul class="search_filtered"> + </ul> + <div class="child-card guides no-display"> + </div> + <div class="child-card training no-display"> + </div> + <div class="child-card samples no-display"> + </div> + </div> + <div class="suggest-card design no-display"> + <ul class="search_filtered"> + </ul> + </div> + <div class="suggest-card distribute no-display"> + <ul class="search_filtered"> + </ul> + </div> + </div> +</div><!-- end menu-container (search and menu widget) --> +<?cs /def ?> + + + <?cs def:custom_left_nav() ?><?cs - if:fullpage ?><?cs - call:fullpage() ?><?cs + if:fullpage ?><?cs + call:fullpage() ?><?cs + elif:nonavpage ?><?cs + call:no_nav() ?><?cs elif:guide ?><?cs call:guide_nav() ?><?cs elif:design ?><?cs @@ -324,15 +533,33 @@ def:custom_left_nav() ?><?cs call:google_nav() ?><?cs elif:samples ?><?cs call:samples_nav() ?><?cs - elif:more ?><?cs - call:dist_more_nav() ?><?cs elif:distribute ?><?cs - call:distribute_nav() ?><?cs - elif:about ?><?cs - call:about_nav() ?><?cs - else ?><?cs - call:default_left_nav() ?> <?cs - /if ?><?cs + if:googleplay ?><?cs + call:googleplay_nav() ?><?cs + elif:essentials ?><?cs + call:essentials_nav() ?><?cs + elif:users ?><?cs + call:users_nav() ?><?cs + elif:engage ?><?cs + call:engage_nav() ?><?cs + elif:monetize ?><?cs + call:monetize_nav() ?><?cs + elif:disttools ?><?cs + call:disttools_nav() ?><?cs + elif:stories ?><?cs + call:stories_nav() ?><?cs + /if ?><?cs + elif:about ?><?cs + call:about_nav() ?><?cs + elif:distribute ?><?cs + call:distribute_nav() ?><?cs + elif:wear ?><?cs + call:wear_nav() ?><?cs + elif:preview ?><?cs + call:preview_nav() ?><?cs + else ?><?cs + call:default_left_nav() ?> <?cs + /if ?><?cs /def ?> <?cs # appears at the bottom of every page ?><?cs diff --git a/tools/droiddoc/templates-sdk/docpage.cs b/tools/droiddoc/templates-sdk/docpage.cs index ea462c9..4d1404b 100644 --- a/tools/droiddoc/templates-sdk/docpage.cs +++ b/tools/droiddoc/templates-sdk/docpage.cs @@ -2,19 +2,36 @@ <?cs include:"macros.cs" ?> <html<?cs if:devsite ?> devsite<?cs /if ?>> <?cs include:"head_tag.cs" ?> -<body class="gc-documentation <?cs if:(google || reference.gms || reference.gcm) ?>google<?cs /if ?> - <?cs if:(guide||develop||training||reference||tools||sdk||samples) ?>develop<?cs if:guide ?> guide<?cs /if ?><?cs if:samples ?> samples<?cs /if ?><?cs - elif:about ?>about<?cs +<body class="gc-documentation + +<?cs +if:(google || reference.gms || reference.gcm) ?>google<?cs /if ?><?cs + if:(guide||develop||training||reference||tools||sdk||samples) ?>develop<?cs + if:guide ?> guide<?cs /if ?><?cs + if:samples ?> samples<?cs /if ?><?cs + elif:(distribute||googleplay||essentials||users||engage||monetize||disttools||stories) + ?>distribute<?cs + if:googleplay ?> googleplay<?cs /if ?><?cs + if:essentials ?> essentials<?cs /if ?><?cs + if:users ?> users<?cs /if ?><?cs + if:engage ?> engage<?cs /if ?><?cs + if:monetize ?> monetize<?cs /if ?><?cs + if:disttools ?> disttools<?cs /if ?><?cs + if:stories ?> stories<?cs /if ?><?cs + elif:(about||wear||tv||auto) ?>about<?cs elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?><?cs - if:page.trainingcourse ?> trainingcourse<?cs /if ?>" itemscope itemtype="http://schema.org/Article"> -<?cs include:"header.cs" ?> +/if ?><?cs +if:page.trainingcourse ?> trainingcourse<?cs +/if ?>" itemscope itemtype="http://schema.org/Article"><?cs +include:"header.cs" ?> -<div <?cs if:fullpage -?>class="fullpage"<?cs elif:design||tools||about||sdk||distribute -?>class="col-13" id="doc-col"<?cs else -?>class="col-12" id="doc-col"<?cs /if ?> > +<div <?cs + if:fullpage + ?>class="fullpage"<?cs + elif:(design||tools||about||sdk||googleplay||essentials||users||monetize||disttools) && !nonavpage + ?>class="col-13" id="doc-col"<?cs + elif:!nonavpage + ?>class="col-12" id="doc-col"<?cs /if ?> > <?cs if:(design||training||walkthru) && !page.trainingcourse && !page.article ?><?cs # header logic for docs that provide previous/next buttons ?> <?cs if:header.hide ?> @@ -73,7 +90,8 @@ </div> <?cs /if ?><?cs # end if training ?> </div> - <?cs /if ?> + <?cs /if ?><?cs # end if header.hide ?> + <?cs elif:samplesProjectIndex ?> <div id="api-info-block"> <div class="sum-details-links"> @@ -83,7 +101,17 @@ </div><!-- end sum-details-links --> </div><!-- end breadcurmb block --> <h1 itemprop="name"><?cs var:projectDir ?></h1> + <?cs else ?> + <?cs if:training ?> +<?cs # horrible horrible hack to move TOC up when the next/prev links are not there ?> +<style> + #tb-wrapper { + margin-top:6px; + } +</style> + <?cs /if ?> + <?cs if:(!fullpage && !header.hide) ?> <?cs if:page.landing ?><?cs # header logic for docs that are landing pages ?> <div class="landing-banner"> @@ -129,25 +157,9 @@ if:fullpage ?>wrap<?cs else ?>layout-content-row<?cs /if ?>" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div class="layout-content-col <?cs - if:fullpage ?>col-16<?cs - elif:training||guide ?>col-8<?cs - else ?>col-9<?cs /if ?>" style="padding-top:4px"> - <?cs if:!page.noplus ?><?cs if:fullpage ?><style>#___plusone_0 {float:right !important;}</style><?cs /if ?> - <div class="g-plusone" data-size="medium"></div> - <?cs /if ?> - </div> <?cs if:!fullscreen ?> - <div class="paging-links layout-content-col col-4"> + <div class="paging-links layout-content-col col-10"> <?cs if:(design||training||walkthru) && !page.landing && !page.trainingcourse && !footer.hide ?> - <a href="#" class="prev-page-link hide" - zh-tw-lang="上一堂課" - zh-cn-lang="上一课" - ru-lang="Предыдущий" - ko-lang="이전" - ja-lang="前へ" - es-lang="Anterior" - >Previous</a> <a href="#" class="next-page-link hide" zh-tw-lang="下一堂課" zh-cn-lang="下一课" @@ -164,35 +176,29 @@ ja-lang="開始する" es-lang="Empezar" >Get started</a> + <a href="#" class="next-class-link hide">Next class</a> + <?cs /if ?> + </div> + <div class="layout-content-col plus-container col-2" > + <?cs if:!page.noplus ?><?cs if:fullpage ?><style>#___plusone_0 {float:right !important;}</style><?cs /if ?> + <div class="g-plusone" data-size="medium"></div> <?cs /if ?> </div> <?cs /if ?> </div> - <?cs # for training classes, provide a different kind of link when the next page is a different class ?> - <?cs if:training && !page.article ?> - <div class="layout-content-row content-footer next-class" style="display:none" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <a href="#" class="next-class-link hide">Next class: </a> - </div> - <?cs /if ?> - </div> <!-- end jd-content --> <?cs include:"footer.cs" ?> </div><!-- end doc-content --> <?cs include:"trailer.cs" ?> + <script src="https://developer.android.com/ytblogger_lists_unified.js" type="text/javascript"></script> + <script src="<?cs var:toroot ?>jd_lists_unified.js?v=2" type="text/javascript"></script> + <script src="<?cs var:toroot ?>jd_extras.js?v=2" type="text/javascript"></script> + <script src="<?cs var:toroot ?>jd_collections.js?v=2" type="text/javascript"></script> + <script src="<?cs var:toroot ?>jd_tag_helpers.js?v=2" type="text/javascript"></script> -<!-- Start of Tag --> -<script type="text/javascript"> -var axel = Math.random() + ""; -var a = axel * 10000000000000; -document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>'); -</script> -<noscript> -<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe> -</noscript> -<!-- End of Tag --> </body> </html> diff --git a/tools/droiddoc/templates-sdk/head_tag.cs b/tools/droiddoc/templates-sdk/head_tag.cs index 54de169..7ecb7f9 100644 --- a/tools/droiddoc/templates-sdk/head_tag.cs +++ b/tools/droiddoc/templates-sdk/head_tag.cs @@ -15,13 +15,13 @@ ?><?cs # END if/else devsite ?> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="viewport" content="width=device-width" /> +<meta name="viewport" content="width=<?cs + if:page.viewport_width ?><?cs + var:page.viewport_width ?><?cs + else ?>device-width<?cs /if ?>" /> <?cs if:page.metaDescription ?> <meta name="Description" content="<?cs var:page.metaDescription ?>"><?cs - /if ?><?cs - if:page.customHeadTag ?> -<?cs var:page.customHeadTag ?><?cs /if ?> <link rel="shortcut icon" type="image/x-icon" href="<?cs var:toroot ?>favicon.ico" /> <title><?cs @@ -31,10 +31,16 @@ <!-- STYLESHEETS --> <link rel="stylesheet" -href="<?cs if:android.whichdoc != 'online' ?>http:<?cs /if ?>//fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic,bold" title="roboto"> -<link href="<?cs var:toroot ?>assets/css/default.css" rel="stylesheet" type="text/css"> +href="<?cs +if:android.whichdoc != 'online' ?>http:<?cs +/if ?>//fonts.googleapis.com/css?family=Roboto+Condensed"> +<link rel="stylesheet" href="<?cs +if:android.whichdoc != 'online' ?>http:<?cs +/if ?>//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" + title="roboto"> +<link href="<?cs var:toroot ?>assets/css/default.css?v=2" rel="stylesheet" type="text/css"> -<?cs if:reference && !(reference.gms || reference.gcm) ?> +<?cs if:reference && !(reference.gms || reference.gcm || preview) ?> <!-- FULLSCREEN STYLESHEET --> <link href="<?cs var:toroot ?>assets/css/fullscreen.css" rel="stylesheet" class="fullscreen" type="text/css"> @@ -47,23 +53,27 @@ if:devsite ?><script src="<?cs var:toroot ?>_static/js/android_3p-bundle.js" type="text/javascript"></script><?cs else ?><script src="<?cs var:toroot ?>assets/js/android_3p-bundle.js" type="text/javascript"></script><?cs -/if ?> +/if ?><?cs + if:page.customHeadTag ?> +<?cs var:page.customHeadTag ?><?cs + /if ?> <script type="text/javascript"> var toRoot = "<?cs var:toroot ?>"; var metaTags = [<?cs var:meta.tags ?>]; var devsite = <?cs if:devsite ?>true<?cs else ?>false<?cs /if ?>; </script> -<script src="<?cs var:toroot ?>assets/js/docs.js" type="text/javascript"></script> +<script src="<?cs var:toroot ?>assets/js/docs.js?v=2" type="text/javascript"></script> -<script type="text/javascript"> - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-5831155-1']); - _gaq.push(['_trackPageview']); +<script> + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); + ga('create', 'UA-5831155-1', 'android.com'); + ga('create', 'UA-49880327-2', 'android.com', {'name': 'universal'}); // New tracker); + ga('send', 'pageview'); + ga('universal.send', 'pageview'); // Send page view for new tracker. </script> -</head>
\ No newline at end of file + +</head> diff --git a/tools/droiddoc/templates-sdk/package.cs b/tools/droiddoc/templates-sdk/package.cs index 99eaff2..abd49f1 100644 --- a/tools/droiddoc/templates-sdk/package.cs +++ b/tools/droiddoc/templates-sdk/package.cs @@ -45,6 +45,7 @@ <?cs /if ?> <?cs /def ?> +<?cs call:class_table("Annotations", package.annotations) ?> <?cs call:class_table("Interfaces", package.interfaces) ?> <?cs call:class_table("Classes", package.classes) ?> <?cs call:class_table("Enums", package.enums) ?> diff --git a/tools/droiddoc/templates-sdk/sdkpage.cs b/tools/droiddoc/templates-sdk/sdkpage.cs index 95f6596..87c5725 100644 --- a/tools/droiddoc/templates-sdk/sdkpage.cs +++ b/tools/droiddoc/templates-sdk/sdkpage.cs @@ -77,7 +77,7 @@ <table class="download" id="download-table"> <tr> - <th>Platform</th> + <th>Platform<br>(32-bit target)</th> <th>Package</th> <th style="white-space:nowrap">Size (Bytes)</th> <th>MD5 Checksum</th> @@ -183,8 +183,117 @@ <td><?cs var:ndk.linux64.legacy_bytes ?></td> <td><?cs var:ndk.linux64.legacy_checksum ?></td> </tr> --> + + <tr> + <th>Platform<br>(64-bit target)</th> + <th>Package</th> + <th style="white-space:nowrap">Size (Bytes)</th> + <th>MD5 Checksum</th> + </tr> + <tr> + <td>Windows 32-bit</td> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.win32_64_download ?>"><?cs var:ndk.win32_64_download ?></a> + </td> + <td><?cs var:ndk.win32_64_bytes ?></td> + <td><?cs var:ndk.win32_64_checksum ?></td> + </tr> + <!-- <tr> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.win32.legacy_download ?>"><?cs var:ndk.win32.legacy_download ?></a> + </td> + <td><?cs var:ndk.win32.legacy_bytes ?></td> + <td><?cs var:ndk.win32.legacy_checksum ?></td> + </tr> --> + <tr> + <td>Windows 64-bit</td> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.win64_64_download ?>"><?cs var:ndk.win64_64_download ?></a> + </td> + <td><?cs var:ndk.win64_64_bytes ?></td> + <td><?cs var:ndk.win64_64_checksum ?></td> + </tr> + <!-- <tr> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.win64.legacy_download ?>"><?cs var:ndk.win64.legacy_download ?></a> + </td> + <td><?cs var:ndk.win64.legacy_bytes ?></td> + <td><?cs var:ndk.win64.legacy_checksum ?></td> + </tr> --> + <tr> + <td>Mac OS X 32-bit</td> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.mac32_64_download ?>"><?cs var:ndk.mac32_64_download ?></a> + </td> + <td><?cs var:ndk.mac32_64_bytes ?></td> + <td><?cs var:ndk.mac32_64_checksum ?></td> + </tr> + <!-- <tr> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.mac32.legacy_download ?>"><?cs var:ndk.mac32.legacy_download ?></a> + </td> + <td><?cs var:ndk.mac32.legacy_bytes ?></td> + <td><?cs var:ndk.mac32.legacy_checksum ?></td> + </tr> --> + <td>Mac OS X 64-bit</td> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.mac64_64_download ?>"><?cs var:ndk.mac64_64_download ?></a> + </td> + <td><?cs var:ndk.mac64_64_bytes ?></td> + <td><?cs var:ndk.mac64_64_checksum ?></td> + </tr> + <!-- <tr> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.mac64.legacy_download ?>"><?cs var:ndk.mac64.legacy_download ?></a> + </td> + <td><?cs var:ndk.mac64.legacy_bytes ?></td> + <td><?cs var:ndk.mac64.legacy_checksum ?></td> + </tr> --> + <tr> + <td>Linux 32-bit (x86)</td> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.linux32_64_download ?>"><?cs var:ndk.linux32_64_download ?></a> + </td> + <td><?cs var:ndk.linux32_64_bytes ?></td> + <td><?cs var:ndk.linux32_64_checksum ?></td> + </tr> + <!-- <tr> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.linux32.legacy_download ?>"><?cs var:ndk.linux32.legacy_download ?></a> + </td> + <td><?cs var:ndk.linux32.legacy_bytes ?></td> + <td><?cs var:ndk.linux32.legacy_checksum ?></td> + </tr> --> + <tr> + <td>Linux 64-bit (x86)</td> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.linux64_64_download ?>"><?cs var:ndk.linux64_64_download ?></a> + </td> + <td><?cs var:ndk.linux64_64_bytes ?></td> + <td><?cs var:ndk.linux64_64_checksum ?></td> + </tr> + <!-- <tr> + <td> + <a onClick="return onDownload(this)" + href="http://dl.google.com/android/ndk/<?cs var:ndk.linux64.legacy_download ?>"><?cs var:ndk.linux64.legacy_download ?></a> + </td> + <td><?cs var:ndk.linux64.legacy_bytes ?></td> + <td><?cs var:ndk.linux64.legacy_checksum ?></td> + </tr> --> + <tr> - <th>Additional Download</th> + <th>Additional Download<br>(32-, 64-bit)</th> <th>Package</th> <th style="white-space:nowrap">Size (Bytes)</th> <th>MD5 Checksum</th> @@ -280,7 +389,7 @@ <h4><a href='' class="expandable" onclick="toggleExpandable(this,'.pax');hideExpandable('.myide,.reqs');return false;" - >DOWNLOAD FOR OTHER PLATFORMS</a></h4> + >VIEW ALL DOWNLOADS AND SIZES</a></h4> <div class="pax col-13 online" style="display:none;margin:0;"> @@ -298,7 +407,7 @@ <td>Windows 32-bit</td> <td> <a onClick="return onDownload(this)" id="win-bundle32" - href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.win32_bundle_download ?>"><?cs var:sdk.win32_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.win32_bundle_download ?>"><?cs var:sdk.win32_bundle_download ?></a> </td> <td><?cs var:sdk.win32_bundle_bytes ?> bytes</td> <td><?cs var:sdk.win32_bundle_checksum ?></td> @@ -307,7 +416,7 @@ <td>Windows 64-bit</td> <td> <a onClick="return onDownload(this)" id="win-bundle64" - href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.win64_bundle_download ?>"><?cs var:sdk.win64_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.win64_bundle_download ?>"><?cs var:sdk.win64_bundle_download ?></a> </td> <td><?cs var:sdk.win64_bundle_bytes ?> bytes</td> <td><?cs var:sdk.win64_bundle_checksum ?></td> @@ -316,7 +425,7 @@ <td><nobr>Mac OS X 64-bit</nobr></td> <td> <a onClick="return onDownload(this)" id="mac-bundle64" - href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.mac64_bundle_download ?>"><?cs var:sdk.mac64_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.mac64_bundle_download ?>"><?cs var:sdk.mac64_bundle_download ?></a> </td> <td><?cs var:sdk.mac64_bundle_bytes ?> bytes</td> <td><?cs var:sdk.mac64_bundle_checksum ?></td> @@ -325,7 +434,7 @@ <td>Linux 32-bit</td> <td> <a onClick="return onDownload(this)" id="linux-bundle32" - href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.linux32_bundle_download ?>"><?cs var:sdk.linux32_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.linux32_bundle_download ?>"><?cs var:sdk.linux32_bundle_download ?></a> </td> <td><?cs var:sdk.linux32_bundle_bytes ?> bytes</td> <td><?cs var:sdk.linux32_bundle_checksum ?></td> @@ -334,7 +443,7 @@ <td>Linux 64-bit</td> <td> <a onClick="return onDownload(this)" id="linux-bundle64" - href="http://dl.google.com/android/adt/<?cs var:sdk.version ?>/<?cs var:sdk.linux64_bundle_download ?>"><?cs var:sdk.linux64_bundle_download ?></a> + href="http://dl.google.com/android/adt/<?cs var:sdk.linux64_bundle_download ?>"><?cs var:sdk.linux64_bundle_download ?></a> </td> <td><?cs var:sdk.linux64_bundle_bytes ?> bytes</td> <td><?cs var:sdk.linux64_bundle_checksum ?></td> @@ -430,12 +539,12 @@ var:sdk.linux_download /* set up primary adt download button */ $('#download-bundle-button').show(); - $('#download-bundle-button').append("Download the SDK <br/><span class='small'>ADT Bundle for " + os + "</span>"); + $('#download-bundle-button').append("Download Eclipse ADT <br/><span class='small'>with the Android SDK for " + os + "</span>"); $('#download-bundle-button').click(function() {return onDownload(this,true,true);}).attr('href', bundlename); /* set up sdk tools only button */ $('#download-tools-button').show(); - $('#download-tools-button').append("Download the SDK Tools for " + os); + $('#download-tools-button').append("Download the stand-alone Android SDK Tools for " + os); $('#download-tools-button').click(function() {return onDownload(this,true);}).attr('href', $toolslink.attr('href')); } else { $('.pax').show(); @@ -501,9 +610,18 @@ var:sdk.linux_download function onDownloadForRealz(link) { if ($("input#agree").is(':checked') && $("#bitpicker input:checked").length) { $("div.sdk-terms").slideUp(); - $("#sdk-terms-form,.sdk-terms-intro").fadeOut('slow'); - $("#next-steps").fadeIn('slow'); - $("h1#tos-header").text('Get Ready to Code!'); + $("h1#tos-header").text('Now redirecting to the install instructions...'); + $("#sdk-terms-form,.sdk-terms-intro").fadeOut('slow', function() { + setTimeout(function() { + if ($("#downloadForRealz").attr('bundle') == 'true') { + // User downloaded the ADT Bundle + window.location = "/sdk/installing/index.html?pkg=adt"; + } else { + // User downloaded the SDK Tools + window.location = "/sdk/installing/index.html?pkg=tools"; + } + }, 500); + }); _gaq.push(['_trackEvent', 'SDK', 'ADT and Tools', $("#downloadForRealz").html()]); return true; } else { diff --git a/tools/post_process_props.py b/tools/post_process_props.py index 32a90bc..030826d 100755 --- a/tools/post_process_props.py +++ b/tools/post_process_props.py @@ -16,6 +16,9 @@ import sys +# Usage: post_process_props.py file.prop [blacklist_key, ...] +# Blacklisted keys are removed from the property file, if present + # See PROP_NAME_MAX and PROP_VALUE_MAX system_properties.h. # The constants in system_properties.h includes the termination NUL, # so we decrease the values by 1 here. @@ -88,8 +91,9 @@ class PropFile: for line in self.lines: if not line or line.startswith("#"): continue - key, value = line.split("=", 1) - props[key] = value + if "=" in line: + key, value = line.split("=", 1) + props[key] = value return props def get(self, name): @@ -107,6 +111,10 @@ class PropFile: return self.lines.append(key + value) + def delete(self, name): + key = name + "=" + self.lines = [ line for line in self.lines if not line.startswith(key) ] + def write(self, f): f.write("\n".join(self.lines)) f.write("\n") @@ -130,6 +138,10 @@ def main(argv): if not validate(properties): sys.exit(1) + # Drop any blacklisted keys + for key in argv[2:]: + properties.delete(key) + f = open(filename, 'w+') properties.write(f) f.close() diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py index f8f2ada..712e0cd 100755 --- a/tools/releasetools/build_image.py +++ b/tools/releasetools/build_image.py @@ -24,6 +24,13 @@ import os import os.path import subprocess import sys +import commands +import shutil +import tempfile + +import simg_map + +FIXED_SALT = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7" def RunCommand(cmd): """ Echo and run the given command @@ -38,13 +45,182 @@ def RunCommand(cmd): p.communicate() return p.returncode -def BuildImage(in_dir, prop_dict, out_file): +def GetVerityTreeSize(partition_size): + cmd = "build_verity_tree -s %d" + cmd %= partition_size + status, output = commands.getstatusoutput(cmd) + if status: + print output + return False, 0 + return True, int(output) + +def GetVerityMetadataSize(partition_size): + cmd = "system/extras/verity/build_verity_metadata.py -s %d" + cmd %= partition_size + status, output = commands.getstatusoutput(cmd) + if status: + print output + return False, 0 + return True, int(output) + +def AdjustPartitionSizeForVerity(partition_size): + """Modifies the provided partition size to account for the verity metadata. + + This information is used to size the created image appropriately. + Args: + partition_size: the size of the partition to be verified. + Returns: + The size of the partition adjusted for verity metadata. + """ + success, verity_tree_size = GetVerityTreeSize(partition_size) + if not success: + return 0; + success, verity_metadata_size = GetVerityMetadataSize(partition_size) + if not success: + return 0 + return partition_size - verity_tree_size - verity_metadata_size + +def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict): + cmd = ("build_verity_tree -A %s %s %s" % (FIXED_SALT, sparse_image_path, verity_image_path)) + print cmd + status, output = commands.getstatusoutput(cmd) + if status: + print "Could not build verity tree! Error: %s" % output + return False + root, salt = output.split() + prop_dict["verity_root_hash"] = root + prop_dict["verity_salt"] = salt + return True + +def BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt, + block_device, signer_path, key): + cmd = ("system/extras/verity/build_verity_metadata.py %s %s %s %s %s %s %s" % + (image_size, + verity_metadata_path, + root_hash, + salt, + block_device, + signer_path, + key)) + print cmd + status, output = commands.getstatusoutput(cmd) + if status: + print "Could not build verity metadata! Error: %s" % output + return False + return True + +def Append2Simg(sparse_image_path, unsparse_image_path, error_message): + """Appends the unsparse image to the given sparse image. + + Args: + sparse_image_path: the path to the (sparse) image + unsparse_image_path: the path to the (unsparse) image + Returns: + True on success, False on failure. + """ + cmd = "append2simg %s %s" + cmd %= (sparse_image_path, unsparse_image_path) + print cmd + status, output = commands.getstatusoutput(cmd) + if status: + print "%s: %s" % (error_message, output) + return False + return True + +def BuildVerifiedImage(data_image_path, verity_image_path, verity_metadata_path): + if not Append2Simg(data_image_path, verity_metadata_path, "Could not append verity metadata!"): + return False + if not Append2Simg(data_image_path, verity_image_path, "Could not append verity tree!"): + return False + return True + +def UnsparseImage(sparse_image_path, replace=True): + img_dir = os.path.dirname(sparse_image_path) + unsparse_image_path = "unsparse_" + os.path.basename(sparse_image_path) + unsparse_image_path = os.path.join(img_dir, unsparse_image_path) + if os.path.exists(unsparse_image_path): + if replace: + os.unlink(unsparse_image_path) + else: + return True, unsparse_image_path + inflate_command = ["simg2img", sparse_image_path, unsparse_image_path] + exit_code = RunCommand(inflate_command) + if exit_code != 0: + os.remove(unsparse_image_path) + return False, None + return True, unsparse_image_path + +def MappedUnsparseImage(sparse_image_path, unsparse_image_path, + map_path, mapped_unsparse_image_path): + if simg_map.ComputeMap(sparse_image_path, unsparse_image_path, + map_path, mapped_unsparse_image_path): + return False + return True + +def MakeVerityEnabledImage(out_file, prop_dict): + """Creates an image that is verifiable using dm-verity. + + Args: + out_file: the location to write the verifiable image at + prop_dict: a dictionary of properties required for image creation and verification + Returns: + True on success, False otherwise. + """ + # get properties + image_size = prop_dict["partition_size"] + block_dev = prop_dict["verity_block_device"] + signer_key = prop_dict["verity_key"] + signer_path = prop_dict["verity_signer_cmd"] + + # make a tempdir + tempdir_name = tempfile.mkdtemp(suffix="_verity_images") + + # get partial image paths + verity_image_path = os.path.join(tempdir_name, "verity.img") + verity_metadata_path = os.path.join(tempdir_name, "verity_metadata.img") + + # build the verity tree and get the root hash and salt + if not BuildVerityTree(out_file, verity_image_path, prop_dict): + shutil.rmtree(tempdir_name, ignore_errors=True) + return False + + # build the metadata blocks + root_hash = prop_dict["verity_root_hash"] + salt = prop_dict["verity_salt"] + if not BuildVerityMetadata(image_size, + verity_metadata_path, + root_hash, + salt, + block_dev, + signer_path, + signer_key): + shutil.rmtree(tempdir_name, ignore_errors=True) + return False + + # build the full verified image + if not BuildVerifiedImage(out_file, + verity_image_path, + verity_metadata_path): + shutil.rmtree(tempdir_name, ignore_errors=True) + return False + + shutil.rmtree(tempdir_name, ignore_errors=True) + return True + +def BuildImage(in_dir, prop_dict, out_file, + fs_config=None, + fc_config=None): """Build an image to out_file from in_dir with property prop_dict. Args: in_dir: path of input directory. prop_dict: property dictionary. out_file: path of the output image file. + fs_config: path to the fs_config file (typically + META/filesystem_config.txt). If None then the configuration in + the local client will be used. + fc_config: path to the SELinux file_contexts file. If None then + the value from prop_dict['selinux_fc'] will be used. Returns: True iff the image is built successfully. @@ -52,6 +228,18 @@ def BuildImage(in_dir, prop_dict, out_file): build_command = [] fs_type = prop_dict.get("fs_type", "") run_fsck = False + + is_verity_partition = "verity_block_device" in prop_dict + verity_supported = prop_dict.get("verity") == "true" + # adjust the partition size to make room for the hashes if this is to be verified + if verity_supported and is_verity_partition: + partition_size = int(prop_dict.get("partition_size")) + adjusted_size = AdjustPartitionSizeForVerity(partition_size) + if not adjusted_size: + return False + prop_dict["partition_size"] = str(adjusted_size) + prop_dict["original_partition_size"] = str(partition_size) + if fs_type.startswith("ext"): build_command = ["mkuserimg.sh"] if "extfs_sparse_flag" in prop_dict: @@ -59,10 +247,18 @@ def BuildImage(in_dir, prop_dict, out_file): run_fsck = True build_command.extend([in_dir, out_file, fs_type, prop_dict["mount_point"]]) - if "partition_size" in prop_dict: - build_command.append(prop_dict["partition_size"]) - if "selinux_fc" in prop_dict: + build_command.append(prop_dict["partition_size"]) + if "timestamp" in prop_dict: + build_command.extend(["-T", str(prop_dict["timestamp"])]) + if fs_config is not None: + build_command.extend(["-C", fs_config]) + if fc_config is not None: + build_command.append(fc_config) + elif "selinux_fc" in prop_dict: build_command.append(prop_dict["selinux_fc"]) + elif fs_type.startswith("f2fs"): + build_command = ["mkf2fsuserimg.sh"] + build_command.extend([out_file, prop_dict["partition_size"]]) else: build_command = ["mkyaffs2image", "-f"] if prop_dict.get("mkyaffs2_extra_flags", None): @@ -77,14 +273,14 @@ def BuildImage(in_dir, prop_dict, out_file): if exit_code != 0: return False + # create the verified image if this is to be verified + if verity_supported and is_verity_partition: + if not MakeVerityEnabledImage(out_file, prop_dict): + return False + if run_fsck and prop_dict.get("skip_fsck") != "true": - # Inflate the sparse image - unsparse_image = os.path.join( - os.path.dirname(out_file), "unsparse_" + os.path.basename(out_file)) - inflate_command = ["simg2img", out_file, unsparse_image] - exit_code = RunCommand(inflate_command) - if exit_code != 0: - os.remove(unsparse_image) + success, unsparse_image = UnsparseImage(out_file, replace=False) + if not success: return False # Run e2fsck on the inflated image file @@ -104,6 +300,10 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): mount_point: such as "system", "data" etc. """ d = {} + if "build.prop" in glob_dict: + bp = glob_dict["build.prop"] + if "ro.build.date.utc" in bp: + d["timestamp"] = bp["ro.build.date.utc"] def copy_prop(src_p, dest_p): if src_p in glob_dict: @@ -114,6 +314,9 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): "mkyaffs2_extra_flags", "selinux_fc", "skip_fsck", + "verity", + "verity_key", + "verity_signer_cmd" ) for p in common_props: copy_prop(p, p) @@ -122,8 +325,11 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): if mount_point == "system": copy_prop("fs_type", "fs_type") copy_prop("system_size", "partition_size") + copy_prop("system_verity_block_device", "verity_block_device") elif mount_point == "data": + # Copy the generic fs type first, override with specific one if available. copy_prop("fs_type", "fs_type") + copy_prop("userdata_fs_type", "fs_type") copy_prop("userdata_size", "partition_size") elif mount_point == "cache": copy_prop("cache_fs_type", "fs_type") @@ -131,6 +337,10 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): elif mount_point == "vendor": copy_prop("vendor_fs_type", "fs_type") copy_prop("vendor_size", "partition_size") + copy_prop("vendor_verity_block_device", "verity_block_device") + elif mount_point == "oem": + copy_prop("fs_type", "fs_type") + copy_prop("oem_size", "partition_size") return d @@ -169,6 +379,8 @@ def main(argv): mount_point = "cache" elif image_filename == "vendor.img": mount_point = "vendor" + elif image_filename == "oem.img": + mount_point = "oem" else: print >> sys.stderr, "error: unknown image file name ", image_filename exit(1) diff --git a/tools/releasetools/check_target_files_signatures b/tools/releasetools/check_target_files_signatures index 45d30a6..b2f46c1 100755 --- a/tools/releasetools/check_target_files_signatures +++ b/tools/releasetools/check_target_files_signatures @@ -41,8 +41,8 @@ Usage: check_target_file_signatures [flags] target_files import sys -if sys.hexversion < 0x02040000: - print >> sys.stderr, "Python 2.4 or newer is required." +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." sys.exit(1) import os diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index b992da3..0da5f35 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -84,17 +84,24 @@ def CloseInheritedPipes(): pass -def LoadInfoDict(zip): +def LoadInfoDict(input): """Read and parse the META/misc_info.txt key/value pairs from the input target files and return a dict.""" + def read_helper(fn): + if isinstance(input, zipfile.ZipFile): + return input.read(fn) + else: + path = os.path.join(input, *fn.split("/")) + try: + with open(path) as f: + return f.read() + except IOError, e: + if e.errno == errno.ENOENT: + raise KeyError(fn) d = {} try: - for line in zip.read("META/misc_info.txt").split("\n"): - line = line.strip() - if not line or line.startswith("#"): continue - k, v = line.split("=", 1) - d[k] = v + d = LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("\n")) except KeyError: # ok if misc_info.txt doesn't exist pass @@ -105,20 +112,20 @@ def LoadInfoDict(zip): if "mkyaffs2_extra_flags" not in d: try: - d["mkyaffs2_extra_flags"] = zip.read("META/mkyaffs2-extra-flags.txt").strip() + d["mkyaffs2_extra_flags"] = read_helper("META/mkyaffs2-extra-flags.txt").strip() except KeyError: # ok if flags don't exist pass if "recovery_api_version" not in d: try: - d["recovery_api_version"] = zip.read("META/recovery-api-version.txt").strip() + d["recovery_api_version"] = read_helper("META/recovery-api-version.txt").strip() except KeyError: raise ValueError("can't find recovery API version in input target-files") if "tool_extensions" not in d: try: - d["tool_extensions"] = zip.read("META/tool-extensions.txt").strip() + d["tool_extensions"] = read_helper("META/tool-extensions.txt").strip() except KeyError: # ok if extensions don't exist pass @@ -127,7 +134,7 @@ def LoadInfoDict(zip): d["fstab_version"] = "1" try: - data = zip.read("META/imagesizes.txt") + data = read_helper("META/imagesizes.txt") for line in data.split("\n"): if not line: continue name, value = line.split(" ", 1) @@ -146,39 +153,43 @@ def LoadInfoDict(zip): makeint("recovery_api_version") makeint("blocksize") makeint("system_size") + makeint("vendor_size") makeint("userdata_size") makeint("cache_size") makeint("recovery_size") makeint("boot_size") makeint("fstab_version") - d["fstab"] = LoadRecoveryFSTab(zip, d["fstab_version"]) - d["build.prop"] = LoadBuildProp(zip) + d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"]) + d["build.prop"] = LoadBuildProp(read_helper) return d -def LoadBuildProp(zip): +def LoadBuildProp(read_helper): try: - data = zip.read("SYSTEM/build.prop") + data = read_helper("SYSTEM/build.prop") except KeyError: print "Warning: could not find SYSTEM/build.prop in %s" % zip data = "" + return LoadDictionaryFromLines(data.split("\n")) +def LoadDictionaryFromLines(lines): d = {} - for line in data.split("\n"): + for line in lines: line = line.strip() if not line or line.startswith("#"): continue - name, value = line.split("=", 1) - d[name] = value + if "=" in line: + name, value = line.split("=", 1) + d[name] = value return d -def LoadRecoveryFSTab(zip, fstab_version): +def LoadRecoveryFSTab(read_helper, fstab_version): class Partition(object): pass try: - data = zip.read("RECOVERY/RAMDISK/etc/recovery.fstab") + data = read_helper("RECOVERY/RAMDISK/etc/recovery.fstab") except KeyError: - print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab in %s." % zip + print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab" data = "" if fstab_version == 1: @@ -347,9 +358,12 @@ def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir, else: print "building image from target_files %s..." % (tree_subdir,) fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt" - return File(name, BuildBootableImage(os.path.join(unpack_dir, tree_subdir), - os.path.join(unpack_dir, fs_config), - info_dict)) + data = BuildBootableImage(os.path.join(unpack_dir, tree_subdir), + os.path.join(unpack_dir, fs_config), + info_dict) + if data: + return File(name, data) + return None def UnzipTemp(filename, pattern=None): @@ -490,6 +504,8 @@ def CheckSize(data, target, info_dict): if target.endswith(".img"): target = target[:-4] mount_point = "/" + target + fs_type = None + limit = None if info_dict["fstab"]: if mount_point == "/userdata": mount_point = "/data" p = info_dict["fstab"][mount_point] @@ -730,11 +746,14 @@ class PasswordManager(object): return result -def ZipWriteStr(zip, filename, data, perms=0644): +def ZipWriteStr(zip, filename, data, perms=0644, compression=None): # use a fixed timestamp so the output is repeatable. zinfo = zipfile.ZipInfo(filename=filename, date_time=(2009, 1, 1, 0, 0, 0)) - zinfo.compress_type = zip.compression + if compression is None: + zinfo.compress_type = zip.compression + else: + zinfo.compress_type = compression zinfo.external_attr = perms << 16 zip.writestr(zinfo, data) @@ -761,6 +780,7 @@ class DeviceSpecificParams(object): if x == ".py": f = b info = imp.find_module(f, [d]) + print "loaded device-specific extensions from", path self.module = imp.load_module("device_specific", *info) except ImportError: print "unable to load device-specific module; assuming none" @@ -839,8 +859,8 @@ class File(object): t.flush() return t - def AddToZip(self, z): - ZipWriteStr(z, self.name, self.data) + def AddToZip(self, z, compression=None): + ZipWriteStr(z, self.name, self.data, compression=compression) DIFF_PROGRAM_BY_EXT = { ".gz" : "imgdiff", @@ -954,7 +974,8 @@ def ComputeDifferences(diffs): # map recovery.fstab's fs_types to mount/format "partition types" PARTITION_TYPES = { "yaffs2": "MTD", "mtd": "MTD", - "ext4": "EMMC", "emmc": "EMMC" } + "ext4": "EMMC", "emmc": "EMMC", + "f2fs": "EMMC" } def GetTypeAndDevice(mount_point, info): fstab = info["fstab"] @@ -977,3 +998,101 @@ def ParseCertificate(data): save = True cert = "".join(cert).decode('base64') return cert + +def XDelta3(source_path, target_path, output_path): + diff_program = ["xdelta3", "-0", "-B", str(64<<20), "-e", "-f", "-s"] + diff_program.append(source_path) + diff_program.append(target_path) + diff_program.append(output_path) + p = Run(diff_program, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + p.communicate() + assert p.returncode == 0, "Couldn't produce patch" + +def XZ(path): + compress_program = ["xz", "-zk", "-9", "--check=crc32"] + compress_program.append(path) + p = Run(compress_program, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + p.communicate() + assert p.returncode == 0, "Couldn't compress patch" + +def MakePartitionPatch(source_file, target_file, partition): + with tempfile.NamedTemporaryFile() as output_file: + XDelta3(source_file.name, target_file.name, output_file.name) + XZ(output_file.name) + with open(output_file.name + ".xz") as patch_file: + patch_data = patch_file.read() + os.unlink(patch_file.name) + return File(partition + ".muimg.p", patch_data) + +def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img, + info_dict=None): + """Generate a binary patch that creates the recovery image starting + with the boot image. (Most of the space in these images is just the + kernel, which is identical for the two, so the resulting patch + should be efficient.) Add it to the output zip, along with a shell + script that is run from init.rc on first boot to actually do the + patching and install the new recovery image. + + recovery_img and boot_img should be File objects for the + corresponding images. info should be the dictionary returned by + common.LoadInfoDict() on the input target_files. + """ + + if info_dict is None: + info_dict = OPTIONS.info_dict + + diff_program = ["imgdiff"] + path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat") + if os.path.exists(path): + diff_program.append("-b") + diff_program.append(path) + bonus_args = "-b /system/etc/recovery-resource.dat" + else: + bonus_args = "" + + d = Difference(recovery_img, boot_img, diff_program=diff_program) + _, _, patch = d.ComputePatch() + output_sink("recovery-from-boot.p", patch) + + td_pair = GetTypeAndDevice("/boot", info_dict) + if not td_pair: + return + boot_type, boot_device = td_pair + td_pair = GetTypeAndDevice("/recovery", info_dict) + if not td_pair: + return + recovery_type, recovery_device = td_pair + + sh = """#!/system/bin/sh +if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then + applypatch %(bonus_args)s %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p && log -t recovery "Installing new recovery image: succeeded" || log -t recovery "Installing new recovery image: failed" +else + log -t recovery "Recovery image already installed" +fi +""" % { 'boot_size': boot_img.size, + 'boot_sha1': boot_img.sha1, + 'recovery_size': recovery_img.size, + 'recovery_sha1': recovery_img.sha1, + 'boot_type': boot_type, + 'boot_device': boot_device, + 'recovery_type': recovery_type, + 'recovery_device': recovery_device, + 'bonus_args': bonus_args, + } + + # The install script location moved from /system/etc to /system/bin + # in the L release. Parse the init.rc file to find out where the + # target-files expects it to be, and put it there. + sh_location = "etc/install-recovery.sh" + try: + with open(os.path.join(input_dir, "BOOT", "RAMDISK", "init.rc")) as f: + for line in f: + m = re.match("^service flash_recovery /system/(\S+)\s*$", line) + if m: + sh_location = m.group(1) + print "putting script in", sh_location + break + except (OSError, IOError), e: + print "failed to read init.rc: %s" % (e,) + + output_sink(sh_location, sh) diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py index 426b713..8620812 100644 --- a/tools/releasetools/edify_generator.py +++ b/tools/releasetools/edify_generator.py @@ -68,19 +68,43 @@ class EdifyGenerator(object): with temporary=True) to this one.""" self.script.extend(other.script) + def AssertOemProperty(self, name, value): + """Assert that a property on the OEM paritition matches a value.""" + if not name: + raise ValueError("must specify an OEM property") + if not value: + raise ValueError("must specify the OEM value") + cmd = ('file_getprop("/oem/oem.prop", "%s") == "%s" || ' + 'abort("This package expects the value \\"%s\\" for ' + '\\"%s\\" on the OEM partition; ' + 'this has value \\"" + file_getprop("/oem/oem.prop") + "\\".");' + ) % (name, value, name, value) + self.script.append(cmd) + def AssertSomeFingerprint(self, *fp): - """Assert that the current system build fingerprint is one of *fp.""" + """Assert that the current recovery build fingerprint is one of *fp.""" if not fp: raise ValueError("must specify some fingerprints") cmd = ( - ' ||\n '.join([('file_getprop("/system/build.prop", ' - '"ro.build.fingerprint") == "%s"') + ' ||\n '.join([('getprop("ro.build.fingerprint") == "%s"') % i for i in fp]) + ' ||\n abort("Package expects build fingerprint of %s; this ' 'device has " + getprop("ro.build.fingerprint") + ".");' ) % (" or ".join(fp),) self.script.append(cmd) + def AssertSomeThumbprint(self, *fp): + """Assert that the current recovery build thumbprint is one of *fp.""" + if not fp: + raise ValueError("must specify some thumbprints") + cmd = ( + ' ||\n '.join([('getprop("ro.build.thumbprint") == "%s"') + % i for i in fp]) + + ' ||\n abort("Package expects build thumbprint of %s; this ' + 'device has " + getprop("ro.build.thumbprint") + ".");' + ) % (" or ".join(fp),) + self.script.append(cmd) + def AssertOlderBuild(self, timestamp, timestamp_text): """Assert that the build on the device is older (or the same as) the given timestamp.""" @@ -178,6 +202,15 @@ class EdifyGenerator(object): (p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device, p.length, p.mount_point)) + def WipeBlockDevice(self, partition): + if partition not in ("/system", "/vendor"): + raise ValueError(("WipeBlockDevice doesn't work on %s\n") % (partition,)) + fstab = self.info.get("fstab", None) + size = self.info.get(partition.lstrip("/") + "_size", None) + device = fstab[partition].device + + self.script.append('wipe_block_device("%s", %s);' % (device, size)) + def DeleteFiles(self, file_list): """Delete all files in file_list.""" if not file_list: return @@ -212,7 +245,7 @@ class EdifyGenerator(object): cmd = "".join(cmd) self.script.append(self._WordWrap(cmd)) - def WriteRawImage(self, mount_point, fn): + def WriteRawImage(self, mount_point, fn, mapfn=None): """Write the given package file into the partition for the given mount point.""" @@ -226,8 +259,13 @@ class EdifyGenerator(object): 'write_raw_image(package_extract_file("%(fn)s"), "%(device)s");' % args) elif partition_type == "EMMC": - self.script.append( - 'package_extract_file("%(fn)s", "%(device)s");' % args) + if mapfn: + args["map"] = mapfn + self.script.append( + 'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args) + else: + self.script.append( + 'package_extract_file("%(fn)s", "%(device)s");' % args) else: raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type,)) @@ -293,6 +331,13 @@ class EdifyGenerator(object): if input_path is None: data = input_zip.read("OTA/bin/updater") else: - data = open(os.path.join(input_path, "updater")).read() + data = open(input_path, "rb").read() common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary", data, perms=0755) + + def Syspatch(self, filename, target_mapfile, target_sha, + source_mapfile, source_sha, patchfile): + """Applies a compressed binary patch to a block device.""" + call = 'syspatch("%s", "%s", "%s", "%s", "%s", "%s");' + self.script.append(call % (filename, target_mapfile, target_sha, + source_mapfile, source_sha, patchfile)) diff --git a/tools/releasetools/img_from_target_files b/tools/releasetools/img_from_target_files index e894c42..afaf24b 100755..120000 --- a/tools/releasetools/img_from_target_files +++ b/tools/releasetools/img_from_target_files @@ -1,270 +1 @@ -#!/usr/bin/env python -# -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Given a target-files zipfile, produces an image zipfile suitable for -use with 'fastboot update'. - -Usage: img_from_target_files [flags] input_target_files output_image_zip - - -b (--board_config) <file> - Deprecated. - - -z (--bootable_zip) - Include only the bootable images (eg 'boot' and 'recovery') in - the output. - -""" - -import sys - -if sys.hexversion < 0x02040000: - print >> sys.stderr, "Python 2.4 or newer is required." - sys.exit(1) - -import errno -import os -import re -import shutil -import subprocess -import tempfile -import zipfile - -# missing in Python 2.4 and before -if not hasattr(os, "SEEK_SET"): - os.SEEK_SET = 0 - -import build_image -import common - -OPTIONS = common.OPTIONS - - -def AddSystem(output_zip): - """Turn the contents of SYSTEM into a system image and store it in - output_zip.""" - - print "creating system.img..." - - img = tempfile.NamedTemporaryFile() - - # The name of the directory it is making an image out of matters to - # mkyaffs2image. It wants "system" but we have a directory named - # "SYSTEM", so create a symlink. - try: - os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"), - os.path.join(OPTIONS.input_tmp, "system")) - except OSError, e: - # bogus error on my mac version? - # File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem - # os.path.join(OPTIONS.input_tmp, "system")) - # OSError: [Errno 17] File exists - if (e.errno == errno.EEXIST): - pass - - image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, - "system") - fstab = OPTIONS.info_dict["fstab"] - if fstab: - image_props["fs_type" ] = fstab["/system"].fs_type - succ = build_image.BuildImage(os.path.join(OPTIONS.input_tmp, "system"), - image_props, img.name) - assert succ, "build system.img image failed" - - img.seek(os.SEEK_SET, 0) - data = img.read() - img.close() - - common.CheckSize(data, "system.img", OPTIONS.info_dict) - common.ZipWriteStr(output_zip, "system.img", data) - - -def AddVendor(output_zip): - """Turn the contents of VENDOR into vendor.img and store it in - output_zip.""" - - image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, - "vendor") - # The build system has to explicitly request for vendor.img. - if "fs_type" not in image_props: - return - - print "creating vendor.img..." - - img = tempfile.NamedTemporaryFile() - - # The name of the directory it is making an image out of matters to - # mkyaffs2image. It wants "vendor" but we have a directory named - # "VENDOR", so create a symlink or an empty directory if VENDOR does not - # exist. - if not os.path.exists(os.path.join(OPTIONS.input_tmp, "vendor")): - if os.path.exists(os.path.join(OPTIONS.input_tmp, "VENDOR")): - os.symlink(os.path.join(OPTIONS.input_tmp, "VENDOR"), - os.path.join(OPTIONS.input_tmp, "vendor")) - else: - os.mkdir(os.path.join(OPTIONS.input_tmp, "vendor")) - - img = tempfile.NamedTemporaryFile() - - fstab = OPTIONS.info_dict["fstab"] - if fstab: - image_props["fs_type" ] = fstab["/vendor"].fs_type - succ = build_image.BuildImage(os.path.join(OPTIONS.input_tmp, "vendor"), - image_props, img.name) - assert succ, "build vendor.img image failed" - - common.CheckSize(img.name, "vendor.img", OPTIONS.info_dict) - output_zip.write(img.name, "vendor.img") - img.close() - - -def AddUserdata(output_zip): - """Create an empty userdata image and store it in output_zip.""" - - image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, - "data") - # If no userdata_size is provided for extfs, skip userdata.img. - if (image_props.get("fs_type", "").startswith("ext") and - not image_props.get("partition_size")): - return - - print "creating userdata.img..." - - # The name of the directory it is making an image out of matters to - # mkyaffs2image. So we create a temp dir, and within it we create an - # empty dir named "data", and build the image from that. - temp_dir = tempfile.mkdtemp() - user_dir = os.path.join(temp_dir, "data") - os.mkdir(user_dir) - img = tempfile.NamedTemporaryFile() - - fstab = OPTIONS.info_dict["fstab"] - if fstab: - image_props["fs_type" ] = fstab["/data"].fs_type - succ = build_image.BuildImage(user_dir, image_props, img.name) - assert succ, "build userdata.img image failed" - - common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict) - output_zip.write(img.name, "userdata.img") - img.close() - os.rmdir(user_dir) - os.rmdir(temp_dir) - - -def AddCache(output_zip): - """Create an empty cache image and store it in output_zip.""" - - image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, - "cache") - # The build system has to explicitly request for cache.img. - if "fs_type" not in image_props: - return - - print "creating cache.img..." - - # The name of the directory it is making an image out of matters to - # mkyaffs2image. So we create a temp dir, and within it we create an - # empty dir named "cache", and build the image from that. - temp_dir = tempfile.mkdtemp() - user_dir = os.path.join(temp_dir, "cache") - os.mkdir(user_dir) - img = tempfile.NamedTemporaryFile() - - fstab = OPTIONS.info_dict["fstab"] - if fstab: - image_props["fs_type" ] = fstab["/cache"].fs_type - succ = build_image.BuildImage(user_dir, image_props, img.name) - assert succ, "build cache.img image failed" - - common.CheckSize(img.name, "cache.img", OPTIONS.info_dict) - output_zip.write(img.name, "cache.img") - img.close() - os.rmdir(user_dir) - os.rmdir(temp_dir) - - -def CopyInfo(output_zip): - """Copy the android-info.txt file from the input to the output.""" - output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"), - "android-info.txt") - - -def main(argv): - bootable_only = [False] - - def option_handler(o, a): - if o in ("-b", "--board_config"): - pass # deprecated - if o in ("-z", "--bootable_zip"): - bootable_only[0] = True - else: - return False - return True - - args = common.ParseOptions(argv, __doc__, - extra_opts="b:z", - extra_long_opts=["board_config=", - "bootable_zip"], - extra_option_handler=option_handler) - - bootable_only = bootable_only[0] - - if len(args) != 2: - common.Usage(__doc__) - sys.exit(1) - - OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0]) - OPTIONS.info_dict = common.LoadInfoDict(input_zip) - - # If this image was originally labelled with SELinux contexts, make sure we - # also apply the labels in our new image. During building, the "file_contexts" - # is in the out/ directory tree, but for repacking from target-files.zip it's - # in the root directory of the ramdisk. - if "selinux_fc" in OPTIONS.info_dict: - OPTIONS.info_dict["selinux_fc"] = os.path.join(OPTIONS.input_tmp, "BOOT", "RAMDISK", - "file_contexts") - - output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) - - common.GetBootableImage( - "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT").AddToZip(output_zip) - common.GetBootableImage( - "recovery.img", "recovery.img", OPTIONS.input_tmp, - "RECOVERY").AddToZip(output_zip) - - if not bootable_only: - AddSystem(output_zip) - AddVendor(output_zip) - AddUserdata(output_zip) - AddCache(output_zip) - CopyInfo(output_zip) - - print "cleaning up..." - output_zip.close() - shutil.rmtree(OPTIONS.input_tmp) - - print "done." - - -if __name__ == '__main__': - try: - common.CloseInheritedPipes() - main(sys.argv[1:]) - except common.ExternalError, e: - print - print " ERROR: %s" % (e,) - print - sys.exit(1) +img_from_target_files.py
\ No newline at end of file diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py new file mode 100755 index 0000000..9aab41c --- /dev/null +++ b/tools/releasetools/img_from_target_files.py @@ -0,0 +1,303 @@ +#!/usr/bin/env python +# +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Given a target-files zipfile, produces an image zipfile suitable for +use with 'fastboot update'. + +Usage: img_from_target_files [flags] input_target_files output_image_zip + + -b (--board_config) <file> + Deprecated. + + -z (--bootable_zip) + Include only the bootable images (eg 'boot' and 'recovery') in + the output. + +""" + +import sys + +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." + sys.exit(1) + +import errno +import os +import re +import shutil +import subprocess +import tempfile +import zipfile + +# missing in Python 2.4 and before +if not hasattr(os, "SEEK_SET"): + os.SEEK_SET = 0 + +import build_image +import common + +OPTIONS = common.OPTIONS + + +def AddSystem(output_zip, sparse=True): + """Turn the contents of SYSTEM into a system image and store it in + output_zip.""" + data = BuildSystem(OPTIONS.input_tmp, OPTIONS.info_dict, sparse=sparse) + common.ZipWriteStr(output_zip, "system.img", data) + +def BuildSystem(input_dir, info_dict, sparse=True, map_file=None): + return CreateImage(input_dir, info_dict, "system", + sparse=sparse, map_file=map_file) + +def AddVendor(output_zip, sparse=True): + data = BuildVendor(OPTIONS.input_tmp, OPTIONS.info_dict, sparse=sparse) + common.ZipWriteStr(output_zip, "vendor.img", data) + +def BuildVendor(input_dir, info_dict, sparse=True, map_file=None): + return CreateImage(input_dir, info_dict, "vendor", + sparse=sparse, map_file=map_file) + + +def CreateImage(input_dir, info_dict, what, sparse=True, map_file=None): + print "creating " + what + ".img..." + + img = tempfile.NamedTemporaryFile() + + # The name of the directory it is making an image out of matters to + # mkyaffs2image. It wants "system" but we have a directory named + # "SYSTEM", so create a symlink. + try: + os.symlink(os.path.join(input_dir, what.upper()), + os.path.join(input_dir, what)) + except OSError, e: + # bogus error on my mac version? + # File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem + # os.path.join(OPTIONS.input_tmp, "system")) + # OSError: [Errno 17] File exists + if (e.errno == errno.EEXIST): + pass + + image_props = build_image.ImagePropFromGlobalDict(info_dict, what) + fstab = info_dict["fstab"] + if fstab: + image_props["fs_type" ] = fstab["/" + what].fs_type + + if what == "system": + fs_config_prefix = "" + else: + fs_config_prefix = what + "_" + + fs_config = os.path.join( + input_dir, "META/" + fs_config_prefix + "filesystem_config.txt") + if not os.path.exists(fs_config): fs_config = None + + fc_config = os.path.join(input_dir, "BOOT/RAMDISK/file_contexts") + if not os.path.exists(fc_config): fc_config = None + + succ = build_image.BuildImage(os.path.join(input_dir, what), + image_props, img.name, + fs_config=fs_config, + fc_config=fc_config) + assert succ, "build " + what + ".img image failed" + + mapdata = None + + if sparse: + data = open(img.name).read() + img.close() + else: + success, name = build_image.UnsparseImage(img.name, replace=False) + if not success: + assert False, "unsparsing " + what + ".img failed" + + if map_file: + mmap = tempfile.NamedTemporaryFile() + mimg = tempfile.NamedTemporaryFile(delete=False) + success = build_image.MappedUnsparseImage( + img.name, name, mmap.name, mimg.name) + if not success: + assert False, "creating sparse map failed" + os.unlink(name) + name = mimg.name + + with open(mmap.name) as f: + mapdata = f.read() + + try: + with open(name) as f: + data = f.read() + finally: + os.unlink(name) + + if mapdata is None: + return data + else: + return mapdata, data + + +def AddUserdata(output_zip): + """Create an empty userdata image and store it in output_zip.""" + + image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, + "data") + # We only allow yaffs to have a 0/missing partition_size. + # Extfs, f2fs must have a size. Skip userdata.img if no size. + if (not image_props.get("fs_type", "").startswith("yaffs") and + not image_props.get("partition_size")): + return + + print "creating userdata.img..." + + # The name of the directory it is making an image out of matters to + # mkyaffs2image. So we create a temp dir, and within it we create an + # empty dir named "data", and build the image from that. + temp_dir = tempfile.mkdtemp() + user_dir = os.path.join(temp_dir, "data") + os.mkdir(user_dir) + img = tempfile.NamedTemporaryFile() + + fstab = OPTIONS.info_dict["fstab"] + if fstab: + image_props["fs_type" ] = fstab["/data"].fs_type + succ = build_image.BuildImage(user_dir, image_props, img.name) + assert succ, "build userdata.img image failed" + + common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict) + output_zip.write(img.name, "userdata.img") + img.close() + os.rmdir(user_dir) + os.rmdir(temp_dir) + + +def AddCache(output_zip): + """Create an empty cache image and store it in output_zip.""" + + image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, + "cache") + # The build system has to explicitly request for cache.img. + if "fs_type" not in image_props: + return + + print "creating cache.img..." + + # The name of the directory it is making an image out of matters to + # mkyaffs2image. So we create a temp dir, and within it we create an + # empty dir named "cache", and build the image from that. + temp_dir = tempfile.mkdtemp() + user_dir = os.path.join(temp_dir, "cache") + os.mkdir(user_dir) + img = tempfile.NamedTemporaryFile() + + fstab = OPTIONS.info_dict["fstab"] + if fstab: + image_props["fs_type" ] = fstab["/cache"].fs_type + succ = build_image.BuildImage(user_dir, image_props, img.name) + assert succ, "build cache.img image failed" + + common.CheckSize(img.name, "cache.img", OPTIONS.info_dict) + output_zip.write(img.name, "cache.img") + img.close() + os.rmdir(user_dir) + os.rmdir(temp_dir) + + +def CopyInfo(output_zip): + """Copy the android-info.txt file from the input to the output.""" + output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"), + "android-info.txt") + + +def main(argv): + bootable_only = [False] + + def option_handler(o, a): + if o in ("-b", "--board_config"): + pass # deprecated + if o in ("-z", "--bootable_zip"): + bootable_only[0] = True + else: + return False + return True + + args = common.ParseOptions(argv, __doc__, + extra_opts="b:z", + extra_long_opts=["board_config=", + "bootable_zip"], + extra_option_handler=option_handler) + + bootable_only = bootable_only[0] + + if len(args) != 2: + common.Usage(__doc__) + sys.exit(1) + + OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0]) + OPTIONS.info_dict = common.LoadInfoDict(input_zip) + + # If this image was originally labelled with SELinux contexts, make sure we + # also apply the labels in our new image. During building, the "file_contexts" + # is in the out/ directory tree, but for repacking from target-files.zip it's + # in the root directory of the ramdisk. + if "selinux_fc" in OPTIONS.info_dict: + OPTIONS.info_dict["selinux_fc"] = os.path.join(OPTIONS.input_tmp, "BOOT", "RAMDISK", + "file_contexts") + + output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) + + boot_image = common.GetBootableImage( + "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") + if boot_image: + boot_image.AddToZip(output_zip) + recovery_image = common.GetBootableImage( + "recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY") + if recovery_image: + recovery_image.AddToZip(output_zip) + + def banner(s): + print "\n\n++++ " + s + " ++++\n\n" + + if not bootable_only: + banner("AddSystem") + AddSystem(output_zip) + try: + input_zip.getinfo("VENDOR/") + banner("AddVendor") + AddVendor(output_zip) + except KeyError: + pass # no vendor partition for this device + banner("AddUserdata") + AddUserdata(output_zip) + banner("AddCache") + AddCache(output_zip) + CopyInfo(output_zip) + + print "cleaning up..." + output_zip.close() + shutil.rmtree(OPTIONS.input_tmp) + + print "done." + + +if __name__ == '__main__': + try: + common.CloseInheritedPipes() + main(sys.argv[1:]) + except common.ExternalError, e: + print + print " ERROR: %s" % (e,) + print + sys.exit(1) diff --git a/tools/releasetools/make_recovery_patch b/tools/releasetools/make_recovery_patch new file mode 100755 index 0000000..08d1450 --- /dev/null +++ b/tools/releasetools/make_recovery_patch @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# +# Copyright (C) 2014 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys + +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." + sys.exit(1) + +import os +import common + +OPTIONS = common.OPTIONS + +def main(argv): + # def option_handler(o, a): + # return False + + args = common.ParseOptions(argv, __doc__) + input_dir, output_dir = args + + OPTIONS.info_dict = common.LoadInfoDict(input_dir) + + recovery_img = common.GetBootableImage("recovery.img", "recovery.img", + input_dir, "RECOVERY") + boot_img = common.GetBootableImage("boot.img", "boot.img", + input_dir, "BOOT") + + if not recovery_img or not boot_img: + sys.exit(0) + + def output_sink(fn, data): + with open(os.path.join(output_dir, "SYSTEM", *fn.split("/")), "wb") as f: + f.write(data) + + common.MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files index e695218..5f2354c 100755 --- a/tools/releasetools/ota_from_target_files +++ b/tools/releasetools/ota_from_target_files @@ -21,7 +21,7 @@ a full OTA is produced. Usage: ota_from_target_files [flags] input_target_files output_ota_package - -b (--board_config) <file> + --board_config <file> Deprecated. -k (--package_key) <key> Key to use to sign the package (default is @@ -37,6 +37,10 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package Generate an incremental OTA using the given target-files zip as the starting build. + -o (--oem_settings) <file> + Use the file to specify the expected OEM-specific properties + on the OEM partition of the intended device. + -w (--wipe_user_data) Generate an OTA package that will wipe the user data partition when installed. @@ -57,6 +61,16 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package first, so that any changes made to the system partition are done using the new recovery (new kernel, etc.). + --block + Generate a block-based OTA if possible. Will fall back to a + file-based OTA if the target_files is older and doesn't support + block-based OTAs. + + -b (--binary) <file> + Use the given binary as the update-binary in the output package, + instead of the binary in the build's target_files. Use for + development only. + -t (--worker_threads) <int> Specifies the number of worker-threads that will be used when generating patches for incremental updates (defaults to 3). @@ -65,8 +79,8 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package import sys -if sys.hexversion < 0x02040000: - print >> sys.stderr, "Python 2.4 or newer is required." +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." sys.exit(1) import copy @@ -84,7 +98,9 @@ except ImportError: from sha import sha as sha1 import common +import img_from_target_files import edify_generator +import build_image OPTIONS = common.OPTIONS OPTIONS.package_key = None @@ -99,6 +115,9 @@ OPTIONS.aslr_mode = True OPTIONS.worker_threads = 3 OPTIONS.two_step = False OPTIONS.no_signing = False +OPTIONS.block_based = False +OPTIONS.updater_binary = None +OPTIONS.oem_source = None def MostPopularKey(d, default): """Given a dict, return the key corresponding to the largest @@ -144,50 +163,21 @@ def ClosestFileMatch(src, tgtfiles, existing): return result return None -class Item: - """Items represent the metadata (user, group, mode) of files and - directories in the system image.""" - ITEMS = {} - def __init__(self, name, dir=False): - self.name = name - self.uid = None - self.gid = None - self.mode = None - self.selabel = None - self.capabilities = None - self.dir = dir - - if name: - self.parent = Item.Get(os.path.dirname(name), dir=True) - self.parent.children.append(self) - else: - self.parent = None - if dir: - self.children = [] - - def Dump(self, indent=0): - if self.uid is not None: - print "%s%s %d %d %o" % (" "*indent, self.name, self.uid, self.gid, self.mode) - else: - print "%s%s %s %s %s" % (" "*indent, self.name, self.uid, self.gid, self.mode) - if self.dir: - print "%s%s" % (" "*indent, self.descendants) - print "%s%s" % (" "*indent, self.best_subtree) - for i in self.children: - i.Dump(indent=indent+1) - - @classmethod - def Get(cls, name, dir=False): - if name not in cls.ITEMS: - cls.ITEMS[name] = Item(name, dir=dir) - return cls.ITEMS[name] +class ItemSet: + def __init__(self, partition, fs_config): + self.partition = partition + self.fs_config = fs_config + self.ITEMS = {} - @classmethod - def GetMetadata(cls, input_zip): + def Get(self, name, dir=False): + if name not in self.ITEMS: + self.ITEMS[name] = Item(self, name, dir=dir) + return self.ITEMS[name] + def GetMetadata(self, input_zip): # The target_files contains a record of what the uid, # gid, and mode are supposed to be. - output = input_zip.read("META/filesystem_config.txt") + output = input_zip.read(self.fs_config) for line in output.split("\n"): if not line: continue @@ -205,7 +195,7 @@ class Item: if key == "capabilities": capabilities = value - i = cls.ITEMS.get(name, None) + i = self.ITEMS.get(name, None) if i is not None: i.uid = int(uid) i.gid = int(gid) @@ -216,11 +206,44 @@ class Item: i.children.sort(key=lambda i: i.name) # set metadata for the files generated by this script. - i = cls.ITEMS.get("system/recovery-from-boot.p", None) + i = self.ITEMS.get("system/recovery-from-boot.p", None) if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0644, None, None - i = cls.ITEMS.get("system/etc/install-recovery.sh", None) + i = self.ITEMS.get("system/etc/install-recovery.sh", None) if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0544, None, None + +class Item: + """Items represent the metadata (user, group, mode) of files and + directories in the system image.""" + def __init__(self, itemset, name, dir=False): + self.itemset = itemset + self.name = name + self.uid = None + self.gid = None + self.mode = None + self.selabel = None + self.capabilities = None + self.dir = dir + + if name: + self.parent = itemset.Get(os.path.dirname(name), dir=True) + self.parent.children.append(self) + else: + self.parent = None + if dir: + self.children = [] + + def Dump(self, indent=0): + if self.uid is not None: + print "%s%s %d %d %o" % (" "*indent, self.name, self.uid, self.gid, self.mode) + else: + print "%s%s %s %s %s" % (" "*indent, self.name, self.uid, self.gid, self.mode) + if self.dir: + print "%s%s" % (" "*indent, self.descendants) + print "%s%s" % (" "*indent, self.best_subtree) + for i in self.children: + i.Dump(indent=indent+1) + def CountChildMetadata(self): """Count up the (uid, gid, mode, selabel, capabilities) tuples for all children and determine the best strategy for using set_perm_recursive and @@ -305,9 +328,8 @@ class Item: recurse(self, (-1, -1, -1, -1, None, None)) -def CopySystemFiles(input_zip, output_zip=None, - substitute=None): - """Copies files underneath system/ in the input zip to the output +def CopyPartitionFiles(itemset, input_zip, output_zip=None, substitute=None): + """Copies files for the partition in the input zip to the output zip. Populates the Item class with their metadata, and returns a list of symlinks. output_zip may be None, in which case the copy is skipped (but the other side effects still happen). substitute is an @@ -317,15 +339,17 @@ def CopySystemFiles(input_zip, output_zip=None, symlinks = [] + partition = itemset.partition + for info in input_zip.infolist(): - if info.filename.startswith("SYSTEM/"): + if info.filename.startswith(partition.upper() + "/"): basefilename = info.filename[7:] if IsSymlink(info): symlinks.append((input_zip.read(info.filename), - "/system/" + basefilename)) + "/" + partition + "/" + basefilename)) else: info2 = copy.copy(info) - fn = info2.filename = "system/" + basefilename + fn = info2.filename = partition + "/" + basefilename if substitute and fn in substitute and substitute[fn] is None: continue if output_zip is not None: @@ -335,9 +359,9 @@ def CopySystemFiles(input_zip, output_zip=None, data = input_zip.read(info.filename) output_zip.writestr(info2, data) if fn.endswith("/"): - Item.Get(fn[:-1], dir=True) + itemset.Get(fn[:-1], dir=True) else: - Item.Get(fn, dir=False) + itemset.Get(fn, dir=False) symlinks.sort() return symlinks @@ -351,64 +375,48 @@ def SignOutput(temp_zip_name, output_zip_name): whole_file=True) -def AppendAssertions(script, info_dict): - device = GetBuildProp("ro.product.device", info_dict) - script.AssertDevice(device) - - -def MakeRecoveryPatch(input_tmp, output_zip, recovery_img, boot_img): - """Generate a binary patch that creates the recovery image starting - with the boot image. (Most of the space in these images is just the - kernel, which is identical for the two, so the resulting patch - should be efficient.) Add it to the output zip, along with a shell - script that is run from init.rc on first boot to actually do the - patching and install the new recovery image. +def AppendAssertions(script, info_dict, oem_dict = None): + oem_props = info_dict.get("oem_fingerprint_properties") + if oem_props is None: + device = GetBuildProp("ro.product.device", info_dict) + script.AssertDevice(device) + else: + if oem_dict is None: + raise common.ExternalError("No OEM file provided to answer expected assertions") + for prop in oem_props.split(): + if oem_dict.get(prop) is None: + raise common.ExternalError("The OEM file is missing the property %s" % prop) + script.AssertOemProperty(prop, oem_dict.get(prop)) - recovery_img and boot_img should be File objects for the - corresponding images. info should be the dictionary returned by - common.LoadInfoDict() on the input target_files. - Returns an Item for the shell script, which must be made - executable. - """ - - diff_program = ["imgdiff"] - path = os.path.join(input_tmp, "SYSTEM", "etc", "recovery-resource.dat") - if os.path.exists(path): - diff_program.append("-b") - diff_program.append(path) - bonus_args = "-b /system/etc/recovery-resource.dat" - else: - bonus_args = "" +def HasRecoveryPatch(target_files_zip): + try: + target_files_zip.getinfo("SYSTEM/recovery-from-boot.p") + return True + except KeyError: + return False - d = common.Difference(recovery_img, boot_img, diff_program=diff_program) - _, _, patch = d.ComputePatch() - common.ZipWriteStr(output_zip, "recovery/recovery-from-boot.p", patch) - Item.Get("system/recovery-from-boot.p", dir=False) +def HasVendorPartition(target_files_zip): + try: + target_files_zip.getinfo("VENDOR/") + return True + except KeyError: + return False - boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict) - recovery_type, recovery_device = common.GetTypeAndDevice("/recovery", OPTIONS.info_dict) +def GetOemProperty(name, oem_props, oem_dict, info_dict): + if oem_props is not None and name in oem_props: + return oem_dict[name] + return GetBuildProp(name, info_dict) - sh = """#!/system/bin/sh -if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then - log -t recovery "Installing new recovery image" - applypatch %(bonus_args)s %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p -else - log -t recovery "Recovery image already installed" -fi -""" % { 'boot_size': boot_img.size, - 'boot_sha1': boot_img.sha1, - 'recovery_size': recovery_img.size, - 'recovery_sha1': recovery_img.sha1, - 'boot_type': boot_type, - 'boot_device': boot_device, - 'recovery_type': recovery_type, - 'recovery_device': recovery_device, - 'bonus_args': bonus_args, - } - common.ZipWriteStr(output_zip, "recovery/etc/install-recovery.sh", sh) - return Item.Get("system/etc/install-recovery.sh", dir=False) +def CalculateFingerprint(oem_props, oem_dict, info_dict): + if oem_props is None: + return GetBuildProp("ro.build.fingerprint", info_dict) + return "%s/%s/%s:%s" % ( + GetOemProperty("ro.product.brand", oem_props, oem_dict, info_dict), + GetOemProperty("ro.product.name", oem_props, oem_dict, info_dict), + GetOemProperty("ro.product.device", oem_props, oem_dict, info_dict), + GetBuildProp("ro.build.thumbprint", info_dict)) def WriteFullOTAPackage(input_zip, output_zip): # TODO: how to determine this? We don't know what version it will @@ -416,9 +424,17 @@ def WriteFullOTAPackage(input_zip, output_zip): # change very often. script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict) - metadata = {"post-build": GetBuildProp("ro.build.fingerprint", - OPTIONS.info_dict), - "pre-device": GetBuildProp("ro.product.device", + oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties") + oem_dict = None + if oem_props is not None: + if OPTIONS.oem_source is None: + raise common.ExternalError("OEM source required for this build") + script.Mount("/oem") + oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) + + metadata = {"post-build": CalculateFingerprint( + oem_props, oem_dict, OPTIONS.info_dict), + "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict, OPTIONS.info_dict), "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict), @@ -433,12 +449,15 @@ def WriteFullOTAPackage(input_zip, output_zip): metadata=metadata, info_dict=OPTIONS.info_dict) + has_recovery_patch = HasRecoveryPatch(input_zip) + block_based = OPTIONS.block_based and has_recovery_patch + if not OPTIONS.omit_prereq: ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict) ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict) script.AssertOlderBuild(ts, ts_text) - AppendAssertions(script, OPTIONS.info_dict) + AppendAssertions(script, OPTIONS.info_dict, oem_dict) device_specific.FullOTA_Assertions() # Two-step package strategy (in chronological order, which is *not* @@ -482,37 +501,82 @@ else if get_stage("%(bcb_dev)s", "stage") == "3/3" then device_specific.FullOTA_InstallBegin() - script.ShowProgress(0.5, 0) + system_progress = 0.75 if OPTIONS.wipe_user_data: - script.FormatPartition("/data") + system_progress -= 0.1 + if HasVendorPartition(input_zip): + system_progress -= 0.1 if "selinux_fc" in OPTIONS.info_dict: WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip) - script.FormatPartition("/system") - script.Mount("/system") - script.UnpackPackageDir("recovery", "/system") - script.UnpackPackageDir("system", "/system") + system_items = ItemSet("system", "META/filesystem_config.txt") + script.ShowProgress(system_progress, 0) + if block_based: + mapdata, data = img_from_target_files.BuildSystem( + OPTIONS.input_tmp, OPTIONS.info_dict, + sparse=False, map_file=True) + + common.ZipWriteStr(output_zip, "system.map", mapdata) + common.ZipWriteStr(output_zip, "system.muimg", data) + script.WipeBlockDevice("/system") + script.WriteRawImage("/system", "system.muimg", mapfn="system.map") + else: + script.FormatPartition("/system") + script.Mount("/system") + if not has_recovery_patch: + script.UnpackPackageDir("recovery", "/system") + script.UnpackPackageDir("system", "/system") - symlinks = CopySystemFiles(input_zip, output_zip) - script.MakeSymlinks(symlinks) + symlinks = CopyPartitionFiles(system_items, input_zip, output_zip) + script.MakeSymlinks(symlinks) boot_img = common.GetBootableImage("boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") - MakeRecoveryPatch(OPTIONS.input_tmp, output_zip, recovery_img, boot_img) - Item.GetMetadata(input_zip) - Item.Get("system").SetPermissions(script) + if not block_based: + def output_sink(fn, data): + common.ZipWriteStr(output_zip, "recovery/" + fn, data) + system_items.Get("system/" + fn, dir=False) + + common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, + recovery_img, boot_img) + + system_items.GetMetadata(input_zip) + system_items.Get("system").SetPermissions(script) + + if HasVendorPartition(input_zip): + vendor_items = ItemSet("vendor", "META/vendor_filesystem_config.txt") + script.ShowProgress(0.1, 0) + + if block_based: + mapdata, data = img_from_target_files.BuildVendor( + OPTIONS.input_tmp, OPTIONS.info_dict, + sparse=False, map_file=True) + + common.ZipWriteStr(output_zip, "vendor.map", mapdata) + common.ZipWriteStr(output_zip, "vendor.muimg", data) + script.WipeBlockDevice("/vendor") + script.WriteRawImage("/vendor", "vendor.muimg", mapfn="vendor.map") + else: + script.FormatPartition("/vendor") + script.Mount("/vendor") + script.UnpackPackageDir("vendor", "/vendor") + + symlinks = CopyPartitionFiles(vendor_items, input_zip, output_zip) + script.MakeSymlinks(symlinks) + + vendor_items.GetMetadata(input_zip) + vendor_items.Get("vendor").SetPermissions(script) common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict) common.ZipWriteStr(output_zip, "boot.img", boot_img.data) - script.ShowProgress(0.2, 0) - script.ShowProgress(0.2, 10) + script.ShowProgress(0.05, 5) script.WriteRawImage("/boot", "boot.img") - script.ShowProgress(0.1, 0) + script.ShowProgress(0.2, 10) device_specific.FullOTA_InstallEnd() if OPTIONS.extra_script is not None: @@ -520,6 +584,10 @@ else if get_stage("%(bcb_dev)s", "stage") == "3/3" then script.UnmountAll() + if OPTIONS.wipe_user_data: + script.ShowProgress(0.1, 10) + script.FormatPartition("/data") + if OPTIONS.two_step: script.AppendExtra(""" set_stage("%(bcb_dev)s", ""); @@ -532,7 +600,7 @@ reboot_now("%(bcb_dev)s", ""); endif; endif; """ % bcb_dev) - script.AddToZip(input_zip, output_zip) + script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) WriteMetadata(metadata, output_zip) def WritePolicyConfig(file_context, output_zip): @@ -546,14 +614,15 @@ def WriteMetadata(metadata, output_zip): "".join(["%s=%s\n" % kv for kv in sorted(metadata.iteritems())])) -def LoadSystemFiles(z): - """Load all the files from SYSTEM/... in a given target-files +def LoadPartitionFiles(z, partition): + """Load all the files from the given partition in a given target-files ZipFile, and return a dict of {filename: File object}.""" out = {} + prefix = partition.upper() + "/" for info in z.infolist(): - if info.filename.startswith("SYSTEM/") and not IsSymlink(info): + if info.filename.startswith(prefix) and not IsSymlink(info): basefilename = info.filename[7:] - fn = "system/" + basefilename + fn = partition + "/" + basefilename data = z.read(info.filename) out[fn] = common.File(fn, data) return out @@ -564,7 +633,7 @@ def GetBuildProp(prop, info_dict): try: return info_dict.get("build.prop", {})[prop] except KeyError: - raise common.ExternalError("couldn't find %s in build.prop" % (property,)) + raise common.ExternalError("couldn't find %s in build.prop" % (prop,)) def AddToKnownPaths(filename, known_paths): if filename[-1] == "/": @@ -577,7 +646,46 @@ def AddToKnownPaths(filename, known_paths): known_paths.add(path) dirs.pop() -def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): +class BlockDifference: + def __init__(self, partition, builder, output_zip): + with tempfile.NamedTemporaryFile() as src_file: + with tempfile.NamedTemporaryFile() as tgt_file: + print "building source " + partition + " image..." + src_file = tempfile.NamedTemporaryFile() + src_mapdata, src_data = builder(OPTIONS.source_tmp, + OPTIONS.source_info_dict, + sparse=False, map_file=True) + + self.src_sha1 = sha1(src_data).hexdigest() + print "source " + partition + " sha1:", self.src_sha1 + src_file.write(src_data) + + print "building target " + partition + " image..." + tgt_file = tempfile.NamedTemporaryFile() + tgt_mapdata, tgt_data = builder(OPTIONS.target_tmp, + OPTIONS.target_info_dict, + sparse=False, map_file=True) + self.tgt_sha1 = sha1(tgt_data).hexdigest() + print "target " + partition + " sha1:", self.tgt_sha1 + tgt_len = len(tgt_data) + tgt_file.write(tgt_data) + + system_type, self.device = common.GetTypeAndDevice("/" + partition, + OPTIONS.info_dict) + self.patch = common.MakePartitionPatch(src_file, tgt_file, partition) + + TestBlockPatch(src_data, src_mapdata, self.patch.data, + tgt_mapdata, self.tgt_sha1) + src_data = None + tgt_data = None + + self.patch.AddToZip(output_zip, compression=zipfile.ZIP_STORED) + self.src_mapfilename = self.patch.name + ".src.map" + common.ZipWriteStr(output_zip, self.src_mapfilename, src_mapdata) + self.tgt_mapfilename = self.patch.name + ".tgt.map" + common.ZipWriteStr(output_zip, self.tgt_mapfilename, tgt_mapdata) + +def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip): source_version = OPTIONS.source_info_dict["recovery_api_version"] target_version = OPTIONS.target_info_dict["recovery_api_version"] @@ -603,81 +711,426 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): metadata=metadata, info_dict=OPTIONS.info_dict) - print "Loading target..." - target_data = LoadSystemFiles(target_zip) - print "Loading source..." - source_data = LoadSystemFiles(source_zip) - - verbatim_targets = [] - patch_list = [] - diffs = [] - renames = {} - known_paths = set() - largest_source_size = 0 - - matching_file_cache = {} - for fn, sf in source_data.items(): - assert fn == sf.name - matching_file_cache["path:" + fn] = sf - if fn in target_data.keys(): - AddToKnownPaths(fn, known_paths) - # Only allow eligibility for filename/sha matching - # if there isn't a perfect path match. - if target_data.get(sf.name) is None: - matching_file_cache["file:" + fn.split("/")[-1]] = sf - matching_file_cache["sha:" + sf.sha1] = sf - - for fn in sorted(target_data.keys()): - tf = target_data[fn] - assert fn == tf.name - sf = ClosestFileMatch(tf, matching_file_cache, renames) - if sf is not None and sf.name != tf.name: - print "File has moved from " + sf.name + " to " + tf.name - renames[sf.name] = tf - - if sf is None or fn in OPTIONS.require_verbatim: - # This file should be included verbatim - if fn in OPTIONS.prohibit_verbatim: - raise common.ExternalError("\"%s\" must be sent verbatim" % (fn,)) - print "send", fn, "verbatim" - tf.AddToZip(output_zip) - verbatim_targets.append((fn, tf.size)) - if fn in target_data.keys(): - AddToKnownPaths(fn, known_paths) - elif tf.sha1 != sf.sha1: - # File is different; consider sending as a patch - diffs.append(common.Difference(tf, sf)) - else: - # Target file data identical to source (may still be renamed) - pass - - common.ComputeDifferences(diffs) - - for diff in diffs: - tf, sf, d = diff.GetPatch() - path = "/".join(tf.name.split("/")[:-1]) - if d is None or len(d) > tf.size * OPTIONS.patch_threshold or \ - path not in known_paths: - # patch is almost as big as the file; don't bother patching - # or a patch + rename cannot take place due to the target - # directory not existing - tf.AddToZip(output_zip) - verbatim_targets.append((tf.name, tf.size)) - if sf.name in renames: - del renames[sf.name] - AddToKnownPaths(tf.name, known_paths) - else: - common.ZipWriteStr(output_zip, "patch/" + sf.name + ".p", d) - patch_list.append((tf, sf, tf.size, common.sha1(d).hexdigest())) - largest_source_size = max(largest_source_size, sf.size) - source_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.source_info_dict) target_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.target_info_dict) metadata["pre-build"] = source_fp metadata["post-build"] = target_fp + source_boot = common.GetBootableImage( + "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", + OPTIONS.source_info_dict) + target_boot = common.GetBootableImage( + "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT") + updating_boot = (not OPTIONS.two_step and + (source_boot.data != target_boot.data)) + + source_recovery = common.GetBootableImage( + "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY", + OPTIONS.source_info_dict) + target_recovery = common.GetBootableImage( + "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") + updating_recovery = (source_recovery.data != target_recovery.data) + + system_diff = BlockDifference("system", img_from_target_files.BuildSystem, + output_zip) + if HasVendorPartition(target_zip): + if not HasVendorPartition(source_zip): + raise RuntimeError("can't generate incremental that adds /vendor") + vendor_diff = BlockDifference("vendor", img_from_target_files.BuildVendor, + output_zip) + + oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties") + oem_dict = None + if oem_props is not None: + if OPTIONS.oem_source is None: + raise common.ExternalError("OEM source required for this build") + script.Mount("/oem") + oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) + + AppendAssertions(script, OPTIONS.target_info_dict, oem_dict) + device_specific.IncrementalOTA_Assertions() + + # Two-step incremental package strategy (in chronological order, + # which is *not* the order in which the generated script has + # things): + # + # if stage is not "2/3" or "3/3": + # do verification on current system + # write recovery image to boot partition + # set stage to "2/3" + # reboot to boot partition and restart recovery + # else if stage is "2/3": + # write recovery image to recovery partition + # set stage to "3/3" + # reboot to recovery partition and restart recovery + # else: + # (stage must be "3/3") + # perform update: + # patch system files, etc. + # force full install of new boot image + # set up system to update recovery partition on first boot + # complete script normally (allow recovery to mark itself finished and reboot) + + if OPTIONS.two_step: + if not OPTIONS.info_dict.get("multistage_support", None): + assert False, "two-step packages not supported by this build" + fs = OPTIONS.info_dict["fstab"]["/misc"] + assert fs.fs_type.upper() == "EMMC", \ + "two-step packages only supported on devices with EMMC /misc partitions" + bcb_dev = {"bcb_dev": fs.device} + common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data) + script.AppendExtra(""" +if get_stage("%(bcb_dev)s", "stage") == "2/3" then +""" % bcb_dev) + script.AppendExtra("sleep(20);\n"); + script.WriteRawImage("/recovery", "recovery.img") + script.AppendExtra(""" +set_stage("%(bcb_dev)s", "3/3"); +reboot_now("%(bcb_dev)s", "recovery"); +else if get_stage("%(bcb_dev)s", "stage") != "3/3" then +""" % bcb_dev) + + script.Print("Verifying current system...") + + device_specific.IncrementalOTA_VerifyBegin() + + if oem_props is None: + script.AssertSomeFingerprint(source_fp, target_fp) + else: + script.AssertSomeThumbprint( + GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), + GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) + + if updating_boot: + d = common.Difference(target_boot, source_boot) + _, _, d = d.ComputePatch() + print "boot target: %d source: %d diff: %d" % ( + target_boot.size, source_boot.size, len(d)) + + common.ZipWriteStr(output_zip, "patch/boot.img.p", d) + + boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict) + + script.PatchCheck("%s:%s:%d:%s:%d:%s" % + (boot_type, boot_device, + source_boot.size, source_boot.sha1, + target_boot.size, target_boot.sha1)) + + device_specific.IncrementalOTA_VerifyEnd() + + if OPTIONS.two_step: + script.WriteRawImage("/boot", "recovery.img") + script.AppendExtra(""" +set_stage("%(bcb_dev)s", "2/3"); +reboot_now("%(bcb_dev)s", ""); +else +""" % bcb_dev) + + script.Comment("---- start making changes here ----") + + device_specific.IncrementalOTA_InstallBegin() + + if HasVendorPartition(target_zip): + script.Print("Patching vendor image...") + script.ShowProgress(0.1, 0) + script.Syspatch(vendor_diff.device, + vendor_diff.tgt_mapfilename, vendor_diff.tgt_sha1, + vendor_diff.src_mapfilename, vendor_diff.src_sha1, + vendor_diff.patch.name) + sys_progress = 0.8 + else: + sys_progress = 0.9 + + script.Print("Patching system image...") + script.ShowProgress(sys_progress, 0) + script.Syspatch(system_diff.device, + system_diff.tgt_mapfilename, system_diff.tgt_sha1, + system_diff.src_mapfilename, system_diff.src_sha1, + system_diff.patch.name) + + if OPTIONS.two_step: + common.ZipWriteStr(output_zip, "boot.img", target_boot.data) + script.WriteRawImage("/boot", "boot.img") + print "writing full boot image (forced by two-step mode)" + + if not OPTIONS.two_step: + if updating_boot: + # Produce the boot image by applying a patch to the current + # contents of the boot partition, and write it back to the + # partition. + script.Print("Patching boot image...") + script.ShowProgress(0.1, 10) + script.ApplyPatch("%s:%s:%d:%s:%d:%s" + % (boot_type, boot_device, + source_boot.size, source_boot.sha1, + target_boot.size, target_boot.sha1), + "-", + target_boot.size, target_boot.sha1, + source_boot.sha1, "patch/boot.img.p") + print "boot image changed; including." + else: + print "boot image unchanged; skipping." + + # Do device-specific installation (eg, write radio image). + device_specific.IncrementalOTA_InstallEnd() + + if OPTIONS.extra_script is not None: + script.AppendExtra(OPTIONS.extra_script) + + if OPTIONS.wipe_user_data: + script.Print("Erasing user data...") + script.FormatPartition("/data") + + if OPTIONS.two_step: + script.AppendExtra(""" +set_stage("%(bcb_dev)s", ""); +endif; +endif; +""" % bcb_dev) + + script.SetProgress(1) + script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) + WriteMetadata(metadata, output_zip) + +def ParseMap(map_str): + x = map_str.split() + assert int(x[0]) == 4096 + assert int(x[1]) == len(x)-2 + return int(x[0]), [int(i) for i in x[2:]] + +def TestBlockPatch(src_muimg, src_map, patch_data, tgt_map, tgt_sha1): + src_blksize, src_regions = ParseMap(src_map) + tgt_blksize, tgt_regions = ParseMap(tgt_map) + + with tempfile.NamedTemporaryFile() as src_file,\ + tempfile.NamedTemporaryFile() as patch_file,\ + tempfile.NamedTemporaryFile() as src_map_file,\ + tempfile.NamedTemporaryFile() as tgt_map_file: + + src_total = sum(src_regions) * src_blksize + src_file.truncate(src_total) + p = 0 + for i in range(0, len(src_regions), 2): + c, dc = src_regions[i:i+2] + src_file.write(src_muimg[p:(p+c*src_blksize)]) + p += c*src_blksize + src_file.seek(dc*src_blksize, 1) + assert src_file.tell() == src_total + + patch_file.write(patch_data) + + src_map_file.write(src_map) + tgt_map_file.write(tgt_map) + + src_file.flush() + src_map_file.flush() + patch_file.flush() + tgt_map_file.flush() + + p = common.Run(["syspatch_host", src_file.name, src_map_file.name, + patch_file.name, src_file.name, tgt_map_file.name], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdoutdata, _ = p.communicate() + if p.returncode != 0: + print stdoutdata + raise ValueError("failed to reconstruct target system image from patch") + + h = sha1() + src_file.seek(0, 0) + for i in range(0, len(tgt_regions), 2): + c, dc = tgt_regions[i:i+2] + h.update(src_file.read(c*tgt_blksize)) + src_file.seek(dc*tgt_blksize, 1) + + if h.hexdigest() != tgt_sha1: + raise ValueError("patch reconstructed incorrect target system image") + + print "test of system image patch succeeded" + + +class FileDifference: + def __init__(self, partition, source_zip, target_zip, output_zip): + print "Loading target..." + self.target_data = target_data = LoadPartitionFiles(target_zip, partition) + print "Loading source..." + self.source_data = source_data = LoadPartitionFiles(source_zip, partition) + + self.verbatim_targets = verbatim_targets = [] + self.patch_list = patch_list = [] + diffs = [] + self.renames = renames = {} + known_paths = set() + largest_source_size = 0 + + matching_file_cache = {} + for fn, sf in source_data.items(): + assert fn == sf.name + matching_file_cache["path:" + fn] = sf + if fn in target_data.keys(): + AddToKnownPaths(fn, known_paths) + # Only allow eligibility for filename/sha matching + # if there isn't a perfect path match. + if target_data.get(sf.name) is None: + matching_file_cache["file:" + fn.split("/")[-1]] = sf + matching_file_cache["sha:" + sf.sha1] = sf + + for fn in sorted(target_data.keys()): + tf = target_data[fn] + assert fn == tf.name + sf = ClosestFileMatch(tf, matching_file_cache, renames) + if sf is not None and sf.name != tf.name: + print "File has moved from " + sf.name + " to " + tf.name + renames[sf.name] = tf + + if sf is None or fn in OPTIONS.require_verbatim: + # This file should be included verbatim + if fn in OPTIONS.prohibit_verbatim: + raise common.ExternalError("\"%s\" must be sent verbatim" % (fn,)) + print "send", fn, "verbatim" + tf.AddToZip(output_zip) + verbatim_targets.append((fn, tf.size)) + if fn in target_data.keys(): + AddToKnownPaths(fn, known_paths) + elif tf.sha1 != sf.sha1: + # File is different; consider sending as a patch + diffs.append(common.Difference(tf, sf)) + else: + # Target file data identical to source (may still be renamed) + pass + + common.ComputeDifferences(diffs) + + for diff in diffs: + tf, sf, d = diff.GetPatch() + path = "/".join(tf.name.split("/")[:-1]) + if d is None or len(d) > tf.size * OPTIONS.patch_threshold or \ + path not in known_paths: + # patch is almost as big as the file; don't bother patching + # or a patch + rename cannot take place due to the target + # directory not existing + tf.AddToZip(output_zip) + verbatim_targets.append((tf.name, tf.size)) + if sf.name in renames: + del renames[sf.name] + AddToKnownPaths(tf.name, known_paths) + else: + common.ZipWriteStr(output_zip, "patch/" + sf.name + ".p", d) + patch_list.append((tf, sf, tf.size, common.sha1(d).hexdigest())) + largest_source_size = max(largest_source_size, sf.size) + + self.largest_source_size = largest_source_size + + def EmitVerification(self, script): + so_far = 0 + for tf, sf, size, patch_sha in self.patch_list: + if tf.name != sf.name: + script.SkipNextActionIfTargetExists(tf.name, tf.sha1) + script.PatchCheck("/"+sf.name, tf.sha1, sf.sha1) + so_far += sf.size + return so_far + + def RemoveUnneededFiles(self, script, extras=()): + script.DeleteFiles(["/"+i[0] for i in self.verbatim_targets] + + ["/"+i for i in sorted(self.source_data) + if i not in self.target_data and + i not in self.renames] + + list(extras)) + + def TotalPatchSize(self): + return sum(i[1].size for i in self.patch_list) + + def EmitPatches(self, script, total_patch_size, so_far): + self.deferred_patch_list = deferred_patch_list = [] + for item in self.patch_list: + tf, sf, size, _ = item + if tf.name == "system/build.prop": + deferred_patch_list.append(item) + continue + if (sf.name != tf.name): + script.SkipNextActionIfTargetExists(tf.name, tf.sha1) + script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p") + so_far += tf.size + script.SetProgress(so_far / total_patch_size) + return so_far + + def EmitDeferredPatches(self, script): + for item in self.deferred_patch_list: + tf, sf, size, _ = item + script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p") + script.SetPermissions("/system/build.prop", 0, 0, 0644, None, None) + + def EmitRenames(self, script): + if len(self.renames) > 0: + script.Print("Renaming files...") + for src, tgt in self.renames.iteritems(): + print "Renaming " + src + " to " + tgt.name + script.RenameFile(src, tgt.name) + + + + +def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): + target_has_recovery_patch = HasRecoveryPatch(target_zip) + source_has_recovery_patch = HasRecoveryPatch(source_zip) + + if (OPTIONS.block_based and + target_has_recovery_patch and + source_has_recovery_patch): + return WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip) + + source_version = OPTIONS.source_info_dict["recovery_api_version"] + target_version = OPTIONS.target_info_dict["recovery_api_version"] + + if source_version == 0: + print ("WARNING: generating edify script for a source that " + "can't install it.") + script = edify_generator.EdifyGenerator(source_version, + OPTIONS.target_info_dict) + + oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties") + oem_dict = None + if oem_props is not None: + if OPTIONS.oem_source is None: + raise common.ExternalError("OEM source required for this build") + script.Mount("/oem") + oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) + + metadata = {"pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict, + OPTIONS.source_info_dict), + "post-timestamp": GetBuildProp("ro.build.date.utc", + OPTIONS.target_info_dict), + } + + device_specific = common.DeviceSpecificParams( + source_zip=source_zip, + source_version=source_version, + target_zip=target_zip, + target_version=target_version, + output_zip=output_zip, + script=script, + metadata=metadata, + info_dict=OPTIONS.info_dict) + + system_diff = FileDifference("system", source_zip, target_zip, output_zip) script.Mount("/system") - script.AssertSomeFingerprint(source_fp, target_fp) + if HasVendorPartition(target_zip): + vendor_diff = FileDifference("vendor", source_zip, target_zip, output_zip) + script.Mount("/vendor") + else: + vendor_diff = None + + target_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.target_info_dict) + source_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.source_info_dict) + + if oem_props is None: + script.AssertSomeFingerprint(source_fp, target_fp) + else: + script.AssertSomeThumbprint( + GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), + GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) + + metadata["pre-build"] = source_fp + metadata["post-build"] = target_fp source_boot = common.GetBootableImage( "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", @@ -700,7 +1153,7 @@ def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): # 0.1 for unpacking verbatim files, symlinking, and doing the # device-specific commands. - AppendAssertions(script, OPTIONS.target_info_dict) + AppendAssertions(script, OPTIONS.target_info_dict, oem_dict) device_specific.IncrementalOTA_Assertions() # Two-step incremental package strategy (in chronological order, @@ -748,17 +1201,9 @@ else if get_stage("%(bcb_dev)s", "stage") != "3/3" then device_specific.IncrementalOTA_VerifyBegin() script.ShowProgress(0.1, 0) - total_verify_size = float(sum([i[1].size for i in patch_list]) + 1) - if updating_boot: - total_verify_size += source_boot.size - so_far = 0 - - for tf, sf, size, patch_sha in patch_list: - if tf.name != sf.name: - script.SkipNextActionIfTargetExists(tf.name, tf.sha1) - script.PatchCheck("/"+sf.name, tf.sha1, sf.sha1) - so_far += sf.size - script.SetProgress(so_far / total_verify_size) + so_far = system_diff.EmitVerification(script) + if vendor_diff: + so_far += vendor_diff.EmitVerification(script) if updating_boot: d = common.Difference(target_boot, source_boot) @@ -775,10 +1220,13 @@ else if get_stage("%(bcb_dev)s", "stage") != "3/3" then source_boot.size, source_boot.sha1, target_boot.size, target_boot.sha1)) so_far += source_boot.size - script.SetProgress(so_far / total_verify_size) - if patch_list or updating_recovery or updating_boot: - script.CacheFreeSpaceCheck(largest_source_size) + size = [] + if system_diff.patch_list: size.append(system_diff.largest_source_size) + if vendor_diff: + if vendor_diff.patch_list: size.append(vendor_diff.largest_source_size) + if size or updating_recovery or updating_boot: + script.CacheFreeSpaceCheck(max(size)) device_specific.IncrementalOTA_VerifyEnd() @@ -799,35 +1247,23 @@ else script.WriteRawImage("/boot", "boot.img") print "writing full boot image (forced by two-step mode)" - if OPTIONS.wipe_user_data: - script.Print("Erasing user data...") - script.FormatPartition("/data") - script.Print("Removing unneeded files...") - script.DeleteFiles(["/"+i[0] for i in verbatim_targets] + - ["/"+i for i in sorted(source_data) - if i not in target_data and - i not in renames] + - ["/system/recovery.img"]) + system_diff.RemoveUnneededFiles(script, ("/system/recovery.img",)) + if vendor_diff: + vendor_diff.RemoveUnneededFiles(script) script.ShowProgress(0.8, 0) - total_patch_size = float(sum([i[1].size for i in patch_list]) + 1) + total_patch_size = 1.0 + system_diff.TotalPatchSize() + if vendor_diff: + total_patch_size += vendor_diff.TotalPatchSize() if updating_boot: total_patch_size += target_boot.size - so_far = 0 script.Print("Patching system files...") - deferred_patch_list = [] - for item in patch_list: - tf, sf, size, _ = item - if tf.name == "system/build.prop": - deferred_patch_list.append(item) - continue - if (sf.name != tf.name): - script.SkipNextActionIfTargetExists(tf.name, tf.sha1) - script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p") - so_far += tf.size - script.SetProgress(so_far / total_patch_size) + so_far = system_diff.EmitPatches(script, total_patch_size, 0) + if vendor_diff: + script.Print("Patching vendor files...") + so_far = vendor_diff.EmitPatches(script, total_patch_size, so_far) if not OPTIONS.two_step: if updating_boot: @@ -848,6 +1284,10 @@ else else: print "boot image unchanged; skipping." + system_items = ItemSet("system", "META/filesystem_config.txt") + if vendor_diff: + vendor_items = ItemSet("vendor", "META/vendor_filesystem_config.txt") + if updating_recovery: # Recovery is generated as a patch using both the boot image # (which contains the same linux kernel as recovery) and the file @@ -858,26 +1298,39 @@ else # For older builds where recovery-resource.dat is not present, we # use only the boot image as the source. - MakeRecoveryPatch(OPTIONS.target_tmp, output_zip, - target_recovery, target_boot) - script.DeleteFiles(["/system/recovery-from-boot.p", - "/system/etc/install-recovery.sh"]) + if not target_has_recovery_patch: + def output_sink(fn, data): + common.ZipWriteStr(output_zip, "recovery/" + fn, data) + system_items.Get("system/" + fn, dir=False) + + common.MakeRecoveryPatch(OPTIONS.target_tmp, output_sink, + target_recovery, target_boot) + script.DeleteFiles(["/system/recovery-from-boot.p", + "/system/etc/install-recovery.sh"]) print "recovery image changed; including as patch from boot." else: print "recovery image unchanged; skipping." script.ShowProgress(0.1, 10) - target_symlinks = CopySystemFiles(target_zip, None) + target_symlinks = CopyPartitionFiles(system_items, target_zip, None) + if vendor_diff: + target_symlinks.extend(CopyPartitionFiles(vendor_items, target_zip, None)) - target_symlinks_d = dict([(i[1], i[0]) for i in target_symlinks]) temp_script = script.MakeTemporary() - Item.GetMetadata(target_zip) - Item.Get("system").SetPermissions(temp_script) + system_items.GetMetadata(target_zip) + system_items.Get("system").SetPermissions(temp_script) + if vendor_diff: + vendor_items.GetMetadata(target_zip) + vendor_items.Get("vendor").SetPermissions(temp_script) + + # Note that this call will mess up the trees of Items, so make sure + # we're done with them. + source_symlinks = CopyPartitionFiles(system_items, source_zip, None) + if vendor_diff: + source_symlinks.extend(CopyPartitionFiles(vendor_items, source_zip, None)) - # Note that this call will mess up the tree of Items, so make sure - # we're done with it. - source_symlinks = CopySystemFiles(source_zip, None) + target_symlinks_d = dict([(i[1], i[0]) for i in target_symlinks]) source_symlinks_d = dict([(i[1], i[0]) for i in source_symlinks]) # Delete all the symlinks in source that aren't in target. This @@ -889,20 +1342,20 @@ else to_delete.append(link) script.DeleteFiles(to_delete) - if verbatim_targets: - script.Print("Unpacking new files...") + if system_diff.verbatim_targets: + script.Print("Unpacking new system files...") script.UnpackPackageDir("system", "/system") + if vendor_diff and vendor_diff.verbatim_targets: + script.Print("Unpacking new vendor files...") + script.UnpackPackageDir("vendor", "/vendor") - if updating_recovery: + if updating_recovery and not target_has_recovery_patch: script.Print("Unpacking new recovery...") script.UnpackPackageDir("recovery", "/system") - if len(renames) > 0: - script.Print("Renaming files...") - - for src in renames: - print "Renaming " + src + " to " + renames[src].name - script.RenameFile(src, renames[src].name) + system_diff.EmitRenames(script) + if vendor_diff: + vendor_diff.EmitRenames(script) script.Print("Symlinks and permissions...") @@ -933,10 +1386,11 @@ else # device can still come up, it appears to be the old build and will # get set the OTA package again to retry. script.Print("Patching remaining system files...") - for item in deferred_patch_list: - tf, sf, size, _ = item - script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p") - script.SetPermissions("/system/build.prop", 0, 0, 0644, None, None) + system_diff.EmitDeferredPatches(script) + + if OPTIONS.wipe_user_data: + script.Print("Erasing user data...") + script.FormatPartition("/data") if OPTIONS.two_step: script.AppendExtra(""" @@ -945,14 +1399,14 @@ endif; endif; """ % bcb_dev) - script.AddToZip(target_zip, output_zip) + script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) WriteMetadata(metadata, output_zip) def main(argv): def option_handler(o, a): - if o in ("-b", "--board_config"): + if o == "--board_config": pass # deprecated elif o in ("-k", "--package_key"): OPTIONS.package_key = a @@ -962,6 +1416,8 @@ def main(argv): OPTIONS.wipe_user_data = True elif o in ("-n", "--no_prereq"): OPTIONS.omit_prereq = True + elif o in ("-o", "--oem_settings"): + OPTIONS.oem_source = a elif o in ("-e", "--extra_script"): OPTIONS.extra_script = a elif o in ("-a", "--aslr_mode"): @@ -977,14 +1433,18 @@ def main(argv): "integers are allowed." % (a, o)) elif o in ("-2", "--two_step"): OPTIONS.two_step = True - elif o in ("--no_signing"): + elif o == "--no_signing": OPTIONS.no_signing = True + elif o == "--block": + OPTIONS.block_based = True + elif o in ("-b", "--binary"): + OPTIONS.updater_binary = a else: return False return True args = common.ParseOptions(argv, __doc__, - extra_opts="b:k:i:d:wne:t:a:2", + extra_opts="b:k:i:d:wne:t:a:2o:", extra_long_opts=["board_config=", "package_key=", "incremental_from=", @@ -995,6 +1455,9 @@ def main(argv): "aslr_mode=", "two_step", "no_signing", + "block", + "binary=", + "oem_settings=", ], extra_option_handler=option_handler) @@ -1023,11 +1486,23 @@ def main(argv): print "--- target info ---" common.DumpInfoDict(OPTIONS.info_dict) + # If the caller explicitly specified the device-specific extensions + # path via -s/--device_specific, use that. Otherwise, use + # META/releasetools.py if it is present in the target target_files. + # Otherwise, take the path of the file from 'tool_extensions' in the + # info dict and look for that in the local filesystem, relative to + # the current directory. + if OPTIONS.device_specific is None: - OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None) + from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py") + if os.path.exists(from_input): + print "(using device-specific extensions from target_files)" + OPTIONS.device_specific = from_input + else: + OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None) + if OPTIONS.device_specific is not None: - OPTIONS.device_specific = os.path.normpath(OPTIONS.device_specific) - print "using device-specific extensions in", OPTIONS.device_specific + OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific) if OPTIONS.no_signing: output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) @@ -1047,6 +1522,9 @@ def main(argv): OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source) OPTIONS.target_info_dict = OPTIONS.info_dict OPTIONS.source_info_dict = common.LoadInfoDict(source_zip) + if "selinux_fc" in OPTIONS.source_info_dict: + OPTIONS.source_info_dict["selinux_fc"] = os.path.join(OPTIONS.source_tmp, "BOOT", "RAMDISK", + "file_contexts") if OPTIONS.package_key is None: OPTIONS.package_key = OPTIONS.source_info_dict.get( "default_system_dev_certificate", diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks index ab24706..0ecb906 100755 --- a/tools/releasetools/sign_target_files_apks +++ b/tools/releasetools/sign_target_files_apks @@ -67,8 +67,8 @@ Usage: sign_target_files_apks [flags] input_target_files output_target_files import sys -if sys.hexversion < 0x02040000: - print >> sys.stderr, "Python 2.4 or newer is required." +if sys.hexversion < 0x02070000: + print >> sys.stderr, "Python 2.7 or newer is required." sys.exit(1) import base64 @@ -77,6 +77,7 @@ import copy import errno import os import re +import shutil import subprocess import tempfile import zipfile @@ -139,14 +140,41 @@ def SignApk(data, keyname, pw): return data -def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): +def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info, + apk_key_map, key_passwords): + maxsize = max([len(os.path.basename(i.filename)) for i in input_tf_zip.infolist() if i.filename.endswith('.apk')]) + rebuild_recovery = False + + tmpdir = tempfile.mkdtemp() + def write_to_temp(fn, attr, data): + fn = os.path.join(tmpdir, fn) + if fn.endswith("/"): + fn = os.path.join(tmpdir, fn) + os.mkdir(fn) + else: + d = os.path.dirname(fn) + if d and not os.path.exists(d): + os.makedirs(d) + + if attr >> 16 == 0xa1ff: + os.symlink(data, fn) + else: + with open(fn, "wb") as f: + f.write(data) for info in input_tf_zip.infolist(): data = input_tf_zip.read(info.filename) out_info = copy.copy(info) + + if (info.filename.startswith("BOOT/") or + info.filename.startswith("RECOVERY/") or + info.filename.startswith("META/") or + info.filename == "SYSTEM/etc/recovery-resource.dat"): + write_to_temp(info.filename, info.external_attr, data) + if info.filename.endswith(".apk"): name = os.path.basename(info.filename) key = apk_key_map[name] @@ -161,16 +189,45 @@ def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): elif info.filename in ("SYSTEM/build.prop", "RECOVERY/RAMDISK/default.prop"): print "rewriting %s:" % (info.filename,) - new_data = RewriteProps(data) + new_data = RewriteProps(data, misc_info) output_tf_zip.writestr(out_info, new_data) + if info.filename == "RECOVERY/RAMDISK/default.prop": + write_to_temp(info.filename, info.external_attr, new_data) elif info.filename.endswith("mac_permissions.xml"): print "rewriting %s with new keys." % (info.filename,) new_data = ReplaceCerts(data) output_tf_zip.writestr(out_info, new_data) + elif info.filename in ("SYSTEM/recovery-from-boot.p", + "SYSTEM/bin/install-recovery.sh"): + rebuild_recovery = True + elif (OPTIONS.replace_ota_keys and + info.filename in ("RECOVERY/RAMDISK/res/keys", + "SYSTEM/etc/security/otacerts.zip")): + # don't copy these files if we're regenerating them below + pass else: # a non-APK file; copy it verbatim output_tf_zip.writestr(out_info, data) + if OPTIONS.replace_ota_keys: + new_recovery_keys = ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info) + if new_recovery_keys: + write_to_temp("RECOVERY/RAMDISK/res/keys", 0755 << 16, new_recovery_keys) + + if rebuild_recovery: + recovery_img = common.GetBootableImage( + "recovery.img", "recovery.img", tmpdir, "RECOVERY", info_dict=misc_info) + boot_img = common.GetBootableImage( + "boot.img", "boot.img", tmpdir, "BOOT", info_dict=misc_info) + + def output_sink(fn, data): + output_tf_zip.writestr("SYSTEM/"+fn, data) + + common.MakeRecoveryPatch(tmpdir, output_sink, recovery_img, boot_img, + info_dict=misc_info) + + shutil.rmtree(tmpdir) + def ReplaceCerts(data): """Given a string of data, replace all occurences of a set @@ -214,14 +271,20 @@ def EditTags(tags): return ",".join(sorted(tags)) -def RewriteProps(data): +def RewriteProps(data, misc_info): output = [] for line in data.split("\n"): line = line.strip() original_line = line - if line and line[0] != '#': + if line and line[0] != '#' and "=" in line: key, value = line.split("=", 1) - if key == "ro.build.fingerprint": + if (key == "ro.build.fingerprint" + and misc_info.get("oem_fingerprint_properties") is None): + pieces = value.split("/") + pieces[-1] = EditTags(pieces[-1]) + value = "/".join(pieces) + elif (key == "ro.build.thumbprint" + and misc_info.get("oem_fingerprint_properties") is not None): pieces = value.split("/") pieces[-1] = EditTags(pieces[-1]) value = "/".join(pieces) @@ -235,7 +298,7 @@ def RewriteProps(data): elif key == "ro.build.display.id": # change, eg, "JWR66N dev-keys" to "JWR66N" value = value.split() - if len(value) > 1 and value[-1].endswith("-keys"): + if len(value) > 1 and value[-1].endswith("-keys"): value.pop() value = " ".join(value) line = key + "=" + value @@ -265,7 +328,8 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): for k in keylist: m = re.match(r"^(.*)\.x509\.pem$", k) if not m: - raise common.ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,)) + raise common.ExternalError( + "can't parse \"%s\" from META/otakeys.txt" % (k,)) k = m.group(1) mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem") @@ -287,10 +351,11 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")] + mapped_keys + extra_recovery_keys, stdout=subprocess.PIPE) - data, _ = p.communicate() + new_recovery_keys, _ = p.communicate() if p.returncode != 0: raise common.ExternalError("failed to run dumpkeys") - common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", data) + common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", + new_recovery_keys) # SystemUpdateActivity uses the x509.pem version of the keys, but # put into a zipfile system/etc/security/otacerts.zip. @@ -304,6 +369,8 @@ def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip", tempfile.getvalue()) + return new_recovery_keys + def BuildKeyMap(misc_info, key_mapping_options): for s, d in key_mapping_options: @@ -375,10 +442,8 @@ def main(argv): CheckAllApksSigned(input_zip, apk_key_map) key_passwords = common.GetKeyPasswords(set(apk_key_map.values())) - SignApks(input_zip, output_zip, apk_key_map, key_passwords) - - if OPTIONS.replace_ota_keys: - ReplaceOtaKeys(input_zip, output_zip, misc_info) + ProcessTargetFiles(input_zip, output_zip, misc_info, + apk_key_map, key_passwords) input_zip.close() output_zip.close() diff --git a/tools/releasetools/simg_map.py b/tools/releasetools/simg_map.py new file mode 100644 index 0000000..22dc863 --- /dev/null +++ b/tools/releasetools/simg_map.py @@ -0,0 +1,148 @@ +#! /usr/bin/env python + +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function +import getopt, posixpath, signal, struct, sys + +def main(): + if len(sys.argv) == 4: + print("No sparse_image_file specified") + usage(me) + + sparse_fn = sys.argv[1] + unsparse_fn = sys.argv[2] + map_file = sys.argv[3] + mapped_unsparse_fn = sys.argv[4] + + return ComputeMap(sparse_fn, unsparse_fn, map_file, mapped_unsparse_fn) + + +def ComputeMap(sparse_fn, unsparse_fn, map_file, mapped_unsparse_fn): + care_map = [] + + with open(sparse_fn, "rb") as FH: + header_bin = FH.read(28) + header = struct.unpack("<I4H4I", header_bin) + + magic = header[0] + major_version = header[1] + minor_version = header[2] + file_hdr_sz = header[3] + chunk_hdr_sz = header[4] + blk_sz = header[5] + total_blks = header[6] + total_chunks = header[7] + image_checksum = header[8] + + if magic != 0xED26FF3A: + print("%s: %s: Magic should be 0xED26FF3A but is 0x%08X" + % (me, path, magic)) + return 1 + if major_version != 1 or minor_version != 0: + print("%s: %s: I only know about version 1.0, but this is version %u.%u" + % (me, path, major_version, minor_version)) + return 1 + if file_hdr_sz != 28: + print("%s: %s: The file header size was expected to be 28, but is %u." + % (me, path, file_hdr_sz)) + return 1 + if chunk_hdr_sz != 12: + print("%s: %s: The chunk header size was expected to be 12, but is %u." + % (me, path, chunk_hdr_sz)) + return 1 + + print("%s: Total of %u %u-byte output blocks in %u input chunks." + % (sparse_fn, total_blks, blk_sz, total_chunks)) + + offset = 0 + for i in range(total_chunks): + header_bin = FH.read(12) + header = struct.unpack("<2H2I", header_bin) + chunk_type = header[0] + reserved1 = header[1] + chunk_sz = header[2] + total_sz = header[3] + data_sz = total_sz - 12 + + if chunk_type == 0xCAC1: + if data_sz != (chunk_sz * blk_sz): + print("Raw chunk input size (%u) does not match output size (%u)" + % (data_sz, chunk_sz * blk_sz)) + return 1 + else: + care_map.append((1, chunk_sz)) + FH.seek(data_sz, 1) + + elif chunk_type == 0xCAC2: + print("Fill chunks are not supported") + return 1 + + elif chunk_type == 0xCAC3: + if data_sz != 0: + print("Don't care chunk input size is non-zero (%u)" % (data_sz)) + return 1 + else: + care_map.append((0, chunk_sz)) + + elif chunk_type == 0xCAC4: + print("CRC32 chunks are not supported") + + else: + print("Unknown chunk type 0x%04X not supported" % (chunk_type,)) + return 1 + + offset += chunk_sz + + if total_blks != offset: + print("The header said we should have %u output blocks, but we saw %u" + % (total_blks, offset)) + + junk_len = len(FH.read()) + if junk_len: + print("There were %u bytes of extra data at the end of the file." + % (junk_len)) + return 1 + + last_kind = None + new_care_map = [] + for kind, size in care_map: + if kind != last_kind: + new_care_map.append((kind, size)) + last_kind = kind + else: + new_care_map[-1] = (kind, new_care_map[-1][1] + size) + + if new_care_map[0][0] == 0: + new_care_map.insert(0, (1, 0)) + if len(new_care_map) % 2: + new_care_map.append((0, 0)) + + with open(map_file, "w") as fmap: + fmap.write("%d\n%d\n" % (blk_sz, len(new_care_map))) + for _, sz in new_care_map: + fmap.write("%d\n" % sz) + + with open(unsparse_fn, "rb") as fin: + with open(mapped_unsparse_fn, "wb") as fout: + for k, sz in care_map: + data = fin.read(sz * blk_sz) + if k: + fout.write(data) + else: + assert data == "\x00" * len(data) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/zipalign/Android.mk b/tools/zipalign/Android.mk index 708c8bf..7986798 100644 --- a/tools/zipalign/Android.mk +++ b/tools/zipalign/Android.mk @@ -12,13 +12,15 @@ LOCAL_SRC_FILES := \ ZipEntry.cpp \ ZipFile.cpp -LOCAL_C_INCLUDES += external/zlib +LOCAL_C_INCLUDES += external/zlib \ + external/zopfli/src LOCAL_STATIC_LIBRARIES := \ libandroidfw \ libutils \ libcutils \ - liblog + liblog \ + libzopfli ifeq ($(HOST_OS),linux) LOCAL_LDLIBS += -lrt diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp index 8b2d1af..dc2826b 100644 --- a/tools/zipalign/ZipAlign.cpp +++ b/tools/zipalign/ZipAlign.cpp @@ -32,19 +32,20 @@ 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" + "Usage: zipalign [-f] [-v] [-z] <align> infile.zip outfile.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"); + fprintf(stderr, " -z: recompress using Zopfli\n"); } /* * Copy all entries from "pZin" to "pZout", aligning as needed. */ -static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment) +static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfli) { int numEntries = pZin->getNumEntries(); ZipEntry* pEntry; @@ -67,6 +68,12 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment) // pEntry->getFileName(), (long) pEntry->getFileOffset(), // (long) pEntry->getUncompressedLen()); + if (zopfli) { + status = pZout->addRecompress(pZin, pEntry, &pNewEntry); + bias += pNewEntry->getCompressedLen() - pEntry->getCompressedLen(); + } else { + status = pZout->add(pZin, pEntry, padding, &pNewEntry); + } } else { /* * Copy the entry, adjusting as required. We assume that the @@ -79,9 +86,9 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment) //printf("--- %s: orig at %ld(+%d) len=%ld, adding pad=%d\n", // pEntry->getFileName(), (long) pEntry->getFileOffset(), // bias, (long) pEntry->getUncompressedLen(), padding); + status = pZout->add(pZin, pEntry, padding, &pNewEntry); } - status = pZout->add(pZin, pEntry, padding, &pNewEntry); if (status != NO_ERROR) return 1; bias += padding; @@ -98,7 +105,7 @@ static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment) * output file exists and "force" wasn't specified. */ static int process(const char* inFileName, const char* outFileName, - int alignment, bool force) + int alignment, bool force, bool zopfli) { ZipFile zin, zout; @@ -129,7 +136,7 @@ static int process(const char* inFileName, const char* outFileName, return 1; } - int result = copyAndAlign(&zin, &zout, alignment); + int result = copyAndAlign(&zin, &zout, alignment, zopfli); if (result != 0) { printf("zipalign: failed rewriting '%s' to '%s'\n", inFileName, outFileName); @@ -196,6 +203,7 @@ int main(int argc, char* const argv[]) bool check = false; bool force = false; bool verbose = false; + bool zopfli = false; int result = 1; int alignment; char* endp; @@ -222,6 +230,9 @@ int main(int argc, char* const argv[]) case 'v': verbose = true; break; + case 'z': + zopfli = true; + break; default: fprintf(stderr, "ERROR: unknown flag -%c\n", *cp); wantUsage = true; @@ -252,7 +263,7 @@ int main(int argc, char* const argv[]) result = verify(argv[1], alignment, verbose); } else { /* create the new archive */ - result = process(argv[1], argv[2], alignment, force); + result = process(argv[1], argv[2], alignment, force, zopfli); /* trust, but verify */ if (result == 0) diff --git a/tools/zipalign/ZipFile.cpp b/tools/zipalign/ZipFile.cpp index 8057068..3c5ec15 100644 --- a/tools/zipalign/ZipFile.cpp +++ b/tools/zipalign/ZipFile.cpp @@ -28,6 +28,8 @@ #include <zlib.h> #define DEF_MEM_LEVEL 8 // normally in zutil.h? +#include "zopfli/deflate.h" + #include <memory.h> #include <sys/stat.h> #include <errno.h> @@ -638,6 +640,141 @@ bail: } /* + * Add an entry by copying it from another zip file, recompressing with + * Zopfli if already compressed. + * + * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. + */ +status_t ZipFile::addRecompress(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry, + ZipEntry** ppEntry) +{ + ZipEntry* pEntry = NULL; + status_t result; + long lfhPosn, startPosn, endPosn, uncompressedLen; + + if (mReadOnly) + return INVALID_OPERATION; + + /* make sure we're in a reasonable state */ + assert(mZipFp != NULL); + assert(mEntries.size() == mEOCD.mTotalNumEntries); + + if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { + result = UNKNOWN_ERROR; + goto bail; + } + + pEntry = new ZipEntry; + if (pEntry == NULL) { + result = NO_MEMORY; + goto bail; + } + + result = pEntry->initFromExternal(pSourceZip, pSourceEntry); + if (result != NO_ERROR) + goto bail; + + /* + * From here on out, failures are more interesting. + */ + mNeedCDRewrite = true; + + /* + * Write the LFH, even though it's still mostly blank. We need it + * as a place-holder. In theory the LFH isn't necessary, but in + * practice some utilities demand it. + */ + lfhPosn = ftell(mZipFp); + pEntry->mLFH.write(mZipFp); + startPosn = ftell(mZipFp); + + /* + * Copy the data over. + * + * If the "has data descriptor" flag is set, we want to copy the DD + * fields as well. This is a fixed-size area immediately following + * the data. + */ + if (fseek(pSourceZip->mZipFp, pSourceEntry->getFileOffset(), SEEK_SET) != 0) + { + result = UNKNOWN_ERROR; + goto bail; + } + + uncompressedLen = pSourceEntry->getUncompressedLen(); + + if (pSourceEntry->isCompressed()) { + void *buf = pSourceZip->uncompress(pSourceEntry); + if (buf == NULL) { + result = NO_MEMORY; + goto bail; + } + long startPosn = ftell(mZipFp); + unsigned long crc; + if (compressFpToFp(mZipFp, NULL, buf, uncompressedLen, &crc) != NO_ERROR) { + ALOGW("recompress of '%s' failed\n", pEntry->mCDE.mFileName); + result = UNKNOWN_ERROR; + free(buf); + goto bail; + } + long endPosn = ftell(mZipFp); + pEntry->setDataInfo(uncompressedLen, endPosn - startPosn, + pSourceEntry->getCRC32(), ZipEntry::kCompressDeflated); + free(buf); + } else { + off_t copyLen; + copyLen = pSourceEntry->getCompressedLen(); + if ((pSourceEntry->mLFH.mGPBitFlag & ZipEntry::kUsesDataDescr) != 0) + copyLen += ZipEntry::kDataDescriptorLen; + + if (copyPartialFpToFp(mZipFp, pSourceZip->mZipFp, copyLen, NULL) + != NO_ERROR) + { + ALOGW("copy of '%s' failed\n", pEntry->mCDE.mFileName); + result = UNKNOWN_ERROR; + goto bail; + } + } + + /* + * Update file offsets. + */ + endPosn = ftell(mZipFp); + + /* + * Success! Fill out new values. + */ + pEntry->setLFHOffset(lfhPosn); + mEOCD.mNumEntries++; + mEOCD.mTotalNumEntries++; + mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() + mEOCD.mCentralDirOffset = endPosn; + + /* + * Go back and write the LFH. + */ + if (fseek(mZipFp, lfhPosn, SEEK_SET) != 0) { + result = UNKNOWN_ERROR; + goto bail; + } + pEntry->mLFH.write(mZipFp); + + /* + * Add pEntry to the list. + */ + mEntries.add(pEntry); + if (ppEntry != NULL) + *ppEntry = pEntry; + pEntry = NULL; + + result = NO_ERROR; + +bail: + delete pEntry; + return result; +} + +/* * Copy all of the bytes in "src" to "dst". * * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" @@ -744,73 +881,43 @@ status_t ZipFile::compressFpToFp(FILE* dstFp, FILE* srcFp, const void* data, size_t size, unsigned long* pCRC32) { status_t result = NO_ERROR; - const size_t kBufSize = 32768; + const size_t kBufSize = 1024 * 1024; unsigned char* inBuf = NULL; unsigned char* outBuf = NULL; - z_stream zstream; + size_t outSize = 0; bool atEof = false; // no feof() aviailable yet unsigned long crc; - int zerr; + ZopfliOptions options; + unsigned char bp = 0; - /* - * Create an input buffer and an output buffer. - */ - inBuf = new unsigned char[kBufSize]; - outBuf = new unsigned char[kBufSize]; - if (inBuf == NULL || outBuf == NULL) { - result = NO_MEMORY; - goto bail; - } - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - zstream.data_type = Z_UNKNOWN; - - zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); - if (zerr != Z_OK) { - result = UNKNOWN_ERROR; - if (zerr == Z_VERSION_ERROR) { - ALOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - ALOGD("Call to deflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } + ZopfliInitOptions(&options); crc = crc32(0L, Z_NULL, 0); - /* - * Loop while we have data. - */ - do { - size_t getSize; - int flush; - - /* only read if the input buffer is empty */ - if (zstream.avail_in == 0 && !atEof) { - ALOGV("+++ reading %d bytes\n", (int)kBufSize); - if (data) { - getSize = size > kBufSize ? kBufSize : size; - memcpy(inBuf, data, getSize); - data = ((const char*)data) + getSize; - size -= getSize; - } else { - getSize = fread(inBuf, 1, kBufSize, srcFp); - if (ferror(srcFp)) { - ALOGD("deflate read failed (errno=%d)\n", errno); - goto z_bail; - } + if (data) { + crc = crc32(crc, (const unsigned char*)data, size); + ZopfliDeflate(&options, 2, true, (const unsigned char*)data, size, &bp, + &outBuf, &outSize); + } else { + /* + * Create an input buffer and an output buffer. + */ + inBuf = new unsigned char[kBufSize]; + if (inBuf == NULL) { + result = NO_MEMORY; + goto bail; + } + + /* + * Loop while we have data. + */ + do { + size_t getSize; + getSize = fread(inBuf, 1, kBufSize, srcFp); + if (ferror(srcFp)) { + ALOGD("deflate read failed (errno=%d)\n", errno); + delete[] inBuf; + goto bail; } if (getSize < kBufSize) { ALOGV("+++ got %d bytes, EOF reached\n", @@ -819,51 +926,21 @@ status_t ZipFile::compressFpToFp(FILE* dstFp, FILE* srcFp, } crc = crc32(crc, inBuf, getSize); + ZopfliDeflate(&options, 2, atEof, inBuf, getSize, &bp, &outBuf, &outSize); + } while (!atEof); + delete[] inBuf; + } - zstream.next_in = inBuf; - zstream.avail_in = getSize; - } - - if (atEof) - flush = Z_FINISH; /* tell zlib that we're done */ - else - flush = Z_NO_FLUSH; /* more to come! */ - - zerr = deflate(&zstream, flush); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - ALOGD("zlib deflate call failed (zerr=%d)\n", zerr); - result = UNKNOWN_ERROR; - goto z_bail; - } - - /* write when we're full or when we're done */ - if (zstream.avail_out == 0 || - (zerr == Z_STREAM_END && zstream.avail_out != (uInt) kBufSize)) - { - ALOGV("+++ writing %d bytes\n", (int) (zstream.next_out - outBuf)); - if (fwrite(outBuf, 1, zstream.next_out - outBuf, dstFp) != - (size_t)(zstream.next_out - outBuf)) - { - ALOGD("write %d failed in deflate\n", - (int) (zstream.next_out - outBuf)); - goto z_bail; - } - - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - } - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ + ALOGV("+++ writing %d bytes\n", (int)outSize); + if (fwrite(outBuf, 1, outSize, dstFp) != outSize) { + ALOGD("write %d failed in deflate\n", (int)outSize); + goto bail; + } *pCRC32 = crc; -z_bail: - deflateEnd(&zstream); /* free up any allocated structures */ - bail: - delete[] inBuf; - delete[] outBuf; + free(outBuf); return result; } @@ -1148,7 +1225,7 @@ bool ZipFile::uncompress(const ZipEntry* pEntry, void* buf) const #endif // free the memory when you're done -void* ZipFile::uncompress(const ZipEntry* entry) +void* ZipFile::uncompress(const ZipEntry* entry) const { size_t unlen = entry->getUncompressedLen(); size_t clen = entry->getCompressedLen(); diff --git a/tools/zipalign/ZipFile.h b/tools/zipalign/ZipFile.h index 7877550..b99cda5 100644 --- a/tools/zipalign/ZipFile.h +++ b/tools/zipalign/ZipFile.h @@ -127,6 +127,15 @@ public: int padding, ZipEntry** ppEntry); /* + * Add an entry by copying it from another zip file, recompressing with + * Zopfli if already compressed. + * + * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. + */ + status_t addRecompress(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry, + ZipEntry** ppEntry); + + /* * Mark an entry as having been removed. It is not actually deleted * from the archive or our internal data structures until flush() is * called. @@ -147,7 +156,7 @@ public: */ //bool uncompress(const ZipEntry* pEntry, void* buf) const; //bool uncompress(const ZipEntry* pEntry, FILE* fp) const; - void* uncompress(const ZipEntry* pEntry); + void* uncompress(const ZipEntry* pEntry) const; /* * Get an entry, by name. Returns NULL if not found. |