delete no-longer-used custom sdkpage template. depends on https://googleplex-android-review.git.corp.google.com/#/c/1389393/
am: 42859fae46
Change-Id: I0a5a870f5cbc5c0ba2e620a8cf2cb8b497bbec1d
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 3c8d6ce..a97c71a 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -374,6 +374,10 @@
# $(PRODUCT_OUT)/recovery/root/sdcard goes from symlink to folder.
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sdcard)
+# Add BOARD_USES_SYSTEM_OTHER_ODEX
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/*)
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/core/Makefile b/core/Makefile
index d804c37..7fcf6bf 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -499,11 +499,6 @@
INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
-BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
-ifdef BOARD_KERNEL_CMDLINE
- INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
-endif
-
BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
ifdef BOARD_KERNEL_BASE
INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
@@ -514,6 +509,18 @@
INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
endif
+ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true)
+ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+VERITY_KEYID := veritykeyid=id:`openssl x509 -in $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem -text \
+ | grep keyid | sed 's/://g' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/keyid//g'`
+endif
+endif
+
+BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
+ifdef BOARD_KERNEL_CMDLINE
+INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
+endif
+
INTERNAL_MKBOOTIMG_VERSION_ARGS := \
--os_version $(PLATFORM_VERSION) \
--os_patch_level $(PLATFORM_SECURITY_PATCH)
@@ -708,6 +715,10 @@
$(hide) rm -f $@
$(hide) mkdir -p $(dir $@)
$(hide) openssl x509 -pubkey -noout -in $< > $@
+
+ALL_DEFAULT_INSTALLED_MODULES += $(TARGET_RECOVERY_ROOT_OUT)/etc/update_engine/update-payload-key.pub.pem
+$(TARGET_RECOVERY_ROOT_OUT)/etc/update_engine/update-payload-key.pub.pem: $(TARGET_OUT_ETC)/update_engine/update-payload-key.pub.pem
+ $(hide) cp -f $< $@
endif
endif
@@ -785,6 +796,7 @@
$(if $(BOARD_HAS_EXT4_RESERVED_BLOCKS),$(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_squashfs_compressor=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
+$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "system_squashfs_block_size=$(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "system_squashfs_disable_4k_align=$(BOARD_SYSTEMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH),$(hide) echo "system_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH)" >> $(1))
$(if $(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "userdata_fs_type=$(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
@@ -796,6 +808,7 @@
$(if $(BOARD_VENDORIMAGE_JOURNAL_SIZE),$(hide) echo "vendor_journal_size=$(BOARD_VENDORIMAGE_JOURNAL_SIZE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "vendor_squashfs_compressor=$(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
$(if $(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "vendor_squashfs_compressor_opt=$(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
+$(if $(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "vendor_squashfs_block_size=$(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "vendor_squashfs_disable_4k_align=$(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH),$(hide) echo "vendor_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH)" >> $(1))
$(if $(BOARD_OEMIMAGE_PARTITION_SIZE),$(hide) echo "oem_size=$(BOARD_OEMIMAGE_PARTITION_SIZE)" >> $(1))
@@ -876,6 +889,11 @@
else
recovery_fstab := $(strip $(wildcard $(TARGET_DEVICE_DIR)/recovery.fstab))
endif
+ifdef TARGET_RECOVERY_WIPE
+recovery_wipe := $(TARGET_RECOVERY_WIPE)
+else
+recovery_wipe :=
+endif
# Prior to A/B update, we used to have:
# boot.img + recovery-from-boot.p + recovery-resource.dat = recovery.img.
@@ -946,7 +964,7 @@
$(hide) mkdir -p $(TARGET_RECOVERY_OUT)
$(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/etc $(TARGET_RECOVERY_ROOT_OUT)/sdcard $(TARGET_RECOVERY_ROOT_OUT)/tmp
@echo Copying baseline ramdisk...
- $(hide) rsync -a --exclude=etc --exclude=sdcard $(TARGET_ROOT_OUT) $(TARGET_RECOVERY_OUT) # "cp -Rf" fails to overwrite broken symlinks on Mac.
+ $(hide) rsync -a --exclude=etc --exclude=sdcard $(IGNORE_CACHE_LINK) $(TARGET_ROOT_OUT) $(TARGET_RECOVERY_OUT) # "cp -Rf" fails to overwrite broken symlinks on Mac.
@echo Modifying ramdisk contents...
$(hide) rm -f $(TARGET_RECOVERY_ROOT_OUT)/init*.rc
$(hide) cp -f $(recovery_initrc) $(TARGET_RECOVERY_ROOT_OUT)/
@@ -961,9 +979,12 @@
cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/$(newline))
$(hide) $(foreach item,$(recovery_fstab), \
cp -f $(item) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.fstab)
+ $(if $(strip $(recovery_wipe)), \
+ $(hide) cp -f $(recovery_wipe) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.wipe)
$(hide) cp $(RECOVERY_INSTALL_OTA_KEYS) $(TARGET_RECOVERY_ROOT_OUT)/res/keys
$(hide) cat $(INSTALLED_DEFAULT_PROP_TARGET) $(recovery_build_prop) \
> $(TARGET_RECOVERY_ROOT_OUT)/default.prop
+ $(BOARD_RECOVERY_IMAGE_PREPARE)
$(if $(filter true,$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)), \
$(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system_root; \
rm -rf $(TARGET_RECOVERY_ROOT_OUT)/system; \
@@ -973,10 +994,14 @@
$(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1).unsigned, \
$(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1) --id > $(RECOVERYIMAGE_ID_FILE))
$(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER)),\
- $(BOOT_SIGNER) /recovery $(1) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1))
+ $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\
+ $(BOOT_SIGNER) /boot $(1) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1),\
+ $(BOOT_SIGNER) /recovery $(1) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1)\
+ )\
+ )
$(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)), \
$(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
- $(if $(filter true,BOARD_USES_RECOVERY_AS_BOOT), \
+ $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
$(hide) $(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE)), \
$(hide) $(call assert-max-image-size,$(1),$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)))
@echo ----- Made recovery image: $(1) --------
@@ -1393,10 +1418,66 @@
cacheimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
$(build-cacheimage-target)
+else # BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+# we need to ignore the broken cache link when doing the rsync
+IGNORE_CACHE_LINK := --exclude=cache
endif # BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
# -----------------------------------------------------------------
+# system_other partition image
+ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
+BOARD_USES_SYSTEM_OTHER := true
+
+# Marker file to identify that odex files are installed
+INSTALLED_SYSTEM_OTHER_ODEX_MARKER := $(TARGET_OUT_SYSTEM_OTHER)/system-other-odex-marker
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_OTHER_ODEX_MARKER)
+$(INSTALLED_SYSTEM_OTHER_ODEX_MARKER):
+ $(hide) touch $@
+endif
+
+ifdef BOARD_USES_SYSTEM_OTHER
+INTERNAL_SYSTEMOTHERIMAGE_FILES := \
+ $(filter $(TARGET_OUT_SYSTEM_OTHER)/%,\
+ $(ALL_DEFAULT_INSTALLED_MODULES)\
+ $(ALL_PDK_FUSION_FILES))
+
+INSTALLED_FILES_FILE_SYSTEMOTHER := $(PRODUCT_OUT)/installed-files-system-other.txt
+$(INSTALLED_FILES_FILE_SYSTEMOTHER) : $(INTERNAL_SYSTEMOTHERIMAGE_FILES)
+ @echo Installed file list: $@
+ @mkdir -p $(dir $@)
+ @rm -f $@
+ $(hide) build/tools/fileslist.py $(TARGET_OUT_SYSTEM_OTHER) > $@
+
+systemotherimage_intermediates := \
+ $(call intermediates-dir-for,PACKAGING,system_other)
+BUILT_SYSTEMOTHERIMAGE_TARGET := $(PRODUCT_OUT)/system_other.img
+
+# Note that we assert the size is SYSTEMIMAGE_PARTITION_SIZE since this is the 'b' system image.
+define build-systemotherimage-target
+ $(call pretty,"Target system_other fs image: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET)")
+ @mkdir -p $(TARGET_OUT_SYSTEM_OTHER)
+ @mkdir -p $(systemotherimage_intermediates) && rm -rf $(systemotherimage_intermediates)/system_other_image_info.txt
+ $(call generate-userimage-prop-dictionary, $(systemotherimage_intermediates)/system_other_image_info.txt, skip_fsck=true)
+ $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
+ ./build/tools/releasetools/build_image.py \
+ $(TARGET_OUT_SYSTEM_OTHER) $(systemotherimage_intermediates)/system_other_image_info.txt $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) $(TARGET_OUT)
+ $(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
+endef
+
+# We just build this directly to the install location.
+INSTALLED_SYSTEMOTHERIMAGE_TARGET := $(BUILT_SYSTEMOTHERIMAGE_TARGET)
+$(INSTALLED_SYSTEMOTHERIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEMOTHER)
+ $(build-systemotherimage-target)
+
+.PHONY: systemotherimage-nodeps
+systemotherimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
+ $(build-systemotherimage-target)
+
+endif # BOARD_USES_SYSTEM_OTHER
+
+
+# -----------------------------------------------------------------
# vendor partition image
ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
INTERNAL_VENDORIMAGE_FILES := \
@@ -1627,6 +1708,7 @@
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INSTALLED_CACHEIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
$(INSTALLED_ANDROID_INFO_TXT_TARGET) \
$(SELINUX_FC) \
$(APKCERTS_FILE) \
@@ -1700,6 +1782,11 @@
$(hide) $(call package_files-copy-root, \
$(TARGET_OUT_VENDOR),$(zip_root)/VENDOR)
endif
+ifdef INSTALLED_SYSTEMOTHERIMAGE_TARGET
+ @# Contents of the system_other image
+ $(hide) $(call package_files-copy-root, \
+ $(TARGET_OUT_SYSTEM_OTHER),$(zip_root)/SYSTEM_OTHER)
+endif
@# Extra contents of the OTA package
$(hide) mkdir -p $(zip_root)/OTA
$(hide) $(ACP) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/
@@ -1814,6 +1901,9 @@
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/recovery_filesystem_config.txt
endif
+ifdef INSTALLED_SYSTEMOTHERIMAGE_TARGET
+ $(hide) zipinfo -1 $@ | awk 'BEGIN { FS="SYSTEM_OTHER/" } /^SYSTEM_OTHER\// { print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/system_other_filesystem_config.txt
+endif
$(hide) (cd $(zip_root) && zip -qX ../$(notdir $@) META/*filesystem_config.txt)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
./build/tools/releasetools/add_img_to_target_files -v -p $(HOST_OUT) $@
diff --git a/core/binary.mk b/core/binary.mk
index 918a28d..7b22903 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -629,57 +629,55 @@
## Compile the .proto files to .cc (or .c) and then to .o
###########################################################
proto_sources := $(filter %.proto,$(my_src_files))
-proto_generated_objects :=
-proto_generated_headers :=
ifneq ($(proto_sources),)
-proto_generated_sources_dir := $(generated_sources_dir)/proto
-proto_generated_obj_dir := $(intermediates)/proto
+proto_gen_dir := $(generated_sources_dir)/proto
+my_rename_cpp_ext :=
ifneq (,$(filter nanopb-c nanopb-c-enable_malloc, $(LOCAL_PROTOC_OPTIMIZE_TYPE)))
my_proto_source_suffix := .c
my_proto_c_includes := external/nanopb-c
-my_protoc_flags := --nanopb_out=$(proto_generated_sources_dir) \
+my_protoc_flags := --nanopb_out=$(proto_gen_dir) \
--plugin=external/nanopb-c/generator/protoc-gen-nanopb
else
-my_proto_source_suffix := .cc
+my_proto_source_suffix := $(LOCAL_CPP_EXTENSION)
+ifneq ($(my_proto_source_suffix),.cc)
+# aprotoc is hardcoded to write out only .cc file.
+# We need to rename the extension to $(LOCAL_CPP_EXTENSION) if it's not .cc.
+my_rename_cpp_ext := true
+endif
my_proto_c_includes := external/protobuf/src
my_cflags += -DGOOGLE_PROTOBUF_NO_RTTI
-my_protoc_flags := --cpp_out=$(proto_generated_sources_dir)
+my_protoc_flags := --cpp_out=$(proto_gen_dir)
endif
-my_proto_c_includes += $(proto_generated_sources_dir)
+my_proto_c_includes += $(proto_gen_dir)
proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
-proto_generated_sources := $(addprefix $(proto_generated_sources_dir)/, \
+proto_generated_cpps := $(addprefix $(proto_gen_dir)/, \
$(patsubst %.proto,%.pb$(my_proto_source_suffix),$(proto_sources_fullpath)))
-proto_generated_headers := $(patsubst %.pb$(my_proto_source_suffix),%.pb.h, $(proto_generated_sources))
-proto_generated_objects := $(addprefix $(proto_generated_obj_dir)/, \
- $(patsubst %.proto,%.pb.o,$(proto_sources_fullpath)))
-$(call track-src-file-obj,$(proto_sources),$(proto_generated_objects))
# 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_sources): PRIVATE_PROTO_INCLUDES := $(TOP)
-$(proto_generated_sources): PRIVATE_PROTOC_FLAGS := $(LOCAL_PROTOC_FLAGS) $(my_protoc_flags)
-$(proto_generated_sources): $(proto_generated_sources_dir)/%.pb$(my_proto_source_suffix): %.proto $(PROTOC)
+ifndef $(my_host)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined
+$(proto_generated_cpps): PRIVATE_PROTO_INCLUDES := $(TOP)
+$(proto_generated_cpps): PRIVATE_PROTOC_FLAGS := $(LOCAL_PROTOC_FLAGS) $(my_protoc_flags)
+$(proto_generated_cpps): PRIVATE_RENAME_CPP_EXT := $(my_rename_cpp_ext)
+$(proto_generated_cpps): $(proto_gen_dir)/%.pb$(my_proto_source_suffix): %.proto $(my_protoc_deps) $(PROTOC)
$(transform-proto-to-cc)
-# This is just a dummy rule to make sure gmake doesn't skip updating the dependents.
-$(proto_generated_headers): $(proto_generated_sources_dir)/%.pb.h: $(proto_generated_sources_dir)/%.pb$(my_proto_source_suffix)
- @echo "Updated header file $@."
- $(hide) touch $@
-
-$(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined := true
-endif # transform-proto-to-cc rule included only once
-
-$(proto_generated_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
-$(proto_generated_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-$(proto_generated_objects): $(proto_generated_obj_dir)/%.o: $(proto_generated_sources_dir)/%$(my_proto_source_suffix) $(proto_generated_headers)
-ifeq ($(my_proto_source_suffix),.c)
- $(transform-$(PRIVATE_HOST)c-to-o)
-else
- $(transform-$(PRIVATE_HOST)cpp-to-o)
+$(my_host)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined := true
endif
-$(call include-depfiles-for-objs, $(proto_generated_objects))
+# Ideally we can generate the source directly into $(intermediates).
+# But many Android.mks assume the .pb.hs are in $(generated_sources_dir).
+# As a workaround, we make a copy in the $(intermediates).
+proto_intermediate_dir := $(intermediates)/proto
+proto_intermediate_cpps := $(patsubst $(proto_gen_dir)/%,$(proto_intermediate_dir)/%,\
+ $(proto_generated_cpps))
+$(proto_intermediate_cpps) : $(proto_intermediate_dir)/% : $(proto_gen_dir)/% | $(ACP)
+ @echo "Copy: $@"
+ $(copy-file-to-target)
+ $(hide) cp $(basename $<).h $(basename $@).h
+$(call track-src-file-gen,$(proto_sources),$(proto_intermediate_cpps))
+
+my_generated_sources += $(proto_intermediate_cpps)
my_c_includes += $(my_proto_c_includes)
# Auto-export the generated proto source dir.
@@ -897,7 +895,7 @@
dotdot_arm_objects :=
$(foreach s,$(dotdot_arm_sources),\
$(eval $(call compile-dotdot-cpp-file,$(s),\
- $(yacc_cpps) $(proto_generated_headers) $(my_additional_dependencies),\
+ $(my_additional_dependencies),\
dotdot_arm_objects)))
$(call track-src-file-obj,$(patsubst %,%.arm,$(dotdot_arm_sources)),$(dotdot_arm_objects))
@@ -905,7 +903,7 @@
dotdot_objects :=
$(foreach s,$(dotdot_sources),\
$(eval $(call compile-dotdot-cpp-file,$(s),\
- $(yacc_cpps) $(proto_generated_headers) $(my_additional_dependencies),\
+ $(my_additional_dependencies),\
dotdot_objects)))
$(call track-src-file-obj,$(dotdot_sources),$(dotdot_objects))
@@ -923,7 +921,6 @@
ifneq ($(strip $(cpp_objects)),)
$(cpp_objects): $(intermediates)/%.o: \
$(TOPDIR)$(LOCAL_PATH)/%$(LOCAL_CPP_EXTENSION) \
- $(yacc_cpps) $(proto_generated_headers) \
$(my_additional_dependencies)
$(transform-$(PRIVATE_HOST)cpp-to-o)
$(call include-depfiles-for-objs, $(cpp_objects))
@@ -945,8 +942,7 @@
$(gen_cpp_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
$(gen_cpp_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
$(gen_cpp_objects): $(intermediates)/%.o: \
- $(intermediates)/%$(LOCAL_CPP_EXTENSION) $(yacc_cpps) \
- $(proto_generated_headers) \
+ $(intermediates)/%$(LOCAL_CPP_EXTENSION) \
$(my_additional_dependencies)
$(transform-$(PRIVATE_HOST)cpp-to-o)
$(call include-depfiles-for-objs, $(gen_cpp_objects))
@@ -1001,7 +997,7 @@
dotdot_arm_objects :=
$(foreach s,$(dotdot_arm_sources),\
$(eval $(call compile-dotdot-c-file,$(s),\
- $(yacc_cpps) $(proto_generated_headers) $(my_additional_dependencies),\
+ $(my_additional_dependencies),\
dotdot_arm_objects)))
$(call track-src-file-obj,$(patsubst %,%.arm,$(dotdot_arm_sources)),$(dotdot_arm_objects))
@@ -1009,7 +1005,7 @@
dotdot_objects :=
$(foreach s, $(dotdot_sources),\
$(eval $(call compile-dotdot-c-file,$(s),\
- $(yacc_cpps) $(proto_generated_headers) $(my_additional_dependencies),\
+ $(my_additional_dependencies),\
dotdot_objects)))
$(call track-src-file-obj,$(dotdot_sources),$(dotdot_objects))
@@ -1025,7 +1021,7 @@
c_objects := $(c_arm_objects) $(c_normal_objects)
ifneq ($(strip $(c_objects)),)
-$(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c $(yacc_cpps) $(proto_generated_headers) \
+$(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c \
$(my_additional_dependencies)
$(transform-$(PRIVATE_HOST)c-to-o)
$(call include-depfiles-for-objs, $(c_objects))
@@ -1046,7 +1042,7 @@
# TODO: support compiling certain generated files as arm.
$(gen_c_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
$(gen_c_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-$(gen_c_objects): $(intermediates)/%.o: $(intermediates)/%.c $(yacc_cpps) $(proto_generated_headers) \
+$(gen_c_objects): $(intermediates)/%.o: $(intermediates)/%.c \
$(my_additional_dependencies)
$(transform-$(PRIVATE_HOST)c-to-o)
$(call include-depfiles-for-objs, $(gen_c_objects))
@@ -1061,7 +1057,7 @@
$(call track-src-file-obj,$(objc_sources),$(objc_objects))
ifneq ($(strip $(objc_objects)),)
-$(objc_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.m $(yacc_cpps) $(proto_generated_headers) \
+$(objc_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.m \
$(my_additional_dependencies)
$(transform-$(PRIVATE_HOST)m-to-o)
$(call include-depfiles-for-objs, $(objc_objects))
@@ -1076,7 +1072,7 @@
$(call track-src-file-obj,$(objcpp_sources),$(objcpp_objects))
ifneq ($(strip $(objcpp_objects)),)
-$(objcpp_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.mm $(yacc_cpps) $(proto_generated_headers) \
+$(objcpp_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.mm \
$(my_additional_dependencies)
$(transform-$(PRIVATE_HOST)mm-to-o)
$(call include-depfiles-for-objs, $(objcpp_objects))
@@ -1206,8 +1202,7 @@
$(c_objects) \
$(gen_c_objects) \
$(objc_objects) \
- $(objcpp_objects) \
- $(proto_generated_objects)
+ $(objcpp_objects)
new_order_normal_objects := $(foreach f,$(my_src_files),$(my_src_file_obj_$(f)))
new_order_normal_objects += $(foreach f,$(my_gen_src_files),$(my_src_file_obj_$(f)))
@@ -1420,11 +1415,9 @@
###########################################################
export_includes := $(intermediates)/export_includes
$(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(my_export_c_include_dirs)
-# Make sure .pb.h are already generated before any dependent source files get compiled.
-# Similarly, the generated DBus headers need to exist before we export their location.
-# People are not going to consume the aidl generated cpp file, but the cpp file is
-# generated after the headers, so this is a convenient way to ensure the headers exist.
-$(export_includes) : $(LOCAL_MODULE_MAKEFILE_DEP) $(proto_generated_headers) $(dbus_generated_headers) $(aidl_gen_cpp) $(vts_gen_cpp)
+# By adding $(my_generated_sources) it makes sure the headers get generated
+# before any dependent source files get compiled.
+$(export_includes) : $(my_generated_sources) $(export_include_deps)
@echo Export includes file: $< -- $@
$(hide) mkdir -p $(dir $@) && rm -f $@.tmp
ifdef my_export_c_include_dirs
diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk
index 0d6a406..e46d934 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -242,6 +242,7 @@
$(PRODUCT_OUT)/recovery \
$(PRODUCT_OUT)/root \
$(PRODUCT_OUT)/system \
+ $(PRODUCT_OUT)/system_other \
$(PRODUCT_OUT)/vendor \
$(PRODUCT_OUT)/oem \
$(PRODUCT_OUT)/dex_bootjars \
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 59e907b..5886610 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -204,6 +204,8 @@
# Used to replace the installed file of a presigned prebuilt apk in PDK fusion build,
# to avoid installing the presigned apks with classes.dex unstripped.
LOCAL_REPLACE_PREBUILT_APK_INSTALLED:=
+LOCAL_EXTRACT_APK:=
+LOCAL_EXTRACT_DPI_APK:=
# arch specific variables
LOCAL_SRC_FILES_$(TARGET_ARCH):=
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 6e96880..dbcf276 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -24,6 +24,31 @@
my_sanitize := $(my_global_sanitize)
endif
+# The sanitizer specified in the product configuration wins over the previous.
+ifneq ($(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG),)
+ my_sanitize := $(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG)
+ ifeq ($(my_sanitize),never)
+ my_sanitize :=
+ endif
+endif
+
+# Add a filter point for 32-bit vs 64-bit sanitization (to lighten the burden).
+SANITIZE_ARCH ?= 32 64
+ifeq ($(filter $(SANITIZE_ARCH),$(my_32_64_bit_suffix)),)
+ my_sanitize :=
+endif
+
+# Add a filter point based on module owner (to lighten the burden). The format is a space- or
+# colon-separated list of owner names.
+ifneq (,$(SANITIZE_NEVER_BY_OWNER))
+ ifneq (,$(LOCAL_MODULE_OWNER))
+ ifneq (,$(filter $(LOCAL_MODULE_OWNER),$(subst :, ,$(SANITIZE_NEVER_BY_OWNER))))
+ $(warning Not sanitizing $(LOCAL_MODULE) based on module owner.)
+ my_sanitize :=
+ endif
+ endif
+endif
+
# Don't apply sanitizers to NDK code.
ifdef LOCAL_SDK_VERSION
my_sanitize :=
diff --git a/core/definitions.mk b/core/definitions.mk
index b9ef4d5..84ea801 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -1169,6 +1169,9 @@
$(addprefix --proto_path=, $(PRIVATE_PROTO_INCLUDES)) \
$(PRIVATE_PROTOC_FLAGS) \
$<
+@# aprotoc outputs only .cc. Rename it to .cpp if necessary.
+$(if $(PRIVATE_RENAME_CPP_EXT),\
+ $(hide) mv $(basename $@).cc $@)
endef
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index d182dc0..5df9dc3 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -19,6 +19,10 @@
# The default value for LOCAL_DEX_PREOPT
DEX_PREOPT_DEFAULT ?= true
+# The default filter for which files go into the system_other image (if it is
+# being used). To bundle everything one should set this to '%'
+SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%
+
# The default values for pre-opting: always preopt PIC.
# Conditional to building on linux, as dex2oat currently does not work on darwin.
ifeq ($(HOST_OS),linux)
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 9410c3c..acd4a02 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -59,6 +59,21 @@
$(dir $(2))oat/$(1)/$(basename $(notdir $(2))).odex
endef
+# Returns the full path to the installed .odex file.
+# This handles BOARD_USES_SYSTEM_OTHER_ODEX to install odex files into another
+# partition.
+# $(1): the arch name.
+# $(2): the full install path (including file name) of the corresponding .apk.
+ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
+define get-odex-installed-file-path
+$(if $(filter $(foreach f,$(SYSTEM_OTHER_ODEX_FILTER),$(TARGET_OUT)/$(f)),$(2)),
+ $(call get-odex-file-path,$(1),$(patsubst $(TARGET_OUT)/%,$(TARGET_OUT_SYSTEM_OTHER)/%,$(2))),
+ $(call get-odex-file-path,$(1),$(2)))
+endef
+else
+get-odex-installed-file-path = $(get-odex-file-path)
+endif
+
# Returns the path to the image file (such as "/system/framework/<arch>/boot.art"
# $(1): the arch name (such as "arm")
# $(2): the image location (such as "/system/framework/boot.art")
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 4e486d5..b05d4da 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -39,6 +39,14 @@
LOCAL_DEX_PREOPT :=
endif
endif
+# if installing into system, and odex are being installed into system_other, don't strip
+ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
+ifeq ($(LOCAL_DEX_PREOPT),true)
+ifneq ($(filter $(foreach f,$(SYSTEM_OTHER_ODEX_FILTER),$(TARGET_OUT)/$(f)),$(my_module_path)),)
+LOCAL_DEX_PREOPT := nostripping
+endif
+endif
+endif
built_odex :=
installed_odex :=
@@ -100,14 +108,6 @@
endif
$(built_odex): PRIVATE_DEX_PREOPT_FLAGS := $(LOCAL_DEX_PREOPT_FLAGS)
-
-# Use pattern rule - we may have multiple installed odex files.
-# Ugly syntax - See the definition get-odex-file-path.
-$(installed_odex) : $(dir $(LOCAL_INSTALLED_MODULE))%$(notdir $(word 1,$(installed_odex))) \
- : $(dir $(LOCAL_BUILT_MODULE))%$(notdir $(word 1,$(built_odex))) \
- | $(ACP)
- @echo "Install: $@"
- $(copy-file-to-target)
endif
# Add the installed_odex to the list of installed files for this module.
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 0a72603..26fed24 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -109,6 +109,7 @@
# TARGET_COPY_OUT_* are all relative to the staging directory, ie PRODUCT_OUT.
# Define them here so they can be used in product config files.
TARGET_COPY_OUT_SYSTEM := system
+TARGET_COPY_OUT_SYSTEM_OTHER := system_other
TARGET_COPY_OUT_DATA := data
TARGET_COPY_OUT_OEM := oem
TARGET_COPY_OUT_ODM := odm
@@ -322,6 +323,8 @@
TARGET_OUT_NOTICE_FILES := $(TARGET_OUT_INTERMEDIATES)/NOTICE_FILES
TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages
+TARGET_OUT_SYSTEM_OTHER := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM_OTHER)
+
# Out for TARGET_2ND_ARCH
TARGET_2ND_ARCH_VAR_PREFIX := $(HOST_2ND_ARCH_VAR_PREFIX)
TARGET_2ND_ARCH_MODULE_SUFFIX := $(HOST_2ND_ARCH_MODULE_SUFFIX)
@@ -377,7 +380,7 @@
TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc
$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR_EXECUTABLES)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(TARGET_OUT_VENDOR)/lib
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib
$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR_APPS)
TARGET_OUT_OEM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_OEM)
diff --git a/core/main.mk b/core/main.mk
index 651ba98..a612f83 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -81,6 +81,7 @@
userdataimage-nodeps userdatatarball-nodeps \
cacheimage-nodeps \
vendorimage-nodeps \
+ systemotherimage-nodeps \
ramdisk-nodeps \
bootimage-nodeps \
recoveryimage-nodeps \
@@ -928,6 +929,9 @@
.PHONY: vendorimage
vendorimage: $(INSTALLED_VENDORIMAGE_TARGET)
+.PHONY: systemotherimage
+systemotherimage: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET)
+
.PHONY: bootimage
bootimage: $(INSTALLED_BOOTIMAGE_TARGET)
@@ -955,8 +959,10 @@
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INSTALLED_CACHEIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
$(INSTALLED_FILES_FILE) \
- $(INSTALLED_FILES_FILE_VENDOR)
+ $(INSTALLED_FILES_FILE_VENDOR) \
+ $(INSTALLED_FILES_FILE_SYSTEMOTHER)
# dist_files only for putting your library into the dist directory with a full build.
.PHONY: dist_files
@@ -1017,6 +1023,7 @@
$(SYMBOLS_ZIP) \
$(INSTALLED_FILES_FILE) \
$(INSTALLED_FILES_FILE_VENDOR) \
+ $(INSTALLED_FILES_FILE_SYSTEMOTHER) \
$(INSTALLED_BUILD_PROP_TARGET) \
$(BUILT_TARGET_FILES_PACKAGE) \
$(INSTALLED_ANDROID_INFO_TXT_TARGET) \
diff --git a/core/pathmap.mk b/core/pathmap.mk
index 9b5a7db..edc584b 100644
--- a/core/pathmap.mk
+++ b/core/pathmap.mk
@@ -106,7 +106,11 @@
#
FRAMEWORKS_SUPPORT_SUBDIRS := \
annotations \
- v4 \
+ compat \
+ media-compat \
+ fragment \
+ core-ui \
+ core-utils \
v7/gridlayout \
v7/cardview \
v7/mediarouter \
@@ -147,6 +151,7 @@
#
FRAMEWORKS_SUPPORT_JAVA_LIBRARIES := \
$(foreach dir,$(FRAMEWORKS_SUPPORT_SUBDIRS),android-support-$(subst /,-,$(dir))) \
+ android-support-v4 \
android-support-vectordrawable \
android-support-animatedvectordrawable \
android-support-v7-appcompat \
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index ee68427..b6727fa 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -85,8 +85,10 @@
ifeq ($(LOCAL_MODULE_CLASS),APPS)
LOCAL_BUILT_MODULE_STEM := package.apk
+ifndef LOCAL_INSTALLED_MODULE_STEM
LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk
endif
+endif
ifneq ($(filter true no_debuglink,$(my_strip_module) $(my_pack_module_relocations)),)
ifdef LOCAL_IS_HOST_MODULE
@@ -152,6 +154,8 @@
ifeq ($(LOCAL_MODULE_CLASS),APPS)
PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
+my_extract_apk := $(strip $(LOCAL_EXTRACT_APK))
+
# Select dpi-specific source
ifdef LOCAL_DPI_VARIANTS
my_dpi := $(firstword $(filter $(LOCAL_DPI_VARIANTS),$(PRODUCT_AAPT_PREF_CONFIG) $(PRODUCT_AAPT_PREBUILT_DPI)))
@@ -162,9 +166,27 @@
my_prebuilt_dpi_file_stem := $(LOCAL_MODULE)_%.apk
endif
my_prebuilt_src_file := $(dir $(my_prebuilt_src_file))$(subst %,$(my_dpi),$(my_prebuilt_dpi_file_stem))
+
+ifneq ($(strip $(LOCAL_EXTRACT_DPI_APK)),)
+my_extract_apk := $(subst %,$(my_dpi),$(LOCAL_EXTRACT_DPI_APK))
+endif # LOCAL_EXTRACT_DPI_APK
endif # my_dpi
endif # LOCAL_DPI_VARIANTS
+ifdef my_extract_apk
+my_extracted_apk := $(intermediates)/extracted.apk
+
+$(my_extracted_apk): PRIVATE_EXTRACT := $(my_extract_apk)
+$(my_extracted_apk): $(my_prebuilt_src_file)
+ @echo Extract APK: $@
+ $(hide) mkdir -p $(dir $@) && rm -f $@
+ $(hide) unzip -p $< $(PRIVATE_EXTRACT) >$@
+
+my_prebuilt_src_file := $(my_extracted_apk)
+my_extracted_apk :=
+my_extract_apk :=
+endif
+
rs_compatibility_jni_libs :=
include $(BUILD_SYSTEM)/install_jni_libs.mk
diff --git a/core/product.mk b/core/product.mk
index 94cc2e3..332b015 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -120,6 +120,7 @@
PRODUCT_DEX_PREOPT_MODULE_CONFIGS \
PRODUCT_DEX_PREOPT_DEFAULT_FLAGS \
PRODUCT_DEX_PREOPT_BOOT_FLAGS \
+ PRODUCT_SANITIZER_MODULE_CONFIGS \
PRODUCT_SYSTEM_BASE_FS_PATH \
PRODUCT_VENDOR_BASE_FS_PATH \
PRODUCT_SHIPPING_API_LEVEL \
@@ -333,3 +334,14 @@
$(eval PRODUCT_DEX_PREOPT_MODULE_CONFIGS += \
$(foreach m,$(1),$(m)=$(_c)))
endef
+
+# whitespace placeholder when we record module's sanitizer config.
+_PSMC_SP_PLACE_HOLDER := |@SP@|
+# Set up sanitizer config for a module.
+# $(1) list of module names
+# $(2) the modules' sanitizer config
+define add-product-sanitizer-module-config
+$(eval _c := $(subst $(space),$(_PSMC_SP_PLACE_HOLDER),$(strip $(2))))\
+$(eval PRODUCT_SANITIZER_MODULE_CONFIGS += \
+ $(foreach m,$(1),$(m)=$(_c)))
+endef
diff --git a/core/product_config.mk b/core/product_config.mk
index ed38bc8..6438d51 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -74,7 +74,7 @@
###########################################################
define find-copy-subdir-files
-$(shell find $(2) -name "$(1)" | $(SED_EXTENDED) "s:($(2)/?(.*)):\\1\\:$(3)/\\2:" | sed "s://:/:g")
+$(sort $(shell find $(2) -name "$(1)" -type f | $(SED_EXTENDED) "s:($(2)/?(.*)):\\1\\:$(3)/\\2:" | sed "s://:/:g"))
endef
# ---------------------------------------------------------------
@@ -392,7 +392,7 @@
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
-# Resolve and setup per-module dex-preopot configs.
+# Resolve and setup per-module dex-preopt configs.
PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_MODULE_CONFIGS))
# If a module has multiple setups, the first takes precedence.
@@ -405,3 +405,17 @@
$(eval cf := $(subst $(_PDPMC_SP_PLACE_HOLDER),$(space),$(cf)))\
$(eval DEXPREOPT.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
_pdpmc_modules :=
+
+# Resolve and setup per-module sanitizer configs.
+PRODUCT_SANITIZER_MODULE_CONFIGS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SANITIZER_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_psmc_modules :=
+$(foreach c,$(PRODUCT_SANITIZER_MODULE_CONFIGS),\
+ $(eval m := $(firstword $(subst =,$(space),$(c))))\
+ $(if $(filter $(_psmc_modules),$(m)),,\
+ $(eval _psmc_modules += $(m))\
+ $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+ $(eval cf := $(subst $(_PSMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+ $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_psmc_modules :=
diff --git a/core/setup_one_odex.mk b/core/setup_one_odex.mk
index ec8a28a..36b6817 100644
--- a/core/setup_one_odex.mk
+++ b/core/setup_one_odex.mk
@@ -32,7 +32,9 @@
$(DEXPREOPT_ONE_FILE_DEPENDENCY_TOOLS) \
$(my_dex_preopt_image_filename)
-my_installed_odex := $(call get-odex-file-path,$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH),$(LOCAL_INSTALLED_MODULE))
+my_installed_odex := $(call get-odex-installed-file-path,$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH),$(LOCAL_INSTALLED_MODULE))
+
+$(eval $(call copy-one-file,$(my_built_odex),$(my_installed_odex)))
built_odex += $(my_built_odex)
installed_odex += $(my_installed_odex)
diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk
index 910c8b7..e3761ae 100644
--- a/core/tasks/vendor_module_check.mk
+++ b/core/tasks/vendor_module_check.mk
@@ -43,6 +43,7 @@
synaptics \
ti \
trusted_logic \
+ verizon \
widevine
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 181a1c8..31fb679 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -25,7 +25,7 @@
# BUILD_ID
# BUILD_NUMBER
# BUILD_DATETIME
-# SECURITY_PATCH
+# PLATFORM_SECURITY_PATCH
#
# Look for an optional file containing overrides of the defaults,
@@ -43,7 +43,7 @@
# 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 := 7.0
+ PLATFORM_VERSION := 7.1
endif
ifeq "" "$(PLATFORM_SDK_VERSION)"
@@ -55,7 +55,7 @@
# 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 := 24
+ PLATFORM_SDK_VERSION := 25
endif
ifeq "" "$(PLATFORM_JACK_MIN_SDK_VERSION)"
@@ -64,7 +64,7 @@
# PLATFORM_SDK_VERSION. During development, this number may be incremented
# before PLATFORM_SDK_VERSION if the plateform starts to add new java
# language supports.
- PLATFORM_JACK_MIN_SDK_VERSION := 24
+ PLATFORM_JACK_MIN_SDK_VERSION := 25
endif
ifeq "" "$(PLATFORM_VERSION_CODENAME)"
diff --git a/target/product/core.mk b/target/product/core.mk
index 75cf649..0a4e0fd 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -53,6 +53,7 @@
QuickSearchBox \
Settings \
SharedStorageBackup \
+ StorageManager \
Telecom \
TeleService \
VpnDialogs \
diff --git a/tools/droiddoc/templates-sdk-dev/assets/css/default.css b/tools/droiddoc/templates-sdk-dev/assets/css/default.css
index 43449d4..e422d75 100644
--- a/tools/droiddoc/templates-sdk-dev/assets/css/default.css
+++ b/tools/droiddoc/templates-sdk-dev/assets/css/default.css
@@ -86,6 +86,11 @@
#page-footer #copyright {
margin-bottom: 10px; }
+.hide-text {
+ position: absolute;
+ text-indent: -9999px;
+}
+
#nav-container {
width: 160px;
min-height: 10px;
@@ -150,10 +155,44 @@
max-width: 100%;
vertical-align: middle;
}
+
video {
+ cursor: pointer;
+ margin-bottom: 10px; /* same as img */
max-width: 100%;
object-fit: cover;
}
+
+.video-wrapper {
+ line-height: 0;
+ margin-bottom: 10px; /* same as img */
+ position: relative;
+}
+
+.video-wrapper video {
+ margin:0;
+}
+
+.video-wrapper:before {
+ background: rgba(0, 0, 0, 0.5) url(//material-design.storage.googleapis.com/images/play.svg) no-repeat center center;
+ background-size: 72px 72px;
+ bottom: 0;
+ content: "";
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ transition: opacity .2s;
+}
+
+.video-wrapper:hover:before {
+ opacity: .7;
+}
+
+.video-wrapper.playing:before {
+ opacity: 0;
+}
+
q {
quotes: none;
}
@@ -283,7 +322,8 @@
li pre,
li ul,
li ol,
-li dl {
+li dl,
+#body-content li img {
margin-top: 6px;
margin-bottom: 6px;
}
@@ -346,6 +386,10 @@
border:solid 1px #DDD;
font-weight: normal;
}
+tr.alt th {
+ color:inherit;
+ background-color: #e0e0e0;
+}
tr:first-of-type th:first-of-type:empty {
visibility: hidden;
}
@@ -355,8 +399,18 @@
padding-right:16px;
}
-#jd-content img {
- margin-bottom:15px;
+#body-content img {
+ margin-bottom:12px;
+}
+
+#body-content p>img {
+ margin-bottom:0;
+}
+
+#body-content img.inline-icon {
+ vertical-align:sub;
+ margin:0;
+ height:16px;
}
em {
@@ -1007,6 +1061,35 @@
overflow:hidden;
}
+#api-info-block {
+ color: #999;
+ float: right;
+ font-size: 12px;
+ font-weight: normal;
+ line-height: 14px;
+ margin: 20px 0 0;
+ max-width: 80%;
+ padding: 0 10px 6px;
+ text-align: right;
+}
+
+#api-info-block a,
+#api-info-block a:active,
+#api-info-block a:visited {
+ color: #222;
+}
+
+#jd-header {
+ font-size: 12px;
+ margin: 20px 0 12px;
+ padding: 0 0 12px;
+}
+
+#jd-header h1 {
+ margin: 0;
+ padding: 0 0 6px;
+}
+
#jd-content
.framed-wear-square img {
height:222px;
@@ -1218,6 +1301,12 @@
.locales form {
margin: 0;
}
+
+.locales select,
+.locales option {
+ text-transform: capitalize;
+}
+
.locales select, .sites select {
line-height: 3.08;
margin: 0px 0;
@@ -1439,6 +1528,7 @@
#tb ol,
#tb ul,
+#tb p,
#qv ul {
list-style-type: none;
margin:0 15px 10px 15px;
@@ -1451,10 +1541,6 @@
position: relative;
}
-#tb p {
- margin:0 15px 10px;
-}
-
#qv ol {
list-style:none;
margin:0 15px 15px;
@@ -1472,8 +1558,7 @@
}
.sidebox p,
-#qv p,
-#tb p {
+#qv p {
margin: 0 0 10px;
}
@@ -1837,26 +1922,34 @@
#doc-content-container {
margin-left: 291px
}
+
#doc-header, #doc-content {
- padding: 1em 2em;
+ padding: 0;
}
+
#doc-header {
background: #f7f7f7;
}
+
#doc-header h1 {
line-height: 0;
padding-bottom: 15px;
}
+
+
#api-info-block {
float: right;
font-weight: bold;
}
+
#api-info-block a, #api-info-block a:active, #api-info-block a:visited {
color: #222;
}
+
#api-info-block a:hover, #api-info-block a:focus {
color: #33B5E5;
}
+
#api-nav-header {
height:19px; /* plus 16px padding = 35; same as #nav li */
font-size:14px;
@@ -1867,6 +1960,7 @@
background: rgba(0, 0, 0, 0.05); /* matches #nav li.expanded */
line-height: 19px; /* Fix regression after page line-height is bumped to 24px */
}
+
#api-nav-title {
padding:0 5px;
white-space:nowrap;
@@ -1890,6 +1984,7 @@
display: inline-block;
overflow: hidden;
}
+
#api-level-toggle select {
border: 0;
appearance:none;
@@ -2075,7 +2170,7 @@
Styles for project structure (treeview) page
*/
.structure-dir {
-background-image:url(../../assets/images/folder.png);
+background-image:url(../images/folder.png);
background-repeat:no-repeat;
background-position:16px 2px;
margin:.25em 0 0 0;
@@ -2089,7 +2184,7 @@
}
.structure-java{
-background-image:url(../../assets/images/file-java.png);
+background-image:url(../images/file-java.png);
background-repeat:no-repeat;
background-position:0px 2px;
margin:.3em 0 0 0;
@@ -2097,7 +2192,7 @@
}
.structure-file {
-background-image:url(../../assets/images/file-generic.png);
+background-image:url(../images/file-generic.png);
background-repeat:no-repeat;
background-position:0px 2px;
margin:.3em 0 0 0;
@@ -2105,7 +2200,7 @@
}
.structure-xml {
-background-image:url(../../assets/images/file-xml.png);
+background-image:url(../images/file-xml.png);
background-repeat:no-repeat;
background-position:0px 2px;
margin:.3em 0 0 0;
@@ -2113,7 +2208,7 @@
}
.structure-img {
-background-image:url(../../assets/images/file-image.png);
+background-image:url(../images/file-image.png);
background-repeat:no-repeat;
background-position:0px 2px;
margin:.3em 0 0 0;
@@ -2121,7 +2216,7 @@
}
.structure-manifest {
-background-image:url(../../assets/images/file-manifest.png);
+background-image:url(../images/file-manifest.png);
background-repeat:no-repeat;
margin:.0 0 0 1.25em;
padding:0 0 0 22px;
@@ -2219,6 +2314,25 @@
list-style:none;
margin-left:0;
}
+
+ol.callouts {
+ counter-reset: item;
+ list-style-type: none;
+ margin-left:44px;
+}
+ol.callouts>li:before {
+ counter-increment: item;
+ content: counter(item);
+ position: absolute;
+ color:#fff;
+ font-weight:bold;
+ background-image:url(../images/styles/callout-bg_2x.png);
+ background-size:24px;
+ width:16px;
+ padding-left:8px;
+ margin-left:-34px;
+}
+
#tb .nolist {
margin-left:15px;
}
@@ -2481,20 +2595,20 @@
a.notice-designers-video div,
a.notice-designers div {
min-height:40px;
- background:url('../images/styles/notice-developers@2x.png') no-repeat 10px 10px;
+ background:url('../images/styles/notice-developers_2x.png') no-repeat 10px 10px;
background-size:40px 40px;
padding:10px 10px 10px 60px;
}
a.notice-designers div {
- background:url('../images/styles/notice-designers@2x.png') no-repeat 10px 10px;
+ background:url('../images/styles/notice-designers_2x.png') no-repeat 10px 10px;
background-size:40px 40px;
}
a.notice-designers-video div {
- background:url('../images/styles/notice-designers-video@2x.png') no-repeat 10px 10px;
+ background:url('../images/styles/notice-designers-video_2x.png') no-repeat 10px 10px;
background-size:40px 40px;
}
a.notice-developers-video div {
- background:url('../images/styles/notice-developers-video@2x.png') no-repeat 10px 10px;
+ background:url('../images/styles/notice-developers-video_2x.png') no-repeat 10px 10px;
background-size:40px 40px;
}
a.notice-developers-video:hover,
@@ -3209,11 +3323,16 @@
}
/* offset the <a name=""> tags to account for sticky nav */
-body.reference a[name] {
+body.reference a[name]:not(.nav-start-marker) {
visibility: hidden;
display: block;
position: relative;
top: -56px;
+
+}
+
+.nav-start-marker {
+ position: absolute;
}
@@ -4805,7 +4924,7 @@
background-color: #fff;
background-position: 50% 53%;
background-size: cover;
- background-image: url(../../assets/images/home/android_m_hero_1200.jpg);
+ background-image: url(../images/home/android_m_hero_1200.jpg);
box-sizing: border-box;
font-size: 16px;
min-height: 550px;
@@ -5117,45 +5236,124 @@
left: 0;
overflow: hidden;
background: #fefefe;
- padding: 6px 12px; }
- .card-info .section {
- color: #898989;
- font-size: 11px;
- font-weight: 700;
- letter-spacing: .3px;
- line-height: 20px;
- text-transform: uppercase; }
- .card-info .title {
- color: #333;
- font-size: 18px;
- font-weight: 500;
- line-height: 23px;
- margin-bottom: 7px;
- max-height: 46px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: normal; }
- .card-info .description {
- overflow: hidden; }
- .card-info .description .text {
- color: #666;
- font-size: 14px;
- height: 60px;
- line-height: 20px;
- overflow: hidden;
- width: 100%; }
- .card-info .description .util {
- position: absolute;
- right: 5px;
- bottom: 70px;
- opacity: 0;
- -webkit-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; }
+ padding: 6px 12px;
+}
+
+.card-info .section {
+ color: #898989;
+ font-size: 11px;
+ font-weight: 700;
+ letter-spacing: .3px;
+ line-height: 20px;
+ text-transform: uppercase;
+}
+
+.card-info .title {
+ color: #333;
+ font-size: 18px;
+ font-weight: 500;
+ line-height: 23px;
+ margin-bottom: 7px;
+ max-height: 46px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: normal;
+}
+
+.card-info .description {
+ overflow: hidden;
+}
+
+.card-info .description .text {
+ color: #666;
+ font-size: 14px;
+ height: 60px;
+ line-height: 20px;
+ overflow: hidden;
+ width: 100%;
+}
+
+.card-info .description .util {
+ position: absolute;
+ right: 5px;
+ bottom: 70px;
+ opacity: 0;
+ -webkit-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;
+}
+
+/* Resource card with icon instead of bg image */
+.resource-widget-card-icon {
+ text-align: center;
+}
+
+.card-icon {
+ margin: 20px 0 0;
+}
+
+.resource-widget-card-icon .card-info {
+ height: 210px;
+}
+
+.resource-widget-card-icon .card-info .title {
+ color: #333;
+ line-height: 24px;
+}
+
+.resource-widget-card-icon .card-bg {
+ background: none;
+ bottom: 220px;
+ opacity: 1;
+ top: 30px;
+ -webkit-transition: opacity .3s;
+ transition: opacity .3s;
+}
+
+.resource-widget-card-icon .resource-card:hover .card-bg {
+ opacity: .5;
+}
+
+.resource-widget-card-icon .card-bg img {
+ max-height: 100%;
+}
+
+.resource-widget-card-icon .card-bg::after {
+ background: transparent;
+}
+
+@media (min-width: 1210px) {
+ .resource-widget-card-icon .resource {
+ height: 240px;
+ }
+ .resource-widget-card-icon .card-bg {
+ bottom: 160px;
+ }
+ .resource-widget-card-icon .card-info {
+ height: 160px;
+ }
+}
+
+@media (max-width: 979px) {
+ .resource-widget-card-icon .resource {
+ height: 240px;
+ }
+ .resource-widget-card-icon .card-bg {
+ bottom: 160px;
+ }
+
+ .resource-widget-card-icon .card-info {
+ height: 160px;
+ }
+}
/* Truncate card summaries at bounding box and
* and apply ellipsis at lower right */
@@ -5544,26 +5742,54 @@
height: 558px; }
/* 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 {
+.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; }
+ 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 {
height: 100%;
left: 90px;
padding: 6px 12px;
- overflow: hidden; }
- .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 {
- max-height: 69px;
- white-space: normal; }
- .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; }
- .resource-card-3x2 > .card-info .text, .resource-card-6x2 > .card-info .text, .resource-card-9x2 > .card-info .text, .resource-card-12x2 > .card-info .text, .resource-card-15x2 > .card-info .text, .resource-card-18x2 > .card-info .text {
- height: auto; }
+ overflow: hidden;
+}
+
+.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 {
+ max-height: 69px;
+ white-space: normal;
+}
+
+.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;
+}
+
+.resource-card-3x2 > .card-info .text,
+.resource-card-6x2 > .card-info .text,
+.resource-card-9x2 > .card-info .text,
+.resource-card-12x2 > .card-info .text,
+.resource-card-15x2 > .card-info .text,
+.resource-card-18x2 > .card-info .text {
+ height: auto;
+}
/* Override to show the description instead of the content section */
.no-section .resource-card-3x2 > .card-info .section,
@@ -5716,6 +5942,12 @@
.dac-button.dac-large, .landing-button {
padding: 12px 24px; }
+.landing-button-wrap {
+ float: left;
+ margin-right: 40px;
+ width: auto;
+}
+
.dac-fab, .dac-button-social {
background: #fff;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
@@ -5825,67 +6057,130 @@
margin-top: 96px;
padding-bottom: 20px;
position: relative;
- /* Modifier for landing pages, to snuggle closer to sections. */ }
- .dac-footer a {
- color: #999; }
- .dac-footer p {
- margin: 7px 0 0; }
- .dac-footer-main {
- padding: 30px 0; }
+}
+
+.dac-footer a {
+ color: #999;
+}
+
+.dac-footer p {
+ margin: 7px 0 0;
+}
+
+.dac-footer-main {
+ padding: 30px 0;
+}
+
+.dac-footer-reachout {
+ text-align: right;
+}
+
+.dac-footer-contact,
+.dac-footer-social {
+ display: inline-block;
+}
+
+.dac-footer .dac-footer-getnews,
+.dac-footer .dac-footer-contact-link {
+ color: #000;
+ cursor: pointer;
+ font-size: 20px;
+ font-weight: 300;
+ margin: 8px 0;
+ vertical-align: middle;
+}
+
+.dac-footer .dac-footer-contact-link,
+.dac-footer .dac-footer-social-link {
+ margin-left: 16px;
+ margin-right: 0;
+}
+
+.dac-footer-getnews > .dac-fab, .dac-footer-getnews > .dac-button-social {
+ margin-left: 4px;
+}
+
+.dac-footer-separator {
+ background: #f0f0f0;
+ margin: 0 0 12px;
+}
+
+.dac-footer-links {
+ float: left;
+ margin: 10px 0 60px;
+ width: 50%;
+}
+
+.dac-footer-links a + a:before {
+ content: '|';
+ cursor: default;
+ margin: 0 10px 0 8px;
+}
+
+.devsite-utility-footer-language {
+ float: right;
+ margin: 10px 0 60px;
+ width: 50%;
+}
+
+.dac-footer .locales {
+ float: right;
+ margin: 0;
+}
+
+.dac-footer .locales select {
+ background-color: #f0f0f0;
+ border-radius: 3px;
+ font-size: 12px;
+ height: auto;
+ margin-top: -2px;
+ padding: 8px 12px;
+ width: 146px;
+}
+
+.dac-footer.dac-landing {
+ margin-top: 0;
+ border-top: 0;
+}
+
+@media (max-width: 719px) {
.dac-footer-reachout {
- text-align: right; }
- .dac-footer-contact, .dac-footer-social {
- display: inline-block; }
- .dac-footer .dac-footer-getnews,
- .dac-footer .dac-footer-contact-link {
- color: #000;
- cursor: pointer;
- font-size: 20px;
- font-weight: 300;
- margin: 8px 0;
- vertical-align: middle; }
+ text-align: left;
+ }
+
+ .dac-footer-social {
+ display: block;
+ }
+
+ .dac-footer-social-link,
+ .dac-footer-contact-link {
+ display: inline-block;
+ }
+
.dac-footer .dac-footer-contact-link,
.dac-footer .dac-footer-social-link {
- margin-left: 16px;
- margin-right: 0; }
- .dac-footer-getnews > .dac-fab, .dac-footer-getnews > .dac-button-social {
- margin-left: 4px; }
- .dac-footer-separator {
- background: #f0f0f0;
- margin: 0 0 12px; }
- .dac-footer-links a + a:before {
- content: '|';
- cursor: default;
- margin: 0 10px 0 8px; }
+ margin-left: 0;
+ margin-right: 16px;
+ }
+
+ .dac-footer-links {
+ display: block;
+ float: none;
+ width: 100%;
+ }
+
+ .devsite-utility-footer-language {
+ float: none;
+ margin: 0 0 20px;
+ width: 100%;
+ }
+
.dac-footer .locales {
- float: right;
- margin: 0; }
- .dac-footer .locales select {
- background-color: #f0f0f0;
- border-radius: 3px;
- font-size: 12px;
- height: auto;
- margin-top: -2px;
- padding: 8px 12px;
- width: 146px; }
- .dac-footer.dac-landing {
- margin-top: 0;
- border-top: 0; }
- @media (max-width: 719px) {
- .dac-footer-reachout {
- text-align: left; }
- .dac-footer-social {
- display: block; }
- .dac-footer-social-link, .dac-footer-contact-link {
- display: inline-block; }
- .dac-footer .dac-footer-contact-link,
- .dac-footer .dac-footer-social-link {
- margin-left: 0;
- margin-right: 16px; }
- .dac-footer .locales {
- display: block;
- float: none;
- margin-top: 15px; } }
+ display: block;
+ float: none;
+ margin-top: 15px;
+ }
+}
/* =============================================================================
Columns
@@ -5893,11 +6188,14 @@
.wrap {
margin: 0 auto;
max-width: 940px;
- clear: both; }
- .dac-fullscreen-mode .wrap {
- max-width: none; }
+ clear: both;
+}
-.dac-full-screen-mode .dac-search-open .wrap {
+.dac-fullscreen-mode .wrap {
+ max-width: none;
+}
+
+.dac-fullscreen-mode .dac-search-open .wrap {
max-width: 940px;
}
@@ -6569,11 +6867,11 @@
z-index: 61;
}
-.dac-ndk {
+.dac-ndk .dac-header {
background: #00bcd4;
}
-.dac-studio {
+.dac-studio .dac-header {
background: #424242;
}
@@ -6637,12 +6935,12 @@
display: inline-block;
}
- /* Do not show nav toggle and up-nav button for left nav
- in Studio docs, when header tabs are visible */
- body.studio .dac-nav-back-button {
+ /* Do not show nav toggle and up-nav button for left nav,
+ when header tabs are visible (when no sub navigation) */
+ body.no-subnav .dac-nav-back-button {
display:none;
}
- body.studio .dac-nav-sub {
+ body.no-subnav .dac-nav-sub {
top: 0 !important;
}
}
@@ -6663,7 +6961,8 @@
font-weight: 500;
}
-.dac-header-tab:hover {
+.dac-header-tab:hover,
+.dac-header-tab:focus {
color: #fff;
}
@@ -6757,7 +7056,7 @@
display: inline-block;
}
-body.studio .dac-header-crumbs {
+body.no-crumbs .dac-header-crumbs {
display:none;
}
@@ -6822,6 +7121,10 @@
transition: width 300ms, right 100ms, margin 100ms;
}
+.dac-studio .dac-header-search {
+ right: 20px; /* move searchbar farther right, because there's no button */
+}
+
.dac-header-search-inner {
margin: 0 auto;
max-width: 940px;
@@ -6881,9 +7184,6 @@
width: 100%;
}
-.dac-studio .dac-header-search {
- right:150px;
-}
.dac-studio .dac-header-search-input {
background: rgba(255, 255, 255, 0.3);
}
@@ -6998,6 +7298,7 @@
}
@media (min-width: 720px) and (max-width: 979px) {
+ .dac-studio .dac-header-search,
.dac-header-search {
right: 20px;
width: 200px;
@@ -7168,10 +7469,33 @@
z-index: 1;
}
-.dac-nav-back-button, .dac-nav-back-button:hover, .dac-nav-back-button:active {
+.dac-nav-back-button,
+.dac-nav-back-button:hover,
+.dac-nav-back-button:active,
+.dac-nav-back-button:focus {
color: rgba(255, 255, 255, 0.7);
}
+/* The back button in Studio and NDK left nav */
+.dac-nav-back-button.back-to-dev {
+ background: none;
+ color: #444;
+ position: relative !important;
+ top: -16px;
+}
+
+.dac-nav-back-button.back-to-dev:hover,
+.dac-nav-back-button.back-to-dev:active,
+.dac-nav-back-button.back-to-dev:focus {
+ color: rgba(68, 68, 68, .7);
+}
+
+.dac-nav-back-button:focus .dac-nav-back {
+ outline-color: rgb(77, 144, 254);
+ outline-offset: 15px;
+ outline-style: auto;
+}
+
.dac-nav-back-button > .dac-sprite, .dac-nav-back-button > .dac-modal-header-close:before, .paging-links .dac-nav-back-button > .prev-page-link:before, .paging-links .dac-nav-back-button > .next-page-link:before, .paging-links .dac-nav-back-button > .next-class-link:before, .paging-links .dac-nav-back-button > .start-class-link:after {
opacity: .7;
}
@@ -7335,7 +7659,8 @@
.dac-nav-link {
color: #444;
display: block;
- font-size: 18px;
+ font-size: 14px;
+ text-transform: uppercase;
font-weight: 500;
letter-spacing: .24px;
padding: 5px 20px;
@@ -7356,6 +7681,7 @@
font-size: 12px;
font-weight: 400;
padding-left: 40px;
+ text-transform: none;
}
.dac-nav-link.selected {
@@ -7406,18 +7732,18 @@
padding-left: 250px;
}
- /* Do not show nav toggle for Studio on large screens */
- body.studio .dac-nav-toggle {
+ /* Do not show nav toggle on large screens (when no subnav) */
+ body.no-subnav .dac-nav-toggle {
display:none;
}
- body.studio .dac-header-logo {
+ body.no-subnav .dac-header-logo {
padding-left:20px;
}
- /* And if the page has no subcomponent, don't show left nav at all */
- body.studio.None .dac-nav {
+ /* ...If the page is also full-width, then don't show left nav at all */
+ body.no-subnav.full-width .dac-nav {
display: none;
}
- body.studio.None #body-content {
+ body.no-subnav.full-width #body-content {
padding-left:0;
}
}
@@ -7436,6 +7762,10 @@
height: 100%;
}
+.data-reference-resources-wrapper {
+ display: none;
+}
+
.dac-reference-nav {
height: calc(100% - 36px);
overflow: hidden;
@@ -7480,11 +7810,12 @@
padding: 0 0 0 13px;
}
-.dac-reference-nav-resource, .dac-reference-nav-toggle {
+.dac-reference-nav-resource,
+.dac-reference-nav-toggle {
color: #505050;
cursor: pointer;
display: block;
- font-size: 13px;
+ font-size: 12px;
line-height: 1;
overflow: hidden;
margin: 0;
@@ -7581,7 +7912,7 @@
display: none;
}
-#nav .nav-section-header:after {
+#nav .nav-section-header .toggle-icon {
background: transparent url(../images/styles/disclosure_down.png) no-repeat scroll 50% 50%;
content: '';
height: 34px;
@@ -7616,7 +7947,7 @@
padding: 0 10px;
}
-#nav li.expanded > .nav-section-header:after {
+#nav li.expanded > .nav-section-header .toggle-icon {
content: '';
background: transparent url(../images/styles/disclosure_up.png) no-repeat scroll 50% 50%;
width: 34px;
@@ -7774,7 +8105,26 @@
top: 0;
}
+.dac-hero {
+ background-size: cover;
+ position: relative;
+}
+
+.dac-hero-headline {
+ background-color: #fff;
+ bottom: 25px;
+ float: none !important;
+ padding: 0 10px 10px;
+ position: absolute;
+ right: 0;
+ z-index: 2;
+}
+
@media (max-width: 719px) {
+ .dac-hero-headline {
+ bottom: 0;
+ }
+
.dac-hero.dac-darken::before {
background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.9) 80%);
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.9) 80%);
@@ -7804,6 +8154,10 @@
margin: 0 0 14px;
}
+.dac-studio .dac-hero-title {
+ padding-top:0;
+}
+
@media (max-width: 719px) {
.dac-hero-title {
font-size: 28px;
@@ -7838,6 +8192,24 @@
margin-left: -8px;
}
+.dac-hero-cta.col-16 {
+ line-height: 1.4em;
+ margin-top: 20px;
+ padding-left: 0;
+ position: relative;
+}
+
+.dac-hero-cta.col-16 .dac-sprite {
+ position: absolute;
+ left: 0;
+ top: -3px;
+}
+
+.dac-hero-cta.col-16 .dac-sprite-text {
+ position: relative;
+ left: 12px;
+}
+
@media (max-width: 719px) {
.dac-hero-cta {
line-height: 28px;
@@ -7849,16 +8221,16 @@
}
/* Android Studio download page */
-section#features {
+.dac-studio section#features {
padding-top:0;
}
-.wrap.feature {
+.dac-studio .wrap.feature {
margin:80px auto;
}
-.dac-section-links.feature-more {
+.dac-studio .dac-section-links.feature-more {
margin-top:-20px;
}
-.dac-toggle-content .wrap.feature {
+.dac-studio .dac-toggle-content .wrap.feature {
margin-top:0;
}
@@ -7873,12 +8245,12 @@
}
/* Android Studio download page */
- .feature .dac-hero-figure,
- .feature .dac-hero-figure img {
+ .dac-studio .feature .dac-hero-figure,
+ .dac-studio .feature .dac-hero-figure img {
height:auto;
max-height:none;
}
- .feature .dac-hero-figure img {
+ .dac-studio .feature .dac-hero-figure img {
width:90%;
margin:0 auto;
}
@@ -9028,6 +9400,33 @@
background-color: #dc4d38;
}
+.dac-blue.dac-hero,
+.dac-blue.dac-section {
+ background-color: #0277bd;
+}
+
+.dac-blue.dac-invert .dac-hero-description,
+.dac-blue.dac-invert .dac-section-subtitle {
+ color: #fff;
+}
+
+.dac-dark-gray.dac-hero,
+.dac-dark-gray.dac-section {
+ background-color: #455a64;
+}
+
+.dac-bg-opacity::after {
+ background-color: rgba(0, 0, 0, .3);
+ content : "";
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 1;
+}
+
.dac-hero-cta, .dac-section-title, .dac-section-links {
color: #212121;
color: rgba(0, 0, 0, 0.87);
@@ -9055,6 +9454,47 @@
color: rgba(255, 255, 255, 0.7);
}
+.dac-hero.dac-no-min-height {
+ min-height: 0;
+}
+
+.dac-hero-half-bg {
+ background-size: cover;
+ background-repeat: no-repeat;
+ float: right;
+ height: 440px;
+}
+
+.dac-hero-half-bg-centered {
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ float: right;
+ height: 440px;
+}
+
+@media only screen and (-webkit-min-device-pixel-ratio: 2),
+only screen and (-moz-min-device-pixel-ratio: 2),
+only screen and (min-device-pixel-ratio: 2),
+only screen and (min-resolution: 192dpi),
+only screen and (min-resolution: 2dppx) {
+ .dac-hero-half-bg,
+ .dac-hero-half-bg-centered {
+ background-size: "" "";
+ }
+}
+
+@media (max-width: 719px) {
+ .dac-hero-half-bg,
+ .dac-hero-half-bg-centered {
+ background-position: center;
+ background-size: auto 100%;
+ float: none;
+ height: 200px;
+ margin-top: 32px;
+ }
+}
+
.dac-section {
background-position: 50% 50%;
background-size: cover;
@@ -9070,7 +9510,8 @@
}
}
-.dac-section.dac-small {
+.dac-section.dac-small,
+.dac-hero.dac-small {
padding-bottom: 32px;
padding-top: 32px;
}
@@ -9146,34 +9587,76 @@
*/
.dac-sprite, .dac-modal-header-close:before, .paging-links .prev-page-link:before, .paging-links .next-page-link:before, .paging-links .next-class-link:before, .paging-links .start-class-link:after, .Video-button--picture-in-picture, .Video-button--close, a.video-shadowbox-button.white::after, #tb li:before,
#qv li:before {
- background-image: url(/assets/images/sprite.png);
+ background-image: url(../images/sprite.png);
display: inline-block;
- vertical-align: middle; }
- @media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 1.5dppx), (min-resolution: 144px) {
- .dac-sprite, .dac-modal-header-close:before, .paging-links .prev-page-link:before, .paging-links .next-page-link:before, .paging-links .next-class-link:before, .paging-links .start-class-link:after, .Video-button--picture-in-picture, .Video-button--close, a.video-shadowbox-button.white::after, #tb li:before,
- #qv li:before {
- background-image: url(/assets/images/sprite@2x.png);
- background-size: 36px 883px; } }
+ vertical-align: middle;
+}
-.dac-sprite.dac-auto-chevron, .dac-auto-chevron.dac-modal-header-close:before, .paging-links .dac-auto-chevron.prev-page-link:before, .paging-links .dac-auto-chevron.next-page-link:before, .paging-links .dac-auto-chevron.next-class-link:before, .paging-links .dac-auto-chevron.start-class-link:after {
+@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 1.5dppx), (min-resolution: 144px) {
+
+ .dac-sprite,
+ .dac-modal-header-close:before,
+ .paging-links .prev-page-link:before,
+ .paging-links .next-page-link:before,
+ .paging-links .next-class-link:before,
+ .paging-links .start-class-link:after,
+ .Video-button--picture-in-picture,
+ .Video-button--close,
+ a.video-shadowbox-button.white::after,
+ #tb li:before,
+ #qv li:before {
+ background-image: url(../images/sprite_2x.png);
+ background-size: 36px 900px;
+ }
+}
+
+.dac-chevron {
+ background-size: 9px 39px;
+ display: inline-block;
+ height: 13px;
+ text-indent: -9999px;
+ width: 9px;
+}
+
+.dac-sprite.dac-auto-chevron,
+.dac-auto-chevron.dac-modal-header-close:before,
+.paging-links .dac-auto-chevron.prev-page-link:before,
+.paging-links .dac-auto-chevron.next-page-link:before,
+.paging-links .dac-auto-chevron.next-class-link:before,
+.paging-links .dac-auto-chevron.start-class-link:after {
background-position: 0px -669px;
height: 24px;
width: 24px;
- vertical-align: -6px; }
- .dac-invert .dac-sprite.dac-auto-chevron, .dac-invert .dac-auto-chevron.dac-modal-header-close:before, .dac-invert .paging-links .dac-auto-chevron.prev-page-link:before, .paging-links .dac-invert .dac-auto-chevron.prev-page-link:before, .dac-invert .paging-links .dac-auto-chevron.next-page-link:before, .paging-links .dac-invert .dac-auto-chevron.next-page-link:before, .dac-invert .paging-links .dac-auto-chevron.next-class-link:before, .paging-links .dac-invert .dac-auto-chevron.next-class-link:before, .dac-invert .paging-links .dac-auto-chevron.start-class-link:after, .paging-links .dac-invert .dac-auto-chevron.start-class-link:after {
- background-position: 0px -513px;
- height: 24px;
- width: 24px; }
+ vertical-align: -6px;
+}
+
+.dac-invert .dac-sprite.dac-auto-chevron, .dac-invert .dac-auto-chevron.dac-modal-header-close:before, .dac-invert .paging-links .dac-auto-chevron.prev-page-link:before, .paging-links .dac-invert .dac-auto-chevron.prev-page-link:before, .dac-invert .paging-links .dac-auto-chevron.next-page-link:before, .paging-links .dac-invert .dac-auto-chevron.next-page-link:before, .dac-invert .paging-links .dac-auto-chevron.next-class-link:before, .paging-links .dac-invert .dac-auto-chevron.next-class-link:before, .dac-invert .paging-links .dac-auto-chevron.start-class-link:after, .paging-links .dac-invert .dac-auto-chevron.start-class-link:after {
+ background-position: 0px -513px;
+ height: 24px;
+ width: 24px;
+}
.dac-sprite.dac-auto-chevron-large, .dac-auto-chevron-large.dac-modal-header-close:before, .paging-links .dac-auto-chevron-large.prev-page-link:before, .paging-links .dac-auto-chevron-large.next-page-link:before, .paging-links .dac-auto-chevron-large.next-class-link:before, .paging-links .dac-auto-chevron-large.start-class-link:after {
background-position: 0px -695px;
height: 36px;
width: 36px;
- vertical-align: -10px; }
- .dac-invert .dac-sprite.dac-auto-chevron-large, .dac-invert .dac-auto-chevron-large.dac-modal-header-close:before, .dac-invert .paging-links .dac-auto-chevron-large.prev-page-link:before, .paging-links .dac-invert .dac-auto-chevron-large.prev-page-link:before, .dac-invert .paging-links .dac-auto-chevron-large.next-page-link:before, .paging-links .dac-invert .dac-auto-chevron-large.next-page-link:before, .dac-invert .paging-links .dac-auto-chevron-large.next-class-link:before, .paging-links .dac-invert .dac-auto-chevron-large.next-class-link:before, .dac-invert .paging-links .dac-auto-chevron-large.start-class-link:after, .paging-links .dac-invert .dac-auto-chevron-large.start-class-link:after {
- background-position: 0px -771px;
- height: 36px;
- width: 36px; }
+ vertical-align: -10px;
+}
+
+.dac-invert .dac-sprite.dac-auto-chevron-large,
+.dac-invert .dac-auto-chevron-large.dac-modal-header-close:before,
+.dac-invert .paging-links .dac-auto-chevron-large.prev-page-link:before,
+.paging-links .dac-invert .dac-auto-chevron-large.prev-page-link:before,
+.dac-invert .paging-links .dac-auto-chevron-large.next-page-link:before,
+.paging-links .dac-invert .dac-auto-chevron-large.next-page-link:before,
+.dac-invert .paging-links .dac-auto-chevron-large.next-class-link:before,
+.paging-links .dac-invert .dac-auto-chevron-large.next-class-link:before,
+.dac-invert .paging-links .dac-auto-chevron-large.start-class-link:after,
+.paging-links .dac-invert .dac-auto-chevron-large.start-class-link:after {
+ background-position: 0px -771px;
+ height: 36px;
+ width: 36px;
+}
.dac-sprite.dac-auto-unfold-less, .dac-auto-unfold-less.dac-modal-header-close:before, .paging-links .dac-auto-unfold-less.prev-page-link:before, .paging-links .dac-auto-unfold-less.next-page-link:before, .paging-links .dac-auto-unfold-less.next-class-link:before, .paging-links .dac-auto-unfold-less.start-class-link:after {
background-position: 0px -487px;
@@ -9295,6 +9778,13 @@
height: 16px;
width: 16px; }
+/* The back button in Studio and NDK left nav */
+.dac-nav-back-button.back-to-dev .dac-sprite.dac-nav-back {
+ background-position: 0px -884px;
+ height: 16px;
+ width: 16px;
+}
+
.dac-sprite.dac-nav-forward-blue, .dac-nav-forward-blue.dac-modal-header-close:before, .paging-links .dac-nav-forward-blue.prev-page-link:before, .paging-links .next-page-link:before, .paging-links .next-class-link:before, .paging-links .start-class-link:after {
background-position: 0px -159px;
height: 16px;
@@ -9385,42 +9875,73 @@
background: #ffebc3;
border-top: 1px solid #e5d4a1;
display: none;
- color: rgba(0, 0, 0, 0.87);
+ color: rgba(0, 0, 0, .87);
line-height: 1.4;
- padding: 10px; }
- .dac-toast.dac-visible {
- display: block; }
- .dac-toast-wrap {
- box-sizing: border-box;
- margin: 0 auto;
- max-width: 940px;
- padding-right: 20px;
- position: relative; }
+ padding: 10px;
+}
+
+.dac-toast.dac-visible {
+ display: block;
+}
+
+.dac-toast-wrap {
+ box-sizing: border-box;
+ margin: 0 auto;
+ max-width: 940px;
+ padding-right: 20px;
+ position: relative;
+}
+
+.dac-toast-close-btn {
+ background-color: transparent;
+ border: none;
+ border-radius: 0;
+ cursor: pointer;
+ opacity: .4;
+ padding: 0;
+ position: absolute;
+ right: 0;
+ top: -2px;
+}
+
+.dac-toast-close-btn:hover,
+.dac-toast-close-btn:focus,
+.dac-toast-close-btn:active {
+ opacity: 1;
+ outline: none;
+}
+
+.dac-toast-close-btn .dac-button.dac-raised.dac-primary{
+ margin: 0;
+ padding: 0;
+}
+
+.dac-toast-group {
+ bottom: 0;
+ left: 0;
+ position: fixed;
+ right: 0;
+ z-index: 60;
+}
+
+.dac-toast.dac-danger {
+ background-color: #ffccbc;
+ border-top-color: #e5b7a9;
+}
+
+.dac-toast.dac-success {
+ background-color: #cdedc8;
+ border-top-color: #c6d5b4;
+}
+
+@media (max-width: 719px) {
.dac-toast-close-btn {
- background-color: transparent;
- border: none;
- border-radius: 0;
- cursor: pointer;
- opacity: .4;
- padding: 0;
- position: absolute;
- right: 0;
- top: 1px; }
- .dac-toast-close-btn:hover, .dac-toast-close-btn:focus, .dac-toast-close-btn:active {
- outline: none;
- opacity: 1; }
- .dac-toast-group {
- bottom: 0;
- left: 0;
- position: fixed;
- right: 0;
- z-index: 60; }
- .dac-toast.dac-danger {
- background-color: #ffccbc;
- border-top-color: #e5b7a9; }
- .dac-toast.dac-success {
- background-color: #cdedc8;
- border-top-color: #c6d5b4; }
+ position: relative;
+ top: 0;
+ margin: 10px 0 0;
+ display: block;
+ }
+}
.dac-tab-item {
box-sizing: border-box;
@@ -9910,32 +10431,22 @@
top: -4px;
}
-/** CSS Fixes for DevSite (akassay@) */
-.dac-button-social,
-.dac-fab:not('.dac-scroll-button') {
- position: relative;
+#skip-to-main {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
}
-.dac-button-social .dac-sprite,
-.dac-fab .dac-sprite,
-.play-button .dac-sprite {
- margin-top: -7px;
- position: relative;
- top: 50%;
-}
-
-.dac-fab .dac-sprite.dac-arrow-down-gray {
- margin-top: -3px;
-}
-
-.dac-button-social .dac-sprite.dac-gplus {
- margin-top: -17px;
-}
-
-.play-button .dac-sprite {
- margin-top: -10px;
-}
-
-.dac-nav-link-forward {
- padding: 9px 0;
+#skip-to-main:focus {
+ background: #fff;
+ clip: auto;
+ height: auto;
+ padding: 10px;
+ width: auto;
+ z-index: 10000;
}
diff --git a/tools/droiddoc/templates-sdk-dev/assets/js/docs.js b/tools/droiddoc/templates-sdk-dev/assets/js/docs.js
index efcc363..5ed947c 100644
--- a/tools/droiddoc/templates-sdk-dev/assets/js/docs.js
+++ b/tools/droiddoc/templates-sdk-dev/assets/js/docs.js
@@ -5,6 +5,14 @@
var basePath = getBaseUri(location.pathname);
var SITE_ROOT = toRoot + basePath.substring(1, basePath.indexOf("/", 1));
+// TODO(akassay) generate this var in the reference doc build.
+var API_LEVELS = ['1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '10', '11', '12', '13', '14', '15', '16',
+ '17', '18', '19', '20', '21', '22', '23', '24'];
+var METADATA = METADATA || {};
+var RESERVED_METADATA_CATEGORY_NAMES = ['extras', 'carousel', 'collections',
+ 'searchHeroCollections'];
+
// Ensure that all ajax getScript() requests allow caching
$.ajaxSetup({
cache: true
@@ -15,8 +23,7 @@
$(document).ready(function() {
// prep nav expandos
- var pagePath = devsite ?
- location.href.replace(location.hash, '') : document.location.pathname;
+ var pagePath = location.href.replace(location.hash, '');
// account for intl docs by removing the intl/*/ path
if (pagePath.indexOf("/intl/") == 0) {
pagePath = pagePath.substr(pagePath.indexOf("/", 6)); // start after intl/ to get last /
@@ -53,6 +60,9 @@
// set global variable so we can highlight the sidenav a bit later (such as for google reference)
// and highlight the sidenav
mPagePath = pagePath;
+
+ // Check for params and remove them.
+ mPagePath = mPagePath.split('?')[0];
highlightSidenav();
// set up prev/next links if they exist
@@ -160,8 +170,12 @@
$('.next-page-link').attr('href', $nextLink.attr('href'))
.removeClass("hide");
// for the footer link, also add the previous and next page titles
- $('.content-footer .prev-page-link').append($prevLink.html());
- $('.content-footer .next-page-link').append($nextLink.html());
+ if ($prevLink.length) {
+ $('.content-footer .prev-page-link').append($prevLink.html());
+ }
+ if ($nextLink.length) {
+ $('.content-footer .next-page-link').append($nextLink.html());
+ }
}
if (!startClass && $prevLink.length) {
@@ -172,7 +186,6 @@
$('.prev-page-link').attr('href', $prevLink.attr('href')).removeClass("hide");
}
}
-
}
// Set up the course landing pages for Training with class names and descriptions
@@ -231,6 +244,12 @@
$(this).get(0).play();
});
+ // Set up play-on-click for <video> tags with a "video-wrapper".
+ $('.video-wrapper > video').bind('click', function() {
+ this.play();
+ $(this.parentElement).addClass('playing');
+ });
+
// Set up tooltips
var TOOLTIP_MARGIN = 10;
$('acronym,.tooltip-link').each(function() {
@@ -281,24 +300,13 @@
// END of the onload event
function initExpandableNavItems(rootTag) {
- $(rootTag + ' li.nav-section .nav-section-header').click(function() {
- var section = $(this).closest('li.nav-section');
- if (section.hasClass('expanded')) {
- /* hide me and descendants */
- section.find('ul').slideUp(250, function() {
- // remove 'expanded' class from my section and any children
- section.closest('li').removeClass('expanded');
- $('li.nav-section', section).removeClass('expanded');
- });
- } else {
- /* show me */
- // first hide all other siblings
- var $others = $('li.nav-section.expanded', $(this).closest('ul')).not('.sticky');
- $others.removeClass('expanded').children('ul').slideUp(250);
+ var toggleIcon = $(
+ rootTag + ' li.nav-section .nav-section-header .toggle-icon, ' +
+ rootTag + ' li.nav-section .nav-section-header a[href="#"]');
- // now expand me
- section.closest('li').addClass('expanded');
- section.children('ul').slideDown(250);
+ toggleIcon.on('click keypress', function(e) {
+ if (e.type == 'keypress' && e.which == 13 || e.type == 'click') {
+ doNavToggle(this);
}
});
@@ -311,6 +319,27 @@
});
}
+function doNavToggle(el) {
+ var section = $(el).closest('li.nav-section');
+ if (section.hasClass('expanded')) {
+ /* hide me and descendants */
+ section.find('ul').slideUp(250, function() {
+ // remove 'expanded' class from my section and any children
+ section.closest('li').removeClass('expanded');
+ $('li.nav-section', section).removeClass('expanded');
+ });
+ } else {
+ /* show me */
+ // first hide all other siblings
+ var $others = $('li.nav-section.expanded', $(el).closest('ul')).not('.sticky');
+ $others.removeClass('expanded').children('ul').slideUp(250);
+
+ // now expand me
+ section.closest('li').addClass('expanded');
+ section.children('ul').slideDown(250);
+ }
+}
+
/** 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)
@@ -494,7 +523,7 @@
$(".toggle-content-text:eq(0)", obj).toggle();
div.removeClass("closed").addClass("open");
$(".toggle-content-img:eq(0)", div).attr("title", "hide").attr("src", toRoot +
- "assets/images/triangle-opened.png");
+ "assets/images/styles/disclosure_up.png");
} else { // if it's open, close it
toggleMe.slideUp('fast', function() { // Wait until the animation is done before closing arrow
$(".toggle-content-text:eq(0)", obj).toggle();
@@ -502,7 +531,7 @@
div.find(".toggle-content").removeClass("open").addClass("closed")
.find(".toggle-content-toggleme").hide();
$(".toggle-content-img", div).attr("title", "show").attr("src", toRoot +
- "assets/images/triangle-closed.png");
+ "assets/images/styles/disclosure_down.png");
});
}
return false;
@@ -826,24 +855,14 @@
/* ################# JAVADOC REFERENCE ################### */
/* ######################################################## */
-/* Initialize some droiddoc stuff, but only if we're in the reference */
-if (location.pathname.indexOf("/reference") == 0) {
- if (!(location.pathname.indexOf("/reference-gms/packages.html") == 0) &&
- !(location.pathname.indexOf("/reference-gcm/packages.html") == 0) &&
- !(location.pathname.indexOf("/reference/com/google") == 0)) {
- $(document).ready(function() {
- // init available apis based on user pref
- changeApiLevel();
- });
- }
-}
+
var API_LEVEL_COOKIE = "api_level";
var minLevel = 1;
var maxLevel = 1;
function buildApiLevelSelector() {
- maxLevel = SINCE_DATA.length;
+ maxLevel = API_LEVELS.length;
var userApiLevel = parseInt(readCookie(API_LEVEL_COOKIE));
userApiLevel = userApiLevel == 0 ? maxLevel : userApiLevel; // If there's no cookie (zero), use the max by default
@@ -856,8 +875,8 @@
}
var select = $("#apiLevelSelector").html("").change(changeApiLevel);
for (var i = maxLevel - 1; i >= 0; i--) {
- var option = $("<option />").attr("value", "" + SINCE_DATA[i]).append("" + SINCE_DATA[i]);
- // if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
+ var option = $("<option />").attr("value", "" + API_LEVELS[i]).append("" + API_LEVELS[i]);
+ // if (API_LEVELS[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
select.append(option);
}
@@ -867,7 +886,8 @@
}
function changeApiLevel() {
- maxLevel = SINCE_DATA.length;
+ maxLevel = API_LEVELS.length;
+ minLevel = parseInt($('#doc-api-level').attr('class'));
var selectedLevel = maxLevel;
selectedLevel = parseInt($("#apiLevelSelector option:selected").val());
@@ -876,20 +896,11 @@
writeCookie(API_LEVEL_COOKIE, selectedLevel, null);
if (selectedLevel < minLevel) {
- $("#naMessage").show().html("<div><p><strong>This API" +
- " requires API level " + minLevel + " or higher.</strong></p>" +
- "<p>This document is hidden because your selected API level for the documentation is " +
- selectedLevel + ". You can change the documentation API level with the selector " +
- "above the left navigation.</p>" +
- "<p>For more information about specifying the API level your app requires, " +
- "read <a href='" + toRoot + "training/basics/supporting-devices/platforms.html'" +
- ">Supporting Different Platform Versions</a>.</p>" +
- "<input type='button' value='OK, make this page visible' " +
- "title='Change the API level to " + minLevel + "' " +
- "onclick='$(\"#apiLevelSelector\").val(\"" + minLevel + "\");changeApiLevel();' />" +
- "</div>");
- } else {
- $("#naMessage").hide();
+ // Show the API notice dialog, set number values and button event
+ $('#api-unavailable').trigger('modal-open');
+ $('#api-unavailable .selected-level').text(selectedLevel);
+ $('#api-unavailable .api-level').text(minLevel);
+ $('#api-unavailable button.ok').attr('onclick','$("#apiLevelSelector").val("' + minLevel + '");changeApiLevel();');
}
}
@@ -1248,6 +1259,10 @@
$selectedLi.children("ul").children("li").each(function() {
var $li = $("<li>").append($(this).find("a").first().clone());
+ var $samplesLink = $li.find("a");
+ if ($samplesLink.text().endsWith('/')) {
+ $samplesLink.text($samplesLink.text().slice(0,-1));
+ }
$ul.append($li);
});
@@ -1563,7 +1578,8 @@
// Record number of pages viewed in analytics.
if (!firstPage) {
var clicks = Math.ceil((i - initialResults) / opts.itemsPerPage);
- ga('send', 'event', 'Cards', 'Click More', clicks);
+ devsite.analytics.trackAnalyticsEvent('event',
+ 'Cards', 'Click More', clicks);
}
}
@@ -1585,8 +1601,7 @@
$widget.toggleClass('dac-has-less', false);
opts.currentIndex = Math.min(opts.initialResults, resources.length);
-
- ga('send', 'event', 'Cards', 'Click Less');
+ devsite.analytics.trackAnalyticsEvent('event', 'Cards', 'Click Less');
}
/* A decorator for event functions which finds the surrounding widget and it's options */
@@ -2215,7 +2230,8 @@
}
}
- $(document).on('click.blog-reader', 'a[href*="blogspot.com/"]', wrapLinkWithReader);
+ $(document).on('click.blog-reader', 'a.resource-card[href*="blogspot.com/"]',
+ wrapLinkWithReader);
})(jQuery, window);
(function($) {
@@ -2547,11 +2563,13 @@
if (checkbox.checked) {
this.chipsEl_.append(this.chipForItem(item));
- ga('send', 'event', 'Filters', 'Check', $(checkbox).val());
+ devsite.analytics.trackAnalyticsEvent('event',
+ 'Filters', 'Check', $(checkbox).val());
} else {
item.data('chip.dac-filter').remove();
this.addToItemValue(item, -1);
- ga('send', 'event', 'Filters', 'Uncheck', $(checkbox).val());
+ devsite.analytics.trackAnalyticsEvent('event',
+ 'Filters', 'Uncheck', $(checkbox).val());
}
this.draw_(this.filteredResources());
@@ -3280,20 +3298,9 @@
function changeLangPref(targetLang, submit) {
window.writeCookie('pref_lang', targetLang, null);
-//DD
$('#language').find('option[value="' + targetLang + '"]').attr('selected', true);
- // ####### TODO: Remove this condition once we're stable on devsite #######
- // This condition is only needed if we still need to support legacy GAE server
- if (window.devsite) {
- // Switch language when on Devsite server
- if (submit) {
- $('#setlang').submit();
- }
- } else {
- // Switch language when on legacy GAE server
- if (submit) {
- window.location = getBaseUri(location.pathname);
- }
+ if (submit) {
+ $('#setlang').submit();
}
}
// Redundant usage to appease jshint.
@@ -3378,24 +3385,11 @@
return lang;
})();
var localeTarget = (function() {
- var localeTarget = locale;
- if (window.devsite) {
- if (getQueryVariable('hl')) {
- var target = getQueryVariable('hl');
- if (!(target === 0) || (LANGUAGES.indexOf(target) === -1)) {
- localeTarget = target;
- }
- }
- } else {
- if (location.pathname.substring(0,6) == "/intl/") {
- var target = location.pathname.split('/')[2];
- if (!(target === 0) || (LANGUAGES.indexOf(target) === -1)) {
- localeTarget = target;
- }
- }
+ var lang = getQueryVariable('hl');
+ if (lang === false || LANGUAGES.indexOf(lang) === -1) {
+ lang = locale;
}
-
- return localeTarget;
+ return lang;
})();
/**
@@ -3899,14 +3893,14 @@
};
Modal.prototype.close_ = function() {
+ // When closing the modal for Android Studio downloads, reload the page
+ // because otherwise we might get stuck with post-download dialog state
+ if ($("[data-modal='studio_tos'].dac-active").length) {
+ location.reload();
+ }
this.el.removeClass('dac-active');
$('body').removeClass('dac-modal-open');
this.isOpen = false;
- // When closing the modal for Android Studio downloads, reload the page
- // because otherwise we might get stuck with post-download dialog state
- if ($("[data-modal='studio_tos']").length) {
- location.reload();
- }
};
Modal.prototype.open_ = function() {
@@ -3952,13 +3946,29 @@
// Check if url anchor is targetting a toggle to open the modal.
if (location.hash) {
- $(location.hash + '[data-modal-toggle]').trigger('click');
+ var $elem = $(document.getElementById(location.hash.substr(1)));
+ if ($elem.attr('data-modal-toggle')) {
+ $elem.trigger('click');
+ }
}
- if (window.getLangTarget() !== window.getLangPref()) {
- $('#langform').trigger('modal-open');
- $("#langform button.yes").attr("onclick","window.changeLangPref('" + window.getLangTarget() + "', true); return false;");
- $("#langform button.no").attr("onclick","window.changeLangPref('" + window.getLangPref() + "', true); return false;");
+ var isTargetLangValid = false;
+ $(ANDROID_LANGUAGES).each(function(index, langCode) {
+ if (langCode == window.getLangTarget()) {
+ isTargetLangValid = true;
+ return;
+ }
+ });
+ if (window.getLangTarget() !== window.getLangPref() && isTargetLangValid) {
+ $('#langform').trigger('modal-open');
+ $("#langform button.yes").attr("onclick","window.changeLangPref('" + window.getLangTarget() + "', true); return false;");
+ $("#langform button.no").attr("onclick","window.changeLangPref('" + window.getLangPref() + "', true); return false;");
+ }
+
+ /* Check the current API level, but only if we're in the reference */
+ if (location.pathname.indexOf('/reference') == 0) {
+ // init available apis based on user pref
+ changeApiLevel();
}
});
})(jQuery);
@@ -4093,7 +4103,12 @@
var forwardLink = $('<span/>')
.addClass('dac-nav-link-forward')
.html(icon)
- .on('click', swap_);
+ .attr('tabindex', 0)
+ .on('click keypress', function(e) {
+ if (e.type == 'keypress' && e.which == 13 || e.type == 'click') {
+ swap_(e);
+ }
+ });
/**
* @constructor
@@ -4147,8 +4162,11 @@
// Setup sub navigation collapse/expand
function initCollapsedNavs(toggleIcons) {
toggleIcons.each(setInitiallyActive_($('body')));
- toggleIcons.on('click', handleSubNavToggle_);
-
+ toggleIcons.on('click keypress', function(e) {
+ if (e.type == 'keypress' && e.which == 13 || e.type == 'click') {
+ handleSubNavToggle_(e);
+ }
+ });
}
function setInitiallyActive_(body) {
@@ -4165,6 +4183,10 @@
var expanded = expandedNavs.indexOf(landingPageClass) >= 0;
landingPageClass = landingPageClass === 'home' ? 'about' : landingPageClass;
+ if (landingPageClass == 'about' && location.pathname == '/index.html') {
+ expanded = true;
+ }
+
// TODO: Should read from localStorage
var visible = body.hasClass(landingPageClass) || expanded;
@@ -4220,17 +4242,28 @@
* @param {jQuery} el - The DOM element.
*/
function buildReferenceNav(el) {
+ var supportLibraryPath = '/reference/android/support/';
+ var currPath = location.pathname;
+
+ if (currPath.indexOf(supportLibraryPath) > -1) {
+ updateSupportLibrariesNav(supportLibraryPath, currPath);
+ }
var namespaceList = el.find('[data-reference-namespaces]');
- var resources = el.find('[data-reference-resources]');
+ var resources = $('[data-reference-resources]').detach();
var selected = namespaceList.find('.selected');
+ resources.appendTo(el);
// Links should be toggleable.
namespaceList.find('a').addClass('dac-reference-nav-toggle dac-closed');
+ // Set the path for the navtree data to use.
+ var navtree_filepath = getNavtreeFilePath(supportLibraryPath, currPath);
+
// Load in all resources
- $.getScript('/navtree_data.js', function(data, textStatus, xhr) {
+ $.getScript(navtree_filepath, function(data, textStatus, xhr) {
if (xhr.status === 200) {
- namespaceList.on('click', 'a.dac-reference-nav-toggle', toggleResourcesHandler);
+ namespaceList.on(
+ 'click', 'a.dac-reference-nav-toggle', toggleResourcesHandler);
}
});
@@ -4243,13 +4276,14 @@
var overview = addResourcesToView(resources, selected);
// Currently viewing Overview
- if (location.pathname === overview.attr('href')) {
+ if (location.href === overview.attr('href')) {
overview.parent().addClass('selected');
}
// Open currently selected resource
var listsToOpen = selected.children().eq(1);
- listsToOpen = listsToOpen.add(listsToOpen.find('.selected').parent()).show();
+ listsToOpen = listsToOpen.add(
+ listsToOpen.find('.selected').parent()).show();
// Mark dropdowns as open
listsToOpen.prev().removeClass('dac-closed');
@@ -4258,20 +4292,45 @@
namespaceList.scrollIntoView(selected);
}
+ function getNavtreeFilePath(supportLibraryPath, currPath) {
+ var navtree_filepath = '';
+ var navtree_filename = 'navtree_data.js';
+ if (currPath.indexOf(supportLibraryPath + 'test') > -1) {
+ navtree_filepath = supportLibraryPath + 'test/' + navtree_filename;
+ } else if (currPath.indexOf(supportLibraryPath + 'wearable') > -1) {
+ navtree_filepath = supportLibraryPath + 'wearable/' + navtree_filename;
+ } else {
+ navtree_filepath = '/' + navtree_filename;
+ }
+ return navtree_filepath;
+ }
+
+ function updateSupportLibrariesNav(supportLibraryPath, currPath) {
+ var navTitle = '';
+ if (currPath.indexOf(supportLibraryPath + 'test') > -1) {
+ navTitle = 'Test Support APIs';
+ } else if (currPath.indexOf(supportLibraryPath + 'wearable') > -1) {
+ navTitle = 'Wearable Support APIs';
+ }
+ $('#api-nav-title').text(navTitle);
+ $('#api-level-toggle').hide();
+ }
+
/**
* Handles the toggling of resources.
* @param {Event} event
*/
function toggleResourcesHandler(event) {
event.preventDefault();
- var el = $(this);
+ if (event.type == 'click' || event.type == 'keypress' && event.which == 13) {
+ var el = $(this);
+ // If resources for given namespace is not present, fetch correct data.
+ if (this.tagName === 'A' && !this.hasResources) {
+ addResourcesToView(buildResourcesViewForData(getDataForNamespace(el.text())), el.parent());
+ }
- // If resources for given namespace is not present, fetch correct data.
- if (this.tagName === 'A' && !this.hasResources) {
- addResourcesToView(buildResourcesViewForData(getDataForNamespace(el.text())), el.parent());
+ el.toggleClass('dac-closed').next().slideToggle(200);
}
-
- el.toggleClass('dac-closed').next().slideToggle(200);
}
/**
@@ -4331,9 +4390,9 @@
.find('a')
.addClass('dac-reference-nav-resource')
.end()
- .find('h2')
+ .find('h2').attr('tabindex', 0)
.addClass('dac-reference-nav-toggle dac-closed')
- .on('click', toggleResourcesHandler)
+ .on('click keypress', toggleResourcesHandler)
.end()
.add(resources.find('ul'))
.addClass('dac-reference-nav-resources')
@@ -4343,11 +4402,31 @@
return overview;
}
+ function setActiveReferencePackage(el) {
+ var packageLinkEls = el.find('[data-reference-namespaces] a');
+ var selected = null;
+ var highestMatchCount = 0;
+ packageLinkEls.each(function(index, linkEl) {
+ var matchCount = 0;
+ $(location.pathname.split('/')).each(function(index, subpath) {
+ if (linkEl.href.indexOf('/' + subpath + '/') > -1) {
+ matchCount++;
+ }
+ });
+ if (matchCount > highestMatchCount) {
+ selected = linkEl;
+ highestMatchCount = matchCount;
+ }
+ });
+ $(selected).parent().addClass('selected');
+ }
+
/**
* jQuery plugin
*/
$.fn.dacReferenceNav = function() {
return this.each(function() {
+ setActiveReferencePackage($(this));
buildReferenceNav($(this));
});
};
@@ -4389,7 +4468,7 @@
var parentNavEl;
var selected;
// In NDK docs, highlight appropriate sub-nav
- if (body.hasClass('ndk')) {
+ if (body.hasClass('dac-ndk')) {
if (body.hasClass('guide')) {
selected = navEl.find('> li.guides > a').addClass('selected');
} else if (body.hasClass('reference')) {
@@ -4399,8 +4478,10 @@
} else if (body.hasClass('downloads')) {
selected = navEl.find('> li.downloads > a').addClass('selected');
}
- } else if (body.hasClass('studio')) {
- if (body.hasClass('features')) {
+ } else if (body.hasClass('dac-studio')) {
+ if (body.hasClass('download')) {
+ selected = navEl.find('> li.download > a').addClass('selected');
+ } else if (body.hasClass('features')) {
selected = navEl.find('> li.features > a').addClass('selected');
} else if (body.hasClass('guide')) {
selected = navEl.find('> li.guide > a').addClass('selected');
@@ -4410,7 +4491,7 @@
} else if (body.hasClass('design')) {
selected = navEl.find('> li.design > a').addClass('selected');
// highlight Home nav
- } else if (body.hasClass('about')) {
+ } else if (body.hasClass('about') || location.pathname == '/index.html') {
parentNavEl = navEl.find('> li.home > a');
parentNavEl.addClass('has-subnav');
// In Home docs, also highlight appropriate sub-nav
@@ -4438,8 +4519,6 @@
} else {
selected = subNavEl.find('li.reference > a').addClass('selected');
}
- } else if ((urlSegments[1] === 'tools') || (urlSegments[1] === 'sdk')) {
- selected = subNavEl.find('li.tools > a').addClass('selected');
} else if (body.hasClass('google')) {
selected = subNavEl.find('li.google > a').addClass('selected');
} else if (body.hasClass('samples')) {
@@ -4502,6 +4581,11 @@
*/
function toggleSidebarVisibility(body) {
var wasClosed = ('' + localStorage.getItem('navigation-open')) === 'false';
+ // Override the local storage setting for navigation-open for child sites
+ // with no-subnav class.
+ if (document.body.classList.contains('no-subnav')) {
+ wasClosed = false;
+ }
if (wasClosed) {
body.removeClass(ToggleNav.DEFAULTS_.activeClass);
@@ -4746,28 +4830,66 @@
// Get current language.
var locale = getLangPref();
-
// Merge english resources.
- METADATA.all = mergeArrays(
- METADATA.en.about,
- METADATA.en.design,
- METADATA.en.distribute,
- METADATA.en.develop,
- YOUTUBE_RESOURCES,
- BLOGGER_RESOURCES,
- METADATA.en.extras
- );
+ if (useDevsiteMetadata) {
+ var all_keys = Object.keys(METADATA['en']);
+ METADATA.all = []
+
+ $(all_keys).each(function(index, category) {
+ if (RESERVED_METADATA_CATEGORY_NAMES.indexOf(category) == -1) {
+ METADATA.all = mergeArrays(
+ METADATA.all,
+ METADATA.en[category]
+ );
+ }
+ });
+
+ METADATA.all = mergeArrays(
+ METADATA.all,
+ YOUTUBE_RESOURCES,
+ BLOGGER_RESOURCES,
+ METADATA.en.extras
+ );
+ } else {
+ METADATA.all = mergeArrays(
+ METADATA.en.about,
+ METADATA.en.design,
+ METADATA.en.distribute,
+ METADATA.en.develop,
+ YOUTUBE_RESOURCES,
+ BLOGGER_RESOURCES,
+ METADATA.en.extras
+ );
+ }
// Merge local language resources.
if (locale !== 'en' && METADATA[locale]) {
- METADATA.all = mergeArrays(
- METADATA.all,
- METADATA[locale].about,
- METADATA[locale].design,
- METADATA[locale].distribute,
- METADATA[locale].develop,
- METADATA[locale].extras
- );
+ if (useDevsiteMetadata) {
+ all_keys = Object.keys(METADATA[locale]);
+ $(all_keys).each(function(index, category) {
+ if (RESERVED_METADATA_CATEGORY_NAMES.indexOf(category) == -1) {
+ METADATA.all = mergeArrays(
+ METADATA.all,
+ METADATA.en[category]
+ );
+ }
+ });
+
+ METADATA.all = mergeArrays(
+ METADATA.all,
+ METADATA[locale].extras
+ );
+ } else {
+ METADATA.all = mergeArrays(
+ METADATA.all,
+ METADATA[locale].about,
+ METADATA[locale].design,
+ METADATA[locale].distribute,
+ METADATA[locale].develop,
+ METADATA[locale].extras
+ );
+
+ }
}
mergeMetadataMap('collections', locale);
@@ -4778,7 +4900,8 @@
createIndices(METADATA.all, locale);
// Reference metadata.
- METADATA.androidReference = window.DATA;
+ METADATA.androidReference = mergeArrays(
+ window.DATA, window.SUPPORT_WEARABLE_DATA, window.SUPPORT_TEST_DATA);
METADATA.googleReference = mergeArrays(window.GMS_DATA, window.GCM_DATA);
};
})();
@@ -5478,20 +5601,9 @@
var ROW_COUNT_GOOGLE_EXPANDED = 8;
function onSuggestionClick(e) {
- var normalClick = e.which === 1 && !e.ctrlKey && !e.shiftKey && !e.metaKey;
- if (normalClick) {
- e.preventDefault();
- }
-
- // When user clicks a suggested document, track it
- var url = $(e.currentTarget).attr('href');
- ga('send', 'event', 'Suggestion Click', 'clicked: ' + url,
- 'query: ' + $('#search_autocomplete').val().toLowerCase(),
- {hitCallback: function() {
- if (normalClick) {
- document.location = url;
- }
- }});
+ devsite.analytics.trackAnalyticsEvent('event',
+ 'Suggestion Click', 'clicked: ' + $(e.currentTarget).attr('href'),
+ 'query: ' + $('#search_autocomplete').val().toLowerCase());
}
function buildLink(match) {
@@ -5526,7 +5638,7 @@
function renderAndroidResults(list, gMatches, query) {
list.empty();
- var header = $('<li class="dac-search-results-reference-header">android</li>');
+ var header = $('<li class="dac-search-results-reference-header">android APIs</li>');
list.append(header);
if (gMatches.length > 0) {
@@ -5647,16 +5759,18 @@
this.searchResultsHero = $('#dac-search-results-hero');
this.searchResultsReference = $('#dac-search-results-reference');
this.searchHeader = $('[data-search]').data('search-input.dac');
+ this.pageNav = $('a[name=navigation]');
this.currQueryReferenceResults = {};
+ this.isOpen = false;
}
Search.prototype.init = function() {
- if (!devsite && this.checkRedirectToIndex()) { return; }
-
this.searchHistory = window.dacStore('search-history');
this.searchInput.focus(this.onSearchChanged.bind(this));
- this.searchInput.keydown(this.handleKeyboardShortcut.bind(this));
+ this.searchInput.keypress(this.handleKeyboardShortcut.bind(this));
+ this.pageNav.keyup(this.handleTabbedToNav.bind(this));
+ this.searchResults.keyup(this.handleKeyboardShortcut.bind(this));
this.searchInput.on('input', this.onSearchChanged.bind(this));
this.searchClear.click(this.clear.bind(this));
this.searchClose.click(this.close.bind(this));
@@ -5713,6 +5827,12 @@
}
};
+ Search.prototype.handleTabbedToNav = function(event) {
+ if (this.isOpen) {
+ this.searchClose.trigger('click');
+ }
+ }
+
Search.prototype.goToResult = function(relativeIndex) {
var links = this.searchResults.find('a').filter(':visible');
var selectedLink = this.searchResults.find('.dac-selected');
@@ -5775,6 +5895,8 @@
this.removeQueryFromUrl();
this.searchInput.blur();
this.hideOverlay();
+ this.pageNav.focus();
+ this.isOpen = false;
};
Search.prototype.getUrlQuery = function() {
@@ -5859,6 +5981,7 @@
};
Search.prototype.showOverlay = function() {
+ this.isOpen = true;
this.body.addClass('dac-modal-open dac-search-open');
};
@@ -5956,7 +6079,11 @@
this.initiallyActive = this.containers.children('.' + this.options.activeClass).eq(0);
this.el.on('swap-content', this.swap.bind(this));
this.el.on('swap-reset', this.reset.bind(this));
- this.el.find(this.options.swapButton).on('click', this.swap.bind(this));
+ this.el.find(this.options.swapButton).on('click keypress', function(e) {
+ if (e.type == 'keypress' && e.which == 13 || e.type == 'click') {
+ this.swap();
+ }
+ }.bind(this));
}
/**
@@ -6008,6 +6135,7 @@
if (!this.options.dynamic) {
container.children().toggleClass(this.options.activeClass);
this.complete.bind(this);
+ $('.' + this.options.activeClass).focus();
return;
}
@@ -6139,7 +6267,7 @@
*/
Toast.prototype.closeBtn = function() {
this.closeBtnEl = this.closeBtnEl || $('<button class="' + this.options.closeBtnClass + '">' +
- '<i class="dac-sprite dac-close-black"></i>' +
+ '<span class="dac-button dac-raised dac-primary">OK</span>' +
'</button>');
return this.closeBtnEl;
};
@@ -6461,23 +6589,27 @@
// Video starts, send the video ID
if (event.data === YT.PlayerState.PLAYING) {
if (this.mPlayerPaused) {
- ga('send', 'event', 'Videos', 'Resume', videoId);
+ devsite.analytics.trackAnalyticsEvent('event',
+ 'Videos', 'Resume', videoId);
} else {
// track the start playing event so we know from which page the video was selected
- ga('send', 'event', 'Videos', 'Start: ' + videoId, 'on: ' + document.location.href);
+ devsite.analytics.trackAnalyticsEvent('event',
+ 'Videos', 'Start: ' + videoId, 'on: ' + document.location.href);
}
this.mPlayerPaused = false;
}
// Video paused, send video ID and video elapsed time
if (event.data === YT.PlayerState.PAUSED) {
- ga('send', 'event', 'Videos', 'Paused', videoId, currentTime);
+ devsite.analytics.trackAnalyticsEvent('event',
+ 'Videos', 'Paused: ' + videoId, 'on: ' + currentTime);
this.mPlayerPaused = true;
}
// Video finished, send video ID and video elapsed time
if (event.data === YT.PlayerState.ENDED) {
- ga('send', 'event', 'Videos', 'Finished', videoId, currentTime);
+ devsite.analytics.trackAnalyticsEvent('event',
+ 'Videos', 'Finished: ' + videoId, 'on: ' + currentTime);
this.mPlayerPaused = true;
}
};
diff --git a/tools/droiddoc/templates-sdk-dev/components/masthead.cs b/tools/droiddoc/templates-sdk-dev/components/masthead.cs
index c1e2706..1fef965 100644
--- a/tools/droiddoc/templates-sdk-dev/components/masthead.cs
+++ b/tools/droiddoc/templates-sdk-dev/components/masthead.cs
@@ -51,6 +51,26 @@
>Downloads</a>
</li>
</ul><?cs else
+ ?><?cs
+ #
+ # For the reference only docs, include just one tab
+ #
+ ?><?cs if:referenceonly
+ ?><ul class="dac-header-tabs">
+ <li><a href="<?cs var:toroot ?>reference/packages.html" class="dac-header-tab"><?cs
+ if:sdk.preview
+ ?>Android <?cs var:sdk.codename ?>
+ Preview <?cs var:sdk.preview.version ?><?cs
+ else
+ ?>Android <?cs var:sdk.version ?>
+ r<?cs var:sdk.rel.id ?><?cs
+ /if ?></a>
+ </li>
+ </ul>
+ <?cs else ?><?cs
+ #
+ # End reference only docs, now the online DAC tabs...
+ #
?><ul class="dac-header-tabs">
<li>
<a class="dac-header-tab" href="<?cs var:toroot ?>design/index.html"
@@ -80,7 +100,12 @@
es-lang="Distribuir">Distribute</a>
</li>
</ul><?cs
- /if ?>
+ /if ?><?cs
+ #
+ # End if/else reference only docs
+ #
+ ?><?cs
+ /if ?><?cs # end if/else ndk ?>
<?cs if:ndk ?><a class="dac-header-console-btn" href="http://developer.android.com">
Back to Android Developers
@@ -92,7 +117,9 @@
# ADD SEARCH AND MENU ?><?cs
if:!ndk ?><?cs
- call:header_search_widget() ?><?cs
+ if:!referenceonly ?><?cs
+ call:header_search_widget() ?><?cs
+ /if ?><?cs
/if ?>
</div><!-- end header-wrap.wrap -->
</div><!-- end header -->
@@ -147,8 +174,9 @@
<div class="dac-nav-dimmer" data-dac-toggle-nav></div>
<div class="dac-nav-sidebar" data-swap data-dynamic="false" data-transition-speed="300" data-dac-nav>
- <div data-swap-container>
+ <div <?cs if:!referenceonly ?>data-swap-container<?cs /if ?>>
<?cs call:custom_left_nav() ?>
+ <?cs if:!referenceonly ?>
<ul id="dac-main-navigation" class="dac-nav-list dac-swap-section dac-left dac-no-anim">
<li class="dac-nav-item home">
<a class="dac-nav-link" href="<?cs var:toroot ?>index.html">Home</a>
@@ -265,6 +293,7 @@
<a class="dac-nav-link" href="<?cs var:toroot ?>preview/index.html">Preview</a>
</li>-->
</ul>
+ <?cs /if ?><?cs # end if referenceonly ?>
</div>
</div>
</nav>
diff --git a/tools/droiddoc/templates-sdk-dev/customizations.cs b/tools/droiddoc/templates-sdk-dev/customizations.cs
index a747d3f..0b938ac 100644
--- a/tools/droiddoc/templates-sdk-dev/customizations.cs
+++ b/tools/droiddoc/templates-sdk-dev/customizations.cs
@@ -151,10 +151,14 @@
def:custom_left_nav() ?>
<?cs if:(!fullpage && !nonavpage) || forcelocalnav ?>
+ <?cs if:!referenceonly ?>
<a class="dac-nav-back-button dac-swap-section dac-up dac-no-anim" data-swap-button href="javascript:;">
<i class="dac-sprite dac-nav-back"></i> <span class="dac-nav-back-title">Back</span>
</a>
- <div class="dac-nav-sub dac-swap-section dac-right dac-active" itemscope itemtype="http://schema.org/SiteNavigationElement">
+ <?cs /if ?>
+ <div class="dac-nav-sub dac-swap-section dac-right dac-active" itemscope
+ itemtype="http://schema.org/SiteNavigationElement" <?cs
+ if:referenceonly ?>style="top:0 !important;"<?cs /if ?>>
<?cs if:ndk ?>
<?cs if:guide ?>
<?cs include:"../../../../frameworks/base/docs/html/ndk/guides/guides_toc.cs" ?>
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 7cb9072..6acc69d 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -37,6 +37,7 @@
import build_image
import common
+import sparse_img
OPTIONS = common.OPTIONS
@@ -46,6 +47,19 @@
OPTIONS.replace_verity_private_key = False
OPTIONS.verity_signer_path = None
+def GetCareMap(which, imgname):
+ """Generate care_map of system (or vendor) partition"""
+
+ assert which in ("system", "vendor")
+ _, blk_device = common.GetTypeAndDevice("/" + which, OPTIONS.info_dict)
+
+ simg = sparse_img.SparseImage(imgname)
+ care_map_list = []
+ care_map_list.append(blk_device)
+ care_map_list.append(simg.care_map.to_string_raw())
+ return care_map_list
+
+
def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
"""Turn the contents of SYSTEM into a system image and store it in
output_zip."""
@@ -53,7 +67,7 @@
prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "system.img")
if os.path.exists(prebuilt_path):
print "system.img already exists in %s, no need to rebuild..." % (prefix,)
- return
+ return prebuilt_path
def output_sink(fn, data):
ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
@@ -70,6 +84,7 @@
block_list=block_list)
common.ZipWrite(output_zip, imgname, prefix + "system.img")
common.ZipWrite(output_zip, block_list, prefix + "system.map")
+ return imgname
def BuildSystem(input_dir, info_dict, block_list=None):
@@ -78,6 +93,24 @@
return CreateImage(input_dir, info_dict, "system", block_list=block_list)
+def AddSystemOther(output_zip, prefix="IMAGES/"):
+ """Turn the contents of SYSTEM_OTHER into a system_other image
+ and store it in output_zip."""
+
+ prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "system_other.img")
+ if os.path.exists(prebuilt_path):
+ print "system_other.img already exists in %s, no need to rebuild..." % (prefix,)
+ return
+
+ imgname = BuildSystemOther(OPTIONS.input_tmp, OPTIONS.info_dict)
+ common.ZipWrite(output_zip, imgname, prefix + "system_other.img")
+
+def BuildSystemOther(input_dir, info_dict):
+ """Build the (sparse) system_other image and return the name of a temp
+ file containing it."""
+ return CreateImage(input_dir, info_dict, "system_other", block_list=None)
+
+
def AddVendor(output_zip, prefix="IMAGES/"):
"""Turn the contents of VENDOR into a vendor image and store in it
output_zip."""
@@ -85,13 +118,14 @@
prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "vendor.img")
if os.path.exists(prebuilt_path):
print "vendor.img already exists in %s, no need to rebuild..." % (prefix,)
- return
+ return prebuilt_path
block_list = common.MakeTempFile(prefix="vendor-blocklist-", suffix=".map")
imgname = BuildVendor(OPTIONS.input_tmp, OPTIONS.info_dict,
block_list=block_list)
common.ZipWrite(output_zip, imgname, prefix + "vendor.img")
common.ZipWrite(output_zip, block_list, prefix + "vendor.map")
+ return imgname
def BuildVendor(input_dir, info_dict, block_list=None):
@@ -121,8 +155,9 @@
image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
fstab = info_dict["fstab"]
- if fstab:
- image_props["fs_type"] = fstab["/" + what].fs_type
+ mount_point = "/" + what
+ if fstab and mount_point in fstab:
+ image_props["fs_type"] = fstab[mount_point].fs_type
# Use a fixed timestamp (01/01/2009) when packaging the image.
# Bug: 24377993
@@ -268,6 +303,8 @@
except KeyError:
has_vendor = False
+ has_system_other = "SYSTEM_OTHER/" in input_zip.namelist()
+
OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp)
common.ZipClose(input_zip)
@@ -310,10 +347,15 @@
recovery_image.AddToZip(output_zip)
banner("system")
- AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image)
+ system_imgname = AddSystem(output_zip, recovery_img=recovery_image,
+ boot_img=boot_image)
+ vendor_imgname = None
if has_vendor:
banner("vendor")
- AddVendor(output_zip)
+ vendor_imgname = AddVendor(output_zip)
+ if has_system_other:
+ banner("system_other")
+ AddSystemOther(output_zip)
banner("userdata")
AddUserdata(output_zip)
banner("cache")
@@ -325,7 +367,19 @@
if os.path.exists(ab_partitions):
with open(ab_partitions, 'r') as f:
lines = f.readlines()
+ # For devices using A/B update, generate care_map for system and vendor
+ # partitions (if present), then write this file to target_files package.
+ care_map_list = []
for line in lines:
+ if line.strip() == "system" and OPTIONS.info_dict.get(
+ "system_verity_block_device", None) is not None:
+ assert os.path.exists(system_imgname)
+ care_map_list += GetCareMap("system", system_imgname)
+ if line.strip() == "vendor" and OPTIONS.info_dict.get(
+ "vendor_verity_block_device", None) is not None:
+ assert os.path.exists(vendor_imgname)
+ care_map_list += GetCareMap("vendor", vendor_imgname)
+
img_name = line.strip() + ".img"
img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
if os.path.exists(img_radio_path):
@@ -336,6 +390,10 @@
img_path = 'IMAGES/' + img_name
assert img_path in output_zip.namelist(), "cannot find " + img_name
+ if care_map_list:
+ file_path = "META/care_map.txt"
+ common.ZipWriteStr(output_zip, file_path, '\n'.join(care_map_list))
+
common.ZipClose(output_zip)
def main(argv):
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 66d5907..0d9aabd 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -342,19 +342,20 @@
return ctx.hexdigest()
def WriteTransfers(self, prefix):
- def WriteTransfersZero(out, to_zero):
- """Limit the number of blocks in command zero to 1024 blocks.
+ def WriteSplitTransfers(out, style, target_blocks):
+ """Limit the size of operand in command 'new' and 'zero' to 1024 blocks.
This prevents the target size of one command from being too large; and
might help to avoid fsync errors on some devices."""
- zero_blocks_limit = 1024
+ assert (style == "new" or style == "zero")
+ blocks_limit = 1024
total = 0
- while to_zero:
- zero_blocks = to_zero.first(zero_blocks_limit)
- out.append("zero %s\n" % (zero_blocks.to_string_raw(),))
- total += zero_blocks.size()
- to_zero = to_zero.subtract(zero_blocks)
+ while target_blocks:
+ blocks_to_write = target_blocks.first(blocks_limit)
+ out.append("%s %s\n" % (style, blocks_to_write.to_string_raw()))
+ total += blocks_to_write.size()
+ target_blocks = target_blocks.subtract(blocks_to_write)
return total
out = []
@@ -478,7 +479,7 @@
if xf.style == "new":
assert xf.tgt_ranges
- out.append("%s %s\n" % (xf.style, xf.tgt_ranges.to_string_raw()))
+ assert tgt_size == WriteSplitTransfers(out, xf.style, xf.tgt_ranges)
total += tgt_size
elif xf.style == "move":
assert xf.tgt_ranges
@@ -538,7 +539,7 @@
elif xf.style == "zero":
assert xf.tgt_ranges
to_zero = xf.tgt_ranges.subtract(xf.src_ranges)
- assert WriteTransfersZero(out, to_zero) == to_zero.size()
+ assert WriteSplitTransfers(out, xf.style, to_zero) == to_zero.size()
total += to_zero.size()
else:
raise ValueError("unknown transfer style '%s'\n" % xf.style)
@@ -568,7 +569,7 @@
# Zero out extended blocks as a workaround for bug 20881595.
if self.tgt.extended:
- assert (WriteTransfersZero(out, self.tgt.extended) ==
+ assert (WriteSplitTransfers(out, "zero", self.tgt.extended) ==
self.tgt.extended.size())
total += self.tgt.extended.size()
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index d78896a..a9217ee 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -406,6 +406,8 @@
build_command.extend(["-z", prop_dict["squashfs_compressor"]])
if "squashfs_compressor_opt" in prop_dict:
build_command.extend(["-zo", prop_dict["squashfs_compressor_opt"]])
+ if "squashfs_block_size" in prop_dict:
+ build_command.extend(["-b", prop_dict["squashfs_block_size"]])
if "squashfs_disable_4k_align" in prop_dict and prop_dict.get("squashfs_disable_4k_align") == "true":
build_command.extend(["-a"])
elif fs_type.startswith("f2fs"):
@@ -551,8 +553,22 @@
copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
copy_prop("system_squashfs_compressor", "squashfs_compressor")
copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
+ copy_prop("system_squashfs_block_size", "squashfs_block_size")
copy_prop("system_squashfs_disable_4k_align", "squashfs_disable_4k_align")
copy_prop("system_base_fs_file", "base_fs_file")
+ elif mount_point == "system_other":
+ # We inherit the selinux policies of /system since we contain some of its files.
+ d["mount_point"] = "system"
+ copy_prop("fs_type", "fs_type")
+ copy_prop("system_fs_type", "fs_type")
+ copy_prop("system_size", "partition_size")
+ copy_prop("system_journal_size", "journal_size")
+ copy_prop("system_verity_block_device", "verity_block_device")
+ copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
+ copy_prop("system_squashfs_compressor", "squashfs_compressor")
+ copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
+ copy_prop("system_squashfs_block_size", "squashfs_block_size")
+ copy_prop("system_base_fs_file", "base_fs_file")
elif mount_point == "data":
# Copy the generic fs type first, override with specific one if available.
copy_prop("fs_type", "fs_type")
@@ -569,6 +585,7 @@
copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
copy_prop("vendor_squashfs_compressor", "squashfs_compressor")
copy_prop("vendor_squashfs_compressor_opt", "squashfs_compressor_opt")
+ copy_prop("vendor_squashfs_block_size", "squashfs_block_size")
copy_prop("vendor_squashfs_disable_4k_align", "squashfs_disable_4k_align")
copy_prop("vendor_base_fs_file", "base_fs_file")
elif mount_point == "oem":
@@ -614,6 +631,8 @@
mount_point = ""
if image_filename == "system.img":
mount_point = "system"
+ elif image_filename == "system_other.img":
+ mount_point = "system_other"
elif image_filename == "userdata.img":
mount_point = "data"
elif image_filename == "cache.img":
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index 5c541ab..3048488 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -245,7 +245,7 @@
fullname = os.path.join(dirpath, fn)
displayname = fullname[len(d)+1:]
apk = APK(fullname, displayname)
- self.apks[apk.package] = apk
+ self.apks[apk.filename] = apk
self.apks_by_basename[os.path.basename(apk.filename)] = apk
self.max_pkg_len = max(self.max_pkg_len, len(apk.package))
@@ -316,8 +316,7 @@
self.max_pkg_len, apk.package,
apk.shared_uid)
else:
- print " %-*s %-*s" % (self.max_fn_len, apk.filename,
- self.max_pkg_len, apk.package)
+ print " %-*s %s" % (self.max_fn_len, apk.filename, apk.package)
print
def CompareWith(self, other):
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 422ba43..d7f8b16 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -259,11 +259,18 @@
makeint("boot_size")
makeint("fstab_version")
- if d.get("no_recovery", False) == "true":
- d["fstab"] = None
- else:
+ system_root_image = d.get("system_root_image", None) == "true"
+ if d.get("no_recovery", None) != "true":
+ recovery_fstab_path = "RECOVERY/RAMDISK/etc/recovery.fstab"
d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"],
- d.get("system_root_image", False))
+ recovery_fstab_path, system_root_image)
+ elif d.get("recovery_as_boot", None) == "true":
+ recovery_fstab_path = "BOOT/RAMDISK/etc/recovery.fstab"
+ d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"],
+ recovery_fstab_path, system_root_image)
+ else:
+ d["fstab"] = None
+
d["build.prop"] = LoadBuildProp(read_helper)
return d
@@ -286,7 +293,8 @@
d[name] = value
return d
-def LoadRecoveryFSTab(read_helper, fstab_version, system_root_image=False):
+def LoadRecoveryFSTab(read_helper, fstab_version, recovery_fstab_path,
+ system_root_image=False):
class Partition(object):
def __init__(self, mount_point, fs_type, device, length, device2, context):
self.mount_point = mount_point
@@ -297,9 +305,9 @@
self.context = context
try:
- data = read_helper("RECOVERY/RAMDISK/etc/recovery.fstab")
+ data = read_helper(recovery_fstab_path)
except KeyError:
- print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab"
+ print "Warning: could not find {}".format(recovery_fstab_path)
data = ""
if fstab_version == 1:
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index b69ddac..d3d4974 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -113,6 +113,17 @@
Generate a log file that shows the differences in the source and target
builds for an incremental package. This option is only meaningful when
-i is specified.
+
+ --payload_signer <signer>
+ Specify the signer when signing the payload and metadata for A/B OTAs.
+ By default (i.e. without this flag), it calls 'openssl pkeyutl' to sign
+ with the package private key. If the private key cannot be accessed
+ directly, a payload signer that knows how to do that should be specified.
+ The signer will be supplied with "-inkey <path_to_key>",
+ "-in <input_file>" and "-out <output_file>" parameters.
+
+ --payload_signer_args <args>
+ Specify the arguments needed for payload signer.
"""
import sys
@@ -124,6 +135,7 @@
import multiprocessing
import os
import subprocess
+import shlex
import tempfile
import zipfile
@@ -160,6 +172,8 @@
OPTIONS.stash_threshold = 0.8
OPTIONS.gen_verify = False
OPTIONS.log_diff = None
+OPTIONS.payload_signer = None
+OPTIONS.payload_signer_args = []
def MostPopularKey(d, default):
"""Given a dict, return the key corresponding to the largest
@@ -859,15 +873,17 @@
int(i) for i in
OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
- # Check first block of system partition for remount R/W only if
- # disk type is ext4
- system_partition = OPTIONS.source_info_dict["fstab"]["/system"]
- check_first_block = system_partition.fs_type == "ext4"
+ # Check the first block of the source system partition for remount R/W only
+ # if the filesystem is ext4.
+ system_src_partition = OPTIONS.source_info_dict["fstab"]["/system"]
+ check_first_block = system_src_partition.fs_type == "ext4"
# Disable using imgdiff for squashfs. 'imgdiff -z' expects input files to be
# in zip formats. However with squashfs, a) all files are compressed in LZ4;
# b) the blocks listed in block map may not contain all the bytes for a given
# file (because they're rounded to be 4K-aligned).
- disable_imgdiff = system_partition.fs_type == "squashfs"
+ system_tgt_partition = OPTIONS.target_info_dict["fstab"]["/system"]
+ disable_imgdiff = (system_src_partition.fs_type == "squashfs" or
+ system_tgt_partition.fs_type == "squashfs")
system_diff = common.BlockDifference("system", system_tgt, system_src,
check_first_block,
version=blockimgdiff_version,
@@ -1163,17 +1179,19 @@
"default_system_dev_certificate",
"build/target/product/security/testkey")
- # A/B updater expects key in RSA format.
- cmd = ["openssl", "pkcs8",
- "-in", OPTIONS.package_key + OPTIONS.private_key_suffix,
- "-inform", "DER", "-nocrypt"]
- rsa_key = common.MakeTempFile(prefix="key-", suffix=".key")
- cmd.extend(["-out", rsa_key])
- p1 = common.Run(cmd, stdout=subprocess.PIPE)
- p1.wait()
- assert p1.returncode == 0, "openssl pkcs8 failed"
+ # A/B updater expects a signing key in RSA format. Gets the key ready for
+ # later use in step 3, unless a payload_signer has been specified.
+ if OPTIONS.payload_signer is None:
+ cmd = ["openssl", "pkcs8",
+ "-in", OPTIONS.package_key + OPTIONS.private_key_suffix,
+ "-inform", "DER", "-nocrypt"]
+ rsa_key = common.MakeTempFile(prefix="key-", suffix=".key")
+ cmd.extend(["-out", rsa_key])
+ p1 = common.Run(cmd, stdout=subprocess.PIPE)
+ p1.wait()
+ assert p1.returncode == 0, "openssl pkcs8 failed"
- # Stage the output zip package for signing.
+ # Stage the output zip package for package signing.
temp_zip_file = tempfile.NamedTemporaryFile()
output_zip = zipfile.ZipFile(temp_zip_file, "w",
compression=zipfile.ZIP_DEFLATED)
@@ -1234,21 +1252,30 @@
signed_metadata_sig_file = common.MakeTempFile(prefix="signed-sig-",
suffix=".bin")
# 3a. Sign the payload hash.
- cmd = ["openssl", "pkeyutl", "-sign",
- "-inkey", rsa_key,
- "-pkeyopt", "digest:sha256",
- "-in", payload_sig_file,
- "-out", signed_payload_sig_file]
+ if OPTIONS.payload_signer is not None:
+ cmd = [OPTIONS.payload_signer]
+ cmd.extend(OPTIONS.payload_signer_args)
+ else:
+ cmd = ["openssl", "pkeyutl", "-sign",
+ "-inkey", rsa_key,
+ "-pkeyopt", "digest:sha256"]
+ cmd.extend(["-in", payload_sig_file,
+ "-out", signed_payload_sig_file])
+
p1 = common.Run(cmd, stdout=subprocess.PIPE)
p1.wait()
assert p1.returncode == 0, "openssl sign payload failed"
# 3b. Sign the metadata hash.
- cmd = ["openssl", "pkeyutl", "-sign",
- "-inkey", rsa_key,
- "-pkeyopt", "digest:sha256",
- "-in", metadata_sig_file,
- "-out", signed_metadata_sig_file]
+ if OPTIONS.payload_signer is not None:
+ cmd = [OPTIONS.payload_signer]
+ cmd.extend(OPTIONS.payload_signer_args)
+ else:
+ cmd = ["openssl", "pkeyutl", "-sign",
+ "-inkey", rsa_key,
+ "-pkeyopt", "digest:sha256"]
+ cmd.extend(["-in", metadata_sig_file,
+ "-out", signed_metadata_sig_file])
p1 = common.Run(cmd, stdout=subprocess.PIPE)
p1.wait()
assert p1.returncode == 0, "openssl sign metadata failed"
@@ -1276,12 +1303,30 @@
p1.wait()
assert p1.returncode == 0, "brillo_update_payload properties failed"
+ if OPTIONS.wipe_user_data:
+ with open(properties_file, "a") as f:
+ f.write("POWERWASH=1\n")
+ metadata["ota-wipe"] = "yes"
+
# Add the signed payload file and properties into the zip.
common.ZipWrite(output_zip, properties_file, arcname="payload_properties.txt")
common.ZipWrite(output_zip, signed_payload_file, arcname="payload.bin",
compress_type=zipfile.ZIP_STORED)
WriteMetadata(metadata, output_zip)
+ # If dm-verity is supported for the device, copy contents of care_map
+ # into A/B OTA package.
+ if OPTIONS.info_dict.get("verity") == "true":
+ target_zip = zipfile.ZipFile(target_file, "r")
+ care_map_path = "META/care_map.txt"
+ namelist = target_zip.namelist()
+ if care_map_path in namelist:
+ care_map_data = target_zip.read(care_map_path)
+ common.ZipWriteStr(output_zip, "care_map.txt", care_map_data)
+ else:
+ print "Warning: cannot find care map file in target_file package"
+ common.ZipClose(target_zip)
+
# Sign the whole package to comply with the Android OTA package format.
common.ZipClose(output_zip)
SignOutput(temp_zip_file.name, output_file)
@@ -1900,6 +1945,10 @@
OPTIONS.gen_verify = True
elif o == "--log_diff":
OPTIONS.log_diff = a
+ elif o == "--payload_signer":
+ OPTIONS.payload_signer = a
+ elif o == "--payload_signer_args":
+ OPTIONS.payload_signer_args = shlex.split(a)
else:
return False
return True
@@ -1929,6 +1978,8 @@
"stash_threshold=",
"gen_verify",
"log_diff=",
+ "payload_signer=",
+ "payload_signer_args=",
], extra_option_handler=option_handler)
if len(args) != 2:
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index f758ae0..0f20f82 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -51,10 +51,12 @@
in which they appear on the command line.
-o (--replace_ota_keys)
- Replace the certificate (public key) used by OTA package
- verification with the one specified in the input target_files
- zip (in the META/otakeys.txt file). Key remapping (-k and -d)
- is performed on this key.
+ Replace the certificate (public key) used by OTA package verification
+ with the ones specified in the input target_files zip (in the
+ META/otakeys.txt file). Key remapping (-k and -d) is performed on the
+ keys. For A/B devices, the payload verification key will be replaced
+ as well. If there're multiple OTA keys, only the first one will be used
+ for payload verification.
-t (--tag_changes) <+tag>,<-tag>,...
Comma-separated list of changes to make to the set of tags (in
@@ -63,6 +65,19 @@
removed. Changes are processed in the order they appear.
Default value is "-test-keys,-dev-keys,+release-keys".
+ --replace_verity_private_key <key>
+ Replace the private key used for verity signing. It expects a filename
+ WITHOUT the extension (e.g. verity_key).
+
+ --replace_verity_public_key <key>
+ Replace the certificate (public key) used for verity verification. The
+ key file replaces the one at BOOT/RAMDISK/verity_key (or ROOT/verity_key
+ for devices using system_root_image). It expects the key filename WITH
+ the extension (e.g. verity_key.pub).
+
+ --replace_verity_keyid <path_to_X509_PEM_cert_file>
+ Replace the veritykeyid in BOOT/cmdline of input_target_file_zip
+ with keyid of the cert pointed by <path_to_X509_PEM_cert_file>.
"""
import sys
@@ -92,6 +107,7 @@
OPTIONS.replace_ota_keys = False
OPTIONS.replace_verity_public_key = False
OPTIONS.replace_verity_private_key = False
+OPTIONS.replace_verity_keyid = False
OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys")
def GetApkCerts(tf_zip):
@@ -171,7 +187,9 @@
for i in input_tf_zip.infolist()
if i.filename.endswith('.apk')])
rebuild_recovery = False
+ system_root_image = misc_info.get("system_root_image") == "true"
+ # tmpdir will only be used to regenerate the recovery-from-boot patch.
tmpdir = tempfile.mkdtemp()
def write_to_temp(fn, attr, data):
fn = os.path.join(tmpdir, fn)
@@ -196,25 +214,6 @@
data = input_tf_zip.read(info.filename)
out_info = copy.copy(info)
- # Replace keys if requested.
- if (info.filename == "META/misc_info.txt" and
- OPTIONS.replace_verity_private_key):
- ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info,
- OPTIONS.replace_verity_private_key[1])
- elif (info.filename in ("BOOT/RAMDISK/verity_key",
- "BOOT/verity_key") and
- OPTIONS.replace_verity_public_key):
- new_data = ReplaceVerityPublicKey(output_tf_zip, info.filename,
- OPTIONS.replace_verity_public_key[1])
- write_to_temp(info.filename, info.external_attr, new_data)
- # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch.
- elif (info.filename.startswith("BOOT/") or
- info.filename.startswith("RECOVERY/") or
- info.filename.startswith("META/") or
- info.filename.startswith("ROOT/") or
- info.filename == "SYSTEM/etc/recovery-resource.dat"):
- write_to_temp(info.filename, info.external_attr, data)
-
# Sign APKs.
if info.filename.endswith(".apk"):
name = os.path.basename(info.filename)
@@ -228,44 +227,113 @@
# an APK we're not supposed to sign.
print "NOT signing: %s" % (name,)
common.ZipWriteStr(output_tf_zip, out_info, data)
+
+ # System properties.
elif info.filename in ("SYSTEM/build.prop",
"VENDOR/build.prop",
"BOOT/RAMDISK/default.prop",
+ "ROOT/default.prop",
"RECOVERY/RAMDISK/default.prop"):
print "rewriting %s:" % (info.filename,)
new_data = RewriteProps(data, misc_info)
common.ZipWriteStr(output_tf_zip, out_info, new_data)
if info.filename in ("BOOT/RAMDISK/default.prop",
+ "ROOT/default.prop",
"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)
common.ZipWriteStr(output_tf_zip, out_info, new_data)
+
+ # Trigger a rebuild of the recovery patch if needed.
elif info.filename in ("SYSTEM/recovery-from-boot.p",
"SYSTEM/etc/recovery.img",
"SYSTEM/bin/install-recovery.sh"):
rebuild_recovery = True
+
+ # Don't copy OTA keys if we're replacing them.
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
+ info.filename in (
+ "BOOT/RAMDISK/res/keys",
+ "BOOT/RAMDISK/etc/update_engine/update-payload-key.pub.pem",
+ "RECOVERY/RAMDISK/res/keys",
+ "SYSTEM/etc/security/otacerts.zip",
+ "SYSTEM/etc/update_engine/update-payload-key.pub.pem")):
pass
+
+ # Skip META/misc_info.txt if we will replace the verity private key later.
elif (OPTIONS.replace_verity_private_key and
info.filename == "META/misc_info.txt"):
pass
+
+ # Skip verity public key if we will replace it.
elif (OPTIONS.replace_verity_public_key and
info.filename in ("BOOT/RAMDISK/verity_key",
- "BOOT/verity_key")):
+ "ROOT/verity_key")):
pass
+
+ # Skip verity keyid (for system_root_image use) if we will replace it.
+ elif (OPTIONS.replace_verity_keyid and
+ info.filename == "BOOT/cmdline"):
+ pass
+
+ # Skip the care_map as we will regenerate the system/vendor images.
+ elif (info.filename == "META/care_map.txt"):
+ pass
+
+ # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch. This case
+ # must come AFTER other matching rules.
+ elif (info.filename.startswith("BOOT/") or
+ info.filename.startswith("RECOVERY/") or
+ info.filename.startswith("META/") or
+ info.filename.startswith("ROOT/") or
+ info.filename == "SYSTEM/etc/recovery-resource.dat"):
+ write_to_temp(info.filename, info.external_attr, data)
+ common.ZipWriteStr(output_tf_zip, out_info, data)
+
+ # A non-APK file; copy it verbatim.
else:
- # a non-APK file; copy it verbatim
common.ZipWriteStr(output_tf_zip, 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", 0o755 << 16, new_recovery_keys)
+ if system_root_image:
+ recovery_keys_location = "BOOT/RAMDISK/res/keys"
+ else:
+ recovery_keys_location = "RECOVERY/RAMDISK/res/keys"
+ # The "new_recovery_keys" has been already written into the output_tf_zip
+ # while calling ReplaceOtaKeys(). We're just putting the same copy to
+ # tmpdir in case we need to regenerate the recovery-from-boot patch.
+ write_to_temp(recovery_keys_location, 0o755 << 16, new_recovery_keys)
+
+ # Replace the keyid string in META/misc_info.txt.
+ if OPTIONS.replace_verity_private_key:
+ ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info,
+ OPTIONS.replace_verity_private_key[1])
+
+ if OPTIONS.replace_verity_public_key:
+ if system_root_image:
+ dest = "ROOT/verity_key"
+ else:
+ dest = "BOOT/RAMDISK/verity_key"
+ # We are replacing the one in boot image only, since the one under
+ # recovery won't ever be needed.
+ new_data = ReplaceVerityPublicKey(
+ output_tf_zip, dest, OPTIONS.replace_verity_public_key[1])
+ write_to_temp(dest, 0o755 << 16, new_data)
+
+ # Replace the keyid string in BOOT/cmdline.
+ if OPTIONS.replace_verity_keyid:
+ new_cmdline = ReplaceVerityKeyId(input_tf_zip, output_tf_zip,
+ OPTIONS.replace_verity_keyid[1])
+ # Writing the new cmdline to tmpdir is redundant as the bootimage
+ # gets build in the add_image_to_target_files and rebuild_recovery
+ # is not exercised while building the boot image for the A/B
+ # path
+ write_to_temp("BOOT/cmdline", 0o755 << 16, new_cmdline)
if rebuild_recovery:
recovery_img = common.GetBootableImage(
@@ -398,7 +466,8 @@
"build/target/product/security/testkey")
mapped_keys.append(
OPTIONS.key_map.get(devkey, devkey) + ".x509.pem")
- print "META/otakeys.txt has no keys; using", mapped_keys[0]
+ print("META/otakeys.txt has no keys; using %s for OTA package"
+ " verification." % (mapped_keys[0],))
# recovery uses a version of the key that has been slightly
# predigested (by DumpPublicKey.java) and put in res/keys.
@@ -411,8 +480,13 @@
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",
- new_recovery_keys)
+
+ # system_root_image puts the recovery keys at BOOT/RAMDISK.
+ if misc_info.get("system_root_image") == "true":
+ recovery_keys_location = "BOOT/RAMDISK/res/keys"
+ else:
+ recovery_keys_location = "RECOVERY/RAMDISK/res/keys"
+ common.ZipWriteStr(output_tf_zip, recovery_keys_location, new_recovery_keys)
# SystemUpdateActivity uses the x509.pem version of the keys, but
# put into a zipfile system/etc/security/otacerts.zip.
@@ -426,8 +500,31 @@
common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip",
temp_file.getvalue())
+ # For A/B devices, update the payload verification key.
+ if misc_info.get("ab_update") == "true":
+ # Unlike otacerts.zip that may contain multiple keys, we can only specify
+ # ONE payload verification key.
+ if len(mapped_keys) > 1:
+ print("\n WARNING: Found more than one OTA keys; Using the first one"
+ " as payload verification key.\n\n")
+
+ print "Using %s for payload verification." % (mapped_keys[0],)
+ cmd = common.Run(
+ ["openssl", "x509", "-pubkey", "-noout", "-in", mapped_keys[0]],
+ stdout=subprocess.PIPE)
+ pubkey, _ = cmd.communicate()
+ common.ZipWriteStr(
+ output_tf_zip,
+ "SYSTEM/etc/update_engine/update-payload-key.pub.pem",
+ pubkey)
+ common.ZipWriteStr(
+ output_tf_zip,
+ "BOOT/RAMDISK/etc/update_engine/update-payload-key.pub.pem",
+ pubkey)
+
return new_recovery_keys
+
def ReplaceVerityPublicKey(targetfile_zip, filename, key_path):
print "Replacing verity public key with %s" % key_path
with open(key_path) as f:
@@ -435,6 +532,7 @@
common.ZipWriteStr(targetfile_zip, filename, data)
return data
+
def ReplaceVerityPrivateKey(targetfile_input_zip, targetfile_output_zip,
misc_info, key_path):
print "Replacing verity private key with %s" % key_path
@@ -444,6 +542,32 @@
common.ZipWriteStr(targetfile_output_zip, "META/misc_info.txt", new_misc_info)
misc_info["verity_key"] = key_path
+
+def ReplaceVerityKeyId(targetfile_input_zip, targetfile_output_zip, keypath):
+ in_cmdline = targetfile_input_zip.read("BOOT/cmdline")
+ # copy in_cmdline to output_zip if veritykeyid is not present in in_cmdline
+ if "veritykeyid" not in in_cmdline:
+ common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", in_cmdline)
+ return in_cmdline
+ out_cmdline = []
+ for param in in_cmdline.split():
+ if "veritykeyid" in param:
+ # extract keyid using openssl command
+ p = common.Run(["openssl", "x509", "-in", keypath, "-text"], stdout=subprocess.PIPE)
+ keyid, stderr = p.communicate()
+ keyid = re.search(r'keyid:([0-9a-fA-F:]*)', keyid).group(1).replace(':', '').lower()
+ print "Replacing verity keyid with %s error=%s" % (keyid, stderr)
+ out_cmdline.append("veritykeyid=id:%s" % (keyid,))
+ else:
+ out_cmdline.append(param)
+
+ out_cmdline = ' '.join(out_cmdline)
+ out_cmdline = out_cmdline.strip()
+ print "out_cmdline %s" % (out_cmdline)
+ common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", out_cmdline)
+ return out_cmdline
+
+
def BuildKeyMap(misc_info, key_mapping_options):
for s, d in key_mapping_options:
if s is None: # -d option
@@ -541,6 +665,8 @@
OPTIONS.replace_verity_public_key = (True, a)
elif o == "--replace_verity_private_key":
OPTIONS.replace_verity_private_key = (True, a)
+ elif o == "--replace_verity_keyid":
+ OPTIONS.replace_verity_keyid = (True, a)
else:
return False
return True
@@ -553,7 +679,8 @@
"replace_ota_keys",
"tag_changes=",
"replace_verity_public_key=",
- "replace_verity_private_key="],
+ "replace_verity_private_key=",
+ "replace_verity_keyid="],
extra_option_handler=option_handler)
if len(args) != 2: