diff options
291 files changed, 10721 insertions, 27592 deletions
diff --git a/Changes.md b/Changes.md index 2720a0f402..84c8d950fc 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,115 @@ # Build System Changes for Android.mk Writers +## `LOCAL_REQUIRED_MODULES` requires listed modules to exist {#BUILD_BROKEN_MISSING_REQUIRED_MODULES} + +Modules listed in `LOCAL_REQUIRED_MODULES`, `LOCAL_HOST_REQUIRED_MODULES` and +`LOCAL_TARGET_REQUIRED_MODULES` need to exist unless `ALLOW_MISSING_DEPENDENCIES` +is set. + +To temporarily relax missing required modules check, use: + +`BUILD_BROKEN_MISSING_REQUIRED_MODULES := true` + +## Changes in system properties settings + +### Product variables + +System properties for each of the partition is supposed to be set via following +product config variables. + +For system partititon, + +* `PRODUCT_SYSTEM_PROPERITES` +* `PRODUCT_SYSTEM_DEFAULT_PROPERTIES` is highly discouraged. Will be deprecated. + +For vendor partition, + +* `PRODUCT_VENDOR_PROPERTIES` +* `PRODUCT_PROPERTY_OVERRIDES` is highly discouraged. Will be deprecated. +* `PRODUCT_DEFAULT_PROPERTY_OVERRIDES` is also discouraged. Will be deprecated. + +For odm partition, + +* `PRODUCT_ODM_PROPERTIES` + +For system_ext partition, + +* `PRODUCT_SYSTEM_EXT_PROPERTIES` + +For product partition, + +* `PRODUCT_PRODUCT_PROPERTIES` + +### Duplication is not allowed within a partition + +For each partition, having multiple sysprop assignments for the same name is +prohibited. For example, the following will now trigger an error: + +`PRODUCT_VENDOR_PROPERTIES += foo=true foo=false` + +Having duplication across partitions are still allowed. So, the following is +not an error: + +`PRODUCT_VENDOR_PROPERTIES += foo=true` +`PRODUCT_SYSTEM_PROPERTIES += foo=false` + +In that case, the final value is determined at runtime. The precedence is + +* product +* odm +* vendor +* system_ext +* system + +So, `foo` becomes `true` because vendor has higher priority than system. + +To temporarily turn the build-time restriction off, use + +`BUILD_BROKEN_DUP_SYSPROP := true` + +### Optional assignments + +System properties can now be set as optional using the new syntax: + +`name ?= value` + +Then the system property named `name` gets the value `value` only when there +is no other non-optional assignments having the same name. For example, the +following is allowed and `foo` gets `true` + +`PRODUCT_VENDOR_PROPERTIES += foo=true foo?=false` + +Note that the order between the optional and the non-optional assignments +doesn't matter. The following gives the same result as above. + +`PRODUCT_VENDOR_PROPERTIES += foo?=false foo=true` + +Optional assignments can be duplicated and in that case their order matters. +Specifically, the last one eclipses others. + +`PRODUCT_VENDOR_PROPERTIES += foo?=apple foo?=banana foo?=mango` + +With above, `foo` becomes `mango` since its the last one. + +Note that this behavior is different from the previous behavior of preferring +the first one. To go back to the original behavior for compatability reason, +use: + +`BUILD_BROKEN_DUP_SYSPROP := true` + +## ELF prebuilts in `PRODUCT_COPY_FILES` {#BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES} + +ELF prebuilts in `PRODUCT_COPY_FILES` that are installed into these paths are an +error: + +* `<partition>/bin/*` +* `<partition>/lib/*` +* `<partition>/lib64/*` + +Define prebuilt modules and add them to `PRODUCT_PACKAGES` instead. +To temporarily relax this check and restore the behavior prior to this change, +set `BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES := true` in `BoardConfig.mk`. + ## COPY_HEADERS usage now produces warnings {#copy_headers} We've considered `BUILD_COPY_HEADERS`/`LOCAL_COPY_HEADERS` to be deprecated for diff --git a/CleanSpec.mk b/CleanSpec.mk index 3fc7cbcf02..67aca7c81a 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -748,6 +748,9 @@ $(call add-clean-step, rm -rf $(HOST_OUT)/framework/vts10-tradefed.jar) $(call add-clean-step, rm -rf $(HOST_OUT)/vts/*) $(call add-clean-step, rm -rf $(HOST_OUT)/framework/vts-tradefed.jar) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/default.prop) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/prop.default) + # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/Deprecation.md b/Deprecation.md index 2f936e3542..74b54fadd5 100644 --- a/Deprecation.md +++ b/Deprecation.md @@ -14,21 +14,21 @@ have any problems converting, please contact us via: | Module type | State | | -------------------------------- | --------- | -| `BUILD_AUX_EXECUTABLE` | Error | -| `BUILD_AUX_STATIC_LIBRARY` | Error | +| `BUILD_AUX_EXECUTABLE` | Obsolete | +| `BUILD_AUX_STATIC_LIBRARY` | Obsolete | | `BUILD_COPY_HEADERS` | Error | | `BUILD_HOST_EXECUTABLE` | Error | -| `BUILD_HOST_FUZZ_TEST` | Error | -| `BUILD_HOST_NATIVE_TEST` | Error | +| `BUILD_HOST_FUZZ_TEST` | Obsolete | +| `BUILD_HOST_NATIVE_TEST` | Obsolete | | `BUILD_HOST_SHARED_LIBRARY` | Error | -| `BUILD_HOST_SHARED_TEST_LIBRARY` | Error | +| `BUILD_HOST_SHARED_TEST_LIBRARY` | Obsolete | | `BUILD_HOST_STATIC_LIBRARY` | Error | -| `BUILD_HOST_STATIC_TEST_LIBRARY` | Error | -| `BUILD_HOST_TEST_CONFIG` | Error | -| `BUILD_NATIVE_BENCHMARK` | Error | -| `BUILD_SHARED_TEST_LIBRARY` | Error | -| `BUILD_STATIC_TEST_LIBRARY` | Error | -| `BUILD_TARGET_TEST_CONFIG` | Error | +| `BUILD_HOST_STATIC_TEST_LIBRARY` | Obsolete | +| `BUILD_HOST_TEST_CONFIG` | Obsolete | +| `BUILD_NATIVE_BENCHMARK` | Obsolete | +| `BUILD_SHARED_TEST_LIBRARY` | Obsolete | +| `BUILD_STATIC_TEST_LIBRARY` | Obsolete | +| `BUILD_TARGET_TEST_CONFIG` | Obsolete | | `BUILD_*` | Available | ## Module Type Deprecation Process diff --git a/common/strings.mk b/common/strings.mk index ba20e272c0..e560bf06ea 100644 --- a/common/strings.mk +++ b/common/strings.mk @@ -28,7 +28,7 @@ to-lower=$(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f ########################################################### to-upper=$(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$1)))))))))))))))))))))))))) -# Sanity-check to-lower and to-upper +# Test to-lower and to-upper lower := abcdefghijklmnopqrstuvwxyz-_ upper := ABCDEFGHIJKLMNOPQRSTUVWXYZ-_ diff --git a/core/Makefile b/core/Makefile index 98203d12c2..fcc89b7f9f 100644 --- a/core/Makefile +++ b/core/Makefile @@ -39,6 +39,14 @@ $(if $(filter true,$(BUILD_BROKEN_VINTF_PRODUCT_COPY_FILES)),, \ use ODM_MANIFEST_FILES / vintf_fragments instead!)) \ ) endef + +check_elf_prebuilt_product_copy_files := true +ifneq (,$(filter true,$(BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES))) +check_elf_prebuilt_product_copy_files := +endif +check_elf_prebuilt_product_copy_files_hint := \ + found ELF prebuilt in PRODUCT_COPY_FILES, use cc_prebuilt_binary / cc_prebuilt_library_shared instead. + # filter out the duplicate <source file>:<dest file> pairs. unique_product_copy_files_pairs := $(foreach cf,$(PRODUCT_COPY_FILES), \ @@ -59,7 +67,10 @@ $(foreach cf,$(unique_product_copy_files_pairs), \ $(eval $(call copy-and-uncompress-dexs,$(_src),$(_fulldest))), \ $(if $(filter init%rc,$(notdir $(_dest)))$(filter %/etc/init,$(dir $(_dest))),\ $(eval $(call copy-init-script-file-checked,$(_src),$(_fulldest))),\ - $(eval $(call copy-one-file,$(_src),$(_fulldest)))))) \ + $(if $(and $(filter true,$(check_elf_prebuilt_product_copy_files)), \ + $(filter bin lib lib64,$(subst /,$(space),$(_dest)))), \ + $(eval $(call copy-non-elf-file-checked,$(_src),$(_fulldest),$(check_elf_prebuilt_product_copy_files_hint))), \ + $(eval $(call copy-one-file,$(_src),$(_fulldest))))))) \ $(eval unique_product_copy_files_destinations += $(_dest)))) # Dump a list of overriden (and ignored PRODUCT_COPY_FILES entries) @@ -119,7 +130,7 @@ $(file >$(PRODUCT_OUT)/.copied_headers_list,$(TARGET_OUT_HEADERS) $(ALL_COPIED_H # ----------------------------------------------------------------- # docs/index.html -ifeq (,$(TARGET_BUILD_APPS)) +ifeq (,$(TARGET_BUILD_UNBUNDLED)) gen := $(OUT_DOCS)/index.html ALL_DOCS += $(gen) $(gen): frameworks/base/docs/docs-redirect-index.html @@ -150,341 +161,6 @@ endif $(call dist-for-goals,sdk,$(API_FINGERPRINT)) -# ----------------------------------------------------------------- -# property_overrides_split_enabled -property_overrides_split_enabled := -ifeq ($(BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED), true) - property_overrides_split_enabled := true -endif - -# ----------------------------------------------------------------- -# FINAL_VENDOR_DEFAULT_PROPERTIES will be installed in vendor/default.prop if -# property_overrides_split_enabled is true. Otherwise it will be installed in -# ROOT/default.prop. -ifdef BOARD_VNDK_VERSION - ifeq ($(BOARD_VNDK_VERSION),current) - FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION) - else - FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(BOARD_VNDK_VERSION) - endif - ifdef BOARD_VNDK_RUNTIME_DISABLE - FINAL_VENDOR_DEFAULT_PROPERTIES += ro.vndk.lite=true - endif -else - FINAL_VENDOR_DEFAULT_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION) - FINAL_VENDOR_DEFAULT_PROPERTIES += ro.vndk.lite=true -endif -FINAL_VENDOR_DEFAULT_PROPERTIES += \ - $(call collapse-pairs, $(PRODUCT_DEFAULT_PROPERTY_OVERRIDES)) - -# Add cpu properties for bionic and ART. -FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.arch=$(TARGET_ARCH) -FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT_RUNTIME) -FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.2nd_arch=$(TARGET_2ND_ARCH) -FINAL_VENDOR_DEFAULT_PROPERTIES += ro.bionic.2nd_cpu_variant=$(TARGET_2ND_CPU_VARIANT_RUNTIME) - -FINAL_VENDOR_DEFAULT_PROPERTIES += persist.sys.dalvik.vm.lib.2=libart.so -FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).variant=$(DEX2OAT_TARGET_CPU_VARIANT_RUNTIME) -ifneq ($(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),) - FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) -endif - -ifdef TARGET_2ND_ARCH - FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).variant=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT_RUNTIME) - ifneq ($($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),) - FINAL_VENDOR_DEFAULT_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).features=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) - endif -endif - -# Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger -# mode (via libminui). -ifdef TARGET_RECOVERY_DEFAULT_ROTATION -FINAL_VENDOR_DEFAULT_PROPERTIES += \ - ro.minui.default_rotation=$(TARGET_RECOVERY_DEFAULT_ROTATION) -endif -ifdef TARGET_RECOVERY_OVERSCAN_PERCENT -FINAL_VENDOR_DEFAULT_PROPERTIES += \ - ro.minui.overscan_percent=$(TARGET_RECOVERY_OVERSCAN_PERCENT) -endif -ifdef TARGET_RECOVERY_PIXEL_FORMAT -FINAL_VENDOR_DEFAULT_PROPERTIES += \ - ro.minui.pixel_format=$(TARGET_RECOVERY_PIXEL_FORMAT) -endif -FINAL_VENDOR_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \ - $(FINAL_VENDOR_DEFAULT_PROPERTIES),=) - -# ----------------------------------------------------------------- -# prop.default - -BUILDINFO_SH := build/make/tools/buildinfo.sh -BUILDINFO_COMMON_SH := build/make/tools/buildinfo_common.sh -POST_PROCESS_PROPS :=$= build/make/tools/post_process_props.py - -# Generates a set of sysprops common to all partitions to a file. -# $(1): Partition name -# $(2): Output file name -define generate-common-build-props - PRODUCT_BRAND="$(PRODUCT_BRAND)" \ - PRODUCT_DEVICE="$(TARGET_DEVICE)" \ - PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \ - PRODUCT_MODEL="$(PRODUCT_MODEL)" \ - PRODUCT_NAME="$(TARGET_PRODUCT)" \ - $(call generate-common-build-props-with-product-vars-set,$(1),$(2)) -endef - -# Like the above macro, but requiring the relevant PRODUCT_ environment -# variables to be set when called. -define generate-common-build-props-with-product-vars-set - BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \ - BUILD_ID="$(BUILD_ID)" \ - BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \ - BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \ - DATE="$(DATE_FROM_FILE)" \ - PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \ - PLATFORM_VERSION_LAST_STABLE="$(PLATFORM_VERSION_LAST_STABLE)" \ - PLATFORM_VERSION="$(PLATFORM_VERSION)" \ - TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \ - bash $(BUILDINFO_COMMON_SH) "$(1)" >> $(2) -endef - -ifdef property_overrides_split_enabled -INSTALLED_DEFAULT_PROP_TARGET := $(TARGET_OUT)/etc/prop.default -INSTALLED_DEFAULT_PROP_OLD_TARGET := $(TARGET_ROOT_OUT)/default.prop -ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_DEFAULT_PROP_OLD_TARGET) -$(INSTALLED_DEFAULT_PROP_OLD_TARGET): $(INSTALLED_DEFAULT_PROP_TARGET) -else -# legacy path -INSTALLED_DEFAULT_PROP_TARGET := $(TARGET_ROOT_OUT)/default.prop -endif -ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_DEFAULT_PROP_TARGET) -FINAL_DEFAULT_PROPERTIES := \ - $(call collapse-pairs, $(ADDITIONAL_DEFAULT_PROPERTIES)) \ - $(call collapse-pairs, $(PRODUCT_SYSTEM_DEFAULT_PROPERTIES)) -ifndef property_overrides_split_enabled - FINAL_DEFAULT_PROPERTIES += \ - $(call collapse-pairs, $(FINAL_VENDOR_DEFAULT_PROPERTIES)) -endif -FINAL_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \ - $(FINAL_DEFAULT_PROPERTIES),=) - -intermediate_system_build_prop := $(call intermediates-dir-for,ETC,system_build_prop)/build.prop - -$(INSTALLED_DEFAULT_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(intermediate_system_build_prop) - @echo Target buildinfo: $@ - @mkdir -p $(dir $@) - @rm -f $@ - $(hide) echo "#" > $@; \ - echo "# ADDITIONAL_DEFAULT_PROPERTIES" >> $@; \ - echo "#" >> $@; - $(hide) $(foreach line,$(FINAL_DEFAULT_PROPERTIES), \ - echo "$(line)" >> $@;) - $(hide) $(POST_PROCESS_PROPS) $@ -ifdef property_overrides_split_enabled - $(hide) mkdir -p $(TARGET_ROOT_OUT) - $(hide) ln -sf system/etc/prop.default $(INSTALLED_DEFAULT_PROP_OLD_TARGET) -endif - -# ----------------------------------------------------------------- -# vendor default.prop -INSTALLED_VENDOR_DEFAULT_PROP_TARGET := -ifdef property_overrides_split_enabled -INSTALLED_VENDOR_DEFAULT_PROP_TARGET := $(TARGET_OUT_VENDOR)/default.prop -ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_VENDOR_DEFAULT_PROP_TARGET) - -$(INSTALLED_VENDOR_DEFAULT_PROP_TARGET): $(INSTALLED_DEFAULT_PROP_TARGET) $(POST_PROCESS_PROPS) - @echo Target buildinfo: $@ - @mkdir -p $(dir $@) - $(hide) echo "#" > $@; \ - echo "# ADDITIONAL VENDOR DEFAULT PROPERTIES" >> $@; \ - echo "#" >> $@; - $(hide) $(foreach line,$(FINAL_VENDOR_DEFAULT_PROPERTIES), \ - echo "$(line)" >> $@;) - $(hide) $(POST_PROCESS_PROPS) $@ - -endif # property_overrides_split_enabled - -# ----------------------------------------------------------------- -# build.prop -INSTALLED_BUILD_PROP_TARGET := $(TARGET_OUT)/build.prop -ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_BUILD_PROP_TARGET) -FINAL_BUILD_PROPERTIES := \ - $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES)) -FINAL_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \ - $(FINAL_BUILD_PROPERTIES),=) - -# A list of arbitrary tags describing the build configuration. -# Force ":=" so we can use += -BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS) -ifeq ($(TARGET_BUILD_TYPE),debug) - BUILD_VERSION_TAGS += debug -endif -# The "test-keys" tag marks builds signed with the old test keys, -# which are available in the SDK. "dev-keys" marks builds signed with -# non-default dev keys (usually private keys from a vendor directory). -# Both of these tags will be removed and replaced with "release-keys" -# when the target-files is signed in a post-build step. -ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey) -BUILD_KEYS := test-keys -else -BUILD_KEYS := dev-keys -endif -BUILD_VERSION_TAGS += $(BUILD_KEYS) -BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS))) - -# A human-readable string that descibes this build in detail. -build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER_FROM_FILE) $(BUILD_VERSION_TAGS) -$(intermediate_system_build_prop): PRIVATE_BUILD_DESC := $(build_desc) - -# The string used to uniquely identify the combined build and product; used by the OTA server. -ifeq (,$(strip $(BUILD_FINGERPRINT))) - ifeq ($(strip $(HAS_BUILD_NUMBER)),false) - BF_BUILD_NUMBER := $(BUILD_USERNAME)$$($(DATE_FROM_FILE) +%m%d%H%M) - else - BF_BUILD_NUMBER := $(file <$(BUILD_NUMBER_FILE)) - endif - BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BF_BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS) -endif -# unset it for safety. -BF_BUILD_NUMBER := - -BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt -ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE) && grep " " $(BUILD_FINGERPRINT_FILE))) - $(error BUILD_FINGERPRINT cannot contain spaces: "$(file <$(BUILD_FINGERPRINT_FILE))") -endif -BUILD_FINGERPRINT_FROM_FILE := $$(cat $(BUILD_FINGERPRINT_FILE)) -# unset it for safety. -BUILD_FINGERPRINT := - -# The string used to uniquely identify the system build; used by the OTA server. -# This purposefully excludes any product-specific variables. -ifeq (,$(strip $(BUILD_THUMBPRINT))) - BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS) -endif - -BUILD_THUMBPRINT_FILE := $(PRODUCT_OUT)/build_thumbprint.txt -ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_THUMBPRINT) >$(BUILD_THUMBPRINT_FILE) && grep " " $(BUILD_THUMBPRINT_FILE))) - $(error BUILD_THUMBPRINT cannot contain spaces: "$(file <$(BUILD_THUMBPRINT_FILE))") -endif -BUILD_THUMBPRINT_FROM_FILE := $$(cat $(BUILD_THUMBPRINT_FILE)) -# unset it for safety. -BUILD_THUMBPRINT := - -KNOWN_OEM_THUMBPRINT_PROPERTIES := \ - ro.product.brand \ - ro.product.name \ - ro.product.device -OEM_THUMBPRINT_PROPERTIES := $(filter $(KNOWN_OEM_THUMBPRINT_PROPERTIES),\ - $(PRODUCT_OEM_PROPERTIES)) - -# Display parameters shown under Settings -> About Phone -ifeq ($(TARGET_BUILD_VARIANT),user) - # User builds should show: - # release build number or branch.buld_number non-release builds - - # Dev. branches should have DISPLAY_BUILD_NUMBER set - ifeq (true,$(DISPLAY_BUILD_NUMBER)) - BUILD_DISPLAY_ID := $(BUILD_ID).$(BUILD_NUMBER_FROM_FILE) $(BUILD_KEYS) - else - BUILD_DISPLAY_ID := $(BUILD_ID) $(BUILD_KEYS) - endif -else - # Non-user builds should show detailed build information - BUILD_DISPLAY_ID := $(build_desc) -endif - -# Accepts a whitespace separated list of product locales such as -# (en_US en_AU en_GB...) and returns the first locale in the list with -# underscores replaced with hyphens. In the example above, this will -# return "en-US". -define get-default-product-locale -$(strip $(subst _,-, $(firstword $(1)))) -endef - -# TARGET_BUILD_FLAVOR and ro.build.flavor are used only by the test -# harness to distinguish builds. Only add _asan for a sanitized build -# if it isn't already a part of the flavor (via a dedicated lunch -# config for example). -TARGET_BUILD_FLAVOR := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) -ifneq (, $(filter address, $(SANITIZE_TARGET))) -ifeq (,$(findstring _asan,$(TARGET_BUILD_FLAVOR))) -TARGET_BUILD_FLAVOR := $(TARGET_BUILD_FLAVOR)_asan -endif -endif - -ifdef TARGET_SYSTEM_PROP -system_prop_file := $(TARGET_SYSTEM_PROP) -else -system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop) -endif -$(intermediate_system_build_prop): $(BUILDINFO_SH) $(BUILDINFO_COMMON_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(API_FINGERPRINT) $(POST_PROCESS_PROPS) - @echo Target buildinfo: $@ - @mkdir -p $(dir $@) - $(hide) echo > $@ -ifneq ($(PRODUCT_OEM_PROPERTIES),) - $(hide) echo "#" >> $@; \ - echo "# PRODUCT_OEM_PROPERTIES" >> $@; \ - echo "#" >> $@; - $(hide) $(foreach prop,$(PRODUCT_OEM_PROPERTIES), \ - echo "import /oem/oem.prop $(prop)" >> $@;) -endif - $(hide) PRODUCT_BRAND="$(PRODUCT_SYSTEM_BRAND)" \ - PRODUCT_MANUFACTURER="$(PRODUCT_SYSTEM_MANUFACTURER)" \ - PRODUCT_MODEL="$(PRODUCT_SYSTEM_MODEL)" \ - PRODUCT_NAME="$(PRODUCT_SYSTEM_NAME)" \ - PRODUCT_DEVICE="$(PRODUCT_SYSTEM_DEVICE)" \ - $(call generate-common-build-props-with-product-vars-set,system,$@) - $(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \ - TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \ - TARGET_DEVICE="$(TARGET_DEVICE)" \ - PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \ - PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \ - PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \ - BUILD_ID="$(BUILD_ID)" \ - BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \ - DATE="$(DATE_FROM_FILE)" \ - BUILD_USERNAME="$(BUILD_USERNAME)" \ - BUILD_HOSTNAME="$(BUILD_HOSTNAME)" \ - BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \ - BOARD_BUILD_SYSTEM_ROOT_IMAGE="$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)" \ - PLATFORM_VERSION="$(PLATFORM_VERSION)" \ - PLATFORM_VERSION_LAST_STABLE="$(PLATFORM_VERSION_LAST_STABLE)" \ - PLATFORM_SECURITY_PATCH="$(PLATFORM_SECURITY_PATCH)" \ - PLATFORM_BASE_OS="$(PLATFORM_BASE_OS)" \ - PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \ - PLATFORM_PREVIEW_SDK_VERSION="$(PLATFORM_PREVIEW_SDK_VERSION)" \ - PLATFORM_PREVIEW_SDK_FINGERPRINT="$$(cat $(API_FINGERPRINT))" \ - PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \ - PLATFORM_VERSION_ALL_CODENAMES="$(PLATFORM_VERSION_ALL_CODENAMES)" \ - PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION="$(PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION)" \ - BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \ - $(if $(OEM_THUMBPRINT_PROPERTIES),BUILD_THUMBPRINT="$(BUILD_THUMBPRINT_FROM_FILE)") \ - TARGET_CPU_ABI_LIST="$(TARGET_CPU_ABI_LIST)" \ - TARGET_CPU_ABI_LIST_32_BIT="$(TARGET_CPU_ABI_LIST_32_BIT)" \ - TARGET_CPU_ABI_LIST_64_BIT="$(TARGET_CPU_ABI_LIST_64_BIT)" \ - TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \ - TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \ - bash $(BUILDINFO_SH) >> $@ - $(hide) $(foreach file,$(system_prop_file), \ - if [ -f "$(file)" ]; then \ - echo Target buildinfo from: "$(file)"; \ - echo "" >> $@; \ - echo "#" >> $@; \ - echo "# from $(file)" >> $@; \ - echo "#" >> $@; \ - cat $(file) >> $@; \ - echo "# end of $(file)" >> $@; \ - fi;) - $(if $(FINAL_BUILD_PROPERTIES), \ - $(hide) echo >> $@; \ - echo "#" >> $@; \ - echo "# ADDITIONAL_BUILD_PROPERTIES" >> $@; \ - echo "#" >> $@; ) - $(hide) $(foreach line,$(FINAL_BUILD_PROPERTIES), \ - echo "$(line)" >> $@;) - $(hide) $(POST_PROCESS_PROPS) $@ $(PRODUCT_SYSTEM_PROPERTY_BLACKLIST) - -build_desc := - INSTALLED_RECOVERYIMAGE_TARGET := ifdef BUILDING_RECOVERY_IMAGE ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true) @@ -492,198 +168,7 @@ INSTALLED_RECOVERYIMAGE_TARGET := $(PRODUCT_OUT)/recovery.img endif endif -$(INSTALLED_BUILD_PROP_TARGET): $(intermediate_system_build_prop) - @echo "Target build info: $@" - $(hide) grep -v 'ro.product.first_api_level' $(intermediate_system_build_prop) > $@ - -# ----------------------------------------------------------------- -# vendor build.prop -# -# For verifying that the vendor build is what we think it is -INSTALLED_VENDOR_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR)/build.prop -ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_VENDOR_BUILD_PROP_TARGET) - -ifdef TARGET_VENDOR_PROP -vendor_prop_files := $(TARGET_VENDOR_PROP) -else -vendor_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/vendor.prop) -endif - -ifdef property_overrides_split_enabled -FINAL_VENDOR_BUILD_PROPERTIES += \ - $(call collapse-pairs, $(PRODUCT_PROPERTY_OVERRIDES)) -FINAL_VENDOR_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \ - $(FINAL_VENDOR_BUILD_PROPERTIES),=) -endif # property_overrides_split_enabled - -$(INSTALLED_VENDOR_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(intermediate_system_build_prop) $(vendor_prop_files) - @echo Target vendor buildinfo: $@ - @mkdir -p $(dir $@) - $(hide) echo > $@ -ifeq ($(PRODUCT_USE_DYNAMIC_PARTITIONS),true) - $(hide) echo ro.boot.dynamic_partitions=true >> $@ -endif -ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true) - $(hide) echo ro.boot.dynamic_partitions_retrofit=true >> $@ -endif - $(hide) grep 'ro.product.first_api_level' $(intermediate_system_build_prop) >> $@ || true - $(hide) echo ro.vendor.build.security_patch="$(VENDOR_SECURITY_PATCH)">>$@ - $(hide) echo ro.vendor.product.cpu.abilist="$(TARGET_CPU_ABI_LIST)">>$@ - $(hide) echo ro.vendor.product.cpu.abilist32="$(TARGET_CPU_ABI_LIST_32_BIT)">>$@ - $(hide) echo ro.vendor.product.cpu.abilist64="$(TARGET_CPU_ABI_LIST_64_BIT)">>$@ - $(hide) echo ro.product.board="$(TARGET_BOOTLOADER_BOARD_NAME)">>$@ - $(hide) echo ro.board.platform="$(TARGET_BOARD_PLATFORM)">>$@ - $(hide) echo ro.hwui.use_vulkan="$(TARGET_USES_VULKAN)">>$@ -ifdef TARGET_SCREEN_DENSITY - $(hide) echo ro.sf.lcd_density="$(TARGET_SCREEN_DENSITY)">>$@ -endif -ifeq ($(AB_OTA_UPDATER),true) - $(hide) echo ro.build.ab_update=true >> $@ -endif - $(hide) $(call generate-common-build-props,vendor,$@) - $(hide) echo "#" >> $@; \ - echo "# BOOTIMAGE_BUILD_PROPERTIES" >> $@; \ - echo "#" >> $@; - $(hide) echo ro.bootimage.build.date=`$(DATE_FROM_FILE)`>>$@ - $(hide) echo ro.bootimage.build.date.utc=`$(DATE_FROM_FILE) +%s`>>$@ - $(hide) echo ro.bootimage.build.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@ - $(hide) echo "#" >> $@; \ - echo "# ADDITIONAL VENDOR BUILD PROPERTIES" >> $@; \ - echo "#" >> $@; - $(hide) cat $(INSTALLED_ANDROID_INFO_TXT_TARGET) | grep 'require version-' | sed -e 's/require version-/ro.build.expect./g' >> $@ -ifdef property_overrides_split_enabled - $(hide) $(foreach file,$(vendor_prop_files), \ - if [ -f "$(file)" ]; then \ - echo Target vendor properties from: "$(file)"; \ - echo "" >> $@; \ - echo "#" >> $@; \ - echo "# from $(file)" >> $@; \ - echo "#" >> $@; \ - cat $(file) >> $@; \ - echo "# end of $(file)" >> $@; \ - fi;) - $(hide) $(foreach line,$(FINAL_VENDOR_BUILD_PROPERTIES), \ - echo "$(line)" >> $@;) -endif # property_overrides_split_enabled - $(hide) $(POST_PROCESS_PROPS) $@ $(PRODUCT_VENDOR_PROPERTY_BLACKLIST) - -# ----------------------------------------------------------------- -# product build.prop -INSTALLED_PRODUCT_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT)/build.prop -ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_BUILD_PROP_TARGET) - -ifdef TARGET_PRODUCT_PROP -product_prop_files := $(TARGET_PRODUCT_PROP) -else -product_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/product.prop) -endif - -FINAL_PRODUCT_PROPERTIES += \ - $(call collapse-pairs, $(PRODUCT_PRODUCT_PROPERTIES) $(ADDITIONAL_PRODUCT_PROPERTIES)) -FINAL_PRODUCT_PROPERTIES := $(call uniq-pairs-by-first-component, \ - $(FINAL_PRODUCT_PROPERTIES),=) - -$(INSTALLED_PRODUCT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(product_prop_files) - @echo Target product buildinfo: $@ - @mkdir -p $(dir $@) - $(hide) echo > $@ - $(hide) $(call generate-common-build-props,product,$@) - $(hide) $(foreach file,$(product_prop_files), \ - if [ -f "$(file)" ]; then \ - echo Target product properties from: "$(file)"; \ - echo "" >> $@; \ - echo "#" >> $@; \ - echo "# from $(file)" >> $@; \ - echo "#" >> $@; \ - cat $(file) >> $@; \ - echo "# end of $(file)" >> $@; \ - fi;) - $(hide) echo "#" >> $@; \ - echo "# ADDITIONAL PRODUCT PROPERTIES" >> $@; \ - echo "#" >> $@; \ - echo "ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)" >> $@; - $(hide) $(foreach line,$(FINAL_PRODUCT_PROPERTIES), \ - echo "$(line)" >> $@;) - $(hide) $(POST_PROCESS_PROPS) $@ - -# ---------------------------------------------------------------- -# odm build.prop -INSTALLED_ODM_BUILD_PROP_TARGET := $(TARGET_OUT_ODM)/etc/build.prop -ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_ODM_BUILD_PROP_TARGET) - -ifdef TARGET_ODM_PROP -odm_prop_files := $(TARGET_ODM_PROP) -else -odm_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/odm.prop) -endif - -FINAL_ODM_BUILD_PROPERTIES += \ - $(call collapse-pairs, $(PRODUCT_ODM_PROPERTIES)) -FINAL_ODM_BUILD_PROPERTIES := $(call uniq-pairs-by-first-component, \ - $(FINAL_ODM_BUILD_PROPERTIES),=) - -$(INSTALLED_ODM_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(odm_prop_files) - @echo Target odm buildinfo: $@ - @mkdir -p $(dir $@) - $(hide) echo > $@ - $(hide) echo ro.odm.product.cpu.abilist="$(TARGET_CPU_ABI_LIST)">>$@ - $(hide) echo ro.odm.product.cpu.abilist32="$(TARGET_CPU_ABI_LIST_32_BIT)">>$@ - $(hide) echo ro.odm.product.cpu.abilist64="$(TARGET_CPU_ABI_LIST_64_BIT)">>$@ - $(hide) $(call generate-common-build-props,odm,$@) - $(hide) $(foreach file,$(odm_prop_files), \ - if [ -f "$(file)" ]; then \ - echo Target odm properties from: "$(file)"; \ - echo "" >> $@; \ - echo "#" >> $@; \ - echo "# from $(file)" >> $@; \ - echo "#" >> $@; \ - cat $(file) >> $@; \ - echo "# end of $(file)" >> $@; \ - fi;) - $(hide) echo "#" >> $@; \ - echo "# ADDITIONAL ODM BUILD PROPERTIES" >> $@; \ - echo "#" >> $@; - $(hide) $(foreach line,$(FINAL_ODM_BUILD_PROPERTIES), \ - echo "$(line)" >> $@;) - $(hide) $(POST_PROCESS_PROPS) $@ - -# ----------------------------------------------------------------- -# system_ext build.prop -INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET := $(TARGET_OUT_SYSTEM_EXT)/build.prop -ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET) - -ifdef TARGET_SYSTEM_EXT_PROP -system_ext_prop_files := $(TARGET_SYSTEM_EXT_PROP) -else -system_ext_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/system_ext.prop) -endif - -FINAL_SYSTEM_EXT_PROPERTIES += \ - $(call collapse-pairs, $(PRODUCT_SYSTEM_EXT_PROPERTIES)) -FINAL_SYSTEM_EXT_PROPERTIES := $(call uniq-pairs-by-first-component, \ - $(FINAL_SYSTEM_EXT_PROPERTIES),=) - -$(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(system_ext_prop_files) - @echo Target system_ext buildinfo: $@ - @mkdir -p $(dir $@) - $(hide) echo > $@ - $(hide) $(call generate-common-build-props,system_ext,$@) - $(hide) $(foreach file,$(system_ext_prop_files), \ - if [ -f "$(file)" ]; then \ - echo Target system_ext properties from: "$(file)"; \ - echo "" >> $@; \ - echo "#" >> $@; \ - echo "# from $(file)" >> $@; \ - echo "#" >> $@; \ - cat $(file) >> $@; \ - echo "# end of $(file)" >> $@; \ - fi;) - $(hide) echo "#" >> $@; \ - echo "# ADDITIONAL SYSTEM_EXT BUILD PROPERTIES" >> $@; \ - echo "#" >> $@; - $(hide) $(foreach line,$(FINAL_SYSTEM_EXT_PROPERTIES), \ - echo "$(line)" >> $@;) - $(hide) $(POST_PROCESS_PROPS) $@ +include $(BUILD_SYSTEM)/sysprop.mk # ---------------------------------------------------------------- @@ -780,7 +265,7 @@ $(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(1) $(6) rm -rf $$(PRIVATE_STAGING_DIR) mkdir -p $$(PRIVATE_MODULE_DIR) $(if $(6),\ - unzip -qo -d $$(PRIVATE_MODULE_DIR) $$(PRIVATE_MODULE_ARCHIVE); \ + unzip -qoDD -d $$(PRIVATE_MODULE_DIR) $$(PRIVATE_MODULE_ARCHIVE); \ mkdir -p $$(PRIVATE_OUTPUT_DIR)/lib; \ cp -r $(3)/$(DEPMOD_STAGING_SUBDIR)/$(2)/lib/modules $$(PRIVATE_OUTPUT_DIR)/lib/; \ find $$(PRIVATE_MODULE_DIR) -type f -name *.ko | xargs basename -a > $$(PRIVATE_LOAD_FILE); \ @@ -855,6 +340,15 @@ $(if $(filter top,$(1)),\ $(call copy-many-files,$(call module-load-list-copy-paths,$(call intermediates-dir-for,PACKAGING,vendor_ramdisk_recovery_module_list$(_sep)$(_kver)),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES$(_sep)$(_kver)),$(BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD$(_sep)$(_kver)),modules.load.recovery,$(TARGET_VENDOR_RAMDISK_OUT)))) endef +# $(1): kernel module directory name (top is an out of band value for no directory) +define build-vendor-charger-load +$(if $(filter top,$(1)),\ + $(eval _kver :=)$(eval _sep :=),\ + $(eval _kver := $(1))$(eval _sep :=_))\ + $(if $(BOARD_VENDOR_CHARGER_KERNEL_MODULES_LOAD$(_sep)$(_kver)),\ + $(call copy-many-files,$(call module-load-list-copy-paths,$(call intermediates-dir-for,PACKAGING,vendor_charger_module_list$(_sep)$(_kver)),$(BOARD_VENDOR_CHARGER_KERNEL_MODULES$(_sep)$(_kver)),$(BOARD_VENDOR_CHARGER_KERNEL_MODULES_LOAD$(_sep)$(_kver)),modules.load.charger,$(TARGET_OUT_VENDOR)))) +endef + ifneq ($(BUILDING_VENDOR_BOOT_IMAGE),true) # If there is no vendor boot partition, store vendor ramdisk kernel modules in the # boot ramdisk. @@ -889,8 +383,9 @@ $(foreach dir,$(BOARD_KERNEL_MODULE_DIRS), \ $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,RECOVERY,$(TARGET_RECOVERY_ROOT_OUT),,modules.load.recovery,,$(dir))) \ $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,VENDOR_RAMDISK,$(TARGET_VENDOR_RAMDISK_OUT),,modules.load,$(VENDOR_RAMDISK_STRIPPED_MODULE_STAGING_DIR),$(dir))) \ $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-vendor-ramdisk-recovery-load,$(dir))) \ - $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,VENDOR,$(TARGET_OUT_VENDOR),vendor,modules.load,$(VENDOR_STRIPPED_MODULE_STAGING_DIR),$(dir))) \ - $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,ODM,$(TARGET_OUT_ODM),odm,modules.load,,$(dir))) \ + $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,VENDOR,$(if $(filter true,$(BOARD_USES_VENDOR_DLKMIMAGE)),$(TARGET_OUT_VENDOR_DLKM),$(TARGET_OUT_VENDOR)),vendor,modules.load,$(VENDOR_STRIPPED_MODULE_STAGING_DIR),$(dir))) \ + $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-vendor-charger-load,$(dir))) \ + $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,ODM,$(if $(filter true,$(BOARD_USES_ODM_DLKMIMAGE)),$(TARGET_OUT_ODM_DLKM),$(TARGET_OUT_ODM)),odm,modules.load,,$(dir))) \ $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\ $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-recovery-as-boot-load,$(dir))),\ $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,GENERIC_RAMDISK,$(TARGET_RAMDISK_OUT),,modules.load,,$(dir))))) @@ -981,7 +476,7 @@ SOONG_CONV := $(sort $(SOONG_CONV)) SOONG_CONV_DATA := $(call intermediates-dir-for,PACKAGING,soong_conversion)/soong_conv_data $(SOONG_CONV_DATA): @rm -f $@ - @$(foreach s,$(SOONG_CONV),echo "$(s),$(SOONG_CONV.$(s).TYPE),$(sort $(SOONG_CONV.$(s).PROBLEMS)),$(sort $(filter-out $(SOONG_ALREADY_CONV),$(SOONG_CONV.$(s).DEPS)))" >>$@;) + @$(foreach s,$(SOONG_CONV),echo "$(s),$(SOONG_CONV.$(s).TYPE),$(sort $(SOONG_CONV.$(s).PROBLEMS)),$(sort $(filter-out $(SOONG_ALREADY_CONV),$(SOONG_CONV.$(s).DEPS))),$(sort $(SOONG_CONV.$(s).MAKEFILES)),$(sort $(SOONG_CONV.$(s).INSTALLED))" >>$@;) SOONG_TO_CONVERT_SCRIPT := build/make/tools/soong_to_convert.py SOONG_TO_CONVERT := $(PRODUCT_OUT)/soong_to_convert.txt @@ -990,6 +485,30 @@ $(SOONG_TO_CONVERT): $(SOONG_CONV_DATA) $(SOONG_TO_CONVERT_SCRIPT) $(hide) $(SOONG_TO_CONVERT_SCRIPT) $< >$@ $(call dist-for-goals,droidcore,$(SOONG_TO_CONVERT)) +MK2BP_CATALOG_SCRIPT := build/make/tools/mk2bp_catalog.py +MK2BP_REMAINING_HTML := $(PRODUCT_OUT)/mk2bp_remaining.html +$(MK2BP_REMAINING_HTML): PRIVATE_CODE_SEARCH_BASE_URL := "https://cs.android.com/android/platform/superproject/+/master:" +$(MK2BP_REMAINING_HTML): $(SOONG_CONV_DATA) $(MK2BP_CATALOG_SCRIPT) + @rm -f $@ + $(hide) $(MK2BP_CATALOG_SCRIPT) \ + --device=$(TARGET_DEVICE) \ + --title="Remaining Android.mk files for $(TARGET_DEVICE)-$(TARGET_BUILD_VARIANT)" \ + --codesearch=$(PRIVATE_CODE_SEARCH_BASE_URL) \ + --out_dir="$(OUT_DIR)" \ + --mode=html \ + > $@ +$(call dist-for-goals,droidcore,$(MK2BP_REMAINING_HTML)) + +MK2BP_REMAINING_CSV := $(PRODUCT_OUT)/mk2bp_remaining.csv +$(MK2BP_REMAINING_CSV): $(SOONG_CONV_DATA) $(MK2BP_CATALOG_SCRIPT) + @rm -f $@ + $(hide) $(MK2BP_CATALOG_SCRIPT) \ + --device=$(TARGET_DEVICE) \ + --out_dir="$(OUT_DIR)" \ + --mode=csv \ + > $@ +$(call dist-for-goals,droidcore,$(MK2BP_REMAINING_CSV)) + # ----------------------------------------------------------------- # Modules use -Wno-error, or added default -Wall -Werror WALL_WERROR := $(PRODUCT_OUT)/wall_werror.txt @@ -1045,12 +564,8 @@ event_log_tags_file := $(TARGET_OUT)/etc/event-log-tags all_event_log_tags_src := \ $(sort $(foreach m, $(ALL_MODULES), $(ALL_MODULES.$(m).EVENT_LOG_TAGS))) -# PDK builds will already have a full list of tags that needs to get merged -# in with the ones from source -pdk_fusion_log_tags_file := $(patsubst $(PRODUCT_OUT)/%,$(_pdk_fusion_intermediates)/%,$(filter $(event_log_tags_file),$(ALL_PDK_FUSION_FILES))) - -$(all_event_log_tags_file): PRIVATE_SRC_FILES := $(all_event_log_tags_src) $(pdk_fusion_log_tags_file) -$(all_event_log_tags_file): $(all_event_log_tags_src) $(pdk_fusion_log_tags_file) $(MERGETAGS) build/make/tools/event_log_tags.py +$(all_event_log_tags_file): PRIVATE_SRC_FILES := $(all_event_log_tags_src) +$(all_event_log_tags_file): $(all_event_log_tags_src) $(MERGETAGS) build/make/tools/event_log_tags.py $(hide) mkdir -p $(dir $@) $(hide) $(MERGETAGS) -o $@ $(PRIVATE_SRC_FILES) @@ -1059,14 +574,14 @@ $(all_event_log_tags_file): $(all_event_log_tags_src) $(pdk_fusion_log_tags_file # directory). event_log_tags_src := \ $(sort $(foreach m,\ - $(PRODUCT_PACKAGES) \ + $(call resolve-bitness-for-modules,TARGET,$(PRODUCT_PACKAGES)) \ $(call module-names-for-tag-list,user), \ $(ALL_MODULES.$(m).EVENT_LOG_TAGS)) \ $(filter-out vendor/% device/% out/%,$(all_event_log_tags_src))) -$(event_log_tags_file): PRIVATE_SRC_FILES := $(event_log_tags_src) $(pdk_fusion_log_tags_file) +$(event_log_tags_file): PRIVATE_SRC_FILES := $(event_log_tags_src) $(event_log_tags_file): PRIVATE_MERGED_FILE := $(all_event_log_tags_file) -$(event_log_tags_file): $(event_log_tags_src) $(all_event_log_tags_file) $(pdk_fusion_log_tags_file) $(MERGETAGS) build/make/tools/event_log_tags.py +$(event_log_tags_file): $(event_log_tags_src) $(all_event_log_tags_file) $(MERGETAGS) build/make/tools/event_log_tags.py $(hide) mkdir -p $(dir $@) $(hide) $(MERGETAGS) -o $@ -m $(PRIVATE_MERGED_FILE) $(PRIVATE_SRC_FILES) @@ -1080,6 +595,10 @@ ALL_DEFAULT_INSTALLED_MODULES += $(event_log_tags_file) # ################################################################# ifneq ($(strip $(TARGET_NO_BOOTLOADER)),true) INSTALLED_BOOTLOADER_MODULE := $(PRODUCT_OUT)/bootloader + ifdef BOARD_PREBUILT_BOOTLOADER + $(eval $(call copy-one-file,$(BOARD_PREBUILT_BOOTLOADER),$(INSTALLED_BOOTLOADER_MODULE))) + $(call dist-for-goals,dist_files,$(INSTALLED_BOOTLOADER_MODULE)) + endif # BOARD_PREBUILT_BOOTLOADER ifeq ($(strip $(TARGET_BOOTLOADER_IS_2ND)),true) INSTALLED_2NDBOOTLOADER_TARGET := $(PRODUCT_OUT)/2ndbootloader else @@ -1184,6 +703,14 @@ else BUILT_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img endif +# $1: boot image target +# returns the kernel used to make the bootimage +define bootimage-to-kernel + $(if $(BOARD_KERNEL_BINARIES),\ + $(PRODUCT_OUT)/$(subst .img,,$(subst boot,kernel,$(notdir $(1)))),\ + $(INSTALLED_KERNEL_TARGET)) +endef + ifdef BOARD_BOOTIMAGE_PARTITION_SIZE BOARD_KERNEL_BOOTIMAGE_PARTITION_SIZE := $(BOARD_BOOTIMAGE_PARTITION_SIZE) endif @@ -1196,8 +723,7 @@ endef ifneq ($(strip $(TARGET_NO_KERNEL)),true) INTERNAL_BOOTIMAGE_ARGS := \ - $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \ - --kernel $(INSTALLED_KERNEL_TARGET) + $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true) INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET) @@ -1250,69 +776,78 @@ $(error TARGET_BOOTIMAGE_USE_EXT2 is not supported anymore) else ifeq (true,$(BOARD_AVB_ENABLE)) # TARGET_BOOTIMAGE_USE_EXT2 != true -$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH) +# $1: boot image target +define build_boot_board_avb_enabled + $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1) + $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))) + $(AVBTOOL) add_hash_footer \ + --image $(1) \ + --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \ + --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \ + $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS) +endef + +$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH) $(call bootimage-to-kernel,$@) $(call pretty,"Target boot image: $@") - $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@ - $(hide) $(call assert-max-image-size,$@,$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))) - $(hide) $(AVBTOOL) add_hash_footer \ - --image $@ \ - --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \ - --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \ - $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS) + $(call build_boot_board_avb_enabled,$@) .PHONY: bootimage-nodeps bootimage-nodeps: $(MKBOOTIMG) $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH) @echo "make $@: ignoring dependencies" - $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET) - $(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))) - $(hide) $(AVBTOOL) add_hash_footer \ - --image $(INSTALLED_BOOTIMAGE_TARGET) \ - --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \ - --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \ - $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS) + $(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(call build_boot_board_avb_enabled,$(b))) else ifeq (true,$(PRODUCT_SUPPORTS_BOOT_SIGNER)) # BOARD_AVB_ENABLE != true -$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER) +# $1: boot image target +define build_boot_supports_boot_signer + $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1) + $(BOOT_SIGNER) /boot $@ $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1) + $(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE)) +endef + +$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER) $(call bootimage-to-kernel,$@) $(call pretty,"Target boot image: $@") - $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@ - $(BOOT_SIGNER) /boot $@ $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $@ - $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE)) + $(call build_boot_supports_boot_signer,$@) .PHONY: bootimage-nodeps bootimage-nodeps: $(MKBOOTIMG) $(BOOT_SIGNER) @echo "make $@: ignoring dependencies" - $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET) - $(BOOT_SIGNER) /boot $(INSTALLED_BOOTIMAGE_TARGET) $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $(INSTALLED_BOOTIMAGE_TARGET) - $(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE)) + $(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(call build_boot_supports_boot_signer,$(b))) else ifeq (true,$(PRODUCT_SUPPORTS_VBOOT)) # PRODUCT_SUPPORTS_BOOT_SIGNER != true -$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(VBOOT_SIGNER) $(FUTILITY) +# $1: boot image target +define build_boot_supports_vboot + $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1).unsigned + $(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1) + $(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE)) +endef + +$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(VBOOT_SIGNER) $(FUTILITY) $(call bootimage-to-kernel,$@) $(call pretty,"Target boot image: $@") - $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@.unsigned - $(VBOOT_SIGNER) $(FUTILITY) $@.unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $@.keyblock $@ - $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE)) + $(call build_boot_supports_vboot,$@) .PHONY: bootimage-nodeps bootimage-nodeps: $(MKBOOTIMG) $(VBOOT_SIGNER) $(FUTILITY) @echo "make $@: ignoring dependencies" - $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET).unsigned - $(VBOOT_SIGNER) $(FUTILITY) $(INSTALLED_BOOTIMAGE_TARGET).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(INSTALLED_BOOTIMAGE_TARGET).keyblock $(INSTALLED_BOOTIMAGE_TARGET) - $(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE)) + $(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(call build_boot_supports_vboot,$(b))) else # PRODUCT_SUPPORTS_VBOOT != true -$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) +# $1: boot image target +define build_boot_novboot + $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1) + $(call assert-max-image-size,$1,$(BOARD_BOOTIMAGE_PARTITION_SIZE)) +endef + +$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(call bootimage-to-kernel,$@) $(call pretty,"Target boot image: $@") - $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@ - $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE)) + $(call build_boot_novboot,$@) .PHONY: bootimage-nodeps bootimage-nodeps: $(MKBOOTIMG) @echo "make $@: ignoring dependencies" - $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET) - $(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE)) + $(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(call build_boot_novboot,$(b))) endif # TARGET_BOOTIMAGE_USE_EXT2 endif # BUILDING_BOOT_IMAGE @@ -1342,7 +877,7 @@ INTERNAL_VENDOR_RAMDISK_FILES := $(filter $(TARGET_VENDOR_RAMDISK_OUT)/%, \ $(ALL_GENERATED_SOURCES) \ $(ALL_DEFAULT_INSTALLED_MODULES)) -INTERNAL_VENDOR_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor-boot)/vendor-ramdisk.cpio.gz +INTERNAL_VENDOR_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor-boot)/vendor-ramdisk.cpio$(RAMDISK_EXT) $(INTERNAL_VENDOR_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_RAMDISK_FILES) | $(COMPRESSION_COMMAND_DEPS) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_RAMDISK_OUT) | $(COMPRESSION_COMMAND) > $@ @@ -1364,7 +899,7 @@ $(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_VENDOR_RAMDISK_TAR ifeq ($(BOARD_AVB_ENABLE),true) $(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_VENDOR_BOOTIMAGE_KEY_PATH) $(call pretty,"Target vendor_boot image: $@") - $(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INTERNAL_VENDOR_RAMDISK_TARGET) --vendor_boot $@ + $(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INTERNAL_VENDOR_RAMDISK_TARGET) --vendor_boot $@ $(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE)) $(AVBTOOL) add_hash_footer \ --image $@ \ @@ -1374,7 +909,7 @@ $(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_VENDOR_BOOTIMAGE_KE else $(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(call pretty,"Target vendor_boot image: $@") - $(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INTERNAL_VENDOR_RAMDISK_TARGET) --vendor_boot $@ + $(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INTERNAL_VENDOR_RAMDISK_TARGET) --vendor_boot $@ $(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE)) endif endif # BUILDING_VENDOR_BOOT_IMAGE @@ -1394,14 +929,17 @@ endif # BUILDING_VENDOR_BOOT_IMAGE .PHONY: notice_files # Create the rule to combine the files into text and html/xml forms -# $(1) - xml_excluded_system_product_odm|xml_excluded_vendor_product_odm -# xml_product|xml_odm|xml_system_ext|xml_system|html +# $(1) - xml_excluded_system_product_odm_vendor_dlkm_odm_dlkm| +# xml_excluded_vendor_product_odm_vendor_dlkm_odm_dlkm| +# xml_product|xml_odm|xml_system_ext|xml_system|xml_vendor_dlkm| +# xml_odm_dlkm|html # $(2) - Plain text output file # $(3) - HTML/XML output file # $(4) - File title # $(5) - Directory to use. Notice files are all $(5)/src. Other # directories in there will be used for scratch # $(6) - Dependencies for the output files +# $(7) - Directories to exclude # # The algorithm here is that we go collect a hash for each of the notice # files and write the names of the files that match that hash. Then @@ -1415,19 +953,21 @@ endif # BUILDING_VENDOR_BOOT_IMAGE # original notice files instead of making rules to copy them somwehere. # Then we could traverse that without quite as much bash drama. define combine-notice-files -$(2) $(3): PRIVATE_MESSAGE := $(4) -$(2) $(3): PRIVATE_DIR := $(5) -$(2) : $(3) -$(3) : $(6) $(BUILD_SYSTEM)/Makefile build/make/tools/generate-notice-files.py - build/make/tools/generate-notice-files.py --text-output $(2) \ - $(if $(filter $(1),xml_excluded_vendor_product_odm),-e vendor -e product -e system_ext -e odm --xml-output, \ - $(if $(filter $(1),xml_excluded_system_product_odm),-e system -e product -e system_ext -e odm --xml-output, \ +$(2): PRIVATE_MESSAGE := $(4) +$(2): PRIVATE_DIR := $(5) +$(2): .KATI_IMPLICIT_OUTPUTS := $(3) +$(2): $(6) $(BUILD_SYSTEM)/Makefile build/make/tools/generate-notice-files.py + build/make/tools/generate-notice-files.py --text-output $(2) $(foreach xdir, $(7), -e $(xdir) )\ + $(if $(filter $(1),xml_excluded_vendor_product_odm_vendor_dlkm_odm_dlkm),-e vendor -e product -e system_ext -e odm -e vendor_dlkm -e odm_dlkm --xml-output, \ + $(if $(filter $(1),xml_excluded_system_product_odm_vendor_dlkm_odm_dlkm),-e system -e product -e system_ext -e odm -e vendor_dlkm -e odm_dlkm --xml-output, \ $(if $(filter $(1),xml_product),-i product --xml-output, \ $(if $(filter $(1),xml_system_ext),-i system_ext --xml-output, \ $(if $(filter $(1),xml_system),-i system --xml-output, \ $(if $(filter $(1),xml_odm),-i odm --xml-output, \ - --html-output)))))) $(3) \ - -t $$(PRIVATE_MESSAGE) -s $$(PRIVATE_DIR)/src + $(if $(filter $(1),xml_vendor_dlkm),-i vendor_dlkm --xml-output, \ + $(if $(filter $(1),xml_odm_dlkm),-i odm_dlkm --xml-output, \ + --html-output)))))))) $(3) \ + -t $$(PRIVATE_MESSAGE) $$(foreach dir,$$(sort $$(PRIVATE_DIR)), -s $$(dir)/src) notice_files: $(2) $(3) endef @@ -1442,7 +982,11 @@ tools_notice_file_txt := $(HOST_OUT_INTERMEDIATES)/NOTICE.txt tools_notice_file_html := $(HOST_OUT_INTERMEDIATES)/NOTICE.html kernel_notice_file := $(TARGET_OUT_NOTICE_FILES)/src/kernel.txt winpthreads_notice_file := $(TARGET_OUT_NOTICE_FILES)/src/winpthreads.txt -pdk_fusion_notice_files := $(filter $(TARGET_OUT_NOTICE_FILES)/%, $(ALL_PDK_FUSION_FILES)) + +# Some targets get included under $(PRODUCT_OUT) for debug symbols or other +# reasons--not to be flashed onto any device. Targets under these directories +# need no associated notice file on the device UI. +exclude_target_dirs := apex # TODO(b/69865032): Make PRODUCT_NOTICE_SPLIT the default behavior. ifneq ($(PRODUCT_NOTICE_SPLIT),true) @@ -1454,7 +998,8 @@ $(eval $(call combine-notice-files, html, \ $(target_notice_file_html), \ "Notices for files contained in the filesystem images in this directory:", \ $(TARGET_OUT_NOTICE_FILES), \ - $(ALL_DEFAULT_INSTALLED_MODULES) $(kernel_notice_file) $(pdk_fusion_notice_files))) + $(ALL_DEFAULT_INSTALLED_MODULES) $(kernel_notice_file), \ + $(exclude_target_dirs))) $(target_notice_file_html_gz): $(target_notice_file_html) | $(MINIGZIP) $(hide) $(MINIGZIP) -9 < $< > $@ $(installed_notice_html_or_xml_gz): $(target_notice_file_html_gz) @@ -1484,14 +1029,27 @@ target_odm_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM.xml target_odm_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM.xml.gz installed_odm_notice_xml_gz := $(TARGET_OUT_ODM)/etc/NOTICE.xml.gz +target_vendor_dlkm_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR_DLKM.txt +target_vendor_dlkm_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR_DLKM.xml +target_vendor_dlkm_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR_DLKM.xml.gz +installed_vendor_dlkm_notice_xml_gz := $(TARGET_OUT_VENDOR_DLKM)/etc/NOTICE.xml.gz + +target_odm_dlkm_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM_DLKM.txt +target_odm_dlkm_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM_DLKM.xml +target_odm_dlkm_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM_DLKM.xml.gz +installed_odm_dlkm_notice_xml_gz := $(TARGET_OUT_ODM_DLKM)/etc/NOTICE.xml.gz + # Notice files are copied to TARGET_OUT_NOTICE_FILES as a side-effect of their module # being built. A notice xml file must depend on all modules that could potentially # install a license file relevant to it. -license_modules := $(ALL_DEFAULT_INSTALLED_MODULES) $(kernel_notice_file) $(pdk_fusion_notice_files) +license_modules := $(ALL_DEFAULT_INSTALLED_MODULES) $(kernel_notice_file) +# Only files copied to a system image need system image notices. +license_modules := $(filter $(PRODUCT_OUT)/%,$(license_modules)) # Phonys/fakes don't have notice files (though their deps might) license_modules := $(filter-out $(TARGET_OUT_FAKE)/%,$(license_modules)) # testcases are not relevant to the system image. license_modules := $(filter-out $(TARGET_OUT_TESTCASES)/%,$(license_modules)) +# filesystem images: system, vendor, product, system_ext, odm, vendor_dlkm, and odm_dlkm license_modules_system := $(filter $(TARGET_OUT)/%,$(license_modules)) # system_other is relevant to system partition. license_modules_system += $(filter $(TARGET_OUT_SYSTEM_OTHER)/%,$(license_modules)) @@ -1499,21 +1057,53 @@ license_modules_vendor := $(filter $(TARGET_OUT_VENDOR)/%,$(license_modules)) license_modules_product := $(filter $(TARGET_OUT_PRODUCT)/%,$(license_modules)) license_modules_system_ext := $(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(license_modules)) license_modules_odm := $(filter $(TARGET_OUT_ODM)/%,$(license_modules)) +license_modules_vendor_dlkm := $(filter $(TARGET_OUT_VENDOR_DLKM)/%,$(license_modules)) +license_modules_odm_dlkm := $(filter $(TARGET_OUT_ODM_DLKM)/%,$(license_modules)) license_modules_agg := $(license_modules_system) \ $(license_modules_vendor) \ $(license_modules_product) \ $(license_modules_system_ext) \ - $(license_modules_odm) + $(license_modules_odm) \ + $(license_modules_vendor_dlkm) \ + $(license_modules_odm_dlkm) +# targets used for debug symbols only and do not get copied to the device +license_modules_symbols_only := $(filter $(PRODUCT_OUT)/apex/%,$(license_modules)) + license_modules_rest := $(filter-out $(license_modules_agg),$(license_modules)) +license_modules_rest := $(filter-out $(license_modules_symbols_only),$(license_modules_rest)) + +# Identify the other targets we expect to have notices for: +# targets copied to the device but are not readable by the UI (e.g. must boot +# into a different partition to read or don't have an associated /etc +# directory) must have their notices built somewhere readable. +license_modules_rehomed := $(filter-out $(PRODUCT_OUT)/%/%,$(license_modules_rest)) # files in root have no /etc +license_modules_rehomed += $(filter $(PRODUCT_OUT)/recovery/%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/root/%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/data/%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/ramdisk/%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/debug_ramdisk/%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/vendor-ramdisk/%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/persist/%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/persist.img,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/system_other/%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/kernel%,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/%.img,$(license_modules_rest)) +license_modules_rehomed += $(filter $(PRODUCT_OUT)/%.bin,$(license_modules_rest)) + +# after removing targets in system images, targets reported in system images, and +# targets used for debug symbols that do not need notices, nothing must remain. +license_modules_rest := $(filter-out $(license_modules_rehomed),$(license_modules_rest)) +$(call maybe-print-list-and-error, $(license_modules_rest), \ + "Targets added under $(PRODUCT_OUT)/ unaccounted for notice handling.") # If we are building in a configuration that includes a prebuilt vendor.img, we can't # update its notice file, so include those notices in the system partition instead ifdef BOARD_PREBUILT_VENDORIMAGE -license_modules_system += $(license_modules_rest) -system_xml_directories := xml_excluded_vendor_product_odm -system_notice_file_message := "Notices for files contained in all filesystem images except vendor/system_ext/product/odm in this directory:" +license_modules_system += $(license_modules_rehomed) +system_xml_directories := xml_excluded_vendor_product_odm_vendor_dlkm_odm_dlkm +system_notice_file_message := "Notices for files contained in all filesystem images except vendor/system_ext/product/odm/vendor_dlkm/odm_dlkm in this directory:" else -license_modules_vendor += $(license_modules_rest) +license_modules_vendor += $(license_modules_rehomed) system_xml_directories := xml_system system_notice_file_message := "Notices for files contained in the system filesystem image in this directory:" endif @@ -1523,31 +1113,50 @@ $(eval $(call combine-notice-files, $(system_xml_directories), \ $(target_notice_file_xml), \ $(system_notice_file_message), \ $(TARGET_OUT_NOTICE_FILES), \ - $(license_modules_system))) -$(eval $(call combine-notice-files, xml_excluded_system_product_odm, \ + $(license_modules_system), \ + $(exclude_target_dirs))) +$(eval $(call combine-notice-files, xml_excluded_system_product_odm_vendor_dlkm_odm_dlkm, \ $(target_vendor_notice_file_txt), \ $(target_vendor_notice_file_xml), \ - "Notices for files contained in all filesystem images except system/system_ext/product/odm in this directory:", \ + "Notices for files contained in all filesystem images except system/system_ext/product/odm/vendor_dlkm/odm_dlkm in this directory:", \ $(TARGET_OUT_NOTICE_FILES), \ - $(license_modules_vendor))) + $(license_modules_vendor), \ + $(exclude_target_dirs))) $(eval $(call combine-notice-files, xml_product, \ $(target_product_notice_file_txt), \ $(target_product_notice_file_xml), \ "Notices for files contained in the product filesystem image in this directory:", \ $(TARGET_OUT_NOTICE_FILES), \ - $(license_modules_product))) + $(license_modules_product), \ + $(exclude_target_dirs))) $(eval $(call combine-notice-files, xml_system_ext, \ $(target_system_ext_notice_file_txt), \ $(target_system_ext_notice_file_xml), \ "Notices for files contained in the system_ext filesystem image in this directory:", \ $(TARGET_OUT_NOTICE_FILES), \ - $(license_modules_system_ext))) + $(license_modules_system_ext), \ + $(exclude_target_dirs))) $(eval $(call combine-notice-files, xml_odm, \ $(target_odm_notice_file_txt), \ $(target_odm_notice_file_xml), \ "Notices for files contained in the odm filesystem image in this directory:", \ $(TARGET_OUT_NOTICE_FILES), \ - $(license_modules_odm))) + $(license_modules_odm), \ + $(exclude_target_dirs))) +$(eval $(call combine-notice-files, xml_vendor_dlkm, \ + $(target_vendor_dlkm_notice_file_txt), \ + $(target_vendor_dlkm_notice_file_xml), \ + "Notices for files contained in the vendor_dlkm filesystem image in this directory:", \ + $(TARGET_OUT_NOTICE_FILES), \ + $(license_modules_vendor_dlkm), \ + $(exclude_target_dirs))) +$(eval $(call combine-notice-files, xml_odm_dlkm, \ + $(target_odm_dlkm_notice_file_txt), \ + $(target_odm_dlkm_notice_file_xml), \ + "Notices for files contained in the odm_dlkm filesystem image in this directory:", \ + $(TARGET_OUT_NOTICE_FILES), \ + $(license_modules_odm_dlkm), \ + $(exclude_target_dirs))) $(target_notice_file_xml_gz): $(target_notice_file_xml) | $(MINIGZIP) $(hide) $(MINIGZIP) -9 < $< > $@ @@ -1559,6 +1168,10 @@ $(target_system_ext_notice_file_xml_gz): $(target_system_ext_notice_file_xml) | $(hide) $(MINIGZIP) -9 < $< > $@ $(target_odm_notice_file_xml_gz): $(target_odm_notice_file_xml) | $(MINIGZIP) $(hide) $(MINIGZIP) -9 < $< > $@ +$(target_vendor_dlkm_notice_file_xml_gz): $(target_vendor_dlkm_notice_file_xml) | $(MINIGZIP) + $(hide) $(MINIGZIP) -9 < $< > $@ +$(target_odm_dlkm_notice_file_xml_gz): $(target_odm_dlkm_notice_file_xml) | $(MINIGZIP) + $(hide) $(MINIGZIP) -9 < $< > $@ $(installed_notice_html_or_xml_gz): $(target_notice_file_xml_gz) $(copy-file-to-target) $(installed_vendor_notice_xml_gz): $(target_vendor_notice_file_xml_gz) @@ -1569,12 +1182,18 @@ $(installed_system_ext_notice_xml_gz): $(target_system_ext_notice_file_xml_gz) $(copy-file-to-target) $(installed_odm_notice_xml_gz): $(target_odm_notice_file_xml_gz) $(copy-file-to-target) +$(installed_vendor_dlkm_notice_xml_gz): $(target_vendor_dlkm_notice_file_xml_gz) + $(copy-file-to-target) +$(installed_odm_dlkm_notice_xml_gz): $(target_odm_dlkm_notice_file_xml_gz) + $(copy-file-to-target) ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz) ALL_DEFAULT_INSTALLED_MODULES += $(installed_vendor_notice_xml_gz) ALL_DEFAULT_INSTALLED_MODULES += $(installed_product_notice_xml_gz) ALL_DEFAULT_INSTALLED_MODULES += $(installed_system_ext_notice_xml_gz) ALL_DEFAULT_INSTALLED_MODULES += $(installed_odm_notice_xml_gz) +ALL_DEFAULT_INSTALLED_MODULES += $(installed_vendor_dlkm_notice_xml_gz) +ALL_DEFAULT_INSTALLED_MODULES += $(installed_odm_dlkm_notice_xml_gz) endif # PRODUCT_NOTICE_SPLIT ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz) @@ -1585,7 +1204,8 @@ $(eval $(call combine-notice-files, html, \ "Notices for files contained in the tools directory:", \ $(HOST_OUT_NOTICE_FILES), \ $(ALL_DEFAULT_INSTALLED_MODULES) \ - $(winpthreads_notice_file))) + $(winpthreads_notice_file), \ + $(exclude_target_dirs))) endif # TARGET_BUILD_APPS @@ -1640,7 +1260,15 @@ ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) INTERNAL_USERIMAGES_DEPS += $(MKF2FSUSERIMG) endif -ifneq ($(filter $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE) $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE) $(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE) $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE) $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),squashfs),) +ifneq ($(filter \ + $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE) \ + $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE) \ + $(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE) \ + $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE) \ + $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE) \ + $(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE) \ + $(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE) \ + ,squashfs),) INTERNAL_USERIMAGES_DEPS += $(MKSQUASHFSUSERIMG) endif @@ -1670,7 +1298,7 @@ endif endif # PRODUCT_USE_DYNAMIC_PARTITIONS # $(1): the path of the output dictionary file -# $(2): a subset of "system vendor cache userdata product system_ext oem odm" +# $(2): a subset of "system vendor cache userdata product system_ext oem odm vendor_dlkm odm_dlkm" # $(3): additional "key=value" pairs to append to the dictionary file. define generate-image-prop-dictionary $(if $(filter $(2),system),\ @@ -1688,6 +1316,10 @@ $(if $(filter $(2),system),\ $(if $(PRODUCT_SYSTEM_HEADROOM),$(hide) echo "system_headroom=$(PRODUCT_SYSTEM_HEADROOM)" >> $(1)) $(if $(BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "system_reserved_size=$(BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1)) $(hide) echo "system_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_system_image=$(BUILDING_SYSTEM_IMAGE)" >> $(1) +) +$(if $(filter $(2),system_other),\ + $(hide) echo "building_system_other_image=$(BUILDING_SYSTEM_OTHER_IMAGE)" >> $(1) ) $(if $(filter $(2),userdata),\ $(if $(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "userdata_fs_type=$(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) @@ -1695,11 +1327,13 @@ $(if $(filter $(2),userdata),\ $(if $(PRODUCT_FS_CASEFOLD),$(hide) echo "needs_casefold=$(PRODUCT_FS_CASEFOLD)" >> $(1)) $(if $(PRODUCT_QUOTA_PROJID),$(hide) echo "needs_projid=$(PRODUCT_QUOTA_PROJID)" >> $(1)) $(hide) echo "userdata_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_userdata_image=$(BUILDING_USERDATA_IMAGE)" >> $(1) ) $(if $(filter $(2),cache),\ $(if $(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "cache_fs_type=$(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) $(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),$(hide) echo "cache_size=$(BOARD_CACHEIMAGE_PARTITION_SIZE)" >> $(1)) $(hide) echo "cache_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_cache_image=$(BUILDING_CACHE_IMAGE)" >> $(1) ) $(if $(filter $(2),vendor),\ $(if $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_fs_type=$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) @@ -1714,6 +1348,7 @@ $(if $(filter $(2),vendor),\ $(if $(PRODUCT_VENDOR_BASE_FS_PATH),$(hide) echo "vendor_base_fs_file=$(PRODUCT_VENDOR_BASE_FS_PATH)" >> $(1)) $(if $(BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "vendor_reserved_size=$(BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE)" >> $(1)) $(hide) echo "vendor_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_vendor_image=$(BUILDING_VENDOR_IMAGE)" >> $(1) ) $(if $(filter $(2),product),\ $(if $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "product_fs_type=$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) @@ -1728,6 +1363,7 @@ $(if $(filter $(2),product),\ $(if $(PRODUCT_PRODUCT_BASE_FS_PATH),$(hide) echo "product_base_fs_file=$(PRODUCT_PRODUCT_BASE_FS_PATH)" >> $(1)) $(if $(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "product_reserved_size=$(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE)" >> $(1)) $(hide) echo "product_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_product_image=$(BUILDING_PRODUCT_IMAGE)" >> $(1) ) $(if $(filter $(2),system_ext),\ $(if $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_ext_fs_type=$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) @@ -1741,6 +1377,7 @@ $(if $(filter $(2),system_ext),\ $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "system_ext_squashfs_disable_4k_align=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1)) $(if $(BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "system_ext_reserved_size=$(BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE)" >> $(1)) $(hide) echo "system_ext_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_system_ext_image=$(BUILDING_SYSTEM_EXT_IMAGE)" >> $(1) ) $(if $(filter $(2),odm),\ $(if $(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "odm_fs_type=$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) @@ -1755,6 +1392,35 @@ $(if $(filter $(2),odm),\ $(if $(PRODUCT_ODM_BASE_FS_PATH),$(hide) echo "odm_base_fs_file=$(PRODUCT_ODM_BASE_FS_PATH)" >> $(1)) $(if $(BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "odm_reserved_size=$(BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1)) $(hide) echo "odm_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_odm_image=$(BUILDING_ODM_IMAGE)" >> $(1) +) +$(if $(filter $(2),vendor_dlkm),\ + $(if $(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_dlkm_fs_type=$(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "vendor_dlkm_extfs_inode_count=$(BOARD_VENDOR_DLKMIMAGE_EXTFS_INODE_COUNT)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_EXTFS_RSV_PCT),$(hide) echo "vendor_dlkm_extfs_rsv_pct=$(BOARD_VENDOR_DLKMIMAGE_EXTFS_RSV_PCT)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE),$(hide) echo "vendor_dlkm_size=$(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_JOURNAL_SIZE),$(hide) echo "vendor_dlkm_journal_size=$(BOARD_VENDOR_DLKMIMAGE_JOURNAL_SIZE)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "vendor_dlkm_squashfs_compressor=$(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "vendor_dlkm_squashfs_compressor_opt=$(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "vendor_dlkm_squashfs_block_size=$(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "vendor_dlkm_squashfs_disable_4k_align=$(BOARD_VENDOR_DLKMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1)) + $(if $(BOARD_VENDOR_DLKMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "vendor_dlkm_reserved_size=$(BOARD_VENDOR_DLKMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1)) + $(hide) echo "vendor_dlkm_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_vendor_dlkm_image=$(BUILDING_VENDOR_DLKM_IMAGE)" >> $(1) +) +$(if $(filter $(2),odm_dlkm),\ + $(if $(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "odm_dlkm_fs_type=$(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "odm_dlkm_extfs_inode_count=$(BOARD_ODM_DLKMIMAGE_EXTFS_INODE_COUNT)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_EXTFS_RSV_PCT),$(hide) echo "odm_dlkm_extfs_rsv_pct=$(BOARD_ODM_DLKMIMAGE_EXTFS_RSV_PCT)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE),$(hide) echo "odm_dlkm_size=$(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_JOURNAL_SIZE),$(hide) echo "odm_dlkm_journal_size=$(BOARD_ODM_DLKMIMAGE_JOURNAL_SIZE)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "odm_dlkm_squashfs_compressor=$(BOARD_ODM_DLKMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "odm_dlkm_squashfs_compressor_opt=$(BOARD_ODM_DLKMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "odm_dlkm_squashfs_block_size=$(BOARD_ODM_DLKMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "odm_dlkm_squashfs_disable_4k_align=$(BOARD_ODM_DLKMIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1)) + $(if $(BOARD_ODM_DLKMIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "odm_dlkm_reserved_size=$(BOARD_ODM_DLKMIMAGE_PARTITION_RESERVED_SIZE)" >> $(1)) + $(hide) echo "odm_dlkm_selinux_fc=$(SELINUX_FC)" >> $(1) + $(hide) echo "building_odm_dlkm_image=$(BUILDING_ODM_DLKM_IMAGE)" >> $(1) ) $(if $(filter $(2),oem),\ $(if $(BOARD_OEMIMAGE_PARTITION_SIZE),$(hide) echo "oem_size=$(BOARD_OEMIMAGE_PARTITION_SIZE)" >> $(1)) @@ -1782,6 +1448,8 @@ $(if $(PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device $(if $(PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1)) $(if $(PRODUCT_PRODUCT_VERITY_PARTITION),$(hide) echo "product_verity_block_device=$(PRODUCT_PRODUCT_VERITY_PARTITION)" >> $(1)) $(if $(PRODUCT_SYSTEM_EXT_VERITY_PARTITION),$(hide) echo "system_ext_verity_block_device=$(PRODUCT_SYSTEM_EXT_VERITY_PARTITION)" >> $(1)) +$(if $(PRODUCT_VENDOR_DLKM_VERITY_PARTITION),$(hide) echo "vendor_dlkm_verity_block_device=$(PRODUCT_VENDOR_DLKM_VERITY_PARTITION)" >> $(1)) +$(if $(PRODUCT_ODM_DLKM_VERITY_PARTITION),$(hide) echo "odm_dlkm_verity_block_device=$(PRODUCT_ODM_DLKM_VERITY_PARTITION)" >> $(1)) $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCT_SUPPORTS_VBOOT)" >> $(1)) $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCT_VBOOT_SIGNING_KEY)" >> $(1)) $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1)) @@ -1830,6 +1498,22 @@ $(if $(BOARD_AVB_ENABLE),\ $(hide) echo "avb_odm_key_path=$(BOARD_AVB_ODM_KEY_PATH)" >> $(1) $(hide) echo "avb_odm_algorithm=$(BOARD_AVB_ODM_ALGORITHM)" >> $(1) $(hide) echo "avb_odm_rollback_index_location=$(BOARD_AVB_ODM_ROLLBACK_INDEX_LOCATION)" >> $(1))) +$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)) +$(if $(BOARD_AVB_ENABLE),\ + $(hide) echo "avb_vendor_dlkm_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)) +$(if $(BOARD_AVB_ENABLE),\ + $(if $(BOARD_AVB_VENDOR_DLKM_KEY_PATH),\ + $(hide) echo "avb_vendor_dlkm_key_path=$(BOARD_AVB_VENDOR_DLKM_KEY_PATH)" >> $(1) + $(hide) echo "avb_vendor_dlkm_algorithm=$(BOARD_AVB_VENDOR_DLKM_ALGORITHM)" >> $(1) + $(hide) echo "avb_vendor_dlkm_rollback_index_location=$(BOARD_AVB_VENDOR_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1))) +$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_dlkm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1)) +$(if $(BOARD_AVB_ENABLE),\ + $(hide) echo "avb_odm_dlkm_add_hashtree_footer_args=$(BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1)) +$(if $(BOARD_AVB_ENABLE),\ + $(if $(BOARD_AVB_ODM_DLKM_KEY_PATH),\ + $(hide) echo "avb_odm_dlkm_key_path=$(BOARD_AVB_ODM_DLKM_KEY_PATH)" >> $(1) + $(hide) echo "avb_odm_dlkm_algorithm=$(BOARD_AVB_ODM_DLKM_ALGORITHM)" >> $(1) + $(hide) echo "avb_odm_dlkm_rollback_index_location=$(BOARD_AVB_ODM_DLKM_ROLLBACK_INDEX_LOCATION)" >> $(1))) $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\ $(hide) echo "recovery_as_boot=true" >> $(1)) $(if $(filter true,$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)),\ @@ -1849,6 +1533,9 @@ endif ifdef BUILDING_SYSTEM_IMAGE PROP_DICTIONARY_IMAGES += system endif +ifdef BUILDING_SYSTEM_OTHER_IMAGE + PROP_DICTIONARY_IMAGES += system_other +endif ifdef BUILDING_USERDATA_IMAGE PROP_DICTIONARY_IMAGES += userdata endif @@ -1864,6 +1551,12 @@ endif ifdef BUILDING_ODM_IMAGE PROP_DICTIONARY_IMAGES += odm endif +ifdef BUILDING_VENDOR_DLKM_IMAGE + PROP_DICTIONARY_IMAGES += vendor_dlkm +endif +ifdef BUILDING_ODM_DLKM_IMAGE + PROP_DICTIONARY_IMAGES += odm_dlkm +endif define generate-userimage-prop-dictionary $(call generate-image-prop-dictionary,$(1),$(PROP_DICTIONARY_IMAGES),$(2)) endef @@ -1922,9 +1615,11 @@ recovery_sepolicy := \ # SELinux files IGNORE_RECOVERY_SEPOLICY := $(patsubst $(TARGET_RECOVERY_OUT)/%,--exclude=/%,$(recovery_sepolicy)) -recovery_kernel := $(INSTALLED_KERNEL_TARGET) # same as a non-recovery system +# if building multiple boot images from multiple kernels, use the first kernel listed +# for the recovery image +recovery_kernel := $(firstword $(INSTALLED_KERNEL_TARGET)) recovery_ramdisk := $(PRODUCT_OUT)/ramdisk-recovery.img -recovery_resources_common := $(call include-path-for, recovery)/res +recovery_resources_common := bootable/recovery/res # Set recovery_density to a density bucket based on TARGET_SCREEN_DENSITY, PRODUCT_AAPT_PREF_CONFIG, # or mdpi, in order of preference. We support both specific buckets (e.g. xdpi) and numbers, @@ -1952,9 +1647,9 @@ endif # Note that the font selected here can be overridden for a particular device by putting a font.png # in its private recovery resources. ifneq (,$(filter xxxhdpi xxhdpi xhdpi,$(recovery_density))) -recovery_font := $(call include-path-for, recovery)/fonts/18x32.png +recovery_font := bootable/recovery/fonts/18x32.png else -recovery_font := $(call include-path-for, recovery)/fonts/12x22.png +recovery_font := bootable/recovery/fonts/12x22.png endif @@ -1978,7 +1673,7 @@ else endif -RECOVERY_INSTALLING_TEXT_FILE := $(call intermediates-dir-for,PACKAGING,recovery_text_res)/installing_text.png +RECOVERY_INSTALLING_TEXT_FILE := $(call intermediates-dir-for,ETC,recovery_text_res)/installing_text.png RECOVERY_INSTALLING_SECURITY_TEXT_FILE := $(dir $(RECOVERY_INSTALLING_TEXT_FILE))/installing_security_text.png RECOVERY_ERASING_TEXT_FILE := $(dir $(RECOVERY_INSTALLING_TEXT_FILE))/erasing_text.png RECOVERY_ERROR_TEXT_FILE := $(dir $(RECOVERY_INSTALLING_TEXT_FILE))/error_text.png @@ -2002,11 +1697,12 @@ generated_recovery_text_files := \ $(RECOVERY_WIPE_DATA_CONFIRMATION_TEXT_FILE) \ $(RECOVERY_WIPE_DATA_MENU_HEADER_TEXT_FILE) -resource_dir := $(call include-path-for, recovery)/tools/recovery_l10n/res/ +resource_dir := bootable/recovery/tools/recovery_l10n/res/ +resource_dir_deps := $(sort $(shell find $(resource_dir) -name *.xml -not -name .*)) image_generator_jar := $(HOST_OUT_JAVA_LIBRARIES)/RecoveryImageGenerator.jar zopflipng := $(HOST_OUT_EXECUTABLES)/zopflipng $(RECOVERY_INSTALLING_TEXT_FILE): PRIVATE_SOURCE_FONTS := $(recovery_noto-fonts_dep) $(recovery_roboto-fonts_dep) -$(RECOVERY_INSTALLING_TEXT_FILE): PRIVATE_RECOVERY_FONT_FILES_DIR := $(call intermediates-dir-for,PACKAGING,recovery_font_files) +$(RECOVERY_INSTALLING_TEXT_FILE): PRIVATE_RECOVERY_FONT_FILES_DIR := $(call intermediates-dir-for,ETC,recovery_font_files) $(RECOVERY_INSTALLING_TEXT_FILE): PRIVATE_RESOURCE_DIR := $(resource_dir) $(RECOVERY_INSTALLING_TEXT_FILE): PRIVATE_IMAGE_GENERATOR_JAR := $(image_generator_jar) $(RECOVERY_INSTALLING_TEXT_FILE): PRIVATE_ZOPFLIPNG := $(zopflipng) @@ -2024,7 +1720,7 @@ $(RECOVERY_INSTALLING_TEXT_FILE): PRIVATE_RECOVERY_WIPE_DATA_TEXT_LIST := \ recovery_wipe_data_menu_header \ recovery_wipe_data_confirmation $(RECOVERY_INSTALLING_TEXT_FILE): .KATI_IMPLICIT_OUTPUTS := $(filter-out $(RECOVERY_INSTALLING_TEXT_FILE),$(generated_recovery_text_files)) -$(RECOVERY_INSTALLING_TEXT_FILE): $(image_generator_jar) $(resource_dir) $(recovery_noto-fonts_dep) $(recovery_roboto-fonts_dep) $(zopflipng) +$(RECOVERY_INSTALLING_TEXT_FILE): $(image_generator_jar) $(resource_dir_deps) $(recovery_noto-fonts_dep) $(recovery_roboto-fonts_dep) $(zopflipng) # Prepares the font directory. @rm -rf $(PRIVATE_RECOVERY_FONT_FILES_DIR) @mkdir -p $(PRIVATE_RECOVERY_FONT_FILES_DIR) @@ -2131,9 +1827,7 @@ $(foreach prop,$(1), \ endef $(INSTALLED_RECOVERY_BUILD_PROP_TARGET): \ - $(INSTALLED_DEFAULT_PROP_TARGET) \ - $(INSTALLED_VENDOR_DEFAULT_PROP_TARGET) \ - $(intermediate_system_build_prop) \ + $(INSTALLED_BUILD_PROP_TARGET) \ $(INSTALLED_VENDOR_BUILD_PROP_TARGET) \ $(INSTALLED_ODM_BUILD_PROP_TARGET) \ $(INSTALLED_PRODUCT_BUILD_PROP_TARGET) \ @@ -2141,9 +1835,7 @@ $(INSTALLED_RECOVERY_BUILD_PROP_TARGET): \ @echo "Target recovery buildinfo: $@" $(hide) mkdir -p $(dir $@) $(hide) rm -f $@ - $(hide) cat $(INSTALLED_DEFAULT_PROP_TARGET) > $@ - $(hide) cat $(INSTALLED_VENDOR_DEFAULT_PROP_TARGET) >> $@ - $(hide) cat $(intermediate_system_build_prop) >> $@ + $(hide) cat $(INSTALLED_BUILD_PROP_TARGET) >> $@ $(hide) cat $(INSTALLED_VENDOR_BUILD_PROP_TARGET) >> $@ $(hide) cat $(INSTALLED_ODM_BUILD_PROP_TARGET) >> $@ $(hide) cat $(INSTALLED_PRODUCT_BUILD_PROP_TARGET) >> $@ @@ -2294,7 +1986,7 @@ endif .PHONY: recoveryimage-nodeps recoveryimage-nodeps: @echo "make $@: ignoring dependencies" - $(call build-recoveryimage-target, $(INSTALLED_RECOVERYIMAGE_TARGET)) + $(call build-recoveryimage-target, $(INSTALLED_RECOVERYIMAGE_TARGET), $(recovery_kernel)) else # BUILDING_RECOVERY_IMAGE RECOVERY_RESOURCE_ZIP := @@ -2515,7 +2207,7 @@ endif # Depends on vendor_boot.img and vendor-ramdisk-debug.cpio.gz to build the new vendor_boot-debug.img $(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) $(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) $(call pretty,"Target vendor_boot debug image: $@") - $(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) --vendor_boot $@ + $(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) --vendor_boot $@ $(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE)) $(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),$(call test-key-sign-vendor-bootimage,$@)) @@ -2611,19 +2303,47 @@ bootimage_test_harness-nodeps: $(MKBOOTIMG) endif # TARGET_NO_KERNEL endif # BOARD_BUILD_SYSTEM_ROOT_IMAGE is not true +# Creates a compatibility symlink between two partitions, e.g. /system/vendor to /vendor +# $1: from location (e.g $(TARGET_OUT)/vendor) +# $2: destination location (e.g. /vendor) +# $3: partition image name (e.g. vendor.img) +define create-partition-compat-symlink +$(eval \ +$1: + @echo Symlink $(patsubst $(PRODUCT_OUT)/%,%,$1) to $2 + mkdir -p $(dir $1) + if [ -d $1 ] && [ ! -h $1 ]; then \ + echo 'Non-symlink $1 detected!' 1>&2; \ + echo 'You cannot install files to $1 while building a separate $3!' 1>&2; \ + exit 1; \ + fi + ln -sfn $2 $1 +) +$1 +endef + + # ----------------------------------------------------------------- # system image -# -# Remove overridden packages from $(ALL_PDK_FUSION_FILES) -PDK_FUSION_SYSIMG_FILES := \ - $(filter-out $(foreach p,$(overridden_packages),$(p) %/$(p).apk), \ - $(ALL_PDK_FUSION_FILES)) INTERNAL_SYSTEMIMAGE_FILES := $(sort $(filter $(TARGET_OUT)/%, \ $(ALL_GENERATED_SOURCES) \ - $(ALL_DEFAULT_INSTALLED_MODULES) \ - $(PDK_FUSION_SYSIMG_FILES)) \ - $(PDK_FUSION_SYMLINK_STAMP)) + $(ALL_DEFAULT_INSTALLED_MODULES))) + +# Create symlink /system/vendor to /vendor if necessary. +ifdef BOARD_USES_VENDORIMAGE + INTERNAL_SYSTEMIMAGE_FILES += $(call create-partition-compat-symlink,$(TARGET_OUT)/vendor,/vendor,vendor.img) +endif + +# Create symlink /system/product to /product if necessary. +ifdef BOARD_USES_PRODUCTIMAGE + INTERNAL_SYSTEMIMAGE_FILES += $(call create-partition-compat-symlink,$(TARGET_OUT)/product,/product,product.img) +endif + +# Create symlink /system/system_ext to /system_ext if necessary. +ifdef BOARD_USES_SYSTEM_EXTIMAGE + INTERNAL_SYSTEMIMAGE_FILES += $(call create-partition-compat-symlink,$(TARGET_OUT)/system_ext,/system_ext,system_ext.img) +endif FULL_SYSTEMIMAGE_DEPS := $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS) @@ -2664,57 +2384,9 @@ systemimage_intermediates := \ $(call intermediates-dir-for,PACKAGING,systemimage) BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img -# Create symlink /system/vendor to /vendor if necessary. -ifdef BOARD_USES_VENDORIMAGE -define create-system-vendor-symlink -$(hide) if [ -d $(TARGET_OUT)/vendor ] && [ ! -h $(TARGET_OUT)/vendor ]; then \ - echo 'Non-symlink $(TARGET_OUT)/vendor detected!' 1>&2; \ - echo 'You cannot install files to $(TARGET_OUT)/vendor while building a separate vendor.img!' 1>&2; \ - exit 1; \ -fi -$(hide) ln -sf /vendor $(TARGET_OUT)/vendor -endef -else -define create-system-vendor-symlink -endef -endif - -# Create symlink /system/product to /product if necessary. -ifdef BOARD_USES_PRODUCTIMAGE -define create-system-product-symlink -$(hide) if [ -d $(TARGET_OUT)/product ] && [ ! -h $(TARGET_OUT)/product ]; then \ - echo 'Non-symlink $(TARGET_OUT)/product detected!' 1>&2; \ - echo 'You cannot install files to $(TARGET_OUT)/product while building a separate product.img!' 1>&2; \ - exit 1; \ -fi -$(hide) ln -sf /product $(TARGET_OUT)/product -endef -else -define create-system-product-symlink -endef -endif - -# Create symlink /system/system_ext to /system_ext if necessary. -ifdef BOARD_USES_SYSTEM_EXTIMAGE -define create-system-system_ext-symlink -$(hide) if [ -d $(TARGET_OUT)/system_ext ] && [ ! -h $(TARGET_OUT)/system_ext ]; then \ - echo 'Non-symlink $(TARGET_OUT)/system_ext detected!' 1>&2; \ - echo 'You cannot install files to $(TARGET_OUT)/system_ext while building a separate system_ext.img!' 1>&2; \ - exit 1; \ -fi -$(hide) ln -sf /system_ext $(TARGET_OUT)/system_ext -endef -else -define create-system-system_ext-symlink -endef -endif - # $(1): output file define build-systemimage-target @echo "Target system fs image: $(1)" - $(call create-system-vendor-symlink) - $(call create-system-product-symlink) - $(call create-system-system_ext-symlink) @mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt $(call generate-image-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt,system, \ skip_fsck=true) @@ -2757,11 +2429,11 @@ RECOVERY_FROM_BOOT_PATCH := $(intermediates)/recovery_from_boot.p $(RECOVERY_FROM_BOOT_PATCH): PRIVATE_DIFF_TOOL := $(diff_tool) $(RECOVERY_FROM_BOOT_PATCH): \ $(INSTALLED_RECOVERYIMAGE_TARGET) \ - $(INSTALLED_BOOTIMAGE_TARGET) \ + $(firstword $(INSTALLED_BOOTIMAGE_TARGET)) \ $(diff_tool) @echo "Construct recovery from boot" mkdir -p $(dir $@) - $(PRIVATE_DIFF_TOOL) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@ + $(PRIVATE_DIFF_TOOL) $(firstword $(INSTALLED_BOOTIMAGE_TARGET)) $(INSTALLED_RECOVERYIMAGE_TARGET) $@ else # $(BOARD_USES_FULL_RECOVERY_IMAGE) == true RECOVERY_FROM_BOOT_PATCH := $(INSTALLED_RECOVERYIMAGE_TARGET) endif # BOARD_USES_FULL_RECOVERY_IMAGE @@ -2781,11 +2453,8 @@ systemimage-nodeps snod: $(filter-out systemimage-nodeps snod,$(MAKECMDGOALS)) \ @echo "make $@: ignoring dependencies" $(call build-systemimage-target,$(INSTALLED_SYSTEMIMAGE_TARGET)) $(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)) - -ifneq (,$(filter systemimage-nodeps snod, $(MAKECMDGOALS))) ifeq (true,$(WITH_DEXPREOPT)) -$(warning Warning: with dexpreopt enabled, you may need a full rebuild.) -endif + $(warning Warning: with dexpreopt enabled, you may need a full rebuild.) endif endif # BUILDING_SYSTEM_IMAGE @@ -2794,105 +2463,14 @@ endif # BUILDING_SYSTEM_IMAGE sync syncsys: $(INTERNAL_SYSTEMIMAGE_FILES) # ----------------------------------------------------------------- -## platform.zip: system, plus other files to be used in PDK fusion build, -## in a zip file -## -## PDK_PLATFORM_ZIP_PRODUCT_BINARIES is used to store specified files to platform.zip. -## The variable will be typically set from BoardConfig.mk. -## Files under out dir will be rejected to prevent possible conflicts with other rules. -ifneq (,$(BUILD_PLATFORM_ZIP)) -pdk_odex_javalibs := $(strip $(foreach m,$(DEXPREOPT.MODULES.JAVA_LIBRARIES),\ - $(if $(filter $(DEXPREOPT.$(m).INSTALLED_STRIPPED),$(ALL_DEFAULT_INSTALLED_MODULES)),$(m)))) -pdk_odex_apps := $(strip $(foreach m,$(DEXPREOPT.MODULES.APPS),\ - $(if $(filter $(DEXPREOPT.$(m).INSTALLED_STRIPPED),$(ALL_DEFAULT_INSTALLED_MODULES)),$(m)))) -pdk_classes_dex := $(strip \ - $(foreach m,$(pdk_odex_javalibs),$(call intermediates-dir-for,JAVA_LIBRARIES,$(m),,COMMON)/javalib.jar) \ - $(foreach m,$(pdk_odex_apps),$(call intermediates-dir-for,APPS,$(m))/package.apk)) - -pdk_odex_config_mk := $(PRODUCT_OUT)/pdk_dexpreopt_config.mk -$(pdk_odex_config_mk): PRIVATE_JAVA_LIBRARIES := $(pdk_odex_javalibs) -$(pdk_odex_config_mk): PRIVATE_APPS := $(pdk_odex_apps) -$(pdk_odex_config_mk) : - @echo "PDK odex config makefile: $@" - $(hide) mkdir -p $(dir $@) - $(hide) echo "# Auto-generated. Do not modify." > $@ - $(hide) echo "PDK.DEXPREOPT.JAVA_LIBRARIES:=$(PRIVATE_JAVA_LIBRARIES)" >> $@ - $(hide) echo "PDK.DEXPREOPT.APPS:=$(PRIVATE_APPS)" >> $@ - $(foreach m,$(PRIVATE_JAVA_LIBRARIES),\ - $(hide) echo "PDK.DEXPREOPT.$(m).SRC:=$(patsubst $(OUT_DIR)/%,%,$(call intermediates-dir-for,JAVA_LIBRARIES,$(m),,COMMON)/javalib.jar)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).DEX_PREOPT:=$(DEXPREOPT.$(m).DEX_PREOPT)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).MULTILIB:=$(DEXPREOPT.$(m).MULTILIB)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).DEX_PREOPT_FLAGS:=$(DEXPREOPT.$(m).DEX_PREOPT_FLAGS)" >> $@$(newline)\ - ) - $(foreach m,$(PRIVATE_APPS),\ - $(hide) echo "PDK.DEXPREOPT.$(m).SRC:=$(patsubst $(OUT_DIR)/%,%,$(call intermediates-dir-for,APPS,$(m))/package.apk)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).DEX_PREOPT:=$(DEXPREOPT.$(m).DEX_PREOPT)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).MULTILIB:=$(DEXPREOPT.$(m).MULTILIB)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).DEX_PREOPT_FLAGS:=$(DEXPREOPT.$(m).DEX_PREOPT_FLAGS)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).PRIVILEGED_MODULE:=$(DEXPREOPT.$(m).PRIVILEGED_MODULE)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).VENDOR_MODULE:=$(DEXPREOPT.$(m).VENDOR_MODULE)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).TARGET_ARCH:=$(DEXPREOPT.$(m).TARGET_ARCH)" >> $@$(newline)\ - $(hide) echo "PDK.DEXPREOPT.$(m).STRIPPED_SRC:=$(patsubst $(PRODUCT_OUT)/%,%,$(DEXPREOPT.$(m).INSTALLED_STRIPPED))" >> $@$(newline)\ - ) - -PDK_PLATFORM_ZIP_PRODUCT_BINARIES := $(filter-out $(OUT_DIR)/%,$(PDK_PLATFORM_ZIP_PRODUCT_BINARIES)) -INSTALLED_PLATFORM_ZIP := $(PRODUCT_OUT)/platform.zip - -$(INSTALLED_PLATFORM_ZIP): PRIVATE_DEX_FILES := $(pdk_classes_dex) -$(INSTALLED_PLATFORM_ZIP): PRIVATE_ODEX_CONFIG := $(pdk_odex_config_mk) -$(INSTALLED_PLATFORM_ZIP) : $(SOONG_ZIP) -# dependencies for the other partitions are defined below after their file lists -# are known -$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_SYSTEMIMAGE_FILES) $(pdk_classes_dex) $(pdk_odex_config_mk) $(API_FINGERPRINT) - $(call pretty,"Platform zip package: $(INSTALLED_PLATFORM_ZIP)") - rm -f $@ $@.lst - echo "-C $(PRODUCT_OUT)" >> $@.lst - echo "-D $(TARGET_OUT)" >> $@.lst - echo "-D $(TARGET_OUT_NOTICE_FILES)" >> $@.lst - echo "$(addprefix -f $(TARGET_OUT_UNSTRIPPED)/,$(PDK_SYMBOL_FILES_LIST))" >> $@.lst -ifdef BUILDING_VENDOR_IMAGE - echo "-D $(TARGET_OUT_VENDOR)" >> $@.lst -endif -ifdef BUILDING_PRODUCT_IMAGE - echo "-D $(TARGET_OUT_PRODUCT)" >> $@.lst -endif -ifdef BUILDING_SYSTEM_EXT_IMAGE - echo "-D $(TARGET_OUT_SYSTEM_EXT)" >> $@.lst -endif -ifdef BUILDING_ODM_IMAGE - echo "-D $(TARGET_OUT_ODM)" >> $@.lst -endif -ifneq ($(PDK_PLATFORM_JAVA_ZIP_CONTENTS),) - echo "-C $(OUT_DIR)" >> $@.lst - for f in $(filter-out $(PRIVATE_DEX_FILES),$(addprefix -f $(OUT_DIR)/,$(PDK_PLATFORM_JAVA_ZIP_CONTENTS))); do \ - if [ -e $$f ]; then \ - echo "-f $$f"; \ - fi \ - done >> $@.lst -endif -ifneq ($(PDK_PLATFORM_ZIP_PRODUCT_BINARIES),) - echo "-C . $(addprefix -f ,$(PDK_PLATFORM_ZIP_PRODUCT_BINARIES))" >> $@.lst -endif - @# Add dex-preopt files and config. - $(if $(PRIVATE_DEX_FILES),\ - echo "-C $(OUT_DIR) $(addprefix -f ,$(PRIVATE_DEX_FILES))") >> $@.lst - echo "-C $(dir $(API_FINGERPRINT)) -f $(API_FINGERPRINT)" >> $@.lst - touch $(PRODUCT_OUT)/pdk.mk - echo "-C $(PRODUCT_OUT) -f $(PRIVATE_ODEX_CONFIG) -f $(PRODUCT_OUT)/pdk.mk" >> $@.lst - $(SOONG_ZIP) --ignore_missing_files -o $@ @$@.lst - +# Old PDK fusion targets .PHONY: platform -platform: $(INSTALLED_PLATFORM_ZIP) +platform: + echo "Warning: 'platform' is obsolete" .PHONY: platform-java -platform-java: platform - -# Dist the platform.zip -ifneq (,$(filter platform platform-java, $(MAKECMDGOALS))) -$(call dist-for-goals, platform platform-java, $(INSTALLED_PLATFORM_ZIP)) -endif - -endif # BUILD_PLATFORM_ZIP +platform-java: + echo "Warning: 'platform-java' is obsolete" # ----------------------------------------------------------------- # data partition image @@ -3026,9 +2604,7 @@ endif INTERNAL_SYSTEMOTHERIMAGE_FILES := \ $(filter $(TARGET_OUT_SYSTEM_OTHER)/%,\ - $(ALL_DEFAULT_INSTALLED_MODULES)\ - $(ALL_PDK_FUSION_FILES)) \ - $(PDK_FUSION_SYMLINK_STAMP) + $(ALL_DEFAULT_INSTALLED_MODULES)) # system_other dex files are installed as a side-effect of installing system image files INTERNAL_SYSTEMOTHERIMAGE_FILES += $(INTERNAL_SYSTEMIMAGE_FILES) @@ -3091,12 +2667,31 @@ endif # BUILDING_SYSTEM_OTHER_IMAGE ifdef BUILDING_VENDOR_IMAGE INTERNAL_VENDORIMAGE_FILES := \ $(filter $(TARGET_OUT_VENDOR)/%,\ - $(ALL_DEFAULT_INSTALLED_MODULES)\ - $(ALL_PDK_FUSION_FILES)) \ - $(PDK_FUSION_SYMLINK_STAMP) + $(ALL_DEFAULT_INSTALLED_MODULES)) -# platform.zip depends on $(INTERNAL_VENDORIMAGE_FILES). -$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_VENDORIMAGE_FILES) + +# Create symlink /vendor/odm to /odm if necessary. +ifdef BOARD_USES_ODMIMAGE + INTERNAL_VENDORIMAGE_FILES += $(call create-partition-compat-symlink,$(TARGET_OUT_VENDOR)/odm,/odm,odm.img) +endif + +# Create symlinks for vendor_dlkm on devices with a vendor_dlkm partition: +# /vendor/lib/modules -> /vendor_dlkm/lib/modules +# +# On devices with a vendor_dlkm partition, +# - /vendor/lib/modules is a symlink to a directory that stores vendor DLKMs. +# - /vendor_dlkm/{etc,...} store other vendor_dlkm files directly. The vendor_dlkm partition is +# mounted at /vendor_dlkm at runtime and the symlinks created in system/core/rootdir/Android.mk +# are hidden. +# On devices without a vendor_dlkm partition, +# - /vendor/lib/modules stores vendor DLKMs directly. +# - /vendor_dlkm/{etc,...} are symlinks to directories that store other vendor_dlkm files. +# See system/core/rootdir/Android.mk for a list of created symlinks. +# The vendor DLKMs and other vendor_dlkm files must not be accessed using other paths because they +# are not guaranteed to exist on all devices. +ifdef BOARD_USES_VENDOR_DLKMIMAGE + INTERNAL_VENDORIMAGE_FILES += $(call create-partition-compat-symlink,$(TARGET_OUT_VENDOR)/lib/modules,/vendor_dlkm/lib/modules,vendor_dlkm.img) +endif INSTALLED_FILES_FILE_VENDOR := $(PRODUCT_OUT)/installed-files-vendor.txt INSTALLED_FILES_JSON_VENDOR := $(INSTALLED_FILES_FILE_VENDOR:.txt=.json) @@ -3108,28 +2703,12 @@ $(INSTALLED_FILES_FILE_VENDOR) : $(INTERNAL_VENDORIMAGE_FILES) $(FILESLIST) $(FI $(hide) $(FILESLIST) $(TARGET_OUT_VENDOR) > $(@:.txt=.json) $(hide) $(FILESLIST_UTIL) -c $(@:.txt=.json) > $@ -# Create symlink /vendor/odm to /odm if necessary. -ifdef BOARD_USES_ODMIMAGE -define create-vendor-odm-symlink -$(hide) if [ -d $(TARGET_OUT_VENDOR)/odm ] && [ ! -h $(TARGET_OUT_VENDOR)/odm ]; then \ - echo 'Non-symlink $(TARGET_OUT_VENDOR)/odm detected!' 1>&2; \ - echo 'You cannot install files to $(TARGET_OUT_VENDOR)/odm while building a separate odm.img!' 1>&2; \ - exit 1; \ -fi -$(hide) ln -sf /odm $(TARGET_OUT_VENDOR)/odm -endef -else -define create-vendor-odm-symlink -endef -endif - vendorimage_intermediates := \ $(call intermediates-dir-for,PACKAGING,vendor) BUILT_VENDORIMAGE_TARGET := $(PRODUCT_OUT)/vendor.img define build-vendorimage-target $(call pretty,"Target vendor fs image: $(INSTALLED_VENDORIMAGE_TARGET)") @mkdir -p $(TARGET_OUT_VENDOR) - $(call create-vendor-odm-symlink) @mkdir -p $(vendorimage_intermediates) && rm -rf $(vendorimage_intermediates)/vendor_image_info.txt $(call generate-image-prop-dictionary, $(vendorimage_intermediates)/vendor_image_info.txt,vendor,skip_fsck=true) PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \ @@ -3164,12 +2743,7 @@ endif ifdef BUILDING_PRODUCT_IMAGE INTERNAL_PRODUCTIMAGE_FILES := \ $(filter $(TARGET_OUT_PRODUCT)/%,\ - $(ALL_DEFAULT_INSTALLED_MODULES)\ - $(ALL_PDK_FUSION_FILES)) \ - $(PDK_FUSION_SYMLINK_STAMP) - -# platform.zip depends on $(INTERNAL_PRODUCTIMAGE_FILES). -$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_PRODUCTIMAGE_FILES) + $(ALL_DEFAULT_INSTALLED_MODULES)) INSTALLED_FILES_FILE_PRODUCT := $(PRODUCT_OUT)/installed-files-product.txt INSTALLED_FILES_JSON_PRODUCT := $(INSTALLED_FILES_FILE_PRODUCT:.txt=.json) @@ -3220,12 +2794,7 @@ endif ifdef BUILDING_SYSTEM_EXT_IMAGE INTERNAL_SYSTEM_EXTIMAGE_FILES := \ $(filter $(TARGET_OUT_SYSTEM_EXT)/%,\ - $(ALL_DEFAULT_INSTALLED_MODULES)\ - $(ALL_PDK_FUSION_FILES)) \ - $(PDK_FUSION_SYMLINK_STAMP) - -# platform.zip depends on $(INTERNAL_SYSTEM_EXTIMAGE_FILES). -$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_SYSTEM_EXTIMAGE_FILES) + $(ALL_DEFAULT_INSTALLED_MODULES)) INSTALLED_FILES_FILE_SYSTEM_EXT := $(PRODUCT_OUT)/installed-files-system_ext.txt INSTALLED_FILES_JSON_SYSTEM_EXT := $(INSTALLED_FILES_FILE_SYSTEM_EXT:.txt=.json) @@ -3278,11 +2847,25 @@ endif ifdef BUILDING_ODM_IMAGE INTERNAL_ODMIMAGE_FILES := \ $(filter $(TARGET_OUT_ODM)/%,\ - $(ALL_DEFAULT_INSTALLED_MODULES)\ - $(ALL_PDK_FUSION_FILES)) \ - $(PDK_FUSION_SYMLINK_STAMP) -# platform.zip depends on $(INTERNAL_ODMIMAGE_FILES). -$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_ODMIMAGE_FILES) + $(ALL_DEFAULT_INSTALLED_MODULES)) + +# Create symlinks for odm_dlkm on devices with a odm_dlkm partition: +# /odm/lib/modules -> /odm_dlkm/lib/modules +# +# On devices with a odm_dlkm partition, +# - /odm/lib/modules is a symlink to a directory that stores odm DLKMs. +# - /odm_dlkm/{etc,...} store other odm_dlkm files directly. The odm_dlkm partition is +# mounted at /odm_dlkm at runtime and the symlinks created in system/core/rootdir/Android.mk +# are hidden. +# On devices without a odm_dlkm partition, +# - /odm/lib/modules stores odm DLKMs directly. +# - /odm_dlkm/{etc,...} are symlinks to directories that store other odm_dlkm files. +# See system/core/rootdir/Android.mk for a list of created symlinks. +# The odm DLKMs and other odm_dlkm files must not be accessed using other paths because they +# are not guaranteed to exist on all devices. +ifdef BOARD_USES_ODM_DLKMIMAGE + INTERNAL_ODMIMAGE_FILES += $(call create-partition-compat-symlink,$(TARGET_OUT_ODM)/lib/modules,/odm_dlkm/lib/modules,odm_dlkm.img) +endif INSTALLED_FILES_FILE_ODM := $(PRODUCT_OUT)/installed-files-odm.txt INSTALLED_FILES_JSON_ODM := $(INSTALLED_FILES_FILE_ODM:.txt=.json) @@ -3329,6 +2912,109 @@ $(eval $(call copy-one-file,$(BOARD_PREBUILT_ODMIMAGE),$(INSTALLED_ODMIMAGE_TARG endif # ----------------------------------------------------------------- +# vendor_dlkm partition image +ifdef BUILDING_VENDOR_DLKM_IMAGE +INTERNAL_VENDOR_DLKMIMAGE_FILES := \ + $(filter $(TARGET_OUT_VENDOR_DLKM)/%,\ + $(ALL_DEFAULT_INSTALLED_MODULES)) + +INSTALLED_FILES_FILE_VENDOR_DLKM := $(PRODUCT_OUT)/installed-files-vendor_dlkm.txt +INSTALLED_FILES_JSON_VENDOR_DLKM := $(INSTALLED_FILES_FILE_VENDOR_DLKM:.txt=.json) +$(INSTALLED_FILES_FILE_VENDOR_DLKM): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_VENDOR_DLKM) +$(INSTALLED_FILES_FILE_VENDOR_DLKM) : $(INTERNAL_VENDOR_DLKMIMAGE_FILES) $(FILESLIST) $(FILESLIST_UTIL) + @echo Installed file list: $@ + @mkdir -p $(dir $@) + @rm -f $@ + $(hide) $(FILESLIST) $(TARGET_OUT_VENDOR_DLKM) > $(@:.txt=.json) + $(hide) $(FILESLIST_UTIL) -c $(@:.txt=.json) > $@ + +vendor_dlkmimage_intermediates := \ + $(call intermediates-dir-for,PACKAGING,vendor_dlkm) +BUILT_VENDOR_DLKMIMAGE_TARGET := $(PRODUCT_OUT)/vendor_dlkm.img +define build-vendor_dlkmimage-target + $(call pretty,"Target vendor_dlkm fs image: $(INSTALLED_VENDOR_DLKMIMAGE_TARGET)") + @mkdir -p $(TARGET_OUT_VENDOR_DLKM) + @mkdir -p $(vendor_dlkmimage_intermediates) && rm -rf $(vendor_dlkmimage_intermediates)/vendor_dlkm_image_info.txt + $(call generate-userimage-prop-dictionary, $(vendor_dlkmimage_intermediates)/vendor_dlkm_image_info.txt, skip_fsck=true) + PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \ + $(BUILD_IMAGE) \ + $(TARGET_OUT_VENDOR_DLKM) $(vendor_dlkmimage_intermediates)/vendor_dlkm_image_info.txt \ + $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) $(TARGET_OUT) + $(call assert-max-image-size,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),$(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE)) +endef + +# We just build this directly to the install location. +INSTALLED_VENDOR_DLKMIMAGE_TARGET := $(BUILT_VENDOR_DLKMIMAGE_TARGET) +$(INSTALLED_VENDOR_DLKMIMAGE_TARGET): \ + $(INTERNAL_USERIMAGES_DEPS) \ + $(INTERNAL_VENDOR_DLKMIMAGE_FILES) \ + $(INSTALLED_FILES_FILE_VENDOR_DLKM) + $(build-vendor_dlkmimage-target) + +.PHONY: vendor_dlkmimage-nodeps vdnod +vendor_dlkmimage-nodeps vdnod: | $(INTERNAL_USERIMAGES_DEPS) + $(build-vendor_dlkmimage-target) + +sync: $(INTERNAL_VENDOR_DLKMIMAGE_FILES) + +else ifdef BOARD_PREBUILT_VENDOR_DLKMIMAGE +INSTALLED_VENDOR_DLKMIMAGE_TARGET := $(PRODUCT_OUT)/vendor_dlkm.img +$(eval $(call copy-one-file,$(BOARD_PREBUILT_VENDOR_DLKMIMAGE),$(INSTALLED_VENDOR_DLKMIMAGE_TARGET))) +endif + +# ----------------------------------------------------------------- +# odm_dlkm partition image +ifdef BUILDING_ODM_DLKM_IMAGE +INTERNAL_ODM_DLKMIMAGE_FILES := \ + $(filter $(TARGET_OUT_ODM_DLKM)/%,\ + $(ALL_DEFAULT_INSTALLED_MODULES)) + +INSTALLED_FILES_FILE_ODM_DLKM := $(PRODUCT_OUT)/installed-files-odm_dlkm.txt +INSTALLED_FILES_JSON_ODM_DLKM := $(INSTALLED_FILES_FILE_ODM_DLKM:.txt=.json) +$(INSTALLED_FILES_FILE_ODM_DLKM): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_ODM_DLKM) +$(INSTALLED_FILES_FILE_ODM_DLKM) : $(INTERNAL_ODM_DLKMIMAGE_FILES) $(FILESLIST) $(FILESLIST_UTIL) + @echo Installed file list: $@ + @mkdir -p $(dir $@) + @rm -f $@ + $(hide) $(FILESLIST) $(TARGET_OUT_ODM_DLKM) > $(@:.txt=.json) + $(hide) $(FILESLIST_UTIL) -c $(@:.txt=.json) > $@ + +odm_dlkmimage_intermediates := \ + $(call intermediates-dir-for,PACKAGING,odm_dlkm) +BUILT_ODM_DLKMIMAGE_TARGET := $(PRODUCT_OUT)/odm_dlkm.img +define build-odm_dlkmimage-target + $(call pretty,"Target odm_dlkm fs image: $(INSTALLED_ODM_DLKMIMAGE_TARGET)") + @mkdir -p $(TARGET_OUT_ODM_DLKM) + @mkdir -p $(odm_dlkmimage_intermediates) && rm -rf $(odm_dlkmimage_intermediates)/odm_dlkm_image_info.txt + $(call generate-userimage-prop-dictionary, $(odm_dlkmimage_intermediates)/odm_dlkm_image_info.txt, skip_fsck=true) + PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \ + $(BUILD_IMAGE) \ + $(TARGET_OUT_ODM_DLKM) $(odm_dlkmimage_intermediates)/odm_dlkm_image_info.txt \ + $(INSTALLED_ODM_DLKMIMAGE_TARGET) $(TARGET_OUT) + $(call assert-max-image-size,$(INSTALLED_ODM_DLKMIMAGE_TARGET),$(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE)) +endef + +# We just build this directly to the install location. +INSTALLED_ODM_DLKMIMAGE_TARGET := $(BUILT_ODM_DLKMIMAGE_TARGET) +$(INSTALLED_ODM_DLKMIMAGE_TARGET): \ + $(INTERNAL_USERIMAGES_DEPS) \ + $(INTERNAL_ODM_DLKMIMAGE_FILES) \ + $(INSTALLED_FILES_FILE_ODM_DLKM) + $(build-odm_dlkmimage-target) + +.PHONY: odm_dlkmimage-nodeps odnod +odm_dlkmimage-nodeps odnod: | $(INTERNAL_USERIMAGES_DEPS) + $(build-odm_dlkmimage-target) + +sync: $(INTERNAL_ODM_DLKMIMAGE_FILES) + +else ifdef BOARD_PREBUILT_ODM_DLKMIMAGE +INSTALLED_ODM_DLKMIMAGE_TARGET := $(PRODUCT_OUT)/odm_dlkm.img +$(eval $(call copy-one-file,$(BOARD_PREBUILT_ODM_DLKMIMAGE),$(INSTALLED_ODM_DLKMIMAGE_TARGET))) +endif + + +# ----------------------------------------------------------------- # dtbo image ifdef BOARD_PREBUILT_DTBOIMAGE INSTALLED_DTBOIMAGE_TARGET := $(PRODUCT_OUT)/dtbo.img @@ -3484,6 +3170,14 @@ BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += \ --prop com.android.build.odm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \ --prop com.android.build.odm.os_version:$(PLATFORM_VERSION_LAST_STABLE) +BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS += \ + --prop com.android.build.vendor_dlkm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \ + --prop com.android.build.vendor_dlkm.os_version:$(PLATFORM_VERSION_LAST_STABLE) + +BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS += \ + --prop com.android.build.odm_dlkm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \ + --prop com.android.build.odm_dlkm.os_version:$(PLATFORM_VERSION_LAST_STABLE) + BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS += \ --prop com.android.build.dtbo.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) @@ -3503,6 +3197,16 @@ BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += \ --prop com.android.build.odm.security_patch:$(ODM_SECURITY_PATCH) endif +ifdef VENDOR_DLKM_SECURITY_PATCH +BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS += \ + --prop com.android.build.vendor_dlkm.security_patch:$(VENDOR_DLKM_SECURITY_PATCH) +endif + +ifdef ODM_DLKM_SECURITY_PATCH +BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS += \ + --prop com.android.build.odm_dlkm.security_patch:$(ODM_DLKM_SECURITY_PATCH) +endif + BOOT_FOOTER_ARGS := BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS VENDOR_BOOT_FOOTER_ARGS := BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS DTBO_FOOTER_ARGS := BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS @@ -3512,6 +3216,8 @@ RECOVERY_FOOTER_ARGS := BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS PRODUCT_FOOTER_ARGS := BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS SYSTEM_EXT_FOOTER_ARGS := BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS ODM_FOOTER_ARGS := BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS +VENDOR_DLKM_FOOTER_ARGS := BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS +ODM_DLKM_FOOTER_ARGS := BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS # Helper function that checks and sets required build variables for an AVB chained partition. # $(1): the partition to enable AVB chain, e.g., boot or system or vbmeta_system. @@ -3606,6 +3312,14 @@ ifdef INSTALLED_ODMIMAGE_TARGET $(eval $(call check-and-set-avb-args,odm)) endif +ifdef INSTALLED_VENDOR_DLKMIMAGE_TARGET +$(eval $(call check-and-set-avb-args,vendor_dlkm)) +endif + +ifdef INSTALLED_ODM_DLKMIMAGE_TARGET +$(eval $(call check-and-set-avb-args,odm_dlkm)) +endif + ifdef INSTALLED_DTBOIMAGE_TARGET $(eval $(call check-and-set-avb-args,dtbo)) endif @@ -3686,6 +3400,12 @@ define extract-avb-chain-public-keys $(if $(BOARD_AVB_ODM_KEY_PATH),\ $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_ODM_KEY_PATH) \ --output $(1)/odm.avbpubkey) + $(if $(BOARD_AVB_VENDOR_DLKM_KEY_PATH),\ + $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_DLKM_KEY_PATH) \ + --output $(1)/vendor_dlkm.avbpubkey) + $(if $(BOARD_AVB_ODM_DLKM_KEY_PATH),\ + $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_ODM_DLKM_KEY_PATH) \ + --output $(1)/odm_dlkm.avbpubkey) $(if $(BOARD_AVB_DTBO_KEY_PATH),\ $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_DTBO_KEY_PATH) \ --output $(1)/dtbo.avbpubkey) @@ -3768,6 +3488,8 @@ $(INSTALLED_VBMETAIMAGE_TARGET): \ $(INSTALLED_PRODUCTIMAGE_TARGET) \ $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \ $(INSTALLED_ODMIMAGE_TARGET) \ + $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) \ + $(INSTALLED_ODM_DLKMIMAGE_TARGET) \ $(INSTALLED_DTBOIMAGE_TARGET) \ $(INSTALLED_CUSTOMIMAGES_TARGET) \ $(INSTALLED_RECOVERYIMAGE_TARGET) \ @@ -3790,7 +3512,9 @@ endif # BOARD_AVB_ENABLE # ----------------------------------------------------------------- # Check VINTF of build -ifndef TARGET_BUILD_APPS +# Note: vendor_dlkm and odm_dlkm does not have VINTF files. +ifeq (,$(TARGET_BUILD_UNBUNDLED)) + intermediates := $(call intermediates-dir-for,PACKAGING,check_vintf_all) check_vintf_all_deps := @@ -3915,8 +3639,8 @@ my_decompress_tools := \ $(BUILT_KERNEL_CONFIGS_FILE): .KATI_IMPLICIT_OUTPUTS := $(BUILT_KERNEL_VERSION_FILE) $(BUILT_KERNEL_CONFIGS_FILE): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools) $(BUILT_KERNEL_CONFIGS_FILE): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair))) -$(BUILT_KERNEL_CONFIGS_FILE): $(EXTRACT_KERNEL) $(INSTALLED_KERNEL_TARGET) - $< --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(INSTALLED_KERNEL_TARGET) \ +$(BUILT_KERNEL_CONFIGS_FILE): $(EXTRACT_KERNEL) $(firstword $(INSTALLED_KERNEL_TARGET)) + $< --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(firstword $(INSTALLED_KERNEL_TARGET)) \ --output-configs $@ \ --output-version $(BUILT_KERNEL_VERSION_FILE) @@ -3996,13 +3720,12 @@ check_vintf_has_system := check_vintf_common_srcs := check_vintf_all_deps := intermediates := -endif # !TARGET_BUILD_APPS +endif # !TARGET_BUILD_UNBUNDLED # ----------------------------------------------------------------- # Check image sizes <= size of super partition -ifeq (,$(TARGET_BUILD_APPS)) -# Do not check for apps-only build +ifeq (,$(TARGET_BUILD_UNBUNDLED)) ifeq (true,$(PRODUCT_BUILD_SUPER_PARTITION)) @@ -4038,7 +3761,7 @@ check-all-partition-sizes-nodeps: endif # PRODUCT_BUILD_SUPER_PARTITION -endif # TARGET_BUILD_APPS +endif # !TARGET_BUILD_UNBUNDLED # ----------------------------------------------------------------- # bring in the installer image generation defines if necessary @@ -4064,9 +3787,6 @@ else ifeq ($(TARGET_PRODUCT),sdk) build_ota_package := false endif - ifeq ($(TARGET_BUILD_PDK),true) - build_ota_package := false - endif ifneq ($(PRODUCT_BUILD_GENERIC_OTA_PACKAGE),true) ifneq ($(filter generic%,$(TARGET_DEVICE)),) build_ota_package := false @@ -4091,6 +3811,7 @@ ifeq ($(build_otatools_package),true) INTERNAL_OTATOOLS_MODULES := \ aapt2 \ add_img_to_target_files \ + aftltool \ apksigner \ append2simg \ avbtool \ @@ -4123,6 +3844,7 @@ INTERNAL_OTATOOLS_MODULES := \ lpunpack \ lz4 \ make_f2fs \ + make_f2fs_casefold \ merge_target_files \ minigzip \ mk_combined_img \ @@ -4404,6 +4126,9 @@ endif ifdef DEVICE_MANIFEST_FILE $(hide) echo "vintf_include_empty_vendor_sku=true" >> $@ endif +ifeq ($(BOARD_BOOTLOADER_IN_UPDATE_PACKAGE),true) + $(hide) echo "bootloader_in_update_package=true" >> $@ +endif .PHONY: misc_info misc_info: $(INSTALLED_MISC_INFO_TARGET) @@ -4442,7 +4167,7 @@ built_ota_tools := # We can't build static executables when SANITIZE_TARGET=address ifeq (,$(filter address, $(SANITIZE_TARGET))) built_ota_tools += \ - $(call intermediates-dir-for,EXECUTABLES,updater,,,$(TARGET_PREFER_32_BIT))/updater + $(call intermediates-dir-for,EXECUTABLES,updater)/updater endif $(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools) @@ -4521,13 +4246,13 @@ define dump-dynamic-partitions-info $(foreach device,$(BOARD_SUPER_PARTITION_BLOCK_DEVICES), \ echo "super_$(device)_device_size=$(BOARD_SUPER_PARTITION_$(call to-upper,$(device))_DEVICE_SIZE)" >> $(1);) $(if $(BOARD_SUPER_PARTITION_PARTITION_LIST), \ - echo "dynamic_partition_list=$(call filter-out-missing-vendor, $(BOARD_SUPER_PARTITION_PARTITION_LIST))" >> $(1)) + echo "dynamic_partition_list=$(call filter-out-missing-vendor,$(BOARD_SUPER_PARTITION_PARTITION_LIST))" >> $(1)) $(if $(BOARD_SUPER_PARTITION_GROUPS), echo "super_partition_groups=$(BOARD_SUPER_PARTITION_GROUPS)" >> $(1)) $(foreach group,$(BOARD_SUPER_PARTITION_GROUPS), \ echo "super_$(group)_group_size=$(BOARD_$(call to-upper,$(group))_SIZE)" >> $(1); \ $(if $(BOARD_$(call to-upper,$(group))_PARTITION_LIST), \ - echo "super_$(group)_partition_list=$(call filter-out-missing-vendor, $(BOARD_$(call to-upper,$(group))_PARTITION_LIST))" >> $(1);)) + echo "super_$(group)_partition_list=$(call filter-out-missing-vendor,$(BOARD_$(call to-upper,$(group))_PARTITION_LIST))" >> $(1);)) $(if $(filter true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED)), \ echo "build_non_sparse_super_partition=true" >> $(1)) $(if $(filter true,$(TARGET_USERIMAGES_SPARSE_F2FS_DISABLED)), \ @@ -4552,32 +4277,98 @@ endef # full system image deps, we speed up builds that do not build the system # image. ifdef BUILDING_SYSTEM_IMAGE -$(BUILT_TARGET_FILES_PACKAGE): $(FULL_SYSTEMIMAGE_DEPS) + $(BUILT_TARGET_FILES_PACKAGE): $(FULL_SYSTEMIMAGE_DEPS) +endif + +ifdef BUILDING_USERDATA_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_USERDATAIMAGE_FILES) +endif + +ifdef BUILDING_SYSTEM_OTHER_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_SYSTEMOTHERIMAGE_FILES) +endif + +ifdef BUILDING_VENDOR_BOOT_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_VENDOR_RAMDISK_FILES) +endif + +ifdef BUILDING_RECOVERY_IMAGE + # TODO(b/30414428): Can't depend on INTERNAL_RECOVERYIMAGE_FILES alone like other + # BUILD_TARGET_FILES_PACKAGE dependencies because currently there're cp/rsync/rm + # commands in build-recoveryimage-target, which would touch the files under + # TARGET_RECOVERY_OUT and race with packaging target-files.zip. + ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true) + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_BOOTIMAGE_TARGET) + else + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_RECOVERYIMAGE_TARGET) + endif + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_RECOVERYIMAGE_FILES) +endif + +# Conditionally depend on the image files if the image is being built so the +# target-files.zip rule doesn't wait on the image creation rule, or the image +# if it is coming from a prebuilt. + +ifdef BUILDING_VENDOR_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_VENDORIMAGE_FILES) +else ifdef BOARD_PREBUILT_VENDORIMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_VENDORIMAGE_TARGET) +endif + +ifdef BUILDING_PRODUCT_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_PRODUCTIMAGE_FILES) +else ifdef BOARD_PREBUILT_PRODUCTIMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_PRODUCTIMAGE_TARGET) +endif + +ifdef BUILDING_SYSTEM_EXT_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_SYSTEM_EXTIMAGE_FILES) +else ifdef BOARD_PREBUILT_SYSTEM_EXTIMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) +endif + +ifdef BUILDING_BOOT_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_RAMDISK_FILES) +else ifdef BOARD_PREBUILT_BOOTIMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_BOOTIMAGE_TARGET) +endif + +ifdef BUILDING_ODM_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_ODMIMAGE_FILES) +else ifdef BOARD_PREBUILT_ODMIMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_ODMIMAGE_TARGET) +endif + +ifdef BUILDING_VENDOR_DLKM_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_VENDOR_DLKMIMAGE_FILES) +else ifdef BOARD_PREBUILT_VENDOR_DLKIMMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) +endif + +ifdef BUILDING_ODM_DLKM_IMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_ODM_DLKMIMAGE_FILES) +else ifdef BOARD_ODM_VENDOR_DLKIMMAGE + $(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_ODM_DLKMIMAGE_TARGET) endif ifeq ($(BUILD_QEMU_IMAGES),true) -MK_VBMETA_BOOT_KERNEL_CMDLINE_SH := device/generic/goldfish/tools/mk_vbmeta_boot_params.sh -$(BUILT_TARGET_FILES_PACKAGE): $(MK_VBMETA_BOOT_KERNEL_CMDLINE_SH) + MK_VBMETA_BOOT_KERNEL_CMDLINE_SH := device/generic/goldfish/tools/mk_vbmeta_boot_params.sh + $(BUILT_TARGET_FILES_PACKAGE): $(MK_VBMETA_BOOT_KERNEL_CMDLINE_SH) +endif + +ifdef BOARD_PREBUILT_BOOTLOADER +$(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_BOOTLOADER_MODULE) +droidcore: $(INSTALLED_BOOTLOADER_MODULE) endif # Depending on the various images guarantees that the underlying # directories are up-to-date. $(BUILT_TARGET_FILES_PACKAGE): \ - $(INSTALLED_RAMDISK_TARGET) \ - $(INSTALLED_BOOTIMAGE_TARGET) \ - $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \ $(INSTALLED_RADIOIMAGE_TARGET) \ $(INSTALLED_RECOVERYIMAGE_TARGET) \ - $(INSTALLED_USERDATAIMAGE_TARGET) \ $(INSTALLED_CACHEIMAGE_TARGET) \ - $(INSTALLED_VENDORIMAGE_TARGET) \ - $(INSTALLED_PRODUCTIMAGE_TARGET) \ - $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \ - $(INSTALLED_VBMETAIMAGE_TARGET) \ - $(INSTALLED_ODMIMAGE_TARGET) \ $(INSTALLED_DTBOIMAGE_TARGET) \ $(INSTALLED_CUSTOMIMAGES_TARGET) \ - $(INTERNAL_SYSTEMOTHERIMAGE_FILES) \ $(INSTALLED_ANDROID_INFO_TXT_TARGET) \ $(INSTALLED_KERNEL_TARGET) \ $(INSTALLED_DTBIMAGE_TARGET) \ @@ -4590,6 +4381,8 @@ $(BUILT_TARGET_FILES_PACKAGE): \ $(PRODUCT_PRODUCT_BASE_FS_PATH) \ $(PRODUCT_SYSTEM_EXT_BASE_FS_PATH) \ $(PRODUCT_ODM_BASE_FS_PATH) \ + $(PRODUCT_VENDOR_DLKM_BASE_FS_PATH) \ + $(PRODUCT_ODM_DLKM_BASE_FS_PATH) \ $(LPMAKE) \ $(SELINUX_FC) \ $(INSTALLED_MISC_INFO_TARGET) \ @@ -4603,10 +4396,6 @@ $(BUILT_TARGET_FILES_PACKAGE): \ $(BUILT_KERNEL_VERSION_FILE) \ | $(ACP) @echo "Package target files: $@" - $(call create-system-vendor-symlink) - $(call create-system-product-symlink) - $(call create-system-system_ext-symlink) - $(call create-vendor-odm-symlink) $(hide) rm -rf $@ $@.list $(zip_root) $(hide) mkdir -p $(dir $@) $(zip_root) ifneq (,$(INSTALLED_RECOVERYIMAGE_TARGET)$(filter true,$(BOARD_USES_RECOVERY_AS_BOOT))) @@ -4615,7 +4404,11 @@ ifneq (,$(INSTALLED_RECOVERYIMAGE_TARGET)$(filter true,$(BOARD_USES_RECOVERY_AS_ $(hide) $(call package_files-copy-root, \ $(TARGET_RECOVERY_ROOT_OUT),$(zip_root)/$(PRIVATE_RECOVERY_OUT)/RAMDISK) ifdef INSTALLED_KERNEL_TARGET +ifneq (,$(filter true,$(BOARD_USES_RECOVERY_AS_BOOT))) cp $(INSTALLED_KERNEL_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/ +else # BOARD_USES_RECOVERY_AS_BOOT not true + cp $(firstword $(INSTALLED_KERNEL_TARGET)) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/kernel +endif endif ifeq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(AB_OTA_UPDATER))) echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline @@ -4645,7 +4438,7 @@ endif ifdef BOARD_KERNEL_PAGESIZE echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/pagesize endif -endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET not defined +endif # not (BUILDING_VENDOR_BOOT_IMAGE and AB_OTA_UPDATER) endif # INSTALLED_RECOVERYIMAGE_TARGET defined or BOARD_USES_RECOVERY_AS_BOOT is true @# Components of the boot image $(hide) mkdir -p $(zip_root)/BOOT @@ -4659,7 +4452,7 @@ ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true) $(TARGET_RAMDISK_OUT),$(zip_root)/BOOT/RAMDISK) endif ifdef INSTALLED_KERNEL_TARGET - $(hide) cp $(INSTALLED_KERNEL_TARGET) $(zip_root)/BOOT/kernel + $(hide) cp $(INSTALLED_KERNEL_TARGET) $(zip_root)/BOOT/ endif ifndef INSTALLED_VENDOR_BOOTIMAGE_TARGET ifdef INSTALLED_2NDBOOTLOADER_TARGET @@ -4727,6 +4520,16 @@ ifdef BUILDING_ODM_IMAGE $(hide) $(call package_files-copy-root, \ $(TARGET_OUT_ODM),$(zip_root)/ODM) endif +ifdef BUILDING_VENDOR_DLKM_IMAGE + @# Contents of the vendor_dlkm image + $(hide) $(call package_files-copy-root, \ + $(TARGET_OUT_VENDOR_DLKM),$(zip_root)/VENDOR_DLKM) +endif +ifdef BUILDING_ODM_DLKM_IMAGE + @# Contents of the odm_dlkm image + $(hide) $(call package_files-copy-root, \ + $(TARGET_OUT_ODM_DLKM),$(zip_root)/ODM_DLKM) +endif ifdef BUILDING_SYSTEM_OTHER_IMAGE @# Contents of the system_other image $(hide) $(call package_files-copy-root, \ @@ -4772,6 +4575,14 @@ ifneq ($(PRODUCT_ODM_BASE_FS_PATH),) $(hide) cp $(PRODUCT_ODM_BASE_FS_PATH) \ $(zip_root)/META/$(notdir $(PRODUCT_ODM_BASE_FS_PATH)) endif +ifneq ($(PRODUCT_VENDOR_DLKM_BASE_FS_PATH),) + $(hide) cp $(PRODUCT_VENDOR_DLKM_BASE_FS_PATH) \ + $(zip_root)/META/$(notdir $(PRODUCT_VENDOR_DLKM_BASE_FS_PATH)) +endif +ifneq ($(PRODUCT_ODM_DLKM_BASE_FS_PATH),) + $(hide) cp $(PRODUCT_ODM_DLKM_BASE_FS_PATH) \ + $(zip_root)/META/$(notdir $(PRODUCT_ODM_DLKM_BASE_FS_PATH)) +endif ifeq ($(TARGET_OTA_ALLOW_NON_AB),true) ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),) $(hide) PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH MKBOOTIMG=$(MKBOOTIMG) \ @@ -4817,10 +4628,22 @@ ifdef BOARD_PREBUILT_ODMIMAGE $(hide) mkdir -p $(zip_root)/IMAGES $(hide) cp $(INSTALLED_ODMIMAGE_TARGET) $(zip_root)/IMAGES/ endif +ifdef BOARD_PREBUILT_VENDOR_DLKMIMAGE + $(hide) mkdir -p $(zip_root)/IMAGES + $(hide) cp $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) $(zip_root)/IMAGES/ +endif +ifdef BOARD_PREBUILT_ODM_DLKMIMAGE + $(hide) mkdir -p $(zip_root)/IMAGES + $(hide) cp $(INSTALLED_ODM_DLKMIMAGE_TARGET) $(zip_root)/IMAGES/ +endif ifdef BOARD_PREBUILT_DTBOIMAGE $(hide) mkdir -p $(zip_root)/PREBUILT_IMAGES $(hide) cp $(INSTALLED_DTBOIMAGE_TARGET) $(zip_root)/PREBUILT_IMAGES/ endif # BOARD_PREBUILT_DTBOIMAGE +ifdef BOARD_PREBUILT_BOOTLOADER + $(hide) mkdir -p $(zip_root)/IMAGES + $(hide) cp $(INSTALLED_BOOTLOADER_MODULE) $(zip_root)/IMAGES/ +endif ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),) $(hide) mkdir -p $(zip_root)/PREBUILT_IMAGES $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \ @@ -4848,6 +4671,12 @@ endif ifdef BUILDING_ODM_IMAGE $(hide) $(call fs_config,$(zip_root)/ODM,odm/) > $(zip_root)/META/odm_filesystem_config.txt endif +ifdef BUILDING_VENDOR_DLKM_IMAGE + $(hide) $(call fs_config,$(zip_root)/VENDOR_DLKM,vendor_dlkm/) > $(zip_root)/META/vendor_dlkm_filesystem_config.txt +endif +ifdef BUILDING_ODM_DLKM_IMAGE + $(hide) $(call fs_config,$(zip_root)/ODM_DLKM,odm_dlkm/) > $(zip_root)/META/odm_dlkm_filesystem_config.txt +endif @# ROOT always contains the files for the root under normal boot. $(hide) $(call fs_config,$(zip_root)/ROOT,) > $(zip_root)/META/root_filesystem_config.txt ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true) @@ -4893,9 +4722,7 @@ endif .PHONY: target-files-package target-files-package: $(BUILT_TARGET_FILES_PACKAGE) -ifneq ($(filter $(MAKECMDGOALS),target-files-package),) $(call dist-for-goals, target-files-package, $(BUILT_TARGET_FILES_PACKAGE)) -endif # ----------------------------------------------------------------- # NDK Sysroot Package @@ -4968,14 +4795,13 @@ endif # build_ota_package # A zip of the appcompat directory containing logs APPCOMPAT_ZIP := $(PRODUCT_OUT)/appcompat.zip # For apps_only build we'll establish the dependency later in build/make/core/main.mk. -ifndef TARGET_BUILD_APPS -$(APPCOMPAT_ZIP): $(INSTALLED_SYSTEMIMAGE_TARGET) \ - $(INSTALLED_RAMDISK_TARGET) \ - $(INSTALLED_BOOTIMAGE_TARGET) \ - $(INSTALLED_USERDATAIMAGE_TARGET) \ - $(INSTALLED_VENDORIMAGE_TARGET) \ - $(INSTALLED_PRODUCTIMAGE_TARGET) \ - $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) +ifeq (,$(TARGET_BUILD_UNBUNDLED)) +$(APPCOMPAT_ZIP): $(FULL_SYSTEMIMAGE_DEPS) \ + $(INTERNAL_RAMDISK_FILES) \ + $(INTERNAL_USERDATAIMAGE_FILES) \ + $(INTERNAL_VENDORIMAGE_FILES) \ + $(INTERNAL_PRODUCTIMAGE_FILES) \ + $(INTERNAL_SYSTEM_EXTIMAGE_FILES) endif $(APPCOMPAT_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,appcompat)/filelist $(APPCOMPAT_ZIP): $(SOONG_ZIP) @@ -4997,15 +4823,16 @@ name := $(name)-symbols-$(FILE_NAME_TAG) SYMBOLS_ZIP := $(PRODUCT_OUT)/$(name).zip # For apps_only build we'll establish the dependency later in build/make/core/main.mk. -ifndef TARGET_BUILD_APPS -$(SYMBOLS_ZIP): $(INSTALLED_SYSTEMIMAGE_TARGET) \ - $(INSTALLED_RAMDISK_TARGET) \ - $(INSTALLED_BOOTIMAGE_TARGET) \ - $(INSTALLED_USERDATAIMAGE_TARGET) \ - $(INSTALLED_VENDORIMAGE_TARGET) \ - $(INSTALLED_PRODUCTIMAGE_TARGET) \ - $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \ - $(INSTALLED_ODMIMAGE_TARGET) \ +ifeq (,$(TARGET_BUILD_UNBUNDLED)) +$(SYMBOLS_ZIP): $(FULL_SYSTEMIMAGE_DEPS) \ + $(INTERNAL_RAMDISK_FILES) \ + $(INTERNAL_USERDATAIMAGE_FILES) \ + $(INTERNAL_VENDORIMAGE_FILES) \ + $(INTERNAL_PRODUCTIMAGE_FILES) \ + $(INTERNAL_SYSTEM_EXTIMAGE_FILES) \ + $(INTERNAL_ODMIMAGE_FILES) \ + $(INTERNAL_VENDOR_DLKMIMAGE_FILES) \ + $(INTERNAL_ODM_DLKMIMAGE_FILES) \ $(updater_dep) endif $(SYMBOLS_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,symbols)/filelist @@ -5023,15 +4850,16 @@ ifeq ($(TARGET_BUILD_TYPE),debug) name := $(name)_debug endif COVERAGE_ZIP := $(PRODUCT_OUT)/$(name).zip -ifndef TARGET_BUILD_APPS -$(COVERAGE_ZIP): $(INSTALLED_SYSTEMIMAGE_TARGET) \ - $(INSTALLED_RAMDISK_TARGET) \ - $(INSTALLED_BOOTIMAGE_TARGET) \ - $(INSTALLED_USERDATAIMAGE_TARGET) \ - $(INSTALLED_VENDORIMAGE_TARGET) \ - $(INSTALLED_PRODUCTIMAGE_TARGET) \ - $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \ - $(INSTALLED_ODMIMAGE_TARGET) +ifeq (,$(TARGET_BUILD_UNBUNDLED)) +$(COVERAGE_ZIP): $(FULL_SYSTEMIMAGE_DEPS) \ + $(INTERNAL_RAMDISK_FILES) \ + $(INTERNAL_USERDATAIMAGE_FILES) \ + $(INTERNAL_VENDORIMAGE_FILES) \ + $(INTERNAL_PRODUCTIMAGE_FILES) \ + $(INTERNAL_SYSTEM_EXTIMAGE_FILES) \ + $(INTERNAL_ODMIMAGE_FILES) \ + $(INTERNAL_VENDOR_DLKMIMAGE_FILES) \ + $(INTERNAL_ODM_DLKMIMAGE_FILES) endif $(COVERAGE_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,coverage)/filelist $(COVERAGE_ZIP): $(SOONG_ZIP) @@ -5065,7 +4893,7 @@ endif name := $(name)-apps-$(FILE_NAME_TAG) APPS_ZIP := $(PRODUCT_OUT)/$(name).zip -$(APPS_ZIP): $(INSTALLED_SYSTEMIMAGE_TARGET) +$(APPS_ZIP): $(FULL_SYSTEMIMAGE_DEPS) @echo "Package apps: $@" $(hide) rm -rf $@ $(hide) mkdir -p $(dir $@) @@ -5098,8 +4926,34 @@ endif # EMMA_INSTRUMENT=true # PROGUARD_DICT_ZIP := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict-$(FILE_NAME_TAG).zip # For apps_only build we'll establish the dependency later in build/make/core/main.mk. -ifndef TARGET_BUILD_APPS +ifeq (,$(TARGET_BUILD_UNBUNDLED)) $(PROGUARD_DICT_ZIP): \ + $(FULL_SYSTEMIMAGE_DEPS) \ + $(INTERNAL_RAMDISK_FILES) \ + $(INTERNAL_USERDATAIMAGE_FILES) \ + $(INTERNAL_VENDORIMAGE_FILES) \ + $(INTERNAL_PRODUCTIMAGE_FILES) \ + $(INTERNAL_SYSTEM_EXTIMAGE_FILES) \ + $(INTERNAL_ODMIMAGE_FILES) \ + $(INTERNAL_VENDOR_DLKMIMAGE_FILES) \ + $(INTERNAL_ODM_DLKMIMAGE_FILES) \ + $(updater_dep) +endif +$(PROGUARD_DICT_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,proguard)/filelist +$(PROGUARD_DICT_ZIP): $(SOONG_ZIP) + @echo "Packaging Proguard obfuscation dictionary files." + mkdir -p $(dir $@) $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS $(dir $(PRIVATE_LIST_FILE)) + find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary | \ + sed -e 's/\(.*\)\/proguard_dictionary/\0\n\1\/classes.jar/' > $(PRIVATE_LIST_FILE) + $(SOONG_ZIP) --ignore_missing_files -d -o $@ -C $(OUT_DIR)/.. -l $(PRIVATE_LIST_FILE) + +#------------------------------------------------------------------ +# A zip of Proguard usage files. +# +PROGUARD_USAGE_ZIP := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-usage-$(FILE_NAME_TAG).zip +# For apps_only build we'll establish the dependency later in build/make/core/main.mk. +ifeq (,$(TARGET_BUILD_UNBUNDLED)) +$(PROGUARD_USAGE_ZIP): \ $(INSTALLED_SYSTEMIMAGE_TARGET) \ $(INSTALLED_RAMDISK_TARGET) \ $(INSTALLED_BOOTIMAGE_TARGET) \ @@ -5108,16 +4962,16 @@ $(PROGUARD_DICT_ZIP): \ $(INSTALLED_PRODUCTIMAGE_TARGET) \ $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \ $(INSTALLED_ODMIMAGE_TARGET) \ + $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) \ + $(INSTALLED_ODM_DLKMIMAGE_TARGET) \ $(updater_dep) endif -$(PROGUARD_DICT_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,proguard)/filelist -$(PROGUARD_DICT_ZIP): $(SOONG_ZIP) - @echo "Packaging Proguard obfuscation dictionary files." +$(PROGUARD_USAGE_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,proguard_usage)/filelist +$(PROGUARD_USAGE_ZIP): $(MERGE_ZIPS) + @echo "Packaging Proguard usage files." mkdir -p $(dir $@) $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS $(dir $(PRIVATE_LIST_FILE)) - find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary | \ - sed -e 's/\(.*\)\/proguard_dictionary/\0\n\1\/classes.jar/' > $(PRIVATE_LIST_FILE) - $(SOONG_ZIP) --ignore_missing_files -d -o $@ -C $(OUT_DIR)/.. -l $(PRIVATE_LIST_FILE) - + find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_usage.zip > $(PRIVATE_LIST_FILE) + $(MERGE_ZIPS) $@ @$(PRIVATE_LIST_FILE) ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS)) @@ -5346,6 +5200,26 @@ odmimage: $(INSTALLED_QEMU_ODMIMAGE) droidcore: $(INSTALLED_QEMU_ODMIMAGE) endif +ifdef INSTALLED_VENDOR_DLKMIMAGE_TARGET +INSTALLED_QEMU_VENDOR_DLKMIMAGE := $(PRODUCT_OUT)/vendor_dlkm-qemu.img +$(INSTALLED_QEMU_VENDOR_DLKMIMAGE): $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST) + @echo Create vendor_dlkm-qemu.img + (export SGDISK=$(SGDISK_HOST); $(MK_QEMU_IMAGE_SH) $(INSTALLED_VENDOR_DLKMIMAGE_TARGET)) + +vendor_dlkmimage: $(INSTALLED_QEMU_VENDOR_DLKMIMAGE) +droidcore: $(INSTALLED_QEMU_VENDOR_DLKMIMAGE) +endif + +ifdef INSTALLED_ODM_DLKMIMAGE_TARGET +INSTALLED_QEMU_ODM_DLKMIMAGE := $(PRODUCT_OUT)/odm_dlkm-qemu.img +$(INSTALLED_QEMU_ODM_DLKMIMAGE): $(INSTALLED_ODM_DLKMIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST) + @echo Create odm_dlkm-qemu.img + (export SGDISK=$(SGDISK_HOST); $(MK_QEMU_IMAGE_SH) $(INSTALLED_ODM_DLKMIMAGE_TARGET)) + +odm_dlkmimage: $(INSTALLED_QEMU_ODM_DLKMIMAGE) +droidcore: $(INSTALLED_QEMU_ODM_DLKMIMAGE) +endif + QEMU_VERIFIED_BOOT_PARAMS := $(PRODUCT_OUT)/VerifiedBootParams.textproto $(QEMU_VERIFIED_BOOT_PARAMS): $(INSTALLED_VBMETAIMAGE_TARGET) $(INSTALLED_SYSTEMIMAGE_TARGET) \ $(MK_VBMETA_BOOT_KERNEL_CMDLINE_SH) $(AVBTOOL) @@ -5376,13 +5250,6 @@ $(INTERNAL_EMULATOR_PACKAGE_TARGET): $(INTERNAL_EMULATOR_PACKAGE_FILES) $(hide) zip -qjX $@ $(INTERNAL_EMULATOR_PACKAGE_FILES) endif -# ----------------------------------------------------------------- -# Old PDK stuffs, retired -# The pdk package (Platform Development Kit) - -#ifneq (,$(filter pdk,$(MAKECMDGOALS))) -# include development/pdk/Pdk.mk -#endif # ----------------------------------------------------------------- diff --git a/core/OWNERS b/core/OWNERS index 750f1fa20d..459683e851 100644 --- a/core/OWNERS +++ b/core/OWNERS @@ -1,3 +1,2 @@ per-file dex_preopt*.mk = ngeoffray@google.com,calin@google.com,mathewi@google.com,dbrazdil@google.com -per-file construct_context.sh = ngeoffray@google.com,calin@google.com,mathieuc@google.com per-file verify_uses_libraries.sh = ngeoffray@google.com,calin@google.com,mathieuc@google.com diff --git a/core/android_manifest.mk b/core/android_manifest.mk index 8fab9c6aed..254e09bc93 100644 --- a/core/android_manifest.mk +++ b/core/android_manifest.mk @@ -45,7 +45,7 @@ my_target_sdk_version := $(call module-target-sdk-version) my_min_sdk_version := $(call module-min-sdk-version) ifdef TARGET_BUILD_APPS - ifndef TARGET_BUILD_APPS_USE_PREBUILT_SDK + ifndef TARGET_BUILD_USE_PREBUILT_SDKS ifeq ($(my_target_sdk_version),$(PLATFORM_VERSION_CODENAME)) ifdef UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT my_target_sdk_version := $(my_target_sdk_version).$$(cat $(API_FINGERPRINT)) diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk new file mode 100644 index 0000000000..ee12c8c1ed --- /dev/null +++ b/core/android_soong_config_vars.mk @@ -0,0 +1,29 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file defines the Soong Config Variable namespace ANDROID, and also any +# variables in that namespace. + +# The expectation is that no vendor should be using the ANDROID namespace. This +# check ensures that we don't collide with any existing vendor usage. + +ifdef SOONG_CONFIG_ANDROID +$(error The Soong config namespace ANDROID is reserved.) +endif + +$(call add_soong_config_namespace,ANDROID) + +# Add variables to the namespace below: + +$(call add_soong_config_var,ANDROID,TARGET_ENABLE_MEDIADRM_64) diff --git a/core/app_prebuilt_internal.mk b/core/app_prebuilt_internal.mk index ab574b3fa4..576799692f 100644 --- a/core/app_prebuilt_internal.mk +++ b/core/app_prebuilt_internal.mk @@ -45,7 +45,7 @@ built_module := $(LOCAL_BUILT_MODULE) # We skip it for unbundled app builds where we cannot build veridex. module_run_appcompat := ifeq (true,$(non_system_module)) -ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK))) # ! unbundled app build +ifeq (,$(TARGET_BUILD_APPS)) # ! unbundled app build ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true) module_run_appcompat := true endif diff --git a/core/autogen_test_config.mk b/core/autogen_test_config.mk index d4ca56f1b8..137b1185ab 100644 --- a/core/autogen_test_config.mk +++ b/core/autogen_test_config.mk @@ -22,6 +22,17 @@ # autogen_test_config_file: Path to the test config file generated. autogen_test_config_file := $(dir $(LOCAL_BUILT_MODULE))$(LOCAL_MODULE).config +# TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base. +autogen_test_install_base := /data/local/tmp +# Automatically setup test root for native test. +ifeq (true,$(is_native)) + ifeq (true,$(LOCAL_VENDOR_MODULE)) + autogen_test_install_base = /data/local/tests/vendor + endif + ifeq (true,$(LOCAL_USE_VNDK)) + autogen_test_install_base = /data/local/tests/vendor + endif +endif ifeq (true,$(is_native)) ifeq ($(LOCAL_NATIVE_BENCHMARK),true) autogen_test_config_template := $(NATIVE_BENCHMARK_TEST_CONFIG_TEMPLATE) @@ -33,10 +44,11 @@ else endif endif # Auto generating test config file for native test +$(autogen_test_config_file): PRIVATE_TEST_INSTALL_BASE := $(autogen_test_install_base) $(autogen_test_config_file): PRIVATE_MODULE_NAME := $(LOCAL_MODULE) $(autogen_test_config_file) : $(autogen_test_config_template) @echo "Auto generating test config $(notdir $@)" - $(hide) sed 's&{MODULE}&$(PRIVATE_MODULE_NAME)&g;s&{EXTRA_CONFIGS}&&g' $< > $@ + $(hide) sed 's&{MODULE}&$(PRIVATE_MODULE_NAME)&g;s&{TEST_INSTALL_BASE}&$(PRIVATE_TEST_INSTALL_BASE)&g;s&{EXTRA_CONFIGS}&&g' $< > $@ my_auto_generate_config := true else # Auto generating test config file for instrumentation test diff --git a/core/aux_config.mk b/core/aux_config.mk deleted file mode 100644 index 10d2536bc2..0000000000 --- a/core/aux_config.mk +++ /dev/null @@ -1,187 +0,0 @@ -variant_list := $(filter AUX-%,$(MAKECMDGOALS)) - -ifdef variant_list -AUX_OS_VARIANT_LIST := $(patsubst AUX-%,%,$(variant_list)) -else -AUX_OS_VARIANT_LIST := $(TARGET_AUX_OS_VARIANT_LIST) -endif - -# exclude AUX targets from build -ifeq ($(AUX_OS_VARIANT_LIST),none) -AUX_OS_VARIANT_LIST := -endif - -# temporary workaround to support external toolchain -ifeq ($(NANOHUB_TOOLCHAIN),) -AUX_OS_VARIANT_LIST := -endif - -# setup toolchain paths for various CPU architectures -# this one will come from android prebuilts eventually -AUX_TOOLCHAIN_cortexm4 := $(NANOHUB_TOOLCHAIN) -ifeq ($(wildcard $(AUX_TOOLCHAIN_cortexm4)gcc),) -AUX_TOOLCHAIN_cortexm4:= -endif - -# there is no MAKE var that defines path to HOST toolchain -# all the interesting paths are hardcoded in soong, and are not available from here -# There is no other way but to hardcode them again, as we may need host x86 toolcain for AUX -ifeq ($(HOST_OS),linux) -AUX_TOOLCHAIN_x86 := prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/bin/x86_64-linux- -endif - -# setup AUX globals -AUX_SHLIB_SUFFIX := .so -AUX_GLOBAL_ARFLAGS := crsPD -AUX_STATIC_LIB_SUFFIX := .a - -# Load ever-lasting "indexed" version of AUX variant environment; it is treated as READ-ONLY from this -# moment on. -# -# $(1) - variant -# no return value -define aux-variant-setup-paths -$(eval AUX_OUT_ROOT_$(1) := $(PRODUCT_OUT)/aux/$(1)) \ -$(eval AUX_COMMON_OUT_ROOT_$(1) := $(AUX_OUT_ROOT_$(1))/common) \ -$(eval AUX_OUT_$(1) := $(AUX_OUT_ROOT_$(1))/$(AUX_OS_$(1))-$(AUX_ARCH_$(1))-$(AUX_CPU_$(1))) \ -$(eval AUX_OUT_INTERMEDIATES_$(1) := $(AUX_OUT_$(1))/obj) \ -$(eval AUX_OUT_COMMON_INTERMEDIATES_$(1) := $(AUX_COMMON_OUT_ROOT_$(1))/obj) \ -$(eval AUX_OUT_HEADERS_$(1) := $(AUX_OUT_INTERMEDIATES_$(1))/include) \ -$(eval AUX_OUT_NOTICE_FILES_$(1) := $(AUX_OUT_INTERMEDIATES_$(1))/NOTICE_FILES) \ -$(eval AUX_OUT_FAKE_$(1) := $(AUX_OUT_$(1))/fake_packages) \ -$(eval AUX_OUT_GEN_$(1) := $(AUX_OUT_$(1))/gen) \ -$(eval AUX_OUT_COMMON_GEN_$(1) := $(AUX_COMMON_OUT_ROOT_$(1))/gen) \ -$(eval AUX_OUT_EXECUTABLES_$(1) := $(AUX_OUT_$(1))/bin) \ -$(eval AUX_OUT_UNSTRIPPED_$(1) := $(AUX_OUT_$(1))/symbols) -endef - -# Copy "indexed" AUX environment for given VARIANT into -# volatile not-indexed set of variables for simplicity of access. -# Injection of index support throughout the build system is suboptimal -# hence volatile environment is constructed -# Unlike HOST*, TARGET* variables, AUX* variables are NOT read-only, but their -# indexed versions are. -# -# $(1) - variant -# no return value -define aux-variant-load-env -$(eval AUX_OS_VARIANT:=$(1)) \ -$(eval AUX_OS:=$(AUX_OS_$(1))) \ -$(eval AUX_ARCH:=$(AUX_ARCH_$(1))) \ -$(eval AUX_SUBARCH:=$(AUX_SUBARCH_$(1))) \ -$(eval AUX_CPU:=$(AUX_CPU_$(1))) \ -$(eval AUX_OS_PATH:=$(AUX_OS_PATH_$(1))) \ -$(eval AUX_OUT_ROOT := $(AUX_OUT_ROOT_$(1))) \ -$(eval AUX_COMMON_OUT_ROOT := $(AUX_COMMON_OUT_ROOT_$(1))) \ -$(eval AUX_OUT := $(AUX_OUT_$(1))) \ -$(eval AUX_OUT_INTERMEDIATES := $(AUX_OUT_INTERMEDIATES_$(1))) \ -$(eval AUX_OUT_COMMON_INTERMEDIATES := $(AUX_OUT_COMMON_INTERMEDIATES_$(1))) \ -$(eval AUX_OUT_HEADERS := $(AUX_OUT_HEADERS_$(1))) \ -$(eval AUX_OUT_NOTICE_FILES := $(AUX_OUT_NOTICE_FILES_$(1))) \ -$(eval AUX_OUT_FAKE := $(AUX_OUT_FAKE_$(1))) \ -$(eval AUX_OUT_GEN := $(AUX_OUT_GEN_$(1))) \ -$(eval AUX_OUT_COMMON_GEN := $(AUX_OUT_COMMON_GEN_$(1))) \ -$(eval AUX_OUT_EXECUTABLES := $(AUX_OUT_EXECUTABLES_$(1))) \ -$(eval AUX_OUT_UNSTRIPPED := $(AUX_OUT_UNSTRIPPED_$(1))) -endef - -# given a variant:path pair, load the variant conviguration with aux-variant-setup-paths from file -# this is a build system extension mechainsm, since configuration typically resides in non-build -# project space -# -# $(1) - variant:path pair -# $(2) - file suffix -# no return value -define aux-variant-import-from-pair -$(eval _pair := $(subst :, ,$(1))) \ -$(eval _name:=$(word 1,$(_pair))) \ -$(eval _path:=$(word 2,$(_pair))) \ -$(eval include $(_path)/$(_name)$(2)) \ -$(eval AUX_OS_VARIANT_LIST_$(AUX_OS_$(1)):=) \ -$(call aux-variant-setup-paths,$(_name)) \ -$(eval AUX_ALL_VARIANTS += $(_name)) \ -$(eval AUX_ALL_OSES := $(filter-out $(AUX_OS_$(_name)),$(AUX_ALL_OSES)) $(AUX_OS_$(_name))) \ -$(eval AUX_ALL_CPUS := $(filter-out $(AUX_CPU_$(_name)),$(AUX_ALL_CPUS)) $(AUX_CPU_$(_name))) \ -$(eval AUX_ALL_ARCHS := $(filter-out $(AUX_ARCH_$(_name)),$(AUX_ALL_ARCHS)) $(AUX_ARCH_$(_name))) \ -$(eval AUX_ALL_SUBARCHS := $(filter-out $(AUX_SUBARCH_$(_name)),$(AUX_ALL_SUBARCHS)) $(AUX_SUBARCH_$(_name))) -endef - -# Load system configuration referenced by AUX variant config; -# this is a build extension mechanism; typically system config -# resides in a non-build projects; -# system config may define new rules and globally visible BUILD* -# includes to support project-specific build steps and toolchains -# MAintains list of valiants that reference this os config in OS "indexed" var -# this facilitates multivariant build of the OS (or whataver it is the name of common component these variants share) -# -# $(1) - variant -# no return value -define aux-import-os-config -$(eval _aioc_os := $(AUX_OS_$(1))) \ -$(eval AUX_OS_PATH_$(1) := $(patsubst $(_aioc_os):%,%,$(filter $(_aioc_os):%,$(AUX_ALL_OS_PATHS)))) \ -$(eval _aioc_os_cfg := $(AUX_OS_PATH_$(1))/$(_aioc_os)$(os_sfx)) \ -$(if $(wildcard $(_aioc_os_cfg)),,$(error AUX '$(_aioc_os)' OS config file [$(notdir $(_aioc_os_cfg))] required by AUX variant '$(1)' does not exist)) \ -$(if $(filter $(_aioc_os),$(_os_list)),,$(eval include $(_aioc_os_cfg))) \ -$(eval AUX_OS_VARIANT_LIST_$(_aioc_os) += $(1)) \ -$(eval _os_list += $(_aioc_os)) -endef - -# make sure that AUX config variables are minimally sane; -# as a bare minimum they must contain the vars described by aux_env -# Generate error if requirement is not met. -# -#$(1) - variant -# no return value -define aux-variant-validate -$(eval _all:=) \ -$(eval _req:=$(addsuffix _$(1),$(aux_env))) \ -$(foreach var,$(_req),$(eval _all += $(var))) \ -$(eval _missing := $(filter-out $(_all),$(_req))) \ -$(if $(_missing),$(error AUX variant $(1) must define vars: $(_missing))) -endef - -AUX_ALL_VARIANTS := -AUX_ALL_OSES := -AUX_ALL_CPUS := -AUX_ALL_ARCHS := -AUX_ALL_SUBARCHS := - -variant_sfx :=_aux_variant_config.mk -os_sfx :=_aux_os_config.mk - -ifdef AUX_OS_VARIANT_LIST - -config_roots := $(wildcard device vendor) -all_configs := -ifdef config_roots -all_configs := $(sort $(shell find $(config_roots) -maxdepth 4 -name '*$(variant_sfx)' -o -name '*$(os_sfx)')) -endif -all_os_configs := $(filter %$(os_sfx),$(all_configs)) -all_variant_configs := $(filter %$(variant_sfx),$(all_configs)) - -AUX_ALL_OS_PATHS := $(foreach f,$(all_os_configs),$(patsubst %$(os_sfx),%,$(notdir $(f))):$(patsubst %/,%,$(dir $(f)))) -AUX_ALL_OS_VARIANT_PATHS := $(foreach f,$(all_variant_configs),$(patsubst %$(variant_sfx),%,$(notdir $(f))):$(patsubst %/,%,$(dir $(f)))) - -my_variant_pairs := $(foreach v,$(AUX_OS_VARIANT_LIST),$(filter $(v):%,$(AUX_ALL_OS_VARIANT_PATHS))) -my_missing_variants := $(foreach v,$(AUX_OS_VARIANT_LIST),$(if $(filter $(v):%,$(AUX_ALL_OS_VARIANT_PATHS)),,$(v))) - -ifneq ($(strip $(my_missing_variants)),) -$(error Don't know how to build variant(s): $(my_missing_variants)) -endif - -# mandatory variables -aux_env := AUX_OS AUX_ARCH AUX_SUBARCH AUX_CPU - -$(foreach v,$(my_variant_pairs),$(if $(filter $(v),$(AUX_ALL_VARIANTS)),,$(call aux-variant-import-from-pair,$(v),$(variant_sfx)))) - -ifdef AUX_ALL_VARIANTS -_os_list := -$(foreach v,$(AUX_ALL_VARIANTS),\ - $(call aux-import-os-config,$(v)) \ - $(call aux-variant-validate,$(v)) \ -) -endif - -endif # AUX_OS_VARIANT_LIST - -INSTALLED_AUX_TARGETS := diff --git a/core/aux_executable.mk b/core/aux_executable.mk deleted file mode 100644 index 5395e61964..0000000000 --- a/core/aux_executable.mk +++ /dev/null @@ -1,95 +0,0 @@ -# caller might have included aux_toolchain, e.g. if custom build steps are defined -ifeq ($(LOCAL_IS_AUX_MODULE),) -include $(BUILD_SYSTEM)/aux_toolchain.mk -endif - -ifeq ($(AUX_BUILD_NOT_COMPATIBLE),) - -########################################################### -## Standard rules for building an executable file. -## -## Additional inputs from base_rules.make: -## None. -########################################################### - -ifeq ($(strip $(LOCAL_MODULE_CLASS)),) -LOCAL_MODULE_CLASS := EXECUTABLES -endif - -$(call $(aux-executable-hook)) - -########################################################### -## Standard rules for building any target-side binaries -## with dynamic linkage (dynamic libraries or executables -## that link with dynamic libraries) -## -## Files including this file must define a rule to build -## the target $(linked_module). -########################################################### - -# The name of the target file, without any path prepended. -# This duplicates logic from base_rules.mk because we need to -# know its results before base_rules.mk is included. -include $(BUILD_SYSTEM)/configure_module_stem.mk - -intermediates := $(call local-intermediates-dir) - -# Define the target that is the unmodified output of the linker. -# The basename of this target must be the same as the final output -# binary name, because it's used to set the "soname" in the binary. -# The includer of this file will define a rule to build this target. -linked_module := $(intermediates)/LINKED/$(my_built_module_stem) - -ALL_ORIGINAL_DYNAMIC_BINARIES += $(linked_module) - -# Because AUX_SYMBOL_FILTER_FILE depends on ALL_ORIGINAL_DYNAMIC_BINARIES, -# the linked_module rules won't necessarily inherit the PRIVATE_ -# variables from LOCAL_BUILT_MODULE. This tells binary.make to explicitly -# define the PRIVATE_ variables for linked_module as well as for -# LOCAL_BUILT_MODULE. -LOCAL_INTERMEDIATE_TARGETS += $(linked_module) - -################################### -include $(BUILD_SYSTEM)/binary.mk -################################### - -aux_output := $(linked_module) - -ifneq ($(LOCAL_CUSTOM_BUILD_STEP_INPUT),) -ifneq ($(LOCAL_CUSTOM_BUILD_STEP_OUTPUT),) - -# injecting custom build steps -$(LOCAL_CUSTOM_BUILD_STEP_INPUT): $(aux_output) - @echo "$(AUX_DISPLAY) custom copy: $(PRIVATE_MODULE) ($@)" - @mkdir -p $(dir $@) - $(hide) $(copy-file-to-target) - -aux_output := $(LOCAL_CUSTOM_BUILD_STEP_OUTPUT) - -endif -endif - -$(LOCAL_BUILT_MODULE): $(aux_output) - @echo "$(AUX_DISPLAY) final copy: $(PRIVATE_MODULE) ($@)" - @mkdir -p $(dir $@) - $(hide) $(copy-file-to-target) - -INSTALLED_AUX_TARGETS += $(LOCAL_INSTALLED_MODULE) - -$(cleantarget): PRIVATE_CLEAN_FILES += \ - $(linked_module) \ - -# Define PRIVATE_ variables from global vars -$(linked_module): PRIVATE_POST_LINK_CMD := $(LOCAL_POST_LINK_CMD) - -ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true) -$(linked_module): $(all_objects) $(all_libraries) $(LOCAL_ADDITIONAL_DEPENDENCIES) - $(transform-o-to-aux-static-executable) - $(PRIVATE_POST_LINK_CMD) -else -$(linked_module): $(all_objects) $(all_libraries) $(LOCAL_ADDITIONAL_DEPENDENCIES) - $(transform-o-to-aux-executable) - $(PRIVATE_POST_LINK_CMD) -endif - -endif # AUX_BUILD_NOT_COMPATIBLE diff --git a/core/aux_static_library.mk b/core/aux_static_library.mk deleted file mode 100644 index d88478d83e..0000000000 --- a/core/aux_static_library.mk +++ /dev/null @@ -1,27 +0,0 @@ -ifeq ($(LOCAL_IS_AUX_MODULE),) -include $(BUILD_SYSTEM)/aux_toolchain.mk -endif - -ifeq ($(AUX_BUILD_NOT_COMPATIBLE),) - -ifeq ($(strip $(LOCAL_MODULE_CLASS)),) -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -endif -ifeq ($(strip $(LOCAL_MODULE_SUFFIX)),) -LOCAL_MODULE_SUFFIX := .a -endif - -LOCAL_UNINSTALLABLE_MODULE := true - -ifneq ($(strip $(LOCAL_MODULE_STEM)$(LOCAL_BUILT_MODULE_STEM)),) -$(error $(LOCAL_PATH): Cannot set module stem for a library) -endif - -include $(BUILD_SYSTEM)/binary.mk - -$(LOCAL_BUILT_MODULE) : PRIVATE_AR := $(AUX_AR) -$(LOCAL_BUILT_MODULE) : $(built_whole_libraries) -$(LOCAL_BUILT_MODULE) : $(all_objects) - $(transform-o-to-aux-static-lib) - -endif # AUX_BUILD_NOT_COMPATIBLE diff --git a/core/aux_toolchain.mk b/core/aux_toolchain.mk deleted file mode 100644 index c7102288d0..0000000000 --- a/core/aux_toolchain.mk +++ /dev/null @@ -1,52 +0,0 @@ -########################################################### -# takes form LOCAL_AUX_TOOLCHAIN_$(LOCAL_AUX_CPU) -########################################################### - -############################### -# setup AUX environment -############################### - -# shortcuts for targets with a single instance of OS, ARCH, VARIANT, CPU -AUX_TOOLCHAIN := $(if $(LOCAL_AUX_TOOLCHAIN),$(LOCAL_AUX_TOOLCHAIN),$(AUX_TOOLCHAIN_$(AUX_CPU))) -AUX_BUILD_NOT_COMPATIBLE:= -ifeq ($(strip $(AUX_TOOLCHAIN)),) - ifeq ($(strip $(AUX_CPU)),) - $(warning $(LOCAL_PATH): $(LOCAL_MODULE): Undefined CPU for AUX toolchain) - AUX_BUILD_NOT_COMPATIBLE += TOOLCHAIN - else - $(warning $(LOCAL_PATH): $(LOCAL_MODULE): Undefined AUX toolchain for CPU=$(AUX_CPU)) - AUX_BUILD_NOT_COMPATIBLE += TOOLCHAIN - endif -endif - -AUX_BUILD_NOT_COMPATIBLE += $(foreach var,OS ARCH SUBARCH CPU OS_VARIANT,$(if $(LOCAL_AUX_$(var)),$(if \ - $(filter $(LOCAL_AUX_$(var)),$(AUX_$(var))),,$(var)))) - -AUX_BUILD_NOT_COMPATIBLE := $(strip $(AUX_BUILD_NOT_COMPATIBLE)) - -ifneq ($(AUX_BUILD_NOT_COMPATIBLE),) -$(info $(LOCAL_PATH): $(LOCAL_MODULE): not compatible: "$(AUX_BUILD_NOT_COMPATIBLE)" with) -$(info ====> OS=$(AUX_OS) CPU=$(AUX_CPU) ARCH=$(AUX_ARCH) SUBARCH=$(AUX_SUBARCH) OS_VARIANT=$(AUX_OS_VARIANT)) -$(info ====> TOOLCHAIN=$(AUX_TOOLCHAIN)) -endif - -AUX_AR := $(AUX_TOOLCHAIN)ar -AUX_AS := $(AUX_TOOLCHAIN)gcc -AUX_CC := $(AUX_TOOLCHAIN)gcc -AUX_CXX := $(AUX_TOOLCHAIN)g++ -AUX_LINKER := $(AUX_TOOLCHAIN)ld -AUX_OBJCOPY := $(AUX_TOOLCHAIN)objcopy -AUX_OBJDUMP := $(AUX_TOOLCHAIN)objdump - -############################### -# setup Android environment -############################### - -LOCAL_IS_AUX_MODULE := true -LOCAL_2ND_ARCH_VAR_PREFIX := -LOCAL_CC := $(AUX_CC) -LOCAL_CXX := $(AUX_CXX) -LOCAL_NO_DEFAULT_COMPILER_FLAGS := true -LOCAL_SYSTEM_SHARED_LIBRARIES := -LOCAL_CXX_STL := none -LOCAL_NO_PIC := true diff --git a/core/base_rules.mk b/core/base_rules.mk index e608ee7e14..58be7a2d75 100644 --- a/core/base_rules.mk +++ b/core/base_rules.mk @@ -34,7 +34,6 @@ endif $(call verify-module-name) LOCAL_IS_HOST_MODULE := $(strip $(LOCAL_IS_HOST_MODULE)) -LOCAL_IS_AUX_MODULE := $(strip $(LOCAL_IS_AUX_MODULE)) ifdef LOCAL_IS_HOST_MODULE ifneq ($(LOCAL_IS_HOST_MODULE),true) $(error $(LOCAL_PATH): LOCAL_IS_HOST_MODULE must be "true" or empty, not "$(LOCAL_IS_HOST_MODULE)") @@ -47,16 +46,8 @@ ifdef LOCAL_IS_HOST_MODULE my_host := host- my_kind := HOST else - ifdef LOCAL_IS_AUX_MODULE - ifneq ($(LOCAL_IS_AUX_MODULE),true) - $(error $(LOCAL_PATH): LOCAL_IS_AUX_MODULE must be "true" or empty, not "$(LOCAL_IS_AUX_MODULE)") - endif - my_prefix := AUX_ - my_kind := AUX - else - my_prefix := TARGET_ - my_kind := - endif + my_prefix := TARGET_ + my_kind := my_host := endif @@ -102,6 +93,20 @@ ifneq ($(filter-out $(LOCAL_PROPRIETARY_MODULE),$(LOCAL_VENDOR_MODULE))$(filter- $(call pretty-error,Only one of LOCAL_PROPRIETARY_MODULE[$(LOCAL_PROPRIETARY_MODULE)] and LOCAL_VENDOR_MODULE[$(LOCAL_VENDOR_MODULE)] may be set, or they must be equal) endif +ifeq ($(LOCAL_HOST_MODULE),true) +my_image_variant := host +else ifeq ($(LOCAL_VENDOR_MODULE),true) +my_image_variant := vendor +else ifeq ($(LOCAL_OEM_MODULE),true) +my_image_variant := vendor +else ifeq ($(LOCAL_ODM_MODULE),true) +my_image_variant := vendor +else ifeq ($(LOCAL_PRODUCT_MODULE),true) +my_image_variant := product +else +my_image_variant := core +endif + non_system_module := $(filter true, \ $(LOCAL_PRODUCT_MODULE) \ $(LOCAL_SYSTEM_EXT_MODULE) \ @@ -110,6 +115,7 @@ non_system_module := $(filter true, \ include $(BUILD_SYSTEM)/local_vndk.mk include $(BUILD_SYSTEM)/local_systemsdk.mk +include $(BUILD_SYSTEM)/local_current_sdk.mk my_module_tags := $(LOCAL_MODULE_TAGS) ifeq ($(my_host_cross),true) @@ -205,6 +211,7 @@ my_module_path := $(strip $(LOCAL_MODULE_PATH)) endif my_module_path := $(patsubst %/,%,$(my_module_path)) my_module_relative_path := $(strip $(LOCAL_MODULE_RELATIVE_PATH)) + ifdef LOCAL_IS_HOST_MODULE partition_tag := actual_partition_tag := @@ -315,12 +322,9 @@ else my_all_targets := device_$(my_register_name)_all_targets endif -# variant is enough to make nano class unique; it serves as a key to lookup (OS,ARCH) tuple -aux_class := $($(my_prefix)OS_VARIANT) # Make sure that this IS_HOST/CLASS/MODULE combination is unique. module_id := MODULE.$(if \ - $(LOCAL_IS_HOST_MODULE),$($(my_prefix)OS),$(if \ - $(LOCAL_IS_AUX_MODULE),$(aux_class),TARGET)).$(LOCAL_MODULE_CLASS).$(my_register_name) + $(LOCAL_IS_HOST_MODULE),$($(my_prefix)OS),TARGET).$(LOCAL_MODULE_CLASS).$(my_register_name) ifdef $(module_id) $(error $(LOCAL_PATH): $(module_id) already defined by $($(module_id))) endif @@ -366,16 +370,16 @@ LOCAL_BUILT_MODULE := $(intermediates)/$(my_built_module_stem) ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE)) # Apk and its attachments reside in its own subdir. ifeq ($(LOCAL_MODULE_CLASS),APPS) - # framework-res.apk doesn't like the additional layer. - ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true) - # Neither do Runtime Resource Overlay apks, which contain just the overlaid resources. - else ifeq ($(LOCAL_IS_RUNTIME_RESOURCE_OVERLAY),true) - else - ifneq ($(use_testcase_folder),true) - my_module_path := $(my_module_path)/$(LOCAL_MODULE) + # framework-res.apk doesn't like the additional layer. + ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true) + # Neither do Runtime Resource Overlay apks, which contain just the overlaid resources. + else ifeq ($(LOCAL_IS_RUNTIME_RESOURCE_OVERLAY),true) + else + ifneq ($(use_testcase_folder),true) + my_module_path := $(my_module_path)/$(LOCAL_MODULE) + endif endif endif - endif LOCAL_INSTALLED_MODULE := $(my_module_path)/$(my_installed_module_stem) endif @@ -437,7 +441,6 @@ $(cleantarget):: ########################################################### $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_PATH:=$(LOCAL_PATH) $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_IS_HOST_MODULE := $(LOCAL_IS_HOST_MODULE) -$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_IS_AUX_MODULE := $(LOCAL_IS_AUX_MODULE) $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_HOST:= $(my_host) $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_PREFIX := $(my_prefix) @@ -464,12 +467,35 @@ endif # Set up phony targets that covers all modules under the given paths. # This allows us to build everything in given paths by running mmma/mma. -my_path_components := $(subst /,$(space),$(LOCAL_PATH)) -my_path_prefix := MODULES-IN -$(foreach c, $(my_path_components),\ - $(eval my_path_prefix := $(my_path_prefix)-$(c))\ - $(eval .PHONY : $(my_path_prefix))\ - $(eval $(my_path_prefix) : $(my_all_targets))) +define my_path_comp +parent := $(patsubst %/,%,$(dir $(1))) +parent_target := MODULES-IN-$$(subst /,-,$$(parent)) +.PHONY: $$(parent_target) +$$(parent_target): $(2) +ifndef $$(parent_target) + $$(parent_target) := true + ifneq (,$$(findstring /,$$(parent))) + $$(eval $$(call my_path_comp,$$(parent),$$(parent_target))) + endif +endif +endef + +_local_path := $(patsubst %/,%,$(LOCAL_PATH)) +_local_path_target := MODULES-IN-$(subst /,-,$(_local_path)) + +.PHONY: $(_local_path_target) +$(_local_path_target): $(my_register_name) + +ifndef $(_local_path_target) + $(_local_path_target) := true + ifneq (,$(findstring /,$(_local_path))) + $(eval $(call my_path_comp,$(_local_path),$(_local_path_target))) + endif +endif + +_local_path := +_local_path_target := +my_path_comp := ########################################################### ## Module installation rule @@ -490,7 +516,11 @@ ifneq ($(LOCAL_INSTALLED_MODULE),$(my_default_test_module)) $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD) $(LOCAL_INSTALLED_MODULE): $(LOCAL_BUILT_MODULE) @echo "Install: $@" +ifeq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK)) + $(copy-file-or-link-to-new-target) +else $(copy-file-to-new-target) +endif $(PRIVATE_POST_INSTALL_CMD) endif @@ -583,12 +613,22 @@ ifneq ($(strip $(filter NATIVE_TESTS,$(LOCAL_MODULE_CLASS)) $(LOCAL_IS_FUZZ_TARG ifneq ($(strip $(LOCAL_TEST_DATA)),) ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE)) +# Soong LOCAL_TEST_DATA is of the form <from_base>:<file>:<relative_install_path> +# or <from_base>:<file>, to be installed to +# <install_root>/<relative_install_path>/<file> or <install_root>/<file>, +# respectively. ifeq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK)) define copy_test_data_pairs _src_base := $$(call word-colon,1,$$(td)) _file := $$(call word-colon,2,$$(td)) - my_test_data_pairs += $$(call append-path,$$(_src_base),$$(_file)):$$(call append-path,$$(my_module_path),$$(_file)) - my_test_data_file_pairs += $$(call append-path,$$(_src_base),$$(_file)):$$(_file) + _relative_install_path := $$(call word-colon,3,$$(td)) + ifeq (,$$(_relative_install_path)) + _relative_dest_file := $$(_file) + else + _relative_dest_file := $$(call append-path,$$(_relative_install_path),$$(_file)) + endif + my_test_data_pairs += $$(call append-path,$$(_src_base),$$(_file)):$$(call append-path,$$(my_module_path),$$(_relative_dest_file)) + my_test_data_file_pairs += $$(call append-path,$$(_src_base),$$(_file)):$$(_relative_dest_file) endef else define copy_test_data_pairs @@ -722,6 +762,13 @@ else $(test_config):$(dir)/$(LOCAL_MODULE).config))) endif + ifneq (,$(LOCAL_EXTRA_FULL_TEST_CONFIGS)) + $(foreach test_config_file, $(LOCAL_EXTRA_FULL_TEST_CONFIGS), \ + $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \ + $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \ + $(test_config_file):$(dir)/$(basename $(notdir $(test_config_file))).config)))) + endif + ifneq (,$(wildcard $(LOCAL_PATH)/DynamicConfig.xml)) $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \ $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \ @@ -749,13 +796,19 @@ endif ifeq ($(use_testcase_folder),true) ifneq ($(my_test_data_file_pairs),) +# Filter out existng installed test data paths when collecting test data files to be installed and +# indexed as they cause build rule conflicts. Instead put them in a separate list which is only +# used for indexing. $(foreach pair, $(my_test_data_file_pairs), \ $(eval parts := $(subst :,$(space),$(pair))) \ $(eval src_path := $(word 1,$(parts))) \ $(eval file := $(word 2,$(parts))) \ $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \ $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \ - $(call filter-copy-pair,$(src_path),$(call append-path,$(dir),$(file)),$(my_installed_test_data)))))) + $(call filter-copy-pair,$(src_path),$(call append-path,$(dir),$(file)),$(my_installed_test_data)))) \ + $(eval my_compat_dist_test_data_$(suite) += \ + $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \ + $(filter $(my_installed_test_data),$(call append-path,$(dir),$(file))))))) endif else ifneq ($(my_test_data_file_pairs),) @@ -776,7 +829,8 @@ is_native := $(call create-suite-dependencies) $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \ - $(eval my_compat_dist_config_$(suite) := )) + $(eval my_compat_dist_config_$(suite) := ) \ + $(eval my_compat_dist_test_data_$(suite) := )) endif # LOCAL_UNINSTALLABLE_MODULE endif # LOCAL_COMPATIBILITY_SUITE @@ -931,6 +985,8 @@ ALL_MODULES.$(my_register_name).FOR_HOST_CROSS := $(my_host_cross) ALL_MODULES.$(my_register_name).MODULE_NAME := $(LOCAL_MODULE) ALL_MODULES.$(my_register_name).COMPATIBILITY_SUITES := $(LOCAL_COMPATIBILITY_SUITE) ALL_MODULES.$(my_register_name).TEST_CONFIG := $(test_config) +ALL_MODULES.$(my_register_name).EXTRA_TEST_CONFIGS := $(LOCAL_EXTRA_FULL_TEST_CONFIGS) +ALL_MODULES.$(my_register_name).TEST_MAINLINE_MODULES := $(LOCAL_TEST_MAINLINE_MODULES) test_config := INSTALLABLE_FILES.$(LOCAL_INSTALLED_MODULE).MODULE := $(my_register_name) @@ -938,7 +994,7 @@ INSTALLABLE_FILES.$(LOCAL_INSTALLED_MODULE).MODULE := $(my_register_name) ########################################################## # Track module-level dependencies. # Use $(LOCAL_MODULE) instead of $(my_register_name) to ignore module's bitness. -ifneq (,$(filter deps-license,$(MAKECMDGOALS))) +ifdef RECORD_ALL_DEPS ALL_DEPS.MODULES += $(LOCAL_MODULE) ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(sort \ $(ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS) \ diff --git a/core/binary.mk b/core/binary.mk index 23a201c4ef..be008e68a2 100644 --- a/core/binary.mk +++ b/core/binary.mk @@ -64,19 +64,69 @@ my_export_c_include_dirs := $(LOCAL_EXPORT_C_INCLUDE_DIRS) my_export_c_include_deps := $(LOCAL_EXPORT_C_INCLUDE_DEPS) my_arflags := +# Disable clang-tidy if it is not found. +ifeq ($(PATH_TO_CLANG_TIDY),) + my_tidy_enabled := false +else + # If LOCAL_TIDY is not defined, use global WITH_TIDY + my_tidy_enabled := $(LOCAL_TIDY) + ifeq ($(my_tidy_enabled),) + my_tidy_enabled := $(WITH_TIDY) + endif +endif + +# my_tidy_checks is empty if clang-tidy is disabled. +my_tidy_checks := +my_tidy_flags := +ifneq (,$(filter 1 true,$(my_tidy_enabled))) + # Set up global default checks + my_tidy_checks := $(WITH_TIDY_CHECKS) + ifeq ($(my_tidy_checks),) + my_tidy_checks := $(call default_global_tidy_checks,$(LOCAL_PATH)) + endif + # Append local clang-tidy checks. + ifneq ($(LOCAL_TIDY_CHECKS),) + my_tidy_checks := $(my_tidy_checks),$(LOCAL_TIDY_CHECKS) + endif + my_tidy_flags := $(strip $(WITH_TIDY_FLAGS) $(LOCAL_TIDY_FLAGS)) + # If tidy flags are not specified, default to check all header files. + ifeq ($(my_tidy_flags),) + my_tidy_flags := $(call default_tidy_header_filter,$(LOCAL_PATH)) + endif + # If clang-tidy is not enabled globally, add the -quiet flag. + ifeq (,$(filter 1 true,$(WITH_TIDY))) + my_tidy_flags += -quiet -extra-arg-before=-fno-caret-diagnostics + endif + + ifneq ($(my_tidy_checks),) + # We might be using the static analyzer through clang-tidy. + # https://bugs.llvm.org/show_bug.cgi?id=32914 + my_tidy_flags += -extra-arg-before=-D__clang_analyzer__ + + # A recent change in clang-tidy (r328258) enabled destructor inlining, + # which appears to cause a number of false positives. Until that's + # resolved, this turns off the effects of r328258. + # https://bugs.llvm.org/show_bug.cgi?id=37459 + my_tidy_flags += -extra-arg-before=-Xclang + my_tidy_flags += -extra-arg-before=-analyzer-config + my_tidy_flags += -extra-arg-before=-Xclang + my_tidy_flags += -extra-arg-before=c++-temp-dtor-inlining=false + endif +endif + +my_tidy_checks := $(subst $(space),,$(my_tidy_checks)) + # Configure the pool to use for clang rules. # If LOCAL_CC or LOCAL_CXX is set don't use goma or RBE. +# If clang-tidy is being used, don't use the RBE pool (as clang-tidy runs in +# the same action, and is not remoted) my_pool := -ifeq (,$(strip $(my_cc))$(strip $(my_cxx))) +ifeq (,$(strip $(my_cc))$(strip $(my_cxx))$(strip $(my_tidy_checks))) my_pool := $(GOMA_OR_RBE_POOL) endif -# TODO(b/158212027): Remove `$(COVERAGE_PATHS)` from this condition when all users have been moved -# to `NATIVE_COVERAGE_PATHS`. -ifneq (,$(strip $(foreach dir,$(COVERAGE_PATHS) $(NATIVE_COVERAGE_PATHS),$(filter $(dir)%,$(LOCAL_PATH))))) -# TODO(b/158212027): Remove `$(COVERAGE_EXCLUDE_PATHS)` from this condition when all users have been -# moved to `NATIVE_COVERAGE_EXCLUDE_PATHS`. -ifeq (,$(strip $(foreach dir,$(COVERAGE_EXCLUDE_PATHS) $(NATIVE_COVERAGE_EXCLUDE_PATHS),$(filter $(dir)%,$(LOCAL_PATH))))) +ifneq (,$(strip $(foreach dir,$(NATIVE_COVERAGE_PATHS),$(filter $(dir)%,$(LOCAL_PATH))))) +ifeq (,$(strip $(foreach dir,$(NATIVE_COVERAGE_EXCLUDE_PATHS),$(filter $(dir)%,$(LOCAL_PATH))))) my_native_coverage := true else my_native_coverage := false @@ -106,6 +156,8 @@ my_ndk_sysroot_include := my_ndk_sysroot_lib := my_api_level := 10000 +my_arch := $(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH) + ifneq ($(LOCAL_SDK_VERSION),) ifdef LOCAL_IS_HOST_MODULE $(error $(LOCAL_PATH): LOCAL_SDK_VERSION cannot be used in host module) @@ -114,19 +166,7 @@ ifneq ($(LOCAL_SDK_VERSION),) # Make sure we've built the NDK. my_additional_dependencies += $(SOONG_OUT_DIR)/ndk_base.timestamp - # mips32r6 is not supported by the NDK. No released NDK contains these - # libraries, but the r10 in prebuilts/ndk had a local hack to add them :( - # - # We need to find a real solution to this problem, but until we do just drop - # mips32r6 things back to r10 to get the tree building again. - ifeq (mips32r6,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH_VARIANT)) - ifeq ($(LOCAL_NDK_VERSION), current) - LOCAL_NDK_VERSION := r10 - endif - endif - - my_arch := $(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH) - ifneq (,$(filter arm64 mips64 x86_64,$(my_arch))) + ifneq (,$(filter arm64 x86_64,$(my_arch))) my_min_sdk_version := 21 else my_min_sdk_version := $(MIN_SUPPORTED_SDK_VERSION) @@ -141,6 +181,8 @@ ifneq ($(LOCAL_SDK_VERSION),) my_ndk_api := $(call math_max,$(my_ndk_api),$(my_min_sdk_version)) endif + my_ndk_crt_version := $(my_ndk_api) + my_ndk_hist_api := $(my_ndk_api) ifeq ($(my_ndk_api),current) # The last API level supported by the old prebuilt NDKs. @@ -160,17 +202,11 @@ ifneq ($(LOCAL_SDK_VERSION),) $(my_built_ndk)/sysroot/usr/include/$(my_ndk_triple) \ $(my_ndk_sysroot)/usr/include \ - # x86_64 and and mips64 are both multilib toolchains, so their libraries are + # x86_64 is a multilib toolchain, so their libraries are # installed in /usr/lib64. Aarch64, on the other hand, is not a multilib # compiler, so its libraries are in /usr/lib. - # - # Mips32r6 is yet another variation, with libraries installed in libr6. - # - # For the rest, the libraries are installed simply to /usr/lib. - ifneq (,$(filter x86_64 mips64,$(my_arch))) + ifneq (,$(filter x86_64,$(my_arch))) my_ndk_libdir_name := lib64 - else ifeq (mips32r6,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH_VARIANT)) - my_ndk_libdir_name := libr6 else my_ndk_libdir_name := lib endif @@ -184,11 +220,7 @@ ifneq ($(LOCAL_SDK_VERSION),) # hashes (which are much faster!), but shipping to older devices requires # the old style hash. Fortunately, we can build with both and it'll work # anywhere. - # - # This is not currently supported on MIPS architectures. - ifeq (,$(filter mips mips64,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))) - my_ldflags += -Wl,--hash-style=both - endif + my_ldflags += -Wl,--hash-style=both # We don't want to expose the relocation packer to the NDK just yet. LOCAL_PACK_MODULE_RELOCATIONS := false @@ -199,9 +231,6 @@ ifneq ($(LOCAL_SDK_VERSION),) my_ndk_stl_shared_lib_fullpath := my_ndk_stl_static_lib := my_cpu_variant := $(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)CPU_ABI) - ifeq (mips32r6,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH_VARIANT)) - my_cpu_variant := mips32r6 - endif LOCAL_NDK_STL_VARIANT := $(strip $(LOCAL_NDK_STL_VARIANT)) ifeq (,$(LOCAL_NDK_STL_VARIANT)) LOCAL_NDK_STL_VARIANT := system @@ -310,8 +339,7 @@ else # LOCAL_IS_HOST_MODULE endif ifneq ($(LOCAL_SDK_VERSION),) - my_all_ndk_libraries := \ - $(NDK_MIGRATED_LIBS) $(addprefix lib,$(NDK_PREBUILT_SHARED_LIBRARIES)) + my_all_ndk_libraries := $(NDK_KNOWN_LIBS) my_ndk_shared_libraries := \ $(filter $(my_all_ndk_libraries),\ $(my_shared_libraries) $(my_system_shared_libraries)) @@ -623,7 +651,7 @@ rs_generated_cpps := $(addprefix \ $(call track-src-file-gen,$(renderscript_sources),$(rs_generated_cpps)) -# This is just a dummy rule to make sure gmake doesn't skip updating the dependents. +# This is just a no-op rule to make sure gmake doesn't skip updating the dependents. $(rs_generated_cpps) : $(RenderScript_file_stamp) @echo "Updated RS generated cpp file $@." $(hide) touch $@ @@ -1089,37 +1117,39 @@ asm_objects += $(asm_objects_asm) endif ################################################################### -## When compiling a CFI enabled target, use the .cfi variant of any -## static dependencies (where they exist). +## Convert to sanitized names where they exist. +## These lists come from sanitizerStaticLibsMap; see +## build/soong/cc/sanitize.go +## +## $(1): list of static dependencies +## $(2): name of sanitizer (e.g. cfi, hwasan) ################################################################## -define use_soong_cfi_static_libraries - $(foreach l,$(1),$(if $(filter $(l),$(SOONG_CFI_STATIC_LIBRARIES)),\ - $(l).cfi,$(l))) +define use_soong_sanitized_static_libraries + $(foreach lib,$(1),$(if $(filter $(lib),\ + $(SOONG_$(2)_$(my_image_variant)_$(my_arch)_STATIC_LIBRARIES)),\ + $(lib).$(2),$(lib))) endef +################################################################### +## When compiling a CFI enabled target, use the .cfi variant of any +## static dependencies (where they exist). +################################################################## ifneq ($(filter cfi,$(my_sanitize)),) - my_whole_static_libraries := $(call use_soong_cfi_static_libraries,\ - $(my_whole_static_libraries)) - my_static_libraries := $(call use_soong_cfi_static_libraries,\ - $(my_static_libraries)) + my_whole_static_libraries := $(call use_soong_sanitized_static_libraries,\ + $(my_whole_static_libraries),cfi) + my_static_libraries := $(call use_soong_sanitized_static_libraries,\ + $(my_static_libraries),cfi) endif -ifneq ($(LOCAL_USE_VNDK),) - my_soong_hwasan_static_libraries := $(SOONG_HWASAN_VENDOR_STATIC_LIBRARIES) -else - my_soong_hwasan_static_libraries = $(SOONG_HWASAN_STATIC_LIBRARIES) -endif - -define use_soong_hwasan_static_libraries - $(foreach l,$(1),$(if $(filter $(l),$(my_soong_hwasan_static_libraries)),\ - $(l).hwasan,$(l))) -endef - +################################################################### +## When compiling a hwasan enabled target, use the .hwasan variant +## of any static dependencies (where they exist). +################################################################## ifneq ($(filter hwaddress,$(my_sanitize)),) - my_whole_static_libraries := $(call use_soong_hwasan_static_libraries,\ - $(my_whole_static_libraries)) - my_static_libraries := $(call use_soong_hwasan_static_libraries,\ - $(my_static_libraries)) + my_whole_static_libraries := $(call use_soong_sanitized_static_libraries,\ + $(my_whole_static_libraries),hwasan) + my_static_libraries := $(call use_soong_sanitized_static_libraries,\ + $(my_static_libraries),hwasan) endif ########################################################### @@ -1378,7 +1408,7 @@ my_system_shared_libraries_fullpath := \ # lists and use addprefix. my_ndk_shared_libraries_fullpath := \ $(foreach _lib,$(my_ndk_shared_libraries),\ - $(if $(filter $(NDK_MIGRATED_LIBS),$(_lib)),\ + $(if $(filter $(NDK_KNOWN_LIBS),$(_lib)),\ $(my_built_ndk_libs)/$(_lib)$(so_suffix),\ $(my_ndk_sysroot_lib)/$(_lib)$(so_suffix))) @@ -1509,61 +1539,10 @@ ifneq (,$(filter -Weverything,$(my_all_cflags))) endif endif -# Disable clang-tidy if it is not found. -ifeq ($(PATH_TO_CLANG_TIDY),) - my_tidy_enabled := false -else - # If LOCAL_TIDY is not defined, use global WITH_TIDY - my_tidy_enabled := $(LOCAL_TIDY) - ifeq ($(my_tidy_enabled),) - my_tidy_enabled := $(WITH_TIDY) - endif -endif - -# my_tidy_checks is empty if clang-tidy is disabled. -my_tidy_checks := -my_tidy_flags := -ifneq (,$(filter 1 true,$(my_tidy_enabled))) +ifneq ($(my_tidy_checks),) tidy_only: $(cpp_objects) $(c_objects) $(gen_c_objects) $(gen_cpp_objects) - # Set up global default checks - my_tidy_checks := $(WITH_TIDY_CHECKS) - ifeq ($(my_tidy_checks),) - my_tidy_checks := $(call default_global_tidy_checks,$(LOCAL_PATH)) - endif - # Append local clang-tidy checks. - ifneq ($(LOCAL_TIDY_CHECKS),) - my_tidy_checks := $(my_tidy_checks),$(LOCAL_TIDY_CHECKS) - endif - my_tidy_flags := $(strip $(WITH_TIDY_FLAGS) $(LOCAL_TIDY_FLAGS)) - # If tidy flags are not specified, default to check all header files. - ifeq ($(my_tidy_flags),) - my_tidy_flags := $(call default_tidy_header_filter,$(LOCAL_PATH)) - endif - # If clang-tidy is not enabled globally, add the -quiet flag. - ifeq (,$(filter 1 true,$(WITH_TIDY))) - my_tidy_flags += -quiet -extra-arg-before=-fno-caret-diagnostics - endif - ifneq ($(my_tidy_checks),) - # We might be using the static analyzer through clang-tidy. - # https://bugs.llvm.org/show_bug.cgi?id=32914 - my_tidy_flags += -extra-arg-before=-D__clang_analyzer__ - - # A recent change in clang-tidy (r328258) enabled destructor inlining, - # which appears to cause a number of false positives. Until that's - # resolved, this turns off the effects of r328258. - # https://bugs.llvm.org/show_bug.cgi?id=37459 - my_tidy_flags += -extra-arg-before=-Xclang - my_tidy_flags += -extra-arg-before=-analyzer-config - my_tidy_flags += -extra-arg-before=-Xclang - my_tidy_flags += -extra-arg-before=c++-temp-dtor-inlining=false - endif -endif - -my_tidy_checks := $(subst $(space),,$(my_tidy_checks)) - -# Add dependency of clang-tidy and clang-tidy.sh -ifneq ($(my_tidy_checks),) + # Add dependency of clang-tidy and clang-tidy.sh $(cpp_objects): $(intermediates)/%.o: $(PATH_TO_CLANG_TIDY) $(c_objects): $(intermediates)/%.o: $(PATH_TO_CLANG_TIDY) $(gen_cpp_objects): $(intermediates)/%.o: $(PATH_TO_CLANG_TIDY) @@ -1579,7 +1558,7 @@ my_ldflags := $(filter-out -l%,$(my_ldlib_flags)) my_allowed_ldlibs := ifndef LOCAL_IS_HOST_MODULE ifneq ($(LOCAL_SDK_VERSION),) - my_allowed_ldlibs := $(addprefix -l,$(NDK_PREBUILT_SHARED_LIBRARIES)) + my_allowed_ldlibs := $(NDK_KNOWN_LIBS:lib%=-l%) endif else my_allowed_ldlibs := $($(my_prefix)AVAILABLE_LIBRARIES) @@ -1598,28 +1577,22 @@ my_ldlibs += $(my_cxx_ldlibs) ## Define PRIVATE_ variables from global vars ########################################################### ifndef LOCAL_IS_HOST_MODULE + ifdef LOCAL_USE_VNDK -my_target_global_c_includes := \ - $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) -my_target_global_c_system_includes := \ - $(TARGET_OUT_HEADERS) \ - $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) + my_target_global_c_includes := + my_target_global_c_system_includes := $(TARGET_OUT_HEADERS) else ifdef LOCAL_SDK_VERSION -my_target_global_c_includes := -my_target_global_c_system_includes := $(my_ndk_stl_include_path) $(my_ndk_sysroot_include) + my_target_global_c_includes := + my_target_global_c_system_includes := $(my_ndk_stl_include_path) $(my_ndk_sysroot_include) else ifdef BOARD_VNDK_VERSION -my_target_global_c_includes := $(SRC_HEADERS) \ - $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) \ + my_target_global_c_includes := $(SRC_HEADERS) \ $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES) -my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) \ - $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) \ + my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) \ $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES) else -my_target_global_c_includes := $(SRC_HEADERS) \ - $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) \ + my_target_global_c_includes := $(SRC_HEADERS) \ $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES) -my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) $(TARGET_OUT_HEADERS) \ - $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) \ + my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) $(TARGET_OUT_HEADERS) \ $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES) endif @@ -1702,9 +1675,22 @@ endif #################################################### ## Import includes #################################################### +imported_includes := + +ifdef LOCAL_USE_VNDK + imported_includes += $(call intermediates-dir-for,HEADER_LIBRARIES,device_kernel_headers,$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross)) +else ifdef LOCAL_SDK_VERSION + # Apps shouldn't need device-specific kernel headers +else ifdef BOARD_VNDK_VERSION + # For devices building with the VNDK, only the VNDK gets device-specific kernel headers by default + # In soong, it's entirely opt-in +else + # For older non-VNDK builds, continue adding in kernel headers to everything like we used to + imported_includes += $(call intermediates-dir-for,HEADER_LIBRARIES,device_kernel_headers,$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross)) +endif + imported_includes := $(strip \ - $(if $(LOCAL_USE_VNDK),\ - $(call intermediates-dir-for,HEADER_LIBRARIES,device_kernel_headers,$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))) \ + $(imported_includes) \ $(foreach l, $(installed_shared_library_module_names), \ $(call intermediates-dir-for,SHARED_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))) \ $(foreach l, $(my_static_libraries) $(my_whole_static_libraries), \ @@ -1840,6 +1826,10 @@ SOONG_CONV.$(LOCAL_MODULE).DEPS := \ $(my_shared_libraries) \ $(my_system_shared_libraries)) SOONG_CONV.$(LOCAL_MODULE).TYPE := native +SOONG_CONV.$(LOCAL_MODULE).MAKEFILES := \ + $(SOONG_CONV.$(LOCAL_MODULE).MAKEFILES) $(LOCAL_MODULE_MAKEFILE) +SOONG_CONV.$(LOCAL_MODULE).INSTALLED:= \ + $(SOONG_CONV.$(LOCAL_MODULE).INSTALLED) $(LOCAL_INSTALLED_MODULE) SOONG_CONV := $(SOONG_CONV) $(LOCAL_MODULE) ########################################################### diff --git a/core/board_config.mk b/core/board_config.mk index 86162b6f37..95d8af88f0 100644 --- a/core/board_config.mk +++ b/core/board_config.mk @@ -16,10 +16,11 @@ # ############################################################### # This file includes BoardConfig.mk for the device being built, -# and sanity-checks the variable defined therein. +# and checks the variable defined therein. # ############################################################### _board_strip_readonly_list := \ + BOARD_BOOTLOADER_IN_UPDATE_PACKAGE \ BOARD_EGL_CFG \ BOARD_HAVE_BLUETOOTH \ BOARD_INSTALLER_CMDLINE \ @@ -72,12 +73,18 @@ _board_strip_readonly_list += \ BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE \ BOARD_ODMIMAGE_PARTITION_SIZE \ BOARD_ODMIMAGE_FILE_SYSTEM_TYPE \ + BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE \ + BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE \ + BOARD_ODM_DLKMIMAGE_PARTITION_SIZE \ + BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE \ # Logical partitions related variables. _dynamic_partitions_var_list += \ BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE \ BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE \ BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE \ + BOARD_VENDOR_DLKMIMAGE_PARTITION_RESERVED_SIZE \ + BOARD_ODM_DLKMIMAGE_PARTITION_RESERVED_SIZE \ BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE \ BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE \ BOARD_SUPER_PARTITION_SIZE \ @@ -85,8 +92,16 @@ _dynamic_partitions_var_list += \ _board_strip_readonly_list += $(_dynamic_partitions_var_list) +# Kernel related variables +_board_strip_readonly_list += \ + BOARD_KERNEL_BINARIES \ + BOARD_KERNEL_MODULE_INTERFACE_VERSIONS \ + _build_broken_var_list := \ BUILD_BROKEN_DUP_RULES \ + BUILD_BROKEN_DUP_SYSPROP \ + BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES \ + BUILD_BROKEN_MISSING_REQUIRED_MODULES \ BUILD_BROKEN_OUTSIDE_INCLUDE_DIRS \ BUILD_BROKEN_PREBUILT_ELF_FILES \ BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW \ @@ -159,7 +174,7 @@ $(foreach var,$(_board_true_false_vars), \ TARGET_CPU_VARIANT_RUNTIME := $(or $(TARGET_CPU_VARIANT_RUNTIME),$(TARGET_CPU_VARIANT)) TARGET_2ND_CPU_VARIANT_RUNTIME := $(or $(TARGET_2ND_CPU_VARIANT_RUNTIME),$(TARGET_2ND_CPU_VARIANT)) -# The combo makefiles sanity-check and set defaults for various CPU configuration +# The combo makefiles check and set defaults for various CPU configuration combo_target := TARGET_ combo_2nd_arch_prefix := include $(BUILD_SYSTEM)/combo/select.mk @@ -183,7 +198,7 @@ ifeq (,$(filter true,$(TARGET_SUPPORTS_32_BIT_APPS) $(TARGET_SUPPORTS_64_BIT_APP TARGET_SUPPORTS_32_BIT_APPS := true endif -# Sanity check to warn about likely cryptic errors later in the build. +# Quick check to warn about likely cryptic errors later in the build. ifeq ($(TARGET_IS_64_BIT),true) ifeq (,$(filter true false,$(TARGET_SUPPORTS_64_BIT_APPS))) $(error Building a 32-bit-app-only product on a 64-bit device. \ @@ -241,13 +256,8 @@ endif # build a list out of the TARGET_CPU_ABIs specified by the config. # Add NATIVE_BRIDGE_ABIs at the end to keep order of preference. ifeq (,$(TARGET_CPU_ABI_LIST)) - ifeq ($(TARGET_IS_64_BIT)|$(TARGET_PREFER_32_BIT_APPS),true|true) - TARGET_CPU_ABI_LIST := $(TARGET_CPU_ABI_LIST_32_BIT) $(TARGET_CPU_ABI_LIST_64_BIT) \ - $(_target_native_bridge_abi_list_32_bit) $(_target_native_bridge_abi_list_64_bit) - else - TARGET_CPU_ABI_LIST := $(TARGET_CPU_ABI_LIST_64_BIT) $(TARGET_CPU_ABI_LIST_32_BIT) \ - $(_target_native_bridge_abi_list_64_bit) $(_target_native_bridge_abi_list_32_bit) - endif + TARGET_CPU_ABI_LIST := $(TARGET_CPU_ABI_LIST_64_BIT) $(TARGET_CPU_ABI_LIST_32_BIT) \ + $(_target_native_bridge_abi_list_64_bit) $(_target_native_bridge_abi_list_32_bit) endif # Add NATIVE_BRIDGE_ABIs at the end of 32 and 64 bit CPU_ABIs to keep order of preference. @@ -280,7 +290,7 @@ endif ########################################### # Now we can substitute with the real value of TARGET_COPY_OUT_DEBUG_RAMDISK -ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true) +ifneq (,$(filter true,$(BOARD_USES_RECOVERY_AS_BOOT) $(BOARD_GKI_NONAB_COMPAT))) TARGET_COPY_OUT_DEBUG_RAMDISK := debug_ramdisk/first_stage_ramdisk TARGET_COPY_OUT_VENDOR_DEBUG_RAMDISK := vendor_debug_ramdisk/first_stage_ramdisk TARGET_COPY_OUT_TEST_HARNESS_RAMDISK := test_harness_ramdisk/first_stage_ramdisk @@ -515,6 +525,40 @@ endif .KATI_READONLY := BUILDING_SYSTEM_EXT_IMAGE ########################################### +# Now we can substitute with the real value of TARGET_COPY_OUT_VENDOR_DLKM +ifeq ($(TARGET_COPY_OUT_VENDOR_DLKM),$(_vendor_dlkm_path_placeholder)) + TARGET_COPY_OUT_VENDOR_DLKM := $(TARGET_COPY_OUT_VENDOR)/vendor_dlkm +else ifeq ($(filter vendor_dlkm system/vendor/vendor_dlkm vendor/vendor_dlkm,$(TARGET_COPY_OUT_VENDOR_DLKM)),) + $(error TARGET_COPY_OUT_VENDOR_DLKM must be either 'vendor_dlkm', 'system/vendor/vendor_dlkm' or 'vendor/vendor_dlkm', seeing '$(TARGET_COPY_OUT_VENDOR_DLKM)'.) +endif +PRODUCT_COPY_FILES := $(subst $(_vendor_dlkm_path_placeholder),$(TARGET_COPY_OUT_VENDOR_DLKM),$(PRODUCT_COPY_FILES)) + +BOARD_USES_VENDOR_DLKMIMAGE := +ifdef BOARD_PREBUILT_VENDOR_DLKMIMAGE + BOARD_USES_VENDOR_DLKMIMAGE := true +endif +ifdef BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE + BOARD_USES_VENDOR_DLKMIMAGE := true +endif +$(call check_image_config,vendor_dlkm) + +BUILDING_VENDOR_DLKM_IMAGE := +ifeq ($(PRODUCT_BUILD_VENDOR_DLKM_IMAGE),) + ifdef BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE + BUILDING_VENDOR_DLKM_IMAGE := true + endif +else ifeq ($(PRODUCT_BUILD_VENDOR_DLKM_IMAGE),true) + BUILDING_VENDOR_DLKM_IMAGE := true + ifndef BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE + $(error PRODUCT_BUILD_VENDOR_DLKM_IMAGE set to true, but BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE not defined) + endif +endif +ifdef BOARD_PREBUILT_VENDOR_DLKMIMAGE + BUILDING_VENDOR_DLKM_IMAGE := +endif +.KATI_READONLY := BUILDING_VENDOR_DLKM_IMAGE + +########################################### # Now we can substitute with the real value of TARGET_COPY_OUT_ODM ifeq ($(TARGET_COPY_OUT_ODM),$(_odm_path_placeholder)) TARGET_COPY_OUT_ODM := $(TARGET_COPY_OUT_VENDOR)/odm @@ -548,6 +592,41 @@ ifdef BOARD_PREBUILT_ODMIMAGE endif .KATI_READONLY := BUILDING_ODM_IMAGE + +########################################### +# Now we can substitute with the real value of TARGET_COPY_OUT_ODM_DLKM +ifeq ($(TARGET_COPY_OUT_ODM_DLKM),$(_odm_dlkm_path_placeholder)) + TARGET_COPY_OUT_ODM_DLKM := $(TARGET_COPY_OUT_VENDOR)/odm_dlkm +else ifeq ($(filter odm_dlkm system/vendor/odm_dlkm vendor/odm_dlkm,$(TARGET_COPY_OUT_ODM_DLKM)),) + $(error TARGET_COPY_OUT_ODM_DLKM must be either 'odm_dlkm', 'system/vendor/odm_dlkm' or 'vendor/odm_dlkm', seeing '$(TARGET_COPY_OUT_ODM_DLKM)'.) +endif +PRODUCT_COPY_FILES := $(subst $(_odm_dlkm_path_placeholder),$(TARGET_COPY_OUT_ODM_DLKM),$(PRODUCT_COPY_FILES)) + +BOARD_USES_ODM_DLKMIMAGE := +ifdef BOARD_PREBUILT_ODM_DLKMIMAGE + BOARD_USES_ODM_DLKMIMAGE := true +endif +ifdef BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE + BOARD_USES_ODM_DLKMIMAGE := true +endif +$(call check_image_config,odm_dlkm) + +BUILDING_ODM_DLKM_IMAGE := +ifeq ($(PRODUCT_BUILD_ODM_DLKM_IMAGE),) + ifdef BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE + BUILDING_ODM_DLKM_IMAGE := true + endif +else ifeq ($(PRODUCT_BUILD_ODM_DLKM_IMAGE),true) + BUILDING_ODM_DLKM_IMAGE := true + ifndef BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE + $(error PRODUCT_BUILD_ODM_DLKM_IMAGE set to true, but BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE not defined) + endif +endif +ifdef BOARD_PREBUILT_ODM_DLKMIMAGE + BUILDING_ODM_DLKM_IMAGE := +endif +.KATI_READONLY := BUILDING_ODM_DLKM_IMAGE + ########################################### # Ensure consistency among TARGET_RECOVERY_UPDATER_LIBS, AB_OTA_UPDATER, and PRODUCT_OTA_FORCE_NON_AB_PACKAGE. TARGET_RECOVERY_UPDATER_LIBS ?= @@ -577,7 +656,7 @@ ifneq ($(TARGET_OTA_ALLOW_NON_AB),true) endif endif -# Sanity check for building generic OTA packages. Currently it only supports A/B OTAs. +# Quick check for building generic OTA packages. Currently it only supports A/B OTAs. ifeq ($(PRODUCT_BUILD_GENERIC_OTA_PACKAGE),true) ifneq ($(AB_OTA_UPDATER),true) $(error PRODUCT_BUILD_GENERIC_OTA_PACKAGE with 'AB_OTA_UPDATER != true' is not supported) @@ -597,6 +676,9 @@ define check_vndk_version endef ifdef BOARD_VNDK_VERSION + ifeq ($(BOARD_VNDK_VERSION),$(PLATFORM_VNDK_VERSION)) + $(error BOARD_VNDK_VERSION is equal to PLATFORM_VNDK_VERSION; use BOARD_VNDK_VERSION := current)) + endif ifneq ($(BOARD_VNDK_VERSION),current) $(call check_vndk_version,$(BOARD_VNDK_VERSION)) endif @@ -621,7 +703,7 @@ else endif endif -ifeq (,$(TARGET_BUILD_APPS)) +ifeq (,$(TARGET_BUILD_UNBUNDLED)) ifdef PRODUCT_EXTRA_VNDK_VERSIONS $(foreach v,$(PRODUCT_EXTRA_VNDK_VERSIONS),$(call check_vndk_version,$(v))) endif diff --git a/core/build-system.html b/core/build-system.html index cc242d9b6e..b872909c07 100644 --- a/core/build-system.html +++ b/core/build-system.html @@ -440,6 +440,33 @@ $(GEN): $(intermediates)/<font color=red>%.lut.h</font> : $(LOCAL_PATH)/<font co LOCAL_GENERATED_SOURCES += $(GEN) </pre> +<h3><a name="unbundled-build"/>Unbundled build</h3> +<p>Unbundled build has several meanings by the context. +Let me explain the meaning by the flags related to "unbundled build"</p> +<h4>TARGET_BUILD_UNBUNDLED</h4> +<p>The source tree might not have the full platform sources. It is always set if +<code>TARGET_BUILD_APPS</code> or <code>TARGET_BUILD_UNBUNDLED_IMAGE</code> is set.</p> +<h4>TARGET_BUILD_USE_PREBUILT_SDKS</h4> +<p>It is an internal flag. If it is set, prebuilt SDKs are used, even if a module's +<code>LOCAL_SDK_VERSION</code> is <code>current</code> (including <code>system_current</code>, +<code>core_current</code>, and so on). If it is unset, build current SDKs, +and use them as usual.</p> +<h4>DISABLE_PREOPT</h4> +<p>It is an internal flag as well. If it is set, dexpreopt is disabled. +It is always set if <code>TARGET_BUILD_APPS</code> or <code>TARGET_BUILD_UNBUNDLED_IMAGE</code> is set, +because dexpreopt tightly depends on the platform.</p> +<h4>TARGET_BUILD_APPS</h4> +<p>Build the apps that can be distributed outside the platform, so it turns on +<code>TARGET_BUILD_UNBUNDLED</code> and <code>DISABLE_PREOPT</code>. +Also, it turns on <code>TARGET_BUILD_USE_PREBUILT_SDKS</code>, unless +<code>UNBUNDLED_BUILD_SDKS_FROM_SOURCE</code> is set.</p> +<h4>TARGET_BUILD_UNBUNDLED_IMAGE</h4> +<p>It is similar to <code>TARGET_BUILD_APPS</code>, but its target is an unbundled partition +(such as the vendor partition). Accordingly, it sets <code>TARGET_BUILD_UNBUNDLED</code> and <code>DISABLE_PREOPT</code>. +We can call the partition unbundled, because the partition can be distributed outside the platform. +And also, it turns on <code>TARGET_BUILD_USE_PREBUILT_SDKS</code>, unless +<code>UNBUNDLED_BUILD_SDKS_FROM_SOURCE</code> is set.</p> + <h3><a name="platform-specific"/>Platform specific conditionals</h3> <p>Sometimes you need to set flags specifically for different platforms. Here is a list of which values the different build-system defined variables will be @@ -467,8 +494,6 @@ set to and some examples.</p> <b>TARGET_ARCH</b><br/> arm<br/> arm64<br/> - mips<br/> - mips64<br/> x86<br/> x86_64 </td> diff --git a/core/build_id.mk b/core/build_id.mk index 11f4a80669..ba5ca42dc7 100644 --- a/core/build_id.mk +++ b/core/build_id.mk @@ -18,4 +18,4 @@ # (like "CRB01"). It must be a single word, and is # capitalized by convention. -BUILD_ID=RVC +BUILD_ID=AOSP.MASTER diff --git a/core/cc_prebuilt_internal.mk b/core/cc_prebuilt_internal.mk index 99b7d0f6ab..e8e01d865f 100644 --- a/core/cc_prebuilt_internal.mk +++ b/core/cc_prebuilt_internal.mk @@ -65,7 +65,7 @@ ifneq ($(filter true keep_symbols no_debuglink mini-debug-info,$(my_strip_module built_module := $(linked_module) ifneq ($(LOCAL_SDK_VERSION),) - # binary.mk filters out NDK_MIGRATED_LIBS from my_shared_libs, thus those NDK libs are not added + # binary.mk filters out NDK_KNOWN_LIBS from my_shared_libs, thus those NDK libs are not added # to DEPENDENCIES_ON_SHARED_LIBRARIES. Assign $(my_ndk_shared_libraries_fullpath) to # my_check_elf_file_shared_lib_files so that check_elf_file.py can see those NDK stub libs. my_check_elf_file_shared_lib_files := $(my_ndk_shared_libraries_fullpath) diff --git a/core/check_elf_file.mk b/core/check_elf_file.mk index da4168df8a..d54a5b70ba 100644 --- a/core/check_elf_file.mk +++ b/core/check_elf_file.mk @@ -38,6 +38,8 @@ $(check_elf_files_stamp): $(my_prebuilt_src_file) $(my_check_elf_file_shared_lib $< $(hide) touch $@ +CHECK_ELF_FILES.$(check_elf_files_stamp) := 1 + ifneq ($(strip $(LOCAL_CHECK_ELF_FILES)),false) ifneq ($(strip $(BUILD_BROKEN_PREBUILT_ELF_FILES)),true) $(LOCAL_BUILT_MODULE): $(check_elf_files_stamp) diff --git a/core/clang/TARGET_mips.mk b/core/clang/TARGET_mips.mk deleted file mode 100644 index 3e54a6626a..0000000000 --- a/core/clang/TARGET_mips.mk +++ /dev/null @@ -1,9 +0,0 @@ -$(clang_2nd_arch_prefix)RS_TRIPLE := renderscript32-linux-androideabi -$(clang_2nd_arch_prefix)RS_TRIPLE_CFLAGS := -RS_COMPAT_TRIPLE := mipsel-linux-android - -$(clang_2nd_arch_prefix)TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-mipsel-android.a - -# Address sanitizer clang config -$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan -$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan diff --git a/core/clang/TARGET_mips64.mk b/core/clang/TARGET_mips64.mk deleted file mode 100644 index cb6a3cde23..0000000000 --- a/core/clang/TARGET_mips64.mk +++ /dev/null @@ -1,9 +0,0 @@ -RS_TRIPLE := renderscript64-linux-android -RS_TRIPLE_CFLAGS := -RS_COMPAT_TRIPLE := mips64el-linux-android - -TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-mips64el-android.a - -# Address sanitizer clang config -$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64 -$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan64 diff --git a/core/clear_vars.mk b/core/clear_vars.mk index b9f439fb59..d515db3ce4 100644 --- a/core/clear_vars.mk +++ b/core/clear_vars.mk @@ -21,7 +21,7 @@ LOCAL_ANNOTATION_PROCESSOR_CLASSES:= LOCAL_APIDIFF_NEWAPI:= LOCAL_APIDIFF_OLDAPI:= LOCAL_APK_LIBRARIES:= -LOCAL_APK_SET_MASTER_FILE:= +LOCAL_APK_SET_INSTALL_FILE:= LOCAL_APKCERTS_FILE:= LOCAL_ARM_MODE:= LOCAL_ASFLAGS:= @@ -98,6 +98,7 @@ LOCAL_EXPORT_PROGUARD_FLAG_FILES:= LOCAL_EXPORT_SDK_LIBRARIES:= LOCAL_EXPORT_SHARED_LIBRARY_HEADERS:= LOCAL_EXPORT_STATIC_LIBRARY_HEADERS:= +LOCAL_EXTRA_FULL_TEST_CONFIGS:= LOCAL_EXTRACT_APK:= LOCAL_EXTRACT_DPI_APK:= LOCAL_FDO_SUPPORT:= @@ -258,7 +259,7 @@ LOCAL_SANITIZE:= LOCAL_SANITIZE_DIAG:= LOCAL_SANITIZE_RECOVER:= LOCAL_SANITIZE_NO_RECOVER:= -LOCAL_SANITIZE_BLACKLIST := +LOCAL_SANITIZE_BLOCKLIST := LOCAL_SDK_LIBRARIES := LOCAL_SDK_RES_VERSION:= LOCAL_SDK_VERSION:= @@ -273,7 +274,9 @@ LOCAL_SOONG_EXPORT_PROGUARD_FLAGS := LOCAL_SOONG_HEADER_JAR := LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR := LOCAL_SOONG_LINK_TYPE := +LOCAL_SOONG_LINT_REPORTS := LOCAL_SOONG_PROGUARD_DICT := +LOCAL_SOONG_PROGUARD_USAGE_ZIP := LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE := LOCAL_SOONG_DEVICE_RRO_DIRS := LOCAL_SOONG_PRODUCT_RRO_DIRS := @@ -296,8 +299,8 @@ LOCAL_STRIP_MODULE:= LOCAL_SYSTEM_SHARED_LIBRARIES:=none LOCAL_TARGET_REQUIRED_MODULES:= LOCAL_TEST_CONFIG:= -LOCAL_TEST_CONFIG_OPTIONS:= LOCAL_TEST_DATA:= +LOCAL_TEST_MAINLINE_MODULES:= LOCAL_TEST_MODULE_TO_PROGUARD_WITH:= LOCAL_TIDY:= LOCAL_TIDY_CHECKS:= @@ -341,6 +344,7 @@ LOCAL_PREBUILT_JNI_LIBS_$(TARGET_ARCH):= LOCAL_REQUIRED_MODULES_$(TARGET_ARCH):= LOCAL_SHARED_LIBRARIES_$(TARGET_ARCH):= LOCAL_SOONG_JNI_LIBS_$(TARGET_ARCH):= +LOCAL_SOONG_JNI_LIBS_SYMBOLS:= LOCAL_SRC_FILES_EXCLUDE_$(TARGET_ARCH):= LOCAL_SRC_FILES_$(TARGET_ARCH):= LOCAL_STATIC_LIBRARIES_$(TARGET_ARCH):= @@ -477,17 +481,6 @@ LOCAL_ROBOTEST_FILES := LOCAL_ROBOTEST_TIMEOUT := LOCAL_TEST_PACKAGE := -# Aux specific variables -LOCAL_AUX_ARCH := -LOCAL_AUX_CPU := -LOCAL_AUX_OS := -LOCAL_AUX_OS_VARIANT := -LOCAL_AUX_SUBARCH := -LOCAL_AUX_TOOLCHAIN := -LOCAL_CUSTOM_BUILD_STEP_INPUT:= -LOCAL_CUSTOM_BUILD_STEP_OUTPUT:= -LOCAL_IS_AUX_MODULE := - full_android_manifest := non_system_module := diff --git a/core/host_test_config.mk b/core/combo/HOST_CROSS_linux_bionic-arm64.mk index b9975e54e0..df6865f808 100644 --- a/core/host_test_config.mk +++ b/core/combo/HOST_CROSS_linux_bionic-arm64.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2017 The Android Open Source Project +# Copyright (C) 2020 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,12 +14,9 @@ # limitations under the License. # -# -# Common rules for building a TradeFed test XML file for host side tests. -# - -$(call record-module-type,HOST_TEST_CONFIG) - -LOCAL_IS_HOST_MODULE := true +# Configuration for builds hosted on linux_arm-arm64 +# Included by combo/select.mk -include $(BUILD_SYSTEM)/test_config_common.mk +define $(combo_var_prefix)transform-shared-lib-to-toc +$(call _gen_toc_command_for_elf,$(1),$(2)) +endef diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk index cbca1fbfab..e45c1a6bab 100644 --- a/core/combo/TARGET_linux-arm.mk +++ b/core/combo/TARGET_linux-arm.mk @@ -39,7 +39,7 @@ ifeq (,$(strip $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT))) TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT := generic endif -# This sanity checks TARGET_2ND_ARCH_VARIANT against the lists above. +# This quickly checks TARGET_2ND_ARCH_VARIANT against the lists above. ifneq (,$(filter $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT), $(KNOWN_ARMv82a_CORES))) ifeq (,$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT)) TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := armv8-2a diff --git a/core/combo/TARGET_linux-mips.mk b/core/combo/TARGET_linux-mips.mk deleted file mode 100644 index 9f14aa20d2..0000000000 --- a/core/combo/TARGET_linux-mips.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Configuration for Linux on MIPS. -# Included by combo/select.mk - -# You can set TARGET_ARCH_VARIANT to use an arch version other -# than mips32r2-fp. Each value should correspond to a file named -# $(BUILD_COMBOS)/arch/<name>.mk which must contain -# makefile variable definitions. Their -# purpose is to allow module Android.mk files to selectively compile -# different versions of code based upon the funtionality and -# instructions available in a given architecture version. -# -# The blocks also define specific arch_variant_cflags, which -# include defines, and compiler settings for the given architecture -# version. -# -ifeq ($(strip $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT)),) -TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := mips32r2-fp -endif - -include $(BUILD_SYSTEM)/combo/fdo.mk - -define $(combo_var_prefix)transform-shared-lib-to-toc -$(call _gen_toc_command_for_elf,$(1),$(2)) -endef - -$(combo_2nd_arch_prefix)TARGET_PACK_MODULE_RELOCATIONS := true - -$(combo_2nd_arch_prefix)TARGET_LINKER := /system/bin/linker diff --git a/core/combo/TARGET_linux-mips64.mk b/core/combo/TARGET_linux-mips64.mk deleted file mode 100644 index ae17e465ac..0000000000 --- a/core/combo/TARGET_linux-mips64.mk +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright (C) 2013 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Configuration for Linux on MIPS64. -# Included by combo/select.mk - -# You can set TARGET_ARCH_VARIANT to use an arch version other -# than mips64r6. Each value should correspond to a file named -# $(BUILD_COMBOS)/arch/<name>.mk which must contain -# makefile variable definitions. Their -# purpose is to allow module Android.mk files to selectively compile -# different versions of code based upon the funtionality and -# instructions available in a given architecture version. -# -# The blocks also define specific arch_variant_cflags, which -# include defines, and compiler settings for the given architecture -# version. -# -ifeq ($(strip $(TARGET_ARCH_VARIANT)),) -TARGET_ARCH_VARIANT := mips64r6 -endif - -include $(BUILD_SYSTEM)/combo/fdo.mk - -define $(combo_var_prefix)transform-shared-lib-to-toc -$(call _gen_toc_command_for_elf,$(1),$(2)) -endef - -TARGET_PACK_MODULE_RELOCATIONS := true - -TARGET_LINKER := /system/bin/linker64 diff --git a/core/config.mk b/core/config.mk index 90eea5ba99..be0b55cc5a 100644 --- a/core/config.mk +++ b/core/config.mk @@ -22,6 +22,13 @@ BUILD_SYSTEM_COMMON :=$= build/make/common include $(BUILD_SYSTEM_COMMON)/core.mk +# ----------------------------------------------------------------- +# Rules and functions to help copy important files to DIST_DIR +# when requested. This must be included once only, and must be included before +# soong_config (as soong_config calls make_vars-$(TARGET).mk, and soong may +# propagate calls to dist-for-goals there). +include $(BUILD_SYSTEM)/distdir.mk + # Mark variables that should be coming as environment variables from soong_ui # as readonly .KATI_READONLY := OUT_DIR TMPDIR BUILD_DATETIME_FILE @@ -122,8 +129,32 @@ $(KATI_obsolete_var PRODUCT_IOT) $(KATI_obsolete_var MD5SUM) $(KATI_obsolete_var BOARD_HAL_STATIC_LIBRARIES, See $(CHANGES_URL)#BOARD_HAL_STATIC_LIBRARIES) $(KATI_obsolete_var LOCAL_HAL_STATIC_LIBRARIES, See $(CHANGES_URL)#BOARD_HAL_STATIC_LIBRARIES) +$(KATI_obsolete_var \ + TARGET_AUX_OS_VARIANT_LIST \ + LOCAL_AUX_ARCH \ + LOCAL_AUX_CPU \ + LOCAL_AUX_OS \ + LOCAL_AUX_OS_VARIANT \ + LOCAL_AUX_SUBARCH \ + LOCAL_AUX_TOOLCHAIN \ + LOCAL_CUSTOM_BUILD_STEP_INPUT \ + LOCAL_CUSTOM_BUILD_STEP_OUTPUT \ + LOCAL_IS_AUX_MODULE \ + ,AUX support has been removed) +$(KATI_obsolete_var HOST_OUT_TEST_CONFIG TARGET_OUT_TEST_CONFIG LOCAL_TEST_CONFIG_OPTIONS) +$(KATI_obsolete_var \ + TARGET_PROJECT_INCLUDES \ + 2ND_TARGET_PROJECT_INCLUDES \ + TARGET_PROJECT_SYSTEM_INCLUDES \ + 2ND_TARGET_PROJECT_SYSTEM_INCLUDES \ + ,Project include variables have been removed) +$(KATI_obsolete_var TARGET_PREFER_32_BIT TARGET_PREFER_32_BIT_APPS TARGET_PREFER_32_BIT_EXECUTABLES) $(KATI_obsolete_var PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_WHITELIST,Use PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_ALLOW_LIST.) $(KATI_obsolete_var PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST,Use PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST.) +$(KATI_obsolete_var COVERAGE_PATHS,Use NATIVE_COVERAGE_PATHS instead) +$(KATI_obsolete_var COVERAGE_EXCLUDE_PATHS,Use NATIVE_COVERAGE_EXCLUDE_PATHS instead) +$(KATI_obsolete_var BOARD_VNDK_RUNTIME_DISABLE,VNDK-Lite is no longer supported.) +$(KATI_obsolete_var LOCAL_SANITIZE_BLACKLIST,Use LOCAL_SANITIZE_BLOCKLIST instead.) # Used to force goals to build. Only use for conditionally defined goals. .PHONY: FORCE @@ -172,8 +203,6 @@ BUILD_HOST_STATIC_LIBRARY :=$= $(BUILD_SYSTEM)/host_static_library.mk BUILD_HOST_SHARED_LIBRARY :=$= $(BUILD_SYSTEM)/host_shared_library.mk BUILD_STATIC_LIBRARY :=$= $(BUILD_SYSTEM)/static_library.mk BUILD_HEADER_LIBRARY :=$= $(BUILD_SYSTEM)/header_library.mk -BUILD_AUX_STATIC_LIBRARY :=$= $(BUILD_SYSTEM)/aux_static_library.mk -BUILD_AUX_EXECUTABLE :=$= $(BUILD_SYSTEM)/aux_executable.mk BUILD_SHARED_LIBRARY :=$= $(BUILD_SYSTEM)/shared_library.mk BUILD_EXECUTABLE :=$= $(BUILD_SYSTEM)/executable.mk BUILD_HOST_EXECUTABLE :=$= $(BUILD_SYSTEM)/host_executable.mk @@ -188,23 +217,12 @@ BUILD_STATIC_JAVA_LIBRARY :=$= $(BUILD_SYSTEM)/static_java_library.mk BUILD_HOST_JAVA_LIBRARY :=$= $(BUILD_SYSTEM)/host_java_library.mk BUILD_COPY_HEADERS :=$= $(BUILD_SYSTEM)/copy_headers.mk BUILD_NATIVE_TEST :=$= $(BUILD_SYSTEM)/native_test.mk -BUILD_NATIVE_BENCHMARK :=$= $(BUILD_SYSTEM)/native_benchmark.mk -BUILD_HOST_NATIVE_TEST :=$= $(BUILD_SYSTEM)/host_native_test.mk BUILD_FUZZ_TEST :=$= $(BUILD_SYSTEM)/fuzz_test.mk -BUILD_HOST_FUZZ_TEST :=$= $(BUILD_SYSTEM)/host_fuzz_test.mk - -BUILD_SHARED_TEST_LIBRARY :=$= $(BUILD_SYSTEM)/shared_test_lib.mk -BUILD_HOST_SHARED_TEST_LIBRARY :=$= $(BUILD_SYSTEM)/host_shared_test_lib.mk -BUILD_STATIC_TEST_LIBRARY :=$= $(BUILD_SYSTEM)/static_test_lib.mk -BUILD_HOST_STATIC_TEST_LIBRARY :=$= $(BUILD_SYSTEM)/host_static_test_lib.mk BUILD_NOTICE_FILE :=$= $(BUILD_SYSTEM)/notice_files.mk BUILD_HOST_DALVIK_JAVA_LIBRARY :=$= $(BUILD_SYSTEM)/host_dalvik_java_library.mk BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY :=$= $(BUILD_SYSTEM)/host_dalvik_static_java_library.mk -BUILD_HOST_TEST_CONFIG :=$= $(BUILD_SYSTEM)/host_test_config.mk -BUILD_TARGET_TEST_CONFIG :=$= $(BUILD_SYSTEM)/target_test_config.mk - include $(BUILD_SYSTEM)/deprecation.mk # ############################################################### @@ -371,11 +389,6 @@ include $(BUILD_SYSTEM)/goma.mk include $(BUILD_SYSTEM)/rbe.mk endif -ifdef TARGET_PREFER_32_BIT -TARGET_PREFER_32_BIT_APPS := true -TARGET_PREFER_32_BIT_EXECUTABLES := true -endif - # GCC version selection TARGET_GCC_VERSION := 4.9 ifdef TARGET_2ND_ARCH @@ -416,93 +429,13 @@ endif endif endif -# Set up PDK so we can use TARGET_BUILD_PDK to select prebuilt tools below -.PHONY: pdk fusion -pdk fusion: $(DEFAULT_GOAL) - -# What to build: -# pdk fusion if: -# 1) PDK_FUSION_PLATFORM_ZIP / PDK_FUSION_PLATFORM_DIR is passed in from the environment -# or -# 2) the platform.zip / pdk.mk exists in the default location -# or -# 3) fusion is a command line build goal, -# PDK_FUSION_PLATFORM_ZIP is needed anyway, then do we need the 'fusion' goal? -# otherwise pdk only if: -# 1) pdk is a command line build goal -# or -# 2) TARGET_BUILD_PDK is passed in from the environment - -# if PDK_FUSION_PLATFORM_ZIP or PDK_FUSION_PLATFORM_DIR is specified, do not override. -ifeq (,$(strip $(PDK_FUSION_PLATFORM_ZIP)$(PDK_FUSION_PLATFORM_DIR))) - # Most PDK project paths should be using vendor/pdk/TARGET_DEVICE - # but some legacy ones (e.g. mini_armv7a_neon generic PDK) were setup - # with vendor/pdk/TARGET_PRODUCT. - # Others are set up with vendor/pdk/TARGET_DEVICE/TARGET_DEVICE-userdebug - _pdk_fusion_search_paths := \ - vendor/pdk/$(TARGET_DEVICE)/$(TARGET_DEVICE)-$(TARGET_BUILD_VARIANT)/platform \ - vendor/pdk/$(TARGET_DEVICE)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)/platform \ - vendor/pdk/$(TARGET_DEVICE)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform \ - vendor/pdk/$(TARGET_PRODUCT)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)/platform \ - vendor/pdk/$(TARGET_PRODUCT)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform - - _pdk_fusion_default_platform_zip := $(strip $(foreach p,$(_pdk_fusion_search_paths),$(wildcard $(p)/platform.zip))) - ifneq (,$(_pdk_fusion_default_platform_zip)) - PDK_FUSION_PLATFORM_ZIP := $(word 1, $(_pdk_fusion_default_platform_zip)) - _pdk_fusion_default_platform_zip := - else - _pdk_fusion_default_platform_mk := $(strip $(foreach p,$(_pdk_fusion_search_paths),$(wildcard $(p)/pdk.mk))) - ifneq (,$(_pdk_fusion_default_platform_mk)) - PDK_FUSION_PLATFORM_DIR := $(dir $(word 1,$(_pdk_fusion_default_platform_mk))) - _pdk_fusion_default_platform_mk := - endif - endif # _pdk_fusion_default_platform_zip - _pdk_fusion_search_paths := -endif # !PDK_FUSION_PLATFORM_ZIP && !PDK_FUSION_PLATFORM_DIR - -ifneq (,$(PDK_FUSION_PLATFORM_ZIP)) - ifneq (,$(PDK_FUSION_PLATFORM_DIR)) - $(error Only one of PDK_FUSION_PLATFORM_ZIP or PDK_FUSION_PLATFORM_DIR may be specified) - endif -endif - -ifneq (,$(filter pdk fusion, $(MAKECMDGOALS))) -TARGET_BUILD_PDK := true -ifneq (,$(filter fusion, $(MAKECMDGOALS))) -ifeq (,$(strip $(PDK_FUSION_PLATFORM_ZIP)$(PDK_FUSION_PLATFORM_DIR))) - $(error Specify PDK_FUSION_PLATFORM_ZIP or PDK_FUSION_PLATFORM_DIR to do a PDK fusion.) -endif -endif # fusion -endif # pdk or fusion - -ifdef PDK_FUSION_PLATFORM_ZIP -TARGET_BUILD_PDK := true -ifeq (,$(wildcard $(PDK_FUSION_PLATFORM_ZIP))) - ifneq (,$(wildcard $(patsubst %.zip,%,$(PDK_FUSION_PLATFORM_ZIP))/pdk.mk)) - PDK_FUSION_PLATFORM_DIR := $(patsubst %.zip,%,$(PDK_FUSION_PLATFORM_ZIP)) - PDK_FUSION_PLATFORM_ZIP := - else - $(error Cannot find file $(PDK_FUSION_PLATFORM_ZIP).) - endif -endif -endif - -ifdef PDK_FUSION_PLATFORM_DIR -TARGET_BUILD_PDK := true -ifeq (,$(wildcard $(PDK_FUSION_PLATFORM_DIR)/pdk.mk)) - $(error Cannot find file $(PDK_FUSION_PLATFORM_DIR)/pdk.mk.) -endif -endif - -BUILD_PLATFORM_ZIP := $(filter platform platform-java,$(MAKECMDGOALS)) - # --------------------------------------------------------------- # Whether we can expect a full build graph ALLOW_MISSING_DEPENDENCIES := $(filter true,$(ALLOW_MISSING_DEPENDENCIES)) ifneq ($(TARGET_BUILD_APPS),) ALLOW_MISSING_DEPENDENCIES := true endif -ifeq ($(TARGET_BUILD_PDK),true) +ifeq ($(TARGET_BUILD_UNBUNDLED_IMAGE),true) ALLOW_MISSING_DEPENDENCIES := true endif ifneq ($(filter true,$(SOONG_ALLOW_MISSING_DEPENDENCIES)),) @@ -510,13 +443,19 @@ ALLOW_MISSING_DEPENDENCIES := true endif .KATI_READONLY := ALLOW_MISSING_DEPENDENCIES -TARGET_BUILD_APPS_USE_PREBUILT_SDK := -ifdef TARGET_BUILD_APPS +TARGET_BUILD_USE_PREBUILT_SDKS := +DISABLE_PREOPT := +ifneq (,$(TARGET_BUILD_APPS)$(TARGET_BUILD_UNBUNDLED_IMAGE)) + DISABLE_PREOPT := true ifndef UNBUNDLED_BUILD_SDKS_FROM_SOURCE - TARGET_BUILD_APPS_USE_PREBUILT_SDK := true + TARGET_BUILD_USE_PREBUILT_SDKS := true endif endif +.KATI_READONLY := \ + TARGET_BUILD_USE_PREBUILT_SDKS \ + DISABLE_PREOPT \ + prebuilt_sdk_tools := prebuilts/sdk/tools prebuilt_sdk_tools_bin := $(prebuilt_sdk_tools)/$(HOST_OS)/bin @@ -538,25 +477,25 @@ USE_D8 := true .KATI_READONLY := USE_D8 # -# Tools that are prebuilts for TARGET_BUILD_APPS +# Tools that are prebuilts for TARGET_BUILD_USE_PREBUILT_SDKS # -ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK))) +ifeq (,$(TARGET_BUILD_USE_PREBUILT_SDKS)) AAPT := $(HOST_OUT_EXECUTABLES)/aapt MAINDEXCLASSES := $(HOST_OUT_EXECUTABLES)/mainDexClasses -else # TARGET_BUILD_APPS || TARGET_BUILD_PDK +else # TARGET_BUILD_USE_PREBUILT_SDKS AAPT := $(prebuilt_sdk_tools_bin)/aapt MAINDEXCLASSES := $(prebuilt_sdk_tools)/mainDexClasses -endif # TARGET_BUILD_APPS || TARGET_BUILD_PDK +endif # TARGET_BUILD_USE_PREBUILT_SDKS -ifeq (,$(TARGET_BUILD_APPS)) - # Use RenderScript prebuilts for unbundled builds but not PDK builds +ifeq (,$(TARGET_BUILD_USE_PREBUILT_SDKS)) + # Use RenderScript prebuilts for unbundled builds LLVM_RS_CC := $(HOST_OUT_EXECUTABLES)/llvm-rs-cc BCC_COMPAT := $(HOST_OUT_EXECUTABLES)/bcc_compat else LLVM_RS_CC := $(prebuilt_sdk_tools_bin)/llvm-rs-cc BCC_COMPAT := $(prebuilt_sdk_tools_bin)/bcc_compat -endif # TARGET_BUILD_PDK +endif prebuilt_sdk_tools := prebuilt_sdk_tools_bin := @@ -576,16 +515,8 @@ SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip # --------------------------------------------------------------- # Generic tools. -LEX := $(prebuilt_build_tools_bin_noasan)/flex -# The default PKGDATADIR built in the prebuilt bison is a relative path -# prebuilts/build-tools/common/bison. -# To run bison from elsewhere you need to set up enviromental variable -# BISON_PKGDATADIR. -BISON_PKGDATADIR := $(PWD)/prebuilts/build-tools/common/bison -BISON := $(prebuilt_build_tools_bin_noasan)/bison -YACC := $(BISON) -d -BISON_DATA := $(wildcard $(BISON_PKGDATADIR)/* $(BISON_PKGDATADIR)/*/*) -M4 :=$= $(prebuilt_build_tools_bin_noasan)/m4 +# These dependencies are now handled via dependencies on prebuilt_build_tool +BISON_DATA :=$= YASM := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/yasm/yasm @@ -667,7 +598,7 @@ EXTRACT_KERNEL := build/make/tools/extract_kernel.py # Path to tools.jar HOST_JDK_TOOLS_JAR := $(ANDROID_JAVA8_HOME)/lib/tools.jar -APICHECK_COMMAND := $(JAVA) -Xmx4g -jar $(APICHECK) --no-banner --compatible-output=yes +APICHECK_COMMAND := $(JAVA) -Xmx4g -jar $(APICHECK) --no-banner --compatible-output=no # Boolean variable determining if the allow list for compatible properties is enabled PRODUCT_COMPATIBLE_PROPERTY := false @@ -747,33 +678,22 @@ else ifeq ($(call math_gt,$(PRODUCT_SHIPPING_API_LEVEL),27),true) PRODUCT_USE_VNDK := $(PRODUCT_FULL_TREBLE) endif -# Define PRODUCT_PRODUCT_VNDK_VERSION if PRODUCT_USE_VNDK is true and -# PRODUCT_SHIPPING_API_LEVEL is greater than 29. -PRODUCT_USE_PRODUCT_VNDK := false ifeq ($(PRODUCT_USE_VNDK),true) - ifneq ($(PRODUCT_USE_PRODUCT_VNDK_OVERRIDE),) - PRODUCT_USE_PRODUCT_VNDK := $(PRODUCT_USE_PRODUCT_VNDK_OVERRIDE) - else ifeq ($(PRODUCT_SHIPPING_API_LEVEL),) - # No shipping level defined - else ifeq ($(call math_gt,$(PRODUCT_SHIPPING_API_LEVEL),29),true) - PRODUCT_USE_PRODUCT_VNDK := true - endif - ifndef BOARD_VNDK_VERSION BOARD_VNDK_VERSION := current endif - - ifeq ($(PRODUCT_USE_PRODUCT_VNDK),true) - ifndef PRODUCT_PRODUCT_VNDK_VERSION - PRODUCT_PRODUCT_VNDK_VERSION := current - endif - endif endif $(KATI_obsolete_var PRODUCT_USE_VNDK,Use BOARD_VNDK_VERSION instead) $(KATI_obsolete_var PRODUCT_USE_VNDK_OVERRIDE,Use BOARD_VNDK_VERSION instead) -$(KATI_obsolete_var PRODUCT_USE_PRODUCT_VNDK,Use PRODUCT_PRODUCT_VNDK_VERSION instead) -$(KATI_obsolete_var PRODUCT_USE_PRODUCT_VNDK_OVERRIDE,Use PRODUCT_PRODUCT_VNDK_VERSION instead) + +ifdef PRODUCT_PRODUCT_VNDK_VERSION + ifndef BOARD_VNDK_VERSION + # VNDK for product partition is not available unless BOARD_VNDK_VERSION + # defined. + $(error PRODUCT_PRODUCT_VNDK_VERSION cannot be defined without defining BOARD_VNDK_VERSION) + endif +endif # Set BOARD_SYSTEMSDK_VERSIONS to the latest SystemSDK version starting from P-launching # devices if unset. @@ -789,6 +709,16 @@ ifndef BOARD_SYSTEMSDK_VERSIONS endif endif +ifndef BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES + BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES := current +else + ifdef PRODUCT_SHIPPING_API_LEVEL + ifneq ($(call math_lt,$(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES),$(PRODUCT_SHIPPING_API_LEVEL)),) + $(error BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES ($(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES)) must be greater than or equal to PRODUCT_SHIPPING_API_LEVEL ($(PRODUCT_SHIPPING_API_LEVEL))) + endif + endif +endif +.KATI_READONLY := BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES ifdef PRODUCT_SHIPPING_API_LEVEL ifneq ($(call numbers_less_than,$(PRODUCT_SHIPPING_API_LEVEL),$(BOARD_SYSTEMSDK_VERSIONS)),) @@ -919,6 +849,20 @@ $(error Should not define BOARD_ODMIMAGE_PARTITION_SIZE and \ endif endif +ifneq ($(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE),) +ifneq ($(BOARD_VENDOR_DLKMIMAGE_PARTITION_RESERVED_SIZE),) +$(error Should not define BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE and \ + BOARD_VENDOR_DLKMIMAGE_PARTITION_RESERVED_SIZE together) +endif +endif + +ifneq ($(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE),) +ifneq ($(BOARD_ODM_DLKMIMAGE_PARTITION_RESERVED_SIZE),) +$(error Should not define BOARD_ODM_DLKMIMAGE_PARTITION_SIZE and \ + BOARD_ODM_DLKMIMAGE_PARTITION_RESERVED_SIZE together) +endif +endif + ifneq ($(BOARD_PRODUCTIMAGE_PARTITION_SIZE),) ifneq ($(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE),) $(error Should not define BOARD_PRODUCTIMAGE_PARTITION_SIZE and \ @@ -954,7 +898,7 @@ $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \ ) # BOARD_*_PARTITION_LIST: a list of the following tokens -valid_super_partition_list := system vendor product system_ext odm +valid_super_partition_list := system vendor product system_ext odm vendor_dlkm odm_dlkm $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \ $(if $(filter-out $(valid_super_partition_list),$(BOARD_$(group)_PARTITION_LIST)), \ $(error BOARD_$(group)_PARTITION_LIST contains invalid partition name \ @@ -969,8 +913,7 @@ $(error BOARD_SUPER_PARTITION_PARTITION_LIST should not be defined, but computed BOARD_SUPER_PARTITION_GROUPS and BOARD_*_PARTITION_LIST) endif BOARD_SUPER_PARTITION_PARTITION_LIST := \ - $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \ - $(BOARD_$(group)_PARTITION_LIST)) + $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)),$(BOARD_$(group)_PARTITION_LIST)) .KATI_READONLY := BOARD_SUPER_PARTITION_PARTITION_LIST ifneq ($(BOARD_SUPER_PARTITION_SIZE),) @@ -1061,16 +1004,6 @@ else RELATIVE_PWD := endif -TARGET_PROJECT_INCLUDES := -TARGET_PROJECT_SYSTEM_INCLUDES := \ - $(TARGET_DEVICE_KERNEL_HEADERS) $(TARGET_BOARD_KERNEL_HEADERS) \ - $(TARGET_PRODUCT_KERNEL_HEADERS) - -ifdef TARGET_2ND_ARCH -$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_PROJECT_INCLUDES := $(TARGET_PROJECT_INCLUDES) -$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_PROJECT_SYSTEM_INCLUDES := $(TARGET_PROJECT_SYSTEM_INCLUDES) -endif - # Flags for DEX2OAT first_non_empty_of_three = $(if $(1),$(1),$(if $(2),$(2),$(3))) DEX2OAT_TARGET_ARCH := $(TARGET_ARCH) @@ -1094,7 +1027,7 @@ HISTORICAL_SDK_VERSIONS_ROOT := $(TOPDIR)prebuilts/sdk HISTORICAL_NDK_VERSIONS_ROOT := $(TOPDIR)prebuilts/ndk # The path where app can reference the support library resources. -ifdef TARGET_BUILD_APPS +ifdef TARGET_BUILD_USE_PREBUILT_SDKS SUPPORT_LIBRARY_ROOT := $(HISTORICAL_SDK_VERSIONS_ROOT)/current/support else SUPPORT_LIBRARY_ROOT := frameworks/support @@ -1210,26 +1143,10 @@ endif # These goals don't need to collect and include Android.mks/CleanSpec.mks # in the source tree. dont_bother_goals := out \ - snod systemimage-nodeps \ - userdataimage-nodeps \ - cacheimage-nodeps \ - bptimage-nodeps \ - vnod vendorimage-nodeps \ - pnod productimage-nodeps \ - senod systemextimage-nodeps \ - onod odmimage-nodeps \ - systemotherimage-nodeps \ - ramdisk-nodeps \ - ramdisk_debug-nodeps \ - ramdisk_test_harness-nodeps \ - bootimage-nodeps \ - bootimage_debug-nodeps \ - bootimage_test_harness-nodeps \ - recoveryimage-nodeps \ - vbmetaimage-nodeps \ product-graph dump-products ifeq ($(CALLED_FROM_SETUP),true) +include $(BUILD_SYSTEM)/android_soong_config_vars.mk include $(BUILD_SYSTEM)/ninja_config.mk include $(BUILD_SYSTEM)/soong_config.mk endif @@ -1239,4 +1156,7 @@ endif DEFAULT_DATA_OUT_MODULES := ltp $(ltp_packages) $(kselftest_modules) .KATI_READONLY := DEFAULT_DATA_OUT_MODULES +# Make RECORD_ALL_DEPS readonly. +RECORD_ALL_DEPS :=$= $(filter true,$(RECORD_ALL_DEPS)) + include $(BUILD_SYSTEM)/dumpvar.mk diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk index efb21e7c6a..eaab1b5eca 100644 --- a/core/config_sanitizers.mk +++ b/core/config_sanitizers.mk @@ -134,12 +134,6 @@ ifneq ($(filter address,$(my_sanitize)),) my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag)) endif -# CFI needs gold linker, and mips toolchain does not have one. -ifneq ($(filter mips mips64,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),) - my_sanitize := $(filter-out cfi,$(my_sanitize)) - my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag)) -endif - # Disable sanitizers which need the UBSan runtime for host targets. ifdef LOCAL_IS_HOST_MODULE my_sanitize := $(filter-out cfi,$(my_sanitize)) @@ -150,8 +144,8 @@ endif # Support for local sanitize blacklist paths. ifneq ($(my_sanitize)$(my_global_sanitize),) - ifneq ($(LOCAL_SANITIZE_BLACKLIST),) - my_cflags += -fsanitize-blacklist=$(LOCAL_PATH)/$(LOCAL_SANITIZE_BLACKLIST) + ifneq ($(LOCAL_SANITIZE_BLOCKLIST),) + my_cflags += -fsanitize-blacklist=$(LOCAL_PATH)/$(LOCAL_SANITIZE_BLOCKLIST) endif endif @@ -378,8 +372,8 @@ ifneq ($(filter hwaddress,$(my_sanitize)),) my_cflags += $(HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS) endif -# Use minimal diagnostics when integer overflow is enabled; never do it for HOST or AUX modules -ifeq ($(LOCAL_IS_HOST_MODULE)$(LOCAL_IS_AUX_MODULE),) +# Use minimal diagnostics when integer overflow is enabled; never do it for HOST modules +ifeq ($(LOCAL_IS_HOST_MODULE),) # Pre-emptively add UBSAN minimal runtime incase a static library dependency requires it ifeq ($(filter STATIC_LIBRARIES,$(LOCAL_MODULE_CLASS)),) ifndef LOCAL_SDK_VERSION diff --git a/core/construct_context.sh b/core/construct_context.sh deleted file mode 100755 index 794795a7b5..0000000000 --- a/core/construct_context.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2018 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -e - -# target_sdk_version: parsed from manifest -# -# outputs -# class_loader_context_arg: final class loader conext arg -# stored_class_loader_context_arg: final stored class loader context arg - -if [ -z "${target_sdk_version}" ]; then - echo "ERROR: target_sdk_version not set" - exit 2 -fi - -# The hidl.manager shared library has a dependency on hidl.base. We'll manually -# add that information to the class loader context if we see those libraries. -hidl_manager="android.hidl.manager-V1.0-java" -hidl_base="android.hidl.base-V1.0-java" - -function add_to_contexts { - for i in $1; do - if [[ -z "${class_loader_context}" ]]; then - export class_loader_context="PCL[$i]" - else - export class_loader_context+="#PCL[$i]" - fi - if [[ $i == *"$hidl_manager"* ]]; then - export class_loader_context+="{PCL[${i/$hidl_manager/$hidl_base}]}" - fi - done - - for i in $2; do - if [[ -z "${stored_class_loader_context}" ]]; then - export stored_class_loader_context="PCL[$i]" - else - export stored_class_loader_context+="#PCL[$i]" - fi - if [[ $i == *"$hidl_manager"* ]]; then - export stored_class_loader_context+="{PCL[${i/$hidl_manager/$hidl_base}]}" - fi - done -} - -# The order below must match what the package manager also computes for -# class loader context. - -if [[ "${target_sdk_version}" -lt "28" ]]; then - add_to_contexts "${conditional_host_libs_28}" "${conditional_target_libs_28}" -fi - -if [[ "${target_sdk_version}" -lt "29" ]]; then - add_to_contexts "${conditional_host_libs_29}" "${conditional_target_libs_29}" -fi - -add_to_contexts "${dex_preopt_host_libraries}" "${dex_preopt_target_libraries}" - -# Generate the actual context string. -export class_loader_context_arg="--class-loader-context=PCL[]{${class_loader_context}}" -export stored_class_loader_context_arg="--stored-class-loader-context=PCL[]{${stored_class_loader_context}}" diff --git a/core/definitions.mk b/core/definitions.mk index 89c2e276a3..bfbeee3a34 100644 --- a/core/definitions.mk +++ b/core/definitions.mk @@ -95,7 +95,6 @@ ANDROID_RESOURCE_GENERATED_CLASSES := 'R.class' 'R$$*.class' 'Manifest.class' 'M # Display names for various build targets TARGET_DISPLAY := target -AUX_DISPLAY := aux HOST_DISPLAY := host HOST_CROSS_DISPLAY := host cross @@ -111,6 +110,9 @@ ALL_DISABLED_PRESUBMIT_TESTS := # All compatibility suites mentioned in LOCAL_COMPATIBILITY_SUITES ALL_COMPATIBILITY_SUITES := +# All compatibility suite files to dist. +ALL_COMPATIBILITY_DIST_FILES := + # All LINK_TYPE entries ALL_LINK_TYPES := @@ -522,29 +524,32 @@ define reverse-list $(if $(1),$(call reverse-list,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1)) endef -define def-host-aux-target -$(eval _idf_val_:=$(if $(strip $(LOCAL_IS_HOST_MODULE)),HOST,$(if $(strip $(LOCAL_IS_AUX_MODULE)),AUX,))) \ -$(_idf_val_) -endef - ########################################################### ## Returns correct _idfPrefix from the list: -## { HOST, HOST_CROSS, AUX, TARGET } +## { HOST, HOST_CROSS, TARGET } ########################################################### # the following rules checked in order: -# ($1 is in {AUX, HOST_CROSS} => $1; +# ($1 is in {HOST_CROSS} => $1; # ($1 is empty) => TARGET; # ($2 is not empty) => HOST_CROSS; # => HOST; define find-idf-prefix $(strip \ - $(eval _idf_pfx_:=$(strip $(filter AUX HOST_CROSS,$(1)))) \ + $(eval _idf_pfx_:=$(strip $(filter HOST_CROSS,$(1)))) \ $(eval _idf_pfx_:=$(if $(strip $(1)),$(if $(_idf_pfx_),$(_idf_pfx_),$(if $(strip $(2)),HOST_CROSS,HOST)),TARGET)) \ $(_idf_pfx_) ) endef ########################################################### +## Convert install path to on-device path. +########################################################### +# $(1): install path +define install-path-to-on-device-path +$(patsubst $(PRODUCT_OUT)%,%,$(1)) +endef + +########################################################### ## The intermediates directory. Where object files go for ## a given target. We could technically get away without ## the "_intermediates" suffix on the directory, but it's @@ -554,7 +559,7 @@ endef # $(1): target class, like "APPS" # $(2): target name, like "NotePad" -# $(3): { HOST, HOST_CROSS, AUX, <empty (TARGET)>, <other non-empty (HOST)> } +# $(3): { HOST, HOST_CROSS, <empty (TARGET)>, <other non-empty (HOST)> } # $(4): if non-empty, force the intermediates to be COMMON # $(5): if non-empty, force the intermediates to be for the 2nd arch # $(6): if non-empty, force the intermediates to be for the host cross os @@ -591,7 +596,7 @@ $(strip \ $(error $(LOCAL_PATH): LOCAL_MODULE_CLASS not defined before call to local-intermediates-dir)) \ $(if $(strip $(LOCAL_MODULE)),, \ $(error $(LOCAL_PATH): LOCAL_MODULE not defined before call to local-intermediates-dir)) \ - $(call intermediates-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(call def-host-aux-target),$(1),$(2),$(3)) \ + $(call intermediates-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(if $(strip $(LOCAL_IS_HOST_MODULE)),HOST),$(1),$(2),$(3)) \ ) endef @@ -606,7 +611,7 @@ endef # $(1): target class, like "APPS" # $(2): target name, like "NotePad" -# $(3): { HOST, HOST_CROSS, AUX, <empty (TARGET)>, <other non-empty (HOST)> } +# $(3): { HOST, HOST_CROSS, <empty (TARGET)>, <other non-empty (HOST)> } # $(4): if non-empty, force the generated sources to be COMMON define generated-sources-dir-for $(strip \ @@ -636,7 +641,7 @@ $(strip \ $(error $(LOCAL_PATH): LOCAL_MODULE_CLASS not defined before call to local-generated-sources-dir)) \ $(if $(strip $(LOCAL_MODULE)),, \ $(error $(LOCAL_PATH): LOCAL_MODULE not defined before call to local-generated-sources-dir)) \ - $(call generated-sources-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(call def-host-aux-target),$(1)) \ + $(call generated-sources-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(if $(strip $(LOCAL_IS_HOST_MODULE)),HOST),$(1)) \ ) endef @@ -1511,89 +1516,6 @@ $(call split-long-arguments,$($(PRIVATE_2ND_ARCH_VAR_PREFIX)TARGET_AR) \ $(hide) mv -f $@.tmp $@ endef -# $(1): the full path of the source static library. -# $(2): the full path of the destination static library. -define _extract-and-include-single-aux-whole-static-lib -$(hide) ldir=$(PRIVATE_INTERMEDIATES_DIR)/WHOLE/$(basename $(notdir $(1)))_objs;\ - rm -rf $$ldir; \ - mkdir -p $$ldir; \ - cp $(1) $$ldir; \ - lib_to_include=$$ldir/$(notdir $(1)); \ - filelist=; \ - subdir=0; \ - for f in `$(PRIVATE_AR) t $(1)`; do \ - if [ -e $$ldir/$$f ]; then \ - mkdir $$ldir/$$subdir; \ - ext=$$subdir/; \ - subdir=$$((subdir+1)); \ - $(PRIVATE_AR) m $$lib_to_include $$f; \ - else \ - ext=; \ - fi; \ - $(PRIVATE_AR) p $$lib_to_include $$f > $$ldir/$$ext$$f; \ - filelist="$$filelist $$ldir/$$ext$$f"; \ - done ; \ - $(PRIVATE_AR) $(AUX_GLOBAL_ARFLAGS) $(2) $$filelist - -endef - -define extract-and-include-aux-whole-static-libs -$(call extract-and-include-whole-static-libs-first, $(firstword $(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)),$(1)) -$(foreach lib,$(wordlist 2,999,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)), \ - $(call _extract-and-include-single-aux-whole-static-lib, $(lib), $(1))) -endef - -# Explicitly delete the archive first so that ar doesn't -# try to add to an existing archive. -define transform-o-to-aux-static-lib -@echo "$($(PRIVATE_PREFIX)DISPLAY) StaticLib: $(PRIVATE_MODULE) ($@)" -@mkdir -p $(dir $@) -@rm -f $@ $@.tmp -$(call extract-and-include-aux-whole-static-libs,$@.tmp) -$(call split-long-arguments,$(PRIVATE_AR) \ - $(AUX_GLOBAL_ARFLAGS) $@.tmp,$(PRIVATE_ALL_OBJECTS)) -$(hide) mv -f $@.tmp $@ -endef - -define transform-o-to-aux-executable-inner -$(hide) $(PRIVATE_CXX_LINK) -pie \ - -Bdynamic \ - -Wl,--gc-sections \ - $(PRIVATE_ALL_OBJECTS) \ - -Wl,--whole-archive \ - $(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \ - -Wl,--no-whole-archive \ - $(PRIVATE_ALL_STATIC_LIBRARIES) \ - $(PRIVATE_LDFLAGS) \ - -o $@ -endef - -define transform-o-to-aux-executable -@echo "$(AUX_DISPLAY) Executable: $(PRIVATE_MODULE) ($@)" -@mkdir -p $(dir $@) -$(transform-o-to-aux-executable-inner) -endef - -define transform-o-to-aux-static-executable-inner -$(hide) $(PRIVATE_CXX_LINK) \ - -Bstatic \ - -Wl,--gc-sections \ - $(PRIVATE_ALL_OBJECTS) \ - -Wl,--whole-archive \ - $(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \ - -Wl,--no-whole-archive \ - $(PRIVATE_ALL_STATIC_LIBRARIES) \ - $(PRIVATE_LDFLAGS) \ - -Wl,-Map=$(@).map \ - -o $@ -endef - -define transform-o-to-aux-static-executable -@echo "$(AUX_DISPLAY) StaticExecutable: $(PRIVATE_MODULE) ($@)" -@mkdir -p $(dir $@) -$(transform-o-to-aux-static-executable-inner) -endef - ########################################################### ## Commands for running host ar ########################################################### @@ -2105,7 +2027,7 @@ $(if $(PRIVATE_JAR_PACKAGES), \ $(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) rm -rf \ $(foreach pkg, $(PRIVATE_JAR_EXCLUDE_PACKAGES), \ $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg)))) -$(hide) $(JAR) -cf $@ $(call jar-args-sorted-files-in-directory,$(PRIVATE_CLASS_INTERMEDIATES_DIR)) +$(hide) $(SOONG_ZIP) -jar -o $@ -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) -D $(PRIVATE_CLASS_INTERMEDIATES_DIR) $(if $(PRIVATE_EXTRA_JAR_ARGS),$(call add-java-resources-to,$@)) endef @@ -2564,6 +2486,22 @@ $(foreach f, $(1), $(strip \ $(_cmf_dest))) endef +# Copy the file only if it's not an ELF file. For use via $(eval). +# $(1): source file +# $(2): destination file +# $(3): message to print on error +define copy-non-elf-file-checked +$(2): $(1) $(LLVM_READOBJ) + @echo "Copy non-ELF: $$@" + $(hide) \ + if $(LLVM_READOBJ) -h $$< >/dev/null 2>&1; then \ + $(call echo-error,$$@,$(3)); \ + $(call echo-error,$$@,found ELF file: $$<); \ + false; \ + fi + $$(copy-file-to-target) +endef + # The -t option to acp and the -p option to cp is # required for OSX. OSX has a ridiculous restriction # where it's an error for a .a file's modification time @@ -2616,6 +2554,18 @@ $(hide) rm -f $@ $(hide) cp $< $@ endef +# The same as copy-file-to-new-target, but preserve symlinks. Symlinks are +# converted to absolute to not break. +define copy-file-or-link-to-new-target +@mkdir -p $(dir $@) +$(hide) rm -f $@ +$(hide) if [ -h $< ]; then \ + ln -s $$(realpath $<) $@; \ +else \ + cp $< $@; \ +fi +endef + # Copy a prebuilt file to a target location. define transform-prebuilt-to-target @echo "$($(PRIVATE_PREFIX)DISPLAY) Prebuilt: $(PRIVATE_MODULE) ($@)" @@ -2628,6 +2578,13 @@ define transform-prebuilt-to-target-strip-comments $(copy-file-to-target-strip-comments) endef +# Copy a prebuilt file to a target location, but preserve symlinks rather than +# dereference them. +define copy-or-link-prebuilt-to-target +@echo "$($(PRIVATE_PREFIX)DISPLAY) Prebuilt: $(PRIVATE_MODULE) ($@)" +$(copy-file-or-link-to-new-target) +endef + # Copy a list of files/directories to target location, with sub dir structure preserved. # For example $(HOST_OUT_EXECUTABLES)/aapt -> $(staging)/bin/aapt . # $(1): the source list of files/directories. @@ -2778,32 +2735,6 @@ $$(PRODUCT_OUT)/$(2) : $$(LOCAL_PATH)/$(1) $$(transform-prebuilt-to-target) endef - -########################################################### -## API Check -########################################################### - -# eval this to define a rule that runs apicheck. -# -# Args: -# $(1) target -# $(2) stable api file -# $(3) api file to be tested -# $(4) stable removed api file -# $(5) removed api file to be tested -# $(6) arguments for apicheck -# $(7) command to run if apicheck failed -# $(8) target dependent on this api check -# $(9) additional dependencies -define check-api -$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp: $(2) $(3) $(4) $(APICHECK) $(9) - @echo "Checking API:" $(1) - $(hide) ( $(APICHECK_COMMAND) --check-api-files $(6) $(2) $(3) $(4) $(5) || ( $(7) ; exit 38 ) ) - $(hide) mkdir -p $$(dir $$@) - $(hide) touch $$@ -$(8): $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(strip $(1))-timestamp -endef - ## Whether to build from source if prebuilt alternative exists ########################################################### # $(1): module name @@ -2903,6 +2834,7 @@ endef # 2. Add all the files to each suite's dependent files list. # 3. Do the dependency addition to my_all_targets. # 4. Save the module name to COMPATIBILITY.$(suite).MODULES for each suite. +# 5. Collect files to dist to ALL_COMPATIBILITY_DIST_FILES. # Requires for each suite: use my_compat_dist_config_$(suite) to define the test config. # and use my_compat_dist_$(suite) to define the others. define create-suite-dependencies @@ -2913,10 +2845,13 @@ $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \ $(eval COMPATIBILITY.$(suite).MODULES :=)) \ $(eval COMPATIBILITY.$(suite).FILES += \ $$(foreach f,$$(my_compat_dist_$(suite)),$$(call word-colon,2,$$(f))) \ - $$(foreach f,$$(my_compat_dist_config_$(suite)),$$(call word-colon,2,$$(f)))) \ + $$(foreach f,$$(my_compat_dist_config_$(suite)),$$(call word-colon,2,$$(f))) \ + $$(my_compat_dist_test_data_$(suite))) \ + $(eval ALL_COMPATIBILITY_DIST_FILES += $$(my_compat_dist_$(suite))) \ $(eval COMPATIBILITY.$(suite).MODULES += $$(my_register_name))) \ -$(eval $(my_all_targets) : $(call copy-many-files, \ - $(sort $(foreach suite,$(LOCAL_COMPATIBILITY_SUITE),$(my_compat_dist_$(suite))))) \ +$(eval $(my_all_targets) : \ + $(sort $(foreach suite,$(LOCAL_COMPATIBILITY_SUITE), \ + $(foreach f,$(my_compat_dist_$(suite)), $(call word-colon,2,$(f))))) \ $(call copy-many-xml-files-checked, \ $(sort $(foreach suite,$(LOCAL_COMPATIBILITY_SUITE),$(my_compat_dist_config_$(suite)))))) endef @@ -3176,11 +3111,6 @@ endef ## Other includes ########################################################### -# ----------------------------------------------------------------- -# Rules and functions to help copy important files to DIST_DIR -# when requested. -include $(BUILD_SYSTEM)/distdir.mk - # Include any vendor specific definitions.mk file -include $(TOPDIR)vendor/*/build/core/definitions.mk -include $(TOPDIR)device/*/build/core/definitions.mk diff --git a/core/deprecation.mk b/core/deprecation.mk index 19bd4cfb94..2b7a869914 100644 --- a/core/deprecation.mk +++ b/core/deprecation.mk @@ -29,25 +29,25 @@ DEFAULT_WARNING_BUILD_MODULE_TYPES :=$= \ # BUILD_BROKEN_USES_BUILD_* in your BoardConfig.mk in order to turn them back # to warnings. DEFAULT_ERROR_BUILD_MODULE_TYPES :=$= \ - BUILD_AUX_EXECUTABLE \ - BUILD_AUX_STATIC_LIBRARY \ BUILD_COPY_HEADERS \ BUILD_HOST_EXECUTABLE \ - BUILD_HOST_FUZZ_TEST \ - BUILD_HOST_NATIVE_TEST \ BUILD_HOST_SHARED_LIBRARY \ BUILD_HOST_STATIC_LIBRARY \ - BUILD_HOST_STATIC_TEST_LIBRARY \ - BUILD_HOST_TEST_CONFIG \ - BUILD_NATIVE_BENCHMARK \ - BUILD_STATIC_TEST_LIBRARY \ - BUILD_TARGET_TEST_CONFIG \ # These are BUILD_* variables that are always errors to reference. # Setting the BUILD_BROKEN_USES_BUILD_* variables is also an error. OBSOLETE_BUILD_MODULE_TYPES :=$= \ + BUILD_AUX_EXECUTABLE \ + BUILD_AUX_STATIC_LIBRARY \ + BUILD_HOST_FUZZ_TEST \ + BUILD_HOST_NATIVE_TEST \ BUILD_HOST_SHARED_TEST_LIBRARY \ + BUILD_HOST_STATIC_TEST_LIBRARY \ + BUILD_HOST_TEST_CONFIG \ + BUILD_NATIVE_BENCHMARK \ BUILD_SHARED_TEST_LIBRARY \ + BUILD_STATIC_TEST_LIBRARY \ + BUILD_TARGET_TEST_CONFIG \ $(foreach m,$(OBSOLETE_BUILD_MODULE_TYPES),\ $(KATI_obsolete_var $(m),Please convert to Soong) \ diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk index 55eeec663d..dd31999ab7 100644 --- a/core/dex_preopt.mk +++ b/core/dex_preopt.mk @@ -18,9 +18,41 @@ endif ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED),$(PRODUCT_OUT)) # Install boot images. Note that there can be multiple. -DEFAULT_DEX_PREOPT_INSTALLED_IMAGE := -$(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE := -$(foreach my_boot_image_name,$(DEXPREOPT_IMAGE_NAMES),$(eval include $(BUILD_SYSTEM)/dex_preopt_libart.mk)) +my_boot_image_arch := TARGET_ARCH +my_boot_image_out := $(PRODUCT_OUT) +my_boot_image_syms := $(TARGET_OUT_UNSTRIPPED) +DEFAULT_DEX_PREOPT_INSTALLED_IMAGE_MODULE := \ + $(foreach my_boot_image_name,$(DEXPREOPT_IMAGE_NAMES),$(strip \ + $(eval include $(BUILD_SYSTEM)/dex_preopt_libart.mk) \ + $(my_boot_image_module))) +ifdef TARGET_2ND_ARCH + my_boot_image_arch := TARGET_2ND_ARCH + 2ND_DEFAULT_DEX_PREOPT_INSTALLED_IMAGE_MODULE := \ + $(foreach my_boot_image_name,$(DEXPREOPT_IMAGE_NAMES),$(strip \ + $(eval include $(BUILD_SYSTEM)/dex_preopt_libart.mk) \ + $(my_boot_image_module))) +endif +# Install boot images for testing on host. We exclude framework image as it is not part of art manifest. +my_boot_image_arch := HOST_ARCH +my_boot_image_out := $(HOST_OUT) +my_boot_image_syms := $(HOST_OUT)/symbols +HOST_BOOT_IMAGE_MODULE := \ + $(foreach my_boot_image_name,art_host,$(strip \ + $(eval include $(BUILD_SYSTEM)/dex_preopt_libart.mk) \ + $(my_boot_image_module))) +HOST_BOOT_IMAGE := $(call module-installed-files,$(HOST_BOOT_IMAGE_MODULE)) +ifdef HOST_2ND_ARCH + my_boot_image_arch := HOST_2ND_ARCH + 2ND_HOST_BOOT_IMAGE_MODULE := \ + $(foreach my_boot_image_name,art_host,$(strip \ + $(eval include $(BUILD_SYSTEM)/dex_preopt_libart.mk) \ + $(my_boot_image_module))) + 2ND_HOST_BOOT_IMAGE := $(call module-installed-files,$(2ND_HOST_BOOT_IMAGE_MODULE)) +endif +my_boot_image_arch := +my_boot_image_out := +my_boot_image_syms := +my_boot_image_module := # Build the boot.zip which contains the boot jars and their compilation output # We can do this only if preopt is enabled and if the product uses libart config (which sets the diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk index ccf53f5229..41a2be91bb 100644 --- a/core/dex_preopt_config.mk +++ b/core/dex_preopt_config.mk @@ -1,5 +1,14 @@ DEX_PREOPT_CONFIG := $(SOONG_OUT_DIR)/dexpreopt.config +ENABLE_PREOPT := true +ifneq (true,$(filter true,$(WITH_DEXPREOPT))) + ENABLE_PREOPT := +else ifneq (true,$(filter true,$(PRODUCT_USES_DEFAULT_ART_CONFIG))) + ENABLE_PREOPT := +else ifeq (true,$(DISABLE_PREOPT)) + ENABLE_PREOPT := +endif + # The default value for LOCAL_DEX_PREOPT DEX_PREOPT_DEFAULT ?= true @@ -45,10 +54,13 @@ PRELOADED_CLASSES := $(call word-colon,1,$(firstword \ DIRTY_IMAGE_OBJECTS := $(call word-colon,1,$(firstword \ $(filter %system/etc/dirty-image-objects,$(PRODUCT_COPY_FILES)))) +# Get value of a property. It is first searched from PRODUCT_VENDOR_PROPERTIES +# and then falls back to PRODUCT_SYSTEM_PROPERTIES +# $1: name of the property define get-product-default-property $(strip \ - $(eval _prop := $(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))))\ - $(if $(_prop),$(_prop),$(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_SYSTEM_DEFAULT_PROPERTIES))))) + $(eval _prop := $(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_VENDOR_PROPERTIES))))\ + $(if $(_prop),$(_prop),$(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_SYSTEM_PROPERTIES))))) endef DEX2OAT_IMAGE_XMS := $(call get-product-default-property,dalvik.vm.image-dex2oat-Xms) @@ -56,54 +68,45 @@ DEX2OAT_IMAGE_XMX := $(call get-product-default-property,dalvik.vm.image-dex2oat DEX2OAT_XMS := $(call get-product-default-property,dalvik.vm.dex2oat-Xms) DEX2OAT_XMX := $(call get-product-default-property,dalvik.vm.dex2oat-Xmx) -ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64)) -# MIPS specific overrides. -# For MIPS the ART image is loaded at a lower address. This causes issues -# with the image overlapping with memory on the host cross-compiling and -# building the image. We therefore limit the Xmx value. This isn't done -# via a property as we want the larger Xmx value if we're running on a -# MIPS device. -DEX2OAT_XMX := 128m -endif - ifeq ($(WRITE_SOONG_VARIABLES),true) $(call json_start) - $(call add_json_bool, DisablePreopt, $(call invert_bool,$(and $(filter true,$(PRODUCT_USES_DEFAULT_ART_CONFIG)),$(filter true,$(WITH_DEXPREOPT))))) - $(call add_json_list, DisablePreoptModules, $(DEXPREOPT_DISABLED_MODULES)) - $(call add_json_bool, OnlyPreoptBootImageAndSystemServer, $(filter true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))) - $(call add_json_bool, UseArtImage, $(filter true,$(DEXPREOPT_USE_ART_IMAGE))) - $(call add_json_bool, DontUncompressPrivAppsDex, $(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS))) - $(call add_json_list, ModulesLoadedByPrivilegedModules, $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES)) - $(call add_json_bool, HasSystemOther, $(BOARD_USES_SYSTEM_OTHER_ODEX)) - $(call add_json_list, PatternsOnSystemOther, $(SYSTEM_OTHER_ODEX_FILTER)) - $(call add_json_bool, DisableGenerateProfile, $(filter false,$(WITH_DEX_PREOPT_GENERATE_PROFILE))) - $(call add_json_str, ProfileDir, $(PRODUCT_DEX_PREOPT_PROFILE_DIR)) - $(call add_json_list, BootJars, $(PRODUCT_BOOT_JARS)) - $(call add_json_list, UpdatableBootJars, $(PRODUCT_UPDATABLE_BOOT_JARS)) - $(call add_json_list, ArtApexJars, $(ART_APEX_JARS)) - $(call add_json_list, SystemServerJars, $(PRODUCT_SYSTEM_SERVER_JARS)) - $(call add_json_list, SystemServerApps, $(PRODUCT_SYSTEM_SERVER_APPS)) - $(call add_json_list, UpdatableSystemServerJars, $(PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS)) - $(call add_json_list, SpeedApps, $(PRODUCT_DEXPREOPT_SPEED_APPS)) - $(call add_json_list, PreoptFlags, $(PRODUCT_DEX_PREOPT_DEFAULT_FLAGS)) - $(call add_json_str, DefaultCompilerFilter, $(PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER)) - $(call add_json_str, SystemServerCompilerFilter, $(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)) - $(call add_json_bool, GenerateDmFiles, $(PRODUCT_DEX_PREOPT_GENERATE_DM_FILES)) - $(call add_json_bool, NeverAllowStripping, $(PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING)) - $(call add_json_bool, NoDebugInfo, $(filter false,$(WITH_DEXPREOPT_DEBUG_INFO))) - $(call add_json_bool, DontResolveStartupStrings, $(filter false,$(PRODUCT_DEX_PREOPT_RESOLVE_STARTUP_STRINGS))) - $(call add_json_bool, AlwaysSystemServerDebugInfo, $(filter true,$(PRODUCT_SYSTEM_SERVER_DEBUG_INFO))) - $(call add_json_bool, NeverSystemServerDebugInfo, $(filter false,$(PRODUCT_SYSTEM_SERVER_DEBUG_INFO))) - $(call add_json_bool, AlwaysOtherDebugInfo, $(filter true,$(PRODUCT_OTHER_JAVA_DEBUG_INFO))) - $(call add_json_bool, NeverOtherDebugInfo, $(filter false,$(PRODUCT_OTHER_JAVA_DEBUG_INFO))) - $(call add_json_bool, IsEng, $(filter eng,$(TARGET_BUILD_VARIANT))) - $(call add_json_bool, SanitizeLite, $(SANITIZE_LITE)) - $(call add_json_bool, DefaultAppImages, $(WITH_DEX_PREOPT_APP_IMAGE)) - $(call add_json_str, Dex2oatXmx, $(DEX2OAT_XMX)) - $(call add_json_str, Dex2oatXms, $(DEX2OAT_XMS)) - $(call add_json_str, EmptyDirectory, $(OUT_DIR)/empty) + $(call add_json_bool, DisablePreopt, $(call invert_bool,$(ENABLE_PREOPT))) + $(call add_json_list, DisablePreoptModules, $(DEXPREOPT_DISABLED_MODULES)) + $(call add_json_bool, OnlyPreoptBootImageAndSystemServer, $(filter true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))) + $(call add_json_bool, UseArtImage, $(filter true,$(DEXPREOPT_USE_ART_IMAGE))) + $(call add_json_bool, DontUncompressPrivAppsDex, $(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS))) + $(call add_json_list, ModulesLoadedByPrivilegedModules, $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES)) + $(call add_json_bool, HasSystemOther, $(BOARD_USES_SYSTEM_OTHER_ODEX)) + $(call add_json_list, PatternsOnSystemOther, $(SYSTEM_OTHER_ODEX_FILTER)) + $(call add_json_bool, DisableGenerateProfile, $(filter false,$(WITH_DEX_PREOPT_GENERATE_PROFILE))) + $(call add_json_str, ProfileDir, $(PRODUCT_DEX_PREOPT_PROFILE_DIR)) + $(call add_json_list, BootJars, $(PRODUCT_BOOT_JARS)) + $(call add_json_list, UpdatableBootJars, $(PRODUCT_UPDATABLE_BOOT_JARS)) + $(call add_json_list, ArtApexJars, $(ART_APEX_JARS)) + $(call add_json_list, SystemServerJars, $(PRODUCT_SYSTEM_SERVER_JARS)) + $(call add_json_list, SystemServerApps, $(PRODUCT_SYSTEM_SERVER_APPS)) + $(call add_json_list, UpdatableSystemServerJars, $(PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS)) + $(call add_json_bool, BrokenSuboptimalOrderOfSystemServerJars, $(PRODUCT_BROKEN_SUBOPTIMAL_ORDER_OF_SYSTEM_SERVER_JARS)) + $(call add_json_list, SpeedApps, $(PRODUCT_DEXPREOPT_SPEED_APPS)) + $(call add_json_list, PreoptFlags, $(PRODUCT_DEX_PREOPT_DEFAULT_FLAGS)) + $(call add_json_str, DefaultCompilerFilter, $(PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER)) + $(call add_json_str, SystemServerCompilerFilter, $(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)) + $(call add_json_bool, GenerateDmFiles, $(PRODUCT_DEX_PREOPT_GENERATE_DM_FILES)) + $(call add_json_bool, NeverAllowStripping, $(PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING)) + $(call add_json_bool, NoDebugInfo, $(filter false,$(WITH_DEXPREOPT_DEBUG_INFO))) + $(call add_json_bool, DontResolveStartupStrings, $(filter false,$(PRODUCT_DEX_PREOPT_RESOLVE_STARTUP_STRINGS))) + $(call add_json_bool, AlwaysSystemServerDebugInfo, $(filter true,$(PRODUCT_SYSTEM_SERVER_DEBUG_INFO))) + $(call add_json_bool, NeverSystemServerDebugInfo, $(filter false,$(PRODUCT_SYSTEM_SERVER_DEBUG_INFO))) + $(call add_json_bool, AlwaysOtherDebugInfo, $(filter true,$(PRODUCT_OTHER_JAVA_DEBUG_INFO))) + $(call add_json_bool, NeverOtherDebugInfo, $(filter false,$(PRODUCT_OTHER_JAVA_DEBUG_INFO))) + $(call add_json_bool, IsEng, $(filter eng,$(TARGET_BUILD_VARIANT))) + $(call add_json_bool, SanitizeLite, $(SANITIZE_LITE)) + $(call add_json_bool, DefaultAppImages, $(WITH_DEX_PREOPT_APP_IMAGE)) + $(call add_json_str, Dex2oatXmx, $(DEX2OAT_XMX)) + $(call add_json_str, Dex2oatXms, $(DEX2OAT_XMS)) + $(call add_json_str, EmptyDirectory, $(OUT_DIR)/empty) $(call add_json_map, CpuVariant) $(call add_json_str, $(TARGET_ARCH), $(DEX2OAT_TARGET_CPU_VARIANT)) diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk index 79d5f8cd8b..8f0702ba6c 100644 --- a/core/dex_preopt_libart.mk +++ b/core/dex_preopt_libart.mk @@ -1,45 +1,79 @@ #################################### # ART boot image installation -# Input variable: +# Input variables: # my_boot_image_name: the boot image to install +# my_boot_image_arch: the architecture to install (e.g. TARGET_ARCH, not expanded) +# my_boot_image_out: the install directory (e.g. $(PRODUCT_OUT)) +# my_boot_image_syms: the symbols director (e.g. $(TARGET_OUT_UNSTRIPPED)) +# +# Output variables: +# my_boot_image_module: the created module name. Empty if no module is created. +# +# Install the boot images compiled by Soong. +# Create a module named dexpreopt_bootjar.$(my_boot_image_name)_$($(my_boot_image_arch)) +# that installs all of boot image files. +# If there is no file to install for $(my_boot_image_name), for example when +# building an unbundled build, then no module is created. # #################################### -# Install primary arch vdex files into a shared location, and then symlink them to both the primary -# and secondary arch directories. -my_vdex_copy_pairs := $(DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_ARCH)) -my_installed := $(foreach v,$(my_vdex_copy_pairs),$(PRODUCT_OUT)$(call word-colon,2,$(v))) -$(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed)) +# Install $(1) to $(2) so that it is shared between architectures. +# Returns the target path of the shared vdex file and installed symlink. +define copy-vdex-file +$(strip \ + $(eval # Remove the arch dir) \ + $(eval my_vdex_shared := $(dir $(patsubst %/,%,$(dir $(2))))$(notdir $(2))) \ + $(if $(filter-out %_2ND_ARCH,$(my_boot_image_arch)), \ + $(eval # Copy $(1) to directory one level up (i.e. with the arch dir removed).) \ + $(eval $(call copy-one-file,$(1),$(my_vdex_shared))) \ + ) \ + $(eval # Create symlink at $(2) which points to the actual physical copy.) \ + $(call symlink-file,$(my_vdex_shared),../$(notdir $(2)),$(2)) \ + $(my_vdex_shared) $(2) \ +) +endef + +# Same as 'copy-many-files' but it uses the vdex-specific helper above. +define copy-vdex-files +$(foreach v,$(1),$(call copy-vdex-file,$(call word-colon,1,$(v)),$(2)$(call word-colon,2,$(v)))) +endef -my_built_vdex_dir := $(dir $(call word-colon,1,$(firstword $(my_vdex_copy_pairs)))) -my_installed_vdex_dir := $(PRODUCT_OUT)$(dir $(call word-colon,2,$(firstword $(my_vdex_copy_pairs)))) +my_boot_image_module := -$(my_installed): $(my_installed_vdex_dir)% : $(my_built_vdex_dir)% - @echo "Install: $@" - @rm -f $@ - $(copy-file-to-target) - mkdir -p $(dir $@)/$(TARGET_ARCH) - ln -sfn ../$(notdir $@) $(dir $@)/$(TARGET_ARCH) -ifdef TARGET_2ND_ARCH - mkdir -p $(dir $@)/$(TARGET_2ND_ARCH) - ln -sfn ../$(notdir $@) $(dir $@)/$(TARGET_2ND_ARCH) -endif +my_suffix := $(my_boot_image_name)_$($(my_boot_image_arch)) +my_copy_pairs := $(strip $(DEXPREOPT_IMAGE_BUILT_INSTALLED_$(my_suffix))) -my_dexpreopt_image_extra_deps := $(firstword $(my_installed)) +# Generate the boot image module only if there is any file to install. +ifneq (,$(my_copy_pairs)) + my_first_pair := $(firstword $(my_copy_pairs)) + my_rest_pairs := $(wordlist 2,$(words $(my_copy_pairs)),$(my_copy_pairs)) -my_2nd_arch_prefix := -include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk + my_first_src := $(call word-colon,1,$(my_first_pair)) + my_first_dest := $(my_boot_image_out)$(call word-colon,2,$(my_first_pair)) -ifdef TARGET_2ND_ARCH - my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX) - include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk -endif + my_installed := $(call copy-many-files,$(my_rest_pairs),$(my_boot_image_out)) + my_installed += $(call copy-vdex-files,$(DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_$(my_suffix)),$(my_boot_image_out)) + my_unstripped_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_$(my_suffix)),$(my_boot_image_syms)) -my_2nd_arch_prefix := + # We don't have a LOCAL_PATH for the auto-generated modules, so let it be the $(BUILD_SYSTEM). + LOCAL_PATH := $(BUILD_SYSTEM) + include $(CLEAR_VARS) + LOCAL_MODULE := dexpreopt_bootjar.$(my_suffix) + LOCAL_PREBUILT_MODULE_FILE := $(my_first_src) + LOCAL_MODULE_PATH := $(dir $(my_first_dest)) + LOCAL_MODULE_STEM := $(notdir $(my_first_dest)) + ifneq (,$(strip $(filter HOST_%,$(my_boot_image_arch)))) + LOCAL_IS_HOST_MODULE := true + endif + LOCAL_MODULE_CLASS := ETC + include $(BUILD_PREBUILT) + $(LOCAL_BUILT_MODULE): $(my_unstripped_installed) + # Installing boot.art causes all boot image bits to be installed. + # Keep this old behavior in case anyone still needs it. + $(LOCAL_INSTALLED_MODULE): $(my_installed) + ALL_MODULES.$(my_register_name).INSTALLED += $(my_installed) + $(my_all_targets): $(my_installed) -my_vdex_copy_pairs := -my_installed := -my_built_vdex_dir := -my_installed_vdex_dir := -my_dexpreopt_image_extra_deps := + my_boot_image_module := $(LOCAL_MODULE) +endif # my_copy_pairs != empty diff --git a/core/dex_preopt_libart_boot.mk b/core/dex_preopt_libart_boot.mk deleted file mode 100644 index 34b8526581..0000000000 --- a/core/dex_preopt_libart_boot.mk +++ /dev/null @@ -1,25 +0,0 @@ -# Rules to install a boot image built by dexpreopt_bootjars.go -# Input variables: -# my_boot_image_name: the boot image to install -# my_2nd_arch_prefix: indicates if this is to build for the 2nd arch. -# my_dexpreopt_image_extra_deps: extra dependencies to add on the installed boot.art - -# Install the boot images compiled by Soong -# The first file (generally boot.art) is saved as DEFAULT_DEX_PREOPT_INSTALLED_IMAGE, -# and the rest are added as dependencies of the first. - -my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_$(my_2nd_arch_prefix)ARCH)),$(PRODUCT_OUT)) -$(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed)) -$(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE += $(firstword $(my_installed)) - -# Install the unstripped boot images compiled by Soong into the symbols directory -# The first file (generally boot.art) made a dependency of DEFAULT_DEX_PREOPT_INSTALLED_IMAGE, -# and the rest are added as dependencies of the first. -my_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_$(my_boot_image_name)_$(TARGET_$(my_2nd_arch_prefix)ARCH)),$(TARGET_OUT_UNSTRIPPED)) -$(firstword $(my_installed)): $(wordlist 2,9999,$(my_installed)) -$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE): $(firstword $(my_installed)) - -$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE): $(my_dexpreopt_image_extra_deps) - -my_installed := -my_built_installed := diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk index a33b2b4d53..799b62321b 100644 --- a/core/dex_preopt_odex_install.mk +++ b/core/dex_preopt_odex_install.mk @@ -40,8 +40,8 @@ ifneq (,$(filter $(LOCAL_MODULE),$(DEXPREOPT_DISABLED_MODULES))) LOCAL_DEX_PREOPT := endif -# Disable preopt for TARGET_BUILD_APPS -ifneq (,$(TARGET_BUILD_APPS)) +# Disable preopt for DISABLE_PREOPT +ifeq (true,$(DISABLE_PREOPT)) LOCAL_DEX_PREOPT := endif @@ -189,12 +189,13 @@ ifdef LOCAL_DEX_PREOPT my_filtered_optional_uses_libraries := $(filter-out $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES), \ $(LOCAL_OPTIONAL_USES_LIBRARIES)) - # dexpreopt needs the paths to the dex jars of these libraries in case - # construct_context.sh needs to pass them to dex2oat. + # dexpreopt needs the paths to the dex jars of these libraries in order to + # construct class loader context for dex2oat. my_extra_dexpreopt_libs := \ org.apache.http.legacy \ android.hidl.base-V1.0-java \ android.hidl.manager-V1.0-java \ + android.test.base \ my_dexpreopt_libs := $(sort \ $(LOCAL_USES_LIBRARIES) \ @@ -233,7 +234,11 @@ ifdef LOCAL_DEX_PREOPT $(call add_json_list, UsesLibraries, $(LOCAL_USES_LIBRARIES)) $(call add_json_map, LibraryPaths) $(foreach lib,$(my_dexpreopt_libs),\ - $(call add_json_str, $(lib), $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar)) + $(call add_json_map, $(lib)) \ + $(eval file := $(filter %/$(lib).jar, $(call module-installed-files,$(lib)))) \ + $(call add_json_str, Host, $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar) \ + $(call add_json_str, Device, $(call install-path-to-on-device-path,$(file))) \ + $(call end_json_map)) $(call end_json_map) $(call add_json_list, Archs, $(my_dexpreopt_archs)) $(call add_json_list, DexPreoptImages, $(my_dexpreopt_images)) @@ -299,7 +304,7 @@ ifdef LOCAL_DEX_PREOPT for i in $$(zipinfo -1 $(my_dexpreopt_zip)); \ do mkdir -p $(PRODUCT_OUT)/$$(dirname $$i); \ done && \ - ( unzip -qo -d $(PRODUCT_OUT) $(my_dexpreopt_zip) 2>&1 | grep -v "zipfile is empty"; exit $${PIPESTATUS[0]} ) || \ + ( unzip -qoDD -d $(PRODUCT_OUT) $(my_dexpreopt_zip) 2>&1 | grep -v "zipfile is empty"; exit $${PIPESTATUS[0]} ) || \ ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi ) $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD) diff --git a/core/distdir.mk b/core/distdir.mk index 5f404075df..aad8ff3d65 100644 --- a/core/distdir.mk +++ b/core/distdir.mk @@ -28,7 +28,7 @@ _all_dist_src_dst_pairs := # certain files with certain goals. When those goals are built # and "dist" is specified, the marked files will be copied to DIST_DIR. # -# $(1): a list of goals (e.g. droid, sdk, pdk, ndk). These must be PHONY +# $(1): a list of goals (e.g. droid, sdk, ndk). These must be PHONY # $(2): the dist files to add to those goals. If the file contains ':', # the text following the colon is the name that the file is copied # to under the dist directory. Subdirs are ok, and will be created diff --git a/core/envsetup.mk b/core/envsetup.mk index f4650f99f3..a5571ae0c1 100644 --- a/core/envsetup.mk +++ b/core/envsetup.mk @@ -93,15 +93,38 @@ TARGET_BUILD_VARIANT := eng endif TARGET_BUILD_APPS ?= +TARGET_BUILD_UNBUNDLED_IMAGE ?= + +# Set to true for an unbundled build, i.e. a build without +# support for platform targets like the system image. This also +# disables consistency checks that only apply to full platform +# builds. +TARGET_BUILD_UNBUNDLED ?= + +# TARGET_BUILD_APPS implies unbundled build, otherwise we default +# to bundled (i.e. platform targets such as the system image are +# included). +ifneq ($(TARGET_BUILD_APPS),) + TARGET_BUILD_UNBUNDLED := true +endif + +# TARGET_BUILD_UNBUNDLED_IMAGE also implies unbundled build. +# (i.e. it targets to only unbundled image, such as the vendor image, +# ,or the product image). +ifneq ($(TARGET_BUILD_UNBUNDLED_IMAGE),) + TARGET_BUILD_UNBUNDLED := true +endif .KATI_READONLY := \ TARGET_PRODUCT \ TARGET_BUILD_VARIANT \ - TARGET_BUILD_APPS + TARGET_BUILD_APPS \ + TARGET_BUILD_UNBUNDLED \ + TARGET_BUILD_UNBUNDLED_IMAGE \ # --------------------------------------------------------------- # Set up configuration for host machine. We don't do cross- -# compiles except for arm/mips, so the HOST is whatever we are +# compiles except for arm, so the HOST is whatever we are # running on # HOST_OS @@ -125,15 +148,25 @@ HOST_OS_EXTRA := $(subst $(space),-,$(HOST_OS_EXTRA)) # BUILD_OS is the real host doing the build. BUILD_OS := $(HOST_OS) -HOST_CROSS_OS := -# We can cross-build Windows binaries on Linux +# We can do the cross-build only on Linux ifeq ($(HOST_OS),linux) -ifeq ($(BUILD_HOST_static),) -HOST_CROSS_OS := windows -HOST_CROSS_ARCH := x86 -HOST_CROSS_2ND_ARCH := x86_64 -2ND_HOST_CROSS_IS_64_BIT := true -endif + # Windows has been the default host_cross OS + ifeq (,$(filter-out windows,$(HOST_CROSS_OS))) + # We can only create static host binaries for Linux, so if static host + # binaries are requested, turn off Windows cross-builds. + ifeq ($(BUILD_HOST_static),) + HOST_CROSS_OS := windows + HOST_CROSS_ARCH := x86 + HOST_CROSS_2ND_ARCH := x86_64 + 2ND_HOST_CROSS_IS_64_BIT := true + endif + else ifeq ($(HOST_CROSS_OS),linux_bionic) + ifeq (,$(HOST_CROSS_ARCH)) + $(error HOST_CROSS_ARCH missing.) + endif + else + $(error Unsupported HOST_CROSS_OS $(HOST_CROSS_OS)) + endif endif ifeq ($(HOST_OS),) @@ -239,6 +272,8 @@ _vendor_path_placeholder := ||VENDOR-PATH-PH|| _product_path_placeholder := ||PRODUCT-PATH-PH|| _system_ext_path_placeholder := ||SYSTEM_EXT-PATH-PH|| _odm_path_placeholder := ||ODM-PATH-PH|| +_vendor_dlkm_path_placeholder := ||VENDOR_DLKM-PATH-PH|| +_odm_dlkm_path_placeholder := ||ODM_DLKM-PATH-PH|| TARGET_COPY_OUT_VENDOR := $(_vendor_path_placeholder) TARGET_COPY_OUT_VENDOR_RAMDISK := vendor-ramdisk TARGET_COPY_OUT_PRODUCT := $(_product_path_placeholder) @@ -247,6 +282,8 @@ TARGET_COPY_OUT_PRODUCT := $(_product_path_placeholder) TARGET_COPY_OUT_PRODUCT_SERVICES := $(_product_path_placeholder) TARGET_COPY_OUT_SYSTEM_EXT := $(_system_ext_path_placeholder) TARGET_COPY_OUT_ODM := $(_odm_path_placeholder) +TARGET_COPY_OUT_VENDOR_DLKM := $(_vendor_dlkm_path_placeholder) +TARGET_COPY_OUT_ODM_DLKM := $(_odm_dlkm_path_placeholder) # Returns the non-sanitized version of the path provided in $1. define get_non_asan_path @@ -258,7 +295,12 @@ endef # java code with dalvikvm/art. # Jars present in the ART apex. These should match exactly the list of # Java libraries in the ART apex build rule. -ART_APEX_JARS := core-oj core-libart core-icu4j okhttp bouncycastle apache-xml +ART_APEX_JARS := \ + com.android.art:core-oj \ + com.android.art:core-libart \ + com.android.art:okhttp \ + com.android.art:bouncycastle \ + com.android.art:apache-xml ################################################################# # Read the product specs so we can get TARGET_DEVICE and other @@ -296,7 +338,7 @@ HOST_OUT_ROOT := $(OUT_DIR)/host HOST_OUT := $(HOST_OUT_ROOT)/$(HOST_OS)-$(HOST_PREBUILT_ARCH) SOONG_HOST_OUT := $(SOONG_OUT_DIR)/host/$(HOST_OS)-$(HOST_PREBUILT_ARCH) -HOST_CROSS_OUT := $(HOST_OUT_ROOT)/windows-$(HOST_PREBUILT_ARCH) +HOST_CROSS_OUT := $(HOST_OUT_ROOT)/$(HOST_CROSS_OS)-$(HOST_CROSS_ARCH) .KATI_READONLY := HOST_OUT SOONG_HOST_OUT HOST_CROSS_OUT @@ -360,9 +402,6 @@ HOST_OUT_FAKE := $(HOST_OUT)/fake_packages HOST_OUT_COMMON_INTERMEDIATES \ HOST_OUT_FAKE -# Nano environment config -include $(BUILD_SYSTEM)/aux_config.mk - HOST_CROSS_OUT_INTERMEDIATES := $(HOST_CROSS_OUT)/obj HOST_CROSS_OUT_NOTICE_FILES := $(HOST_CROSS_OUT_INTERMEDIATES)/NOTICE_FILES .KATI_READONLY := \ @@ -378,9 +417,6 @@ HOST_OUT_COMMON_GEN := $(HOST_COMMON_OUT_ROOT)/gen HOST_CROSS_OUT_GEN := $(HOST_CROSS_OUT)/gen .KATI_READONLY := HOST_CROSS_OUT_GEN -HOST_OUT_TEST_CONFIG := $(HOST_OUT)/test_config -.KATI_READONLY := HOST_OUT_TEST_CONFIG - # Out for HOST_2ND_ARCH $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATES := $(HOST_OUT)/obj32 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES := $(HOST_OUT)/lib @@ -466,7 +502,6 @@ TARGET_OUT_ETC := $(TARGET_OUT)/etc TARGET_OUT_NOTICE_FILES := $(TARGET_OUT_INTERMEDIATES)/NOTICE_FILES TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages TARGET_OUT_TESTCASES := $(PRODUCT_OUT)/testcases -TARGET_OUT_TEST_CONFIG := $(PRODUCT_OUT)/test_config .KATI_READONLY := \ TARGET_OUT_EXECUTABLES \ TARGET_OUT_OPTIONAL_EXECUTABLES \ @@ -480,8 +515,7 @@ TARGET_OUT_TEST_CONFIG := $(PRODUCT_OUT)/test_config TARGET_OUT_ETC \ TARGET_OUT_NOTICE_FILES \ TARGET_OUT_FAKE \ - TARGET_OUT_TESTCASES \ - TARGET_OUT_TEST_CONFIG + TARGET_OUT_TESTCASES ifeq ($(SANITIZE_LITE),true) # When using SANITIZE_LITE, APKs must not be packaged with sanitized libraries, as they will not @@ -708,6 +742,74 @@ $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS_PRIVILEGED := $(TARGET_OUT_ODM_ $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS \ $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS_PRIVILEGED +TARGET_OUT_VENDOR_DLKM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR_DLKM) + +TARGET_OUT_VENDOR_DLKM_ETC := $(TARGET_OUT_VENDOR_DLKM)/etc +.KATI_READONLY := \ + TARGET_OUT_VENDOR_DLKM_ETC + +# Unlike other partitions, vendor_dlkm should only contain kernel modules. +TARGET_OUT_VENDOR_DLKM_EXECUTABLES := +TARGET_OUT_VENDOR_DLKM_OPTIONAL_EXECUTABLES := +TARGET_OUT_VENDOR_DLKM_SHARED_LIBRARIES := +TARGET_OUT_VENDOR_DLKM_RENDERSCRIPT_BITCODE := +TARGET_OUT_VENDOR_DLKM_JAVA_LIBRARIES := +TARGET_OUT_VENDOR_DLKM_APPS := +TARGET_OUT_VENDOR_DLKM_APPS_PRIVILEGED := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_EXECUTABLES := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_SHARED_LIBRARIES := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_RENDERSCRIPT_BITCODE := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_APPS := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_APPS_PRIVILEGED := +$(KATI_obsolete_var \ + TARGET_OUT_VENDOR_DLKM_EXECUTABLES \ + TARGET_OUT_VENDOR_DLKM_OPTIONAL_EXECUTABLES \ + TARGET_OUT_VENDOR_DLKM_SHARED_LIBRARIES \ + TARGET_OUT_VENDOR_DLKM_RENDERSCRIPT_BITCODE \ + TARGET_OUT_VENDOR_DLKM_JAVA_LIBRARIES \ + TARGET_OUT_VENDOR_DLKM_APPS \ + TARGET_OUT_VENDOR_DLKM_APPS_PRIVILEGED \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_EXECUTABLES \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_SHARED_LIBRARIES \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_RENDERSCRIPT_BITCODE \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_APPS \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_DLKM_APPS_PRIVILEGED \ + , vendor_dlkm should not contain any executables, libraries, or apps) + +TARGET_OUT_ODM_DLKM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ODM_DLKM) + +TARGET_OUT_ODM_DLKM_ETC := $(TARGET_OUT_ODM_DLKM)/etc +.KATI_READONLY := \ + TARGET_OUT_ODM_DLKM_ETC + +# Unlike other partitions, odm_dlkm should only contain kernel modules. +TARGET_OUT_ODM_DLKM_EXECUTABLES := +TARGET_OUT_ODM_DLKM_OPTIONAL_EXECUTABLES := +TARGET_OUT_ODM_DLKM_SHARED_LIBRARIES := +TARGET_OUT_ODM_DLKM_RENDERSCRIPT_BITCODE := +TARGET_OUT_ODM_DLKM_JAVA_LIBRARIES := +TARGET_OUT_ODM_DLKM_APPS := +TARGET_OUT_ODM_DLKM_APPS_PRIVILEGED := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_EXECUTABLES := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_SHARED_LIBRARIES := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_RENDERSCRIPT_BITCODE := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_APPS := +$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_APPS_PRIVILEGED := +$(KATI_obsolete_var \ + TARGET_OUT_ODM_DLKM_EXECUTABLES \ + TARGET_OUT_ODM_DLKM_OPTIONAL_EXECUTABLES \ + TARGET_OUT_ODM_DLKM_SHARED_LIBRARIES \ + TARGET_OUT_ODM_DLKM_RENDERSCRIPT_BITCODE \ + TARGET_OUT_ODM_DLKM_JAVA_LIBRARIES \ + TARGET_OUT_ODM_DLKM_APPS \ + TARGET_OUT_ODM_DLKM_APPS_PRIVILEGED \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_EXECUTABLES \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_SHARED_LIBRARIES \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_RENDERSCRIPT_BITCODE \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_APPS \ + $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_DLKM_APPS_PRIVILEGED \ + , odm_dlkm should not contain any executables, libraries, or apps) + TARGET_OUT_PRODUCT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_PRODUCT) TARGET_OUT_PRODUCT_EXECUTABLES := $(TARGET_OUT_PRODUCT)/bin .KATI_READONLY := TARGET_OUT_PRODUCT diff --git a/core/executable.mk b/core/executable.mk index db8dcc6318..9175e0ad65 100644 --- a/core/executable.mk +++ b/core/executable.mk @@ -40,14 +40,9 @@ else #!LOCAL_MULTILIB == both LOCAL_NO_2ND_ARCH_MODULE_SUFFIX := true endif -# if TARGET_PREFER_32_BIT_EXECUTABLES is set, try to build 32-bit first ifdef TARGET_2ND_ARCH -ifeq ($(TARGET_PREFER_32_BIT_EXECUTABLES),true) -LOCAL_2ND_ARCH_VAR_PREFIX := $(TARGET_2ND_ARCH_VAR_PREFIX) -else LOCAL_2ND_ARCH_VAR_PREFIX := endif -endif my_skip_non_preferred_arch := @@ -65,12 +60,7 @@ endif ifndef my_skip_non_preferred_arch ifdef TARGET_2ND_ARCH -# check if the non-preferred arch is the primary or secondary -ifeq ($(TARGET_PREFER_32_BIT_EXECUTABLES),true) -LOCAL_2ND_ARCH_VAR_PREFIX := -else LOCAL_2ND_ARCH_VAR_PREFIX := $(TARGET_2ND_ARCH_VAR_PREFIX) -endif # check if non-preferred arch is supported include $(BUILD_SYSTEM)/module_arch_supported.mk diff --git a/core/executable_internal.mk b/core/executable_internal.mk index 32e56dd276..c6a8fafc25 100644 --- a/core/executable_internal.mk +++ b/core/executable_internal.mk @@ -56,9 +56,9 @@ my_target_crtbegin_static_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT my_target_crtend_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT_crtend_android) endif ifneq ($(LOCAL_SDK_VERSION),) -my_target_crtbegin_dynamic_o := $(wildcard $(my_ndk_sysroot_lib)/crtbegin_dynamic.o) -my_target_crtbegin_static_o := $(wildcard $(my_ndk_sysroot_lib)/crtbegin_static.o) -my_target_crtend_o := $(wildcard $(my_ndk_sysroot_lib)/crtend_android.o) +my_target_crtbegin_dynamic_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT_crtbegin_dynamic.sdk.$(my_ndk_crt_version)) +my_target_crtbegin_static_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT_crtbegin_static.sdk.$(my_ndk_crt_version)) +my_target_crtend_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT_crtend_android.sdk.$(my_ndk_crt_version)) endif $(linked_module): PRIVATE_TARGET_LIBCRT_BUILTINS := $(my_target_libcrt_builtins) $(linked_module): PRIVATE_TARGET_LIBATOMIC := $(my_target_libatomic) diff --git a/core/executable_prefer_symlink.mk b/core/executable_prefer_symlink.mk index 9b9814e3b8..fea0bef64b 100644 --- a/core/executable_prefer_symlink.mk +++ b/core/executable_prefer_symlink.mk @@ -5,22 +5,13 @@ # Note: now only limited to the binaries that will be installed under system/bin directory # Create link to the one used depending on the target -# configuration. Note that we require the TARGET_IS_64_BIT -# check because 32 bit targets may not define TARGET_PREFER_32_BIT_APPS -# et al. since those variables make no sense in that context. +# configuration. ifneq ($(LOCAL_IS_HOST_MODULE),true) my_symlink := $(addprefix $(TARGET_OUT)/bin/, $(LOCAL_MODULE)) my_src_binary_name := ifeq ($(TARGET_IS_64_BIT),true) ifeq ($(TARGET_SUPPORTS_64_BIT_APPS)|$(TARGET_SUPPORTS_32_BIT_APPS),true|true) - # We support both 32 and 64 bit apps, so we will have to - # base our decision on whether the target prefers one or the - # other. - ifeq ($(TARGET_PREFER_32_BIT_APPS),true) - my_src_binary_name := $(LOCAL_MODULE_STEM_32) - else - my_src_binary_name := $(LOCAL_MODULE_STEM_64) - endif + my_src_binary_name := $(LOCAL_MODULE_STEM_64) else ifeq ($(TARGET_SUPPORTS_64_BIT_APPS),true) # We support only 64 bit apps. my_src_binary_name := $(LOCAL_MODULE_STEM_64) @@ -40,7 +31,7 @@ $(call symlink-file,$(my_module_path)/$(my_src_binary_name),$(my_src_binary_name # We need this so that the installed files could be picked up based on the # local module name -ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(my_symlink) +ALL_MODULES.$(my_register_name).INSTALLED += $(my_symlink) # Create the symlink when you run mm/mmm or "make <module_name>" $(LOCAL_MODULE) : $(my_symlink) diff --git a/core/goma.mk b/core/goma.mk index c265259da0..2b51d8be44 100644 --- a/core/goma.mk +++ b/core/goma.mk @@ -27,7 +27,8 @@ ifneq ($(filter-out false,$(USE_GOMA)),) # use both ccache and gomacc. CC_WRAPPER := $(strip $(CC_WRAPPER) $(GOMA_CC)) CXX_WRAPPER := $(strip $(CXX_WRAPPER) $(GOMA_CC)) - JAVAC_WRAPPER := $(strip $(JAVAC_WRAPPER) $(GOMA_CC)) + # b/143658984: goma can't handle the --system argument to javac + #JAVAC_WRAPPER := $(strip $(JAVAC_WRAPPER) $(GOMA_CC)) goma_dir := endif diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk index 882fe3a835..da329788e8 100644 --- a/core/host_dalvik_java_library.mk +++ b/core/host_dalvik_java_library.mk @@ -79,7 +79,8 @@ java_sources_deps := \ $(java_source_list_file): $(java_sources_deps) $(write-java-source-list) -$(full_classes_compiled_jar): .KATI_NINJA_POOL := $(GOMA_POOL) +# TODO(b/143658984): goma can't handle the --system argument to javac. +#$(full_classes_compiled_jar): .KATI_NINJA_POOL := $(GOMA_POOL) $(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) $(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(annotation_processor_flags) $(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := @@ -98,6 +99,7 @@ $(full_classes_compiled_jar): \ $(NORMALIZE_PATH) \ $(JAR_ARGS) \ $(ZIPSYNC) \ + $(SOONG_ZIP) \ | $(SOONG_JAVAC_WRAPPER) $(transform-host-java-to-dalvik-package) diff --git a/core/host_fuzz_test.mk b/core/host_fuzz_test.mk deleted file mode 100644 index 54c6577fdb..0000000000 --- a/core/host_fuzz_test.mk +++ /dev/null @@ -1,10 +0,0 @@ -################################################ -## A thin wrapper around BUILD_HOST_EXECUTABLE -## Common flags for host fuzz tests are added. -################################################ -$(call record-module-type,HOST_FUZZ_TEST) - -LOCAL_SANITIZE += fuzzer -LOCAL_STATIC_LIBRARIES += libLLVMFuzzer - -include $(BUILD_HOST_EXECUTABLE) diff --git a/core/host_java_library.mk b/core/host_java_library.mk index beaea2ad71..f9abe9bc4e 100644 --- a/core/host_java_library.mk +++ b/core/host_java_library.mk @@ -70,7 +70,8 @@ java_sources_deps := \ $(java_source_list_file): $(java_sources_deps) $(write-java-source-list) -$(full_classes_compiled_jar): .KATI_NINJA_POOL := $(GOMA_POOL) +# TODO(b/143658984): goma can't handle the --system argument to javac. +#$(full_classes_compiled_jar): .KATI_NINJA_POOL := $(GOMA_POOL) $(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file) $(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(annotation_processor_flags) $(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := @@ -89,6 +90,7 @@ $(full_classes_compiled_jar): \ $(ZIPTIME) \ $(JAR_ARGS) \ $(ZIPSYNC) \ + $(SOONG_ZIP) \ | $(SOONG_JAVAC_WRAPPER) $(transform-host-java-to-package) $(remove-timestamps-from-package) diff --git a/core/host_native_test.mk b/core/host_native_test.mk deleted file mode 100644 index aa05bb3156..0000000000 --- a/core/host_native_test.mk +++ /dev/null @@ -1,23 +0,0 @@ -################################################ -## A thin wrapper around BUILD_HOST_EXECUTABLE -## Common flags for host native tests are added. -################################################ -$(call record-module-type,HOST_NATIVE_TEST) - -ifdef LOCAL_MODULE_CLASS -ifneq ($(LOCAL_MODULE_CLASS),NATIVE_TESTS) -$(error $(LOCAL_PATH): LOCAL_MODULE_CLASS must be NATIVE_TESTS with BUILD_HOST_NATIVE_TEST) -endif -endif - -LOCAL_MODULE_CLASS := NATIVE_TESTS - -include $(BUILD_SYSTEM)/host_test_internal.mk - -ifndef LOCAL_MULTILIB -ifndef LOCAL_32_BIT_ONLY -LOCAL_MULTILIB := both -endif -endif - -include $(BUILD_HOST_EXECUTABLE) diff --git a/core/host_shared_test_lib.mk b/core/host_shared_test_lib.mk deleted file mode 100644 index ed7e23abc1..0000000000 --- a/core/host_shared_test_lib.mk +++ /dev/null @@ -1 +0,0 @@ -$(error BUILD_HOST_SHARED_TEST_LIBRARY is obsolete) diff --git a/core/host_static_test_lib.mk b/core/host_static_test_lib.mk deleted file mode 100644 index a9e39b1baf..0000000000 --- a/core/host_static_test_lib.mk +++ /dev/null @@ -1,9 +0,0 @@ -################################################## -## A thin wrapper around BUILD_HOST_STATIC_LIBRARY -## Common flags for host native tests are added. -################################################## -$(call record-module-type,HOST_STATIC_TEST_LIBRARY) - -include $(BUILD_SYSTEM)/host_test_internal.mk - -include $(BUILD_SYSTEM)/host_static_library.mk diff --git a/core/host_test_internal.mk b/core/host_test_internal.mk deleted file mode 100644 index dfe8cf1505..0000000000 --- a/core/host_test_internal.mk +++ /dev/null @@ -1,28 +0,0 @@ -##################################################### -## Shared definitions for all host test compilations. -##################################################### - -ifeq ($(LOCAL_GTEST),true) - LOCAL_CFLAGS_linux += -DGTEST_OS_LINUX - LOCAL_CFLAGS_darwin += -DGTEST_OS_MAC - - LOCAL_CFLAGS += -DGTEST_HAS_STD_STRING -O0 -g - - LOCAL_STATIC_LIBRARIES += libgtest_main_host libgtest_host -endif - -ifdef LOCAL_MODULE_PATH -$(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH when building test $(LOCAL_MODULE)) -endif - -ifdef LOCAL_MODULE_PATH_32 -$(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH_32 when building test $(LOCAL_MODULE)) -endif - -ifdef LOCAL_MODULE_PATH_64 -$(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH_64 when building test $(LOCAL_MODULE)) -endif - -ifndef LOCAL_MODULE_RELATIVE_PATH -LOCAL_MODULE_RELATIVE_PATH := $(LOCAL_MODULE) -endif diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk index 48c93de45f..289d16fc6e 100644 --- a/core/install_jni_libs_internal.mk +++ b/core/install_jni_libs_internal.mk @@ -57,9 +57,9 @@ else ifneq ($(my_jni_shared_libraries),) # not my_embed_jni # Make sure the JNI libraries get installed my_shared_library_path := $(call get_non_asan_path,\ $($(my_2nd_arch_prefix)TARGET_OUT$(partition_tag)_SHARED_LIBRARIES)) - my_installed_library := $(addprefix $(my_shared_library_path)/, $(my_jni_filenames)) - ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(my_installed_library) + bit_suffix := $(if $(filter %64,$(TARGET_$(my_2nd_arch_prefix)ARCH)),:64,:32) + ALL_MODULES.$(my_register_name).REQUIRED_FROM_TARGET += $(addsuffix $(bit_suffix),$(LOCAL_JNI_SHARED_LIBRARIES)) # Create symlink in the app specific lib path # Skip creating this symlink when running the second part of a target sanitization build. @@ -72,7 +72,7 @@ else ifneq ($(my_jni_shared_libraries),) # not my_embed_jni $(my_symlink_target_dir)/$(lib), \ $(my_app_lib_path)/$(lib)) \ $(eval $$(LOCAL_INSTALLED_MODULE) : $$(my_app_lib_path)/$$(lib)) \ - $(eval ALL_MODULES.$$(LOCAL_MODULE).INSTALLED += $$(my_app_lib_path)/$$(lib))) + $(eval ALL_MODULES.$(my_register_name).INSTALLED += $$(my_app_lib_path)/$$(lib))) endif # Clear jni_shared_libraries to not embed it into the apk. @@ -100,7 +100,7 @@ ifdef my_prebuilt_jni_libs my_installed_library := $(addprefix $(my_app_lib_path)/, $(notdir $(my_prebuilt_jni_libs))) $(LOCAL_INSTALLED_MODULE) : $(my_installed_library) - ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(my_installed_library) + ALL_MODULES.$(my_register_name).INSTALLED += $(my_installed_library) endif # my_embed_jni endif # inner my_prebuilt_jni_libs endif # outer my_prebuilt_jni_libs diff --git a/core/jacoco.mk b/core/jacoco.mk index 148bb045ec..e8fb89bf6c 100644 --- a/core/jacoco.mk +++ b/core/jacoco.mk @@ -47,7 +47,7 @@ $(my_unzipped_timestamp_path): PRIVATE_FULL_CLASSES_PRE_JACOCO_JAR := $(LOCAL_FU $(my_unzipped_timestamp_path): $(LOCAL_FULL_CLASSES_PRE_JACOCO_JAR) rm -rf $(PRIVATE_UNZIPPED_PATH) $@ mkdir -p $(PRIVATE_UNZIPPED_PATH) - unzip -q $(PRIVATE_FULL_CLASSES_PRE_JACOCO_JAR) \ + unzip -qDD $(PRIVATE_FULL_CLASSES_PRE_JACOCO_JAR) \ -d $(PRIVATE_UNZIPPED_PATH) \ $(PRIVATE_INCLUDE_ARGS) (cd $(PRIVATE_UNZIPPED_PATH) && rm -rf $(PRIVATE_EXCLUDE_ARGS)) diff --git a/core/java.mk b/core/java.mk index a041321b63..5fe8da5714 100644 --- a/core/java.mk +++ b/core/java.mk @@ -4,17 +4,6 @@ # LOCAL_MODULE_CLASS # all_res_assets -ifeq ($(TARGET_BUILD_PDK),true) -ifeq ($(TARGET_BUILD_PDK_JAVA_PLATFORM),) -# LOCAL_SDK not defined or set to current -ifeq ($(filter-out current,$(LOCAL_SDK_VERSION)),) -ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true) -LOCAL_SDK_VERSION := $(PDK_BUILD_SDK_VERSION) -endif #!LOCAL_NO_STANDARD_LIBRARIES -endif -endif # !PDK_JAVA -endif #PDK - LOCAL_NO_STANDARD_LIBRARIES:=$(strip $(LOCAL_NO_STANDARD_LIBRARIES)) LOCAL_SDK_VERSION:=$(strip $(LOCAL_SDK_VERSION)) @@ -106,8 +95,8 @@ ifneq ($(strip $(aidl_sources)),) aidl_preprocess_import := ifdef LOCAL_SDK_VERSION -ifneq ($(filter current system_current test_current core_current, $(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS_USE_PREBUILT_SDK)),) - # LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS +ifneq ($(filter current system_current test_current core_current, $(LOCAL_SDK_VERSION)$(TARGET_BUILD_USE_PREBUILT_SDKS)),) + # LOCAL_SDK_VERSION is current and no TARGET_BUILD_USE_PREBUILT_SDKS aidl_preprocess_import := $(FRAMEWORK_AIDL) else aidl_preprocess_import := $(call resolve-prebuilt-sdk-aidl-path,$(LOCAL_SDK_VERSION)) @@ -207,7 +196,7 @@ ifdef full_classes_jar # allowing it to use the classes.jar as the "stubs" that would be use to link # against, for the cases where someone needs the jar to link against. $(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_stubs_jar))) -ALL_MODULES.$(LOCAL_MODULE).STUBS := $(full_classes_stubs_jar) +ALL_MODULES.$(my_register_name).STUBS := $(full_classes_stubs_jar) # The layers file allows you to enforce a layering between java packages. # Run build/make/tools/java-layers.py for more details. @@ -274,7 +263,8 @@ $(eval $(call copy-one-file,$(full_classes_header_jarjar),$(full_classes_header_ endif # TURBINE_ENABLED != false -$(full_classes_compiled_jar): .KATI_NINJA_POOL := $(GOMA_POOL) +# TODO(b/143658984): goma can't handle the --system argument to javac. +#$(full_classes_compiled_jar): .KATI_NINJA_POOL := $(GOMA_POOL) $(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(annotation_processor_flags) $(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := $(LOCAL_JAR_EXCLUDE_FILES) $(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES := $(LOCAL_JAR_PACKAGES) @@ -295,6 +285,7 @@ $(full_classes_compiled_jar): \ $(NORMALIZE_PATH) \ $(JAR_ARGS) \ $(ZIPSYNC) \ + $(SOONG_ZIP) \ | $(SOONG_JAVAC_WRAPPER) @echo "Target Java: $@ $(call compile-java,$(TARGET_JAVAC),$(PRIVATE_ALL_JAVA_HEADER_LIBRARIES)) @@ -391,7 +382,7 @@ endif else # For platform build, we can't just raise to the "current" SDK, # that would break apps that use APIs removed from the current SDK. - my_proguard_sdk_raise := $(call java-lib-header-files,$(TARGET_DEFAULT_BOOTCLASSPATH_LIBRARIES) $(TARGET_DEFAULT_JAVA_LIBRARIES)) + my_proguard_sdk_raise := $(call java-lib-header-files,$(LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES) $(FRAMEWORK_LIBRARIES)) endif ifdef BOARD_SYSTEMSDK_VERSIONS ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_PROPRIETARY_MODULE))) @@ -499,9 +490,9 @@ else # !LOCAL_PROGUARD_ENABLED $(transform-classes.jar-to-dex) endif -ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),) - $(call pretty-error,Modules in PRODUCT_BOOT_JARS must be defined in Android.bp files) -endif +$(foreach pair,$(PRODUCT_BOOT_JARS), \ + $(if $(filter $(LOCAL_MODULE),$(call word-colon,2,$(pair))), \ + $(call pretty-error,Modules in PRODUCT_BOOT_JARS must be defined in Android.bp files))) $(built_dex): $(built_dex_intermediate) @echo Copying: $@ diff --git a/core/java_common.mk b/core/java_common.mk index f6e01d226f..1798ca8452 100644 --- a/core/java_common.mk +++ b/core/java_common.mk @@ -6,10 +6,6 @@ ifneq ($(filter ../%,$(LOCAL_SRC_FILES)),) my_soong_problems += dotdot_srcs endif -ifneq (,$(LOCAL_JNI_SHARED_LIBRARIES)) -my_soong_problems += jni_libs -endif - ########################################################### ## Java version ########################################################### @@ -29,7 +25,7 @@ ifeq (,$(LOCAL_JAVA_LANGUAGE_VERSION)) LOCAL_JAVA_LANGUAGE_VERSION := 1.7 else ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_19_SUPPORT))) LOCAL_JAVA_LANGUAGE_VERSION := 1.8 - else ifneq (,$(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS_USE_PREBUILT_SDK)) + else ifneq (,$(LOCAL_SDK_VERSION)$(TARGET_BUILD_USE_PREBUILT_SDKS)) # TODO(ccross): allow 1.9 for current and unbundled once we have SDK system modules LOCAL_JAVA_LANGUAGE_VERSION := 1.8 else @@ -235,7 +231,7 @@ $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAVA_SOURCE_LIST := $(java_source_list_fi $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RMTYPEDEFS := $(LOCAL_RMTYPEDEFS) -# Sanity check class path vars. +# Quickly check class path vars. disallowed_deps := $(foreach sdk,$(TARGET_AVAILABLE_SDK_VERSIONS),$(call resolve-prebuilt-sdk-module,$(sdk))) disallowed_deps += $(foreach sdk,$(TARGET_AVAILABLE_SDK_VERSIONS),\ $(foreach sdk_lib,$(JAVA_SDK_LIBRARIES),$(call resolve-prebuilt-sdk-module,$(sdk),$(sdk_lib)))) @@ -265,14 +261,14 @@ ifndef LOCAL_IS_HOST_MODULE # Most users of LOCAL_NO_STANDARD_LIBRARIES really mean no framework libs, # and manually add back the core libs. The ones that don't are in soong # now, so just always assume that they want the default system modules - my_system_modules := $(DEFAULT_SYSTEM_MODULES) + my_system_modules := $(LEGACY_CORE_PLATFORM_SYSTEM_MODULES) else # LOCAL_NO_STANDARD_LIBRARIES - full_java_bootclasspath_libs := $(call java-lib-header-files,$(TARGET_DEFAULT_BOOTCLASSPATH_LIBRARIES) $(TARGET_DEFAULT_JAVA_LIBRARIES)) - LOCAL_JAVA_LIBRARIES := $(filter-out $(TARGET_DEFAULT_BOOTCLASSPATH_LIBRARIES) $(TARGET_DEFAULT_JAVA_LIBRARIES),$(LOCAL_JAVA_LIBRARIES)) - my_system_modules := $(DEFAULT_SYSTEM_MODULES) + full_java_bootclasspath_libs := $(call java-lib-header-files,$(LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES) $(FRAMEWORK_LIBRARIES)) + LOCAL_JAVA_LIBRARIES := $(filter-out $(LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES) $(FRAMEWORK_LIBRARIES),$(LOCAL_JAVA_LIBRARIES)) + my_system_modules := $(LEGACY_CORE_PLATFORM_SYSTEM_MODULES) endif # LOCAL_NO_STANDARD_LIBRARIES - ifneq (,$(TARGET_BUILD_APPS_USE_PREBUILT_SDK)) + ifneq (,$(TARGET_BUILD_USE_PREBUILT_SDKS)) sdk_libs := $(foreach lib_name,$(LOCAL_SDK_LIBRARIES),$(call resolve-prebuilt-sdk-module,system_current,$(lib_name))) else # When SDK libraries are referenced from modules built without SDK, provide the all APIs to them @@ -287,8 +283,8 @@ ifndef LOCAL_IS_HOST_MODULE Choices are: $(TARGET_AVAILABLE_SDK_VERSIONS)) endif - ifneq (,$(TARGET_BUILD_APPS_USE_PREBUILT_SDK)$(filter-out %current,$(LOCAL_SDK_VERSION))) - # TARGET_BUILD_APPS mode or numbered SDK. Use prebuilt modules. + ifneq (,$(TARGET_BUILD_USE_PREBUILT_SDKS)$(filter-out %current,$(LOCAL_SDK_VERSION))) + # TARGET_BUILD_USE_PREBUILT_SDKS mode or numbered SDK. Use prebuilt modules. sdk_module := $(call resolve-prebuilt-sdk-module,$(LOCAL_SDK_VERSION)) sdk_libs := $(foreach lib_name,$(LOCAL_SDK_LIBRARIES),$(call resolve-prebuilt-sdk-module,$(LOCAL_SDK_VERSION),$(lib_name))) else @@ -329,7 +325,7 @@ ifndef LOCAL_IS_HOST_MODULE # related classes to be present. This change adds stubs needed for # javac to compile lambdas. ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true) - ifdef TARGET_BUILD_APPS_USE_PREBUILT_SDK + ifdef TARGET_BUILD_USE_PREBUILT_SDKS full_java_bootclasspath_libs += $(call java-lib-header-files,sdk-core-lambda-stubs) else full_java_bootclasspath_libs += $(call java-lib-header-files,core-lambda-stubs) @@ -352,10 +348,10 @@ else # LOCAL_IS_HOST_MODULE ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true) empty_bootclasspath := "" else - full_java_bootclasspath_libs := $(call java-lib-header-files,$(addsuffix -hostdex,$(TARGET_DEFAULT_BOOTCLASSPATH_LIBRARIES)),true) + full_java_bootclasspath_libs := $(call java-lib-header-files,$(addsuffix -hostdex,$(LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES)),true) endif - my_system_modules := $(DEFAULT_SYSTEM_MODULES) + my_system_modules := $(LEGACY_CORE_PLATFORM_SYSTEM_MODULES) full_shared_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),true) full_shared_java_header_libs := $(call java-lib-header-files,$(LOCAL_JAVA_LIBRARIES),true) else # !USE_CORE_LIB_BOOTCLASSPATH @@ -382,7 +378,9 @@ else # LOCAL_IS_HOST_MODULE endif # USE_CORE_LIB_BOOTCLASSPATH endif # !LOCAL_IS_HOST_MODULE +ifdef RECORD_ALL_DEPS ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS) $(full_java_bootclasspath_libs) +endif # Export the SDK libs. The sdk library names listed in LOCAL_SDK_LIBRARIES are first exported. # Then sdk library names exported from dependencies are all re-exported. @@ -544,6 +542,10 @@ SOONG_CONV.$(LOCAL_MODULE).DEPS := \ $(LOCAL_JAVA_LIBRARIES) \ $(LOCAL_JNI_SHARED_LIBRARIES) SOONG_CONV.$(LOCAL_MODULE).TYPE := java +SOONG_CONV.$(LOCAL_MODULE).MAKEFILES := \ + $(SOONG_CONV.$(LOCAL_MODULE).MAKEFILES) $(LOCAL_MODULE_MAKEFILE) +SOONG_CONV.$(LOCAL_MODULE).INSTALLED := \ + $(SOONG_CONV.$(LOCAL_MODULE).INSTALLED) $(LOCAL_INSTALLED_MODULE) SOONG_CONV := $(SOONG_CONV) $(LOCAL_MODULE) endif diff --git a/core/java_prebuilt_internal.mk b/core/java_prebuilt_internal.mk index 8a2091e7e2..279b0e4a91 100644 --- a/core/java_prebuilt_internal.mk +++ b/core/java_prebuilt_internal.mk @@ -35,9 +35,9 @@ ifeq ($(prebuilt_module_is_dex_javalib),true) my_dex_jar := $(my_prebuilt_src_file) # This is a target shared library, i.e. a jar with classes.dex. -ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),) - $(call pretty-error,Modules in PRODUCT_BOOT_JARS must be defined in Android.bp files) -endif +$(foreach pair,$(PRODUCT_BOOT_JARS), \ + $(if $(filter $(LOCAL_MODULE),$(call word-colon,2,$(pair))), \ + $(call pretty-error,Modules in PRODUCT_BOOT_JARS must be defined in Android.bp files))) ALL_MODULES.$(my_register_name).CLASSES_JAR := $(common_classes_jar) @@ -126,11 +126,8 @@ $(my_src_jar) : .KATI_IMPLICIT_OUTPUTS := $(my_src_proguard_options) $(my_src_jar) : .KATI_IMPLICIT_OUTPUTS += $(my_src_android_manifest) $(my_src_jar) : $(my_src_aar) $(hide) rm -rf $(dir $@) && mkdir -p $(dir $@) $(dir $@)/res - $(hide) unzip -qo -d $(dir $@) $< - # Make sure the extracted classes.jar has a new timestamp. - $(hide) touch $@ + $(hide) unzip -qoDD -d $(dir $@) $< # Make sure the proguard and AndroidManifest.xml files exist - # and have a new timestamp. $(hide) touch $(dir $@)/proguard.txt $(hide) touch $(dir $@)/AndroidManifest.xml @@ -176,7 +173,7 @@ endif framework_res_package_export := # Please refer to package.mk ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true) -ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),) +ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_USE_PREBUILT_SDKS),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),) framework_res_package_export := \ $(call resolve-prebuilt-sdk-jar-path,$(LOCAL_SDK_RES_VERSION)) else diff --git a/core/java_renderscript.mk b/core/java_renderscript.mk index 672863ba49..572d6e4a4b 100644 --- a/core/java_renderscript.mk +++ b/core/java_renderscript.mk @@ -50,8 +50,8 @@ renderscript_flags := -Wall -Werror renderscript_flags += $(LOCAL_RENDERSCRIPT_FLAGS) # prepend the RenderScript system include path -ifneq ($(filter-out current system_current test_current core_current,$(LOCAL_SDK_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current test_current,$(LOCAL_SDK_VERSION))),) -# if a numeric LOCAL_SDK_VERSION, or current LOCAL_SDK_VERSION with TARGET_BUILD_APPS +ifneq ($(filter-out current system_current test_current core_current,$(LOCAL_SDK_VERSION))$(if $(TARGET_BUILD_USE_PREBUILT_SDKS),$(filter current system_current test_current,$(LOCAL_SDK_VERSION))),) +# if a numeric LOCAL_SDK_VERSION, or current LOCAL_SDK_VERSION with TARGET_BUILD_USE_PREBUILT_SDKS LOCAL_RENDERSCRIPT_INCLUDES := \ $(HISTORICAL_SDK_VERSIONS_ROOT)/renderscript/clang-include \ $(HISTORICAL_SDK_VERSIONS_ROOT)/renderscript/include \ @@ -110,7 +110,7 @@ renderscript_intermediate := $(intermediates)/renderscript rs_jni_lib := $(call intermediates-dir-for,SHARED_LIBRARIES,librsjni.so)/librsjni.so LOCAL_JNI_SHARED_LIBRARIES += librsjni -ifneq (,$(TARGET_BUILD_APPS)$(FORCE_BUILD_RS_COMPAT)) +ifneq (,$(TARGET_BUILD_USE_PREBUILT_SDKS)$(FORCE_BUILD_RS_COMPAT)) rs_compatibility_jni_libs := $(addprefix \ $(renderscript_intermediate)/librs., \ @@ -129,7 +129,7 @@ LOCAL_JNI_SHARED_LIBRARIES += libRSSupportIO endif my_arch := $(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH) -ifneq (,$(filter arm64 mips64 x86_64,$(my_arch))) +ifneq (,$(filter arm64 x86_64,$(my_arch))) my_min_sdk_version := 21 else my_min_sdk_version := $(MIN_SUPPORTED_SDK_VERSION) diff --git a/core/line_coverage.mk b/core/line_coverage.mk index c89642e630..6bfbb8da6c 100644 --- a/core/line_coverage.mk +++ b/core/line_coverage.mk @@ -12,11 +12,11 @@ # ----------------------------------------------------------------- # TODO(b/148306195): Due this issue some fuzz targets cannot be built with -# line coverage instrumentation. For now we just blacklist them. -blacklisted_fuzz_targets := libneuralnetworks_fuzzer +# line coverage instrumentation. For now we just block them. +blocked_fuzz_targets := libneuralnetworks_fuzzer fuzz_targets := $(ALL_FUZZ_TARGETS) -fuzz_targets := $(filter-out $(blacklisted_fuzz_targets),$(fuzz_targets)) +fuzz_targets := $(filter-out $(blocked_fuzz_targets),$(fuzz_targets)) # Android components that considered critical. @@ -46,7 +46,6 @@ critical_components_shared := \ libinputflinger \ libopus \ libstagefright \ - libunwind \ libvixl:com.android.art.debug # Use the intermediates directory to avoid installing libraries to the device. diff --git a/core/link_type.mk b/core/link_type.mk index e8cfd2e7f8..48cd8f3e8a 100644 --- a/core/link_type.mk +++ b/core/link_type.mk @@ -10,7 +10,7 @@ # my_link_deps: the dependencies, in the form of <MODULE_CLASS>:<name> # -my_link_prefix := LINK_TYPE:$(call find-idf-prefix,$(my_kind),$(my_host_cross))$(if $(filter AUX,$(my_kind)),-$(AUX_OS_VARIANT)):$(if $(my_common),$(my_common):_,_:$(if $(my_2nd_arch_prefix),$(my_2nd_arch_prefix),_)) +my_link_prefix := LINK_TYPE:$(call find-idf-prefix,$(my_kind),$(my_host_cross)):$(if $(my_common),$(my_common):_,_:$(if $(my_2nd_arch_prefix),$(my_2nd_arch_prefix),_)) link_type := $(my_link_prefix):$(LOCAL_MODULE_CLASS):$(LOCAL_MODULE) ALL_LINK_TYPES += $(link_type) $(link_type).TYPE := $(my_link_type) diff --git a/core/local_current_sdk.mk b/core/local_current_sdk.mk new file mode 100644 index 0000000000..ea7da8a766 --- /dev/null +++ b/core/local_current_sdk.mk @@ -0,0 +1,26 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +ifdef BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES + ifneq (current,$(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES)) + ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_PROPRIETARY_MODULE))) + ifeq (current,$(LOCAL_SDK_VERSION)) + LOCAL_SDK_VERSION := $(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES) + else ifeq (system_current,$(LOCAL_SDK_VERSION)) + LOCAL_SDK_VERSION := system_$(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES) + endif + endif + endif +endif diff --git a/core/main.mk b/core/main.mk index 9e1d6b7024..ebec885869 100644 --- a/core/main.mk +++ b/core/main.mk @@ -33,6 +33,8 @@ endif include $(SOONG_MAKEVARS_MK) +YACC :=$= $(BISON) -d + include $(BUILD_SYSTEM)/clang/config.mk # Write the build number to a file so it can be read back in @@ -113,44 +115,38 @@ SKIP_BOOT_JARS_CHECK := true endif endif -# -# ----------------------------------------------------------------- -# Validate ADDITIONAL_DEFAULT_PROPERTIES. -ifneq ($(ADDITIONAL_DEFAULT_PROPERTIES),) -$(error ADDITIONAL_DEFAULT_PROPERTIES must not be set before here: $(ADDITIONAL_DEFAULT_PROPERTIES)) -endif - -# -# ----------------------------------------------------------------- -# Validate ADDITIONAL_BUILD_PROPERTIES. -ifneq ($(ADDITIONAL_BUILD_PROPERTIES),) -$(error ADDITIONAL_BUILD_PROPERTIES must not be set before here: $(ADDITIONAL_BUILD_PROPERTIES)) -endif - -ADDITIONAL_BUILD_PROPERTIES := - -# -# ----------------------------------------------------------------- -# Validate ADDITIONAL_PRODUCT_PROPERTIES. -ifneq ($(ADDITIONAL_PRODUCT_PROPERTIES),) -$(error ADDITIONAL_PRODUCT_PROPERTIES must not be set before here: $(ADDITIONAL_PRODUCT_PROPERTIES)) -endif +# ADDITIONAL_<partition>_PROPERTIES are properties that are determined by the +# build system itself. Don't let it be defined from outside of the core build +# system like Android.mk or <product>.mk files. +_additional_prop_var_names := \ + ADDITIONAL_SYSTEM_PROPERTIES \ + ADDITIONAL_VENDOR_PROPERTIES \ + ADDITIONAL_ODM_PROPERTIES \ + ADDITIONAL_PRODUCT_PROPERTIES + +$(foreach name, $(_additional_prop_var_names),\ + $(if $($(name)),\ + $(error $(name) must not set before here. $($(name)))\ + ,)\ + $(eval $(name) :=)\ +) +_additional_prop_var_names := -ADDITIONAL_PRODUCT_PROPERTIES := +$(KATI_obsolete_var ADDITIONAL_BUILD_PROPERTIES, Please use ADDITIONAL_SYSTEM_PROPERTIES) # # ----------------------------------------------------------------- # Add the product-defined properties to the build properties. ifdef PRODUCT_SHIPPING_API_LEVEL -ADDITIONAL_BUILD_PROPERTIES += \ +ADDITIONAL_SYSTEM_PROPERTIES += \ ro.product.first_api_level=$(PRODUCT_SHIPPING_API_LEVEL) endif ifneq ($(BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED), true) - ADDITIONAL_BUILD_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES) + ADDITIONAL_SYSTEM_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES) else ifndef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE - ADDITIONAL_BUILD_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES) + ADDITIONAL_SYSTEM_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES) endif endif @@ -158,9 +154,6 @@ endif # Bring in standard build system definitions. include $(BUILD_SYSTEM)/definitions.mk -# Bring in dex_preopt.mk -include $(BUILD_SYSTEM)/dex_preopt.mk - ifneq ($(filter user userdebug eng,$(MAKECMDGOALS)),) $(info ***************************************************************) $(info ***************************************************************) @@ -186,20 +179,12 @@ $(error stopping) endif # ----------------------------------------------------------------- -# Variable to check java support level inside PDK build. -# Not necessary if the components is not in PDK. -# not defined : not supported -# "sdk" : sdk API only -# "platform" : platform API supproted -TARGET_BUILD_JAVA_SUPPORT_LEVEL := platform +# PDK builds are no longer supported, this is always platform +TARGET_BUILD_JAVA_SUPPORT_LEVEL :=$= platform # ----------------------------------------------------------------- -# The pdk (Platform Development Kit) build -include build/make/core/pdk_config.mk -# ----------------------------------------------------------------- - -ADDITIONAL_BUILD_PROPERTIES += ro.treble.enabled=${PRODUCT_FULL_TREBLE} +ADDITIONAL_SYSTEM_PROPERTIES += ro.treble.enabled=${PRODUCT_FULL_TREBLE} $(KATI_obsolete_var PRODUCT_FULL_TREBLE,\ Code should be written to work regardless of a device being Treble or \ @@ -209,9 +194,9 @@ $(KATI_obsolete_var PRODUCT_FULL_TREBLE,\ # Sets ro.actionable_compatible_property.enabled to know on runtime whether the # allowed list of actionable compatible properties is enabled or not. ifeq ($(PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE),true) -ADDITIONAL_DEFAULT_PROPERTIES += ro.actionable_compatible_property.enabled=false +ADDITIONAL_SYSTEM_PROPERTIES += ro.actionable_compatible_property.enabled=false else -ADDITIONAL_DEFAULT_PROPERTIES += ro.actionable_compatible_property.enabled=${PRODUCT_COMPATIBLE_PROPERTY} +ADDITIONAL_SYSTEM_PROPERTIES += ro.actionable_compatible_property.enabled=${PRODUCT_COMPATIBLE_PROPERTY} endif # Add the system server compiler filter if they are specified for the product. @@ -221,9 +206,12 @@ endif # Enable core platform API violation warnings on userdebug and eng builds. ifneq ($(TARGET_BUILD_VARIANT),user) -ADDITIONAL_BUILD_PROPERTIES += persist.debug.dalvik.vm.core_platform_api_policy=just-warn +ADDITIONAL_SYSTEM_PROPERTIES += persist.debug.dalvik.vm.core_platform_api_policy=just-warn endif +# Define ro.sanitize.<name> properties for all global sanitizers. +ADDITIONAL_SYSTEM_PROPERTIES += $(foreach s,$(SANITIZE_TARGET),ro.sanitize.$(s)=true) + # Sets the default value of ro.postinstall.fstab.prefix to /system. # Device board config should override the value to /product when needed by: # @@ -231,7 +219,92 @@ endif # # It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to # mount system_other partition. -ADDITIONAL_DEFAULT_PROPERTIES += ro.postinstall.fstab.prefix=/system +ADDITIONAL_SYSTEM_PROPERTIES += ro.postinstall.fstab.prefix=/system + +# ----------------------------------------------------------------- +# ADDITIONAL_VENDOR_PROPERTIES will be installed in vendor/build.prop if +# property_overrides_split_enabled is true. Otherwise it will be installed in +# /system/build.prop +ifdef BOARD_VNDK_VERSION + ifeq ($(BOARD_VNDK_VERSION),current) + ADDITIONAL_VENDOR_PROPERTIES := ro.vndk.version=$(PLATFORM_VNDK_VERSION) + else + ADDITIONAL_VENDOR_PROPERTIES := ro.vndk.version=$(BOARD_VNDK_VERSION) + endif +endif + +# Add cpu properties for bionic and ART. +ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.arch=$(TARGET_ARCH) +ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT_RUNTIME) +ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.2nd_arch=$(TARGET_2ND_ARCH) +ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.2nd_cpu_variant=$(TARGET_2ND_CPU_VARIANT_RUNTIME) + +ADDITIONAL_VENDOR_PROPERTIES += persist.sys.dalvik.vm.lib.2=libart.so +ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).variant=$(DEX2OAT_TARGET_CPU_VARIANT_RUNTIME) +ifneq ($(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),) + ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) +endif + +ifdef TARGET_2ND_ARCH + ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).variant=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT_RUNTIME) + ifneq ($($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),) + ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).features=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) + endif +endif + +# Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger +# mode (via libminui). +ifdef TARGET_RECOVERY_DEFAULT_ROTATION +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.minui.default_rotation=$(TARGET_RECOVERY_DEFAULT_ROTATION) +endif +ifdef TARGET_RECOVERY_OVERSCAN_PERCENT +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.minui.overscan_percent=$(TARGET_RECOVERY_OVERSCAN_PERCENT) +endif +ifdef TARGET_RECOVERY_PIXEL_FORMAT +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.minui.pixel_format=$(TARGET_RECOVERY_PIXEL_FORMAT) +endif + +ifdef PRODUCT_USE_DYNAMIC_PARTITIONS +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.boot.dynamic_partitions=$(PRODUCT_USE_DYNAMIC_PARTITIONS) +endif + +ifdef PRODUCT_RETROFIT_DYNAMIC_PARTITIONS +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.boot.dynamic_partitions_retrofit=$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS) +endif + +ifdef PRODUCT_SHIPPING_API_LEVEL +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.product.first_api_level=$(PRODUCT_SHIPPING_API_LEVEL) +endif + +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.vendor.build.security_patch=$(VENDOR_SECURITY_PATCH) \ + ro.vendor.product.cpu.abilist=$(TARGET_CPU_ABI_LIST) \ + ro.vendor.product.cpu.abilist32=$(TARGET_CPU_ABI_LIST_32_BIT) \ + ro.vendor.product.cpu.abilist64=$(TARGET_CPU_ABI_LIST_64_BIT) \ + ro.product.board=$(TARGET_BOOTLOADER_BOARD_NAME) \ + ro.board.platform=$(TARGET_BOARD_PLATFORM) \ + ro.hwui.use_vulkan=$(TARGET_USES_VULKAN) + +ifdef TARGET_SCREEN_DENSITY +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.sf.lcd_density=$(TARGET_SCREEN_DENSITY) +endif + +ifdef AB_OTA_UPDATER +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.build.ab_update=$(AB_OTA_UPDATER) +endif + +ADDITIONAL_ODM_PROPERTIES += \ + ro.odm.product.cpu.abilist=$(TARGET_CPU_ABI_LIST) \ + ro.odm.product.cpu.abilist32=$(TARGET_CPU_ABI_LIST_32_BIT) \ + ro.odm.product.cpu.abilist64=$(TARGET_CPU_ABI_LIST_64_BIT) # Set ro.product.vndk.version to know the VNDK version required by product # modules. It uses the version in PRODUCT_PRODUCT_VNDK_VERSION. If the value @@ -244,6 +317,12 @@ ADDITIONAL_PRODUCT_PROPERTIES += ro.product.vndk.version=$(PRODUCT_PRODUCT_VNDK_ endif endif +ADDITIONAL_PRODUCT_PROPERTIES += ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS) + +ifeq ($(AB_OTA_UPDATER),true) +ADDITIONAL_PRODUCT_PROPERTIES += ro.product.ab_ota_partitions=$(subst $(space),$(comma),$(AB_OTA_PARTITIONS)) +endif + # ----------------------------------------------------------------- ### ### In this section we set up the things that are different @@ -263,11 +342,11 @@ enable_target_debugging := true tags_to_install := ifneq (,$(user_variant)) # Target is secure in user builds. - ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1 - ADDITIONAL_DEFAULT_PROPERTIES += security.perf_harden=1 + ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=1 + ADDITIONAL_SYSTEM_PROPERTIES += security.perf_harden=1 ifeq ($(user_variant),user) - ADDITIONAL_DEFAULT_PROPERTIES += ro.adb.secure=1 + ADDITIONAL_SYSTEM_PROPERTIES += ro.adb.secure=1 endif ifeq ($(user_variant),userdebug) @@ -279,40 +358,40 @@ ifneq (,$(user_variant)) endif # Disallow mock locations by default for user builds - ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0 + ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=0 else # !user_variant # Turn on checkjni for non-user builds. - ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1 + ADDITIONAL_SYSTEM_PROPERTIES += ro.kernel.android.checkjni=1 # Set device insecure for non-user builds. - ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0 + ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=0 # Allow mock locations by default for non user builds - ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1 + ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=1 endif # !user_variant ifeq (true,$(strip $(enable_target_debugging))) # Target is more debuggable and adbd is on by default - ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1 + ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=1 # Enable Dalvik lock contention logging. - ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.lockprof.threshold=500 + ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.lockprof.threshold=500 else # !enable_target_debugging # Target is less debuggable and adbd is off by default - ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0 + ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=0 endif # !enable_target_debugging ## eng ## ifeq ($(TARGET_BUILD_VARIANT),eng) tags_to_install := debug eng -ifneq ($(filter ro.setupwizard.mode=ENABLED, $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))),) +ifneq ($(filter ro.setupwizard.mode=ENABLED, $(call collapse-pairs, $(ADDITIONAL_SYSTEM_PROPERTIES))),) # Don't require the setup wizard on eng builds - ADDITIONAL_BUILD_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\ - $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))) \ + ADDITIONAL_SYSTEM_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\ + $(call collapse-pairs, $(ADDITIONAL_SYSTEM_PROPERTIES))) \ ro.setupwizard.mode=OPTIONAL endif ifndef is_sdk_build # To speedup startup of non-preopted builds, don't verify or compile the boot image. - ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.image-dex2oat-filter=extract + ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.image-dex2oat-filter=extract endif endif @@ -342,24 +421,21 @@ ifdef is_sdk_build sdk_repo_goal := $(strip $(filter sdk_repo,$(MAKECMDGOALS))) MAKECMDGOALS := $(strip $(filter-out sdk_repo,$(MAKECMDGOALS))) -ifneq ($(words $(sort $(filter-out $(INTERNAL_MODIFIER_TARGETS) checkbuild emulator_tests target-files-package,$(MAKECMDGOALS)))),1) +ifneq ($(words $(sort $(filter-out $(INTERNAL_MODIFIER_TARGETS) checkbuild emulator_tests,$(MAKECMDGOALS)))),1) $(error The 'sdk' target may not be specified with any other targets) endif -# AUX dependencies are already added by now; remove triggers from the MAKECMDGOALS -MAKECMDGOALS := $(strip $(filter-out AUX-%,$(MAKECMDGOALS))) - # TODO: this should be eng I think. Since the sdk is built from the eng # variant. tags_to_install := debug eng -ADDITIONAL_BUILD_PROPERTIES += xmpp.auto-presence=true -ADDITIONAL_BUILD_PROPERTIES += ro.config.nocheckin=yes +ADDITIONAL_SYSTEM_PROPERTIES += xmpp.auto-presence=true +ADDITIONAL_SYSTEM_PROPERTIES += ro.config.nocheckin=yes else # !sdk endif BUILD_WITHOUT_PV := true -ADDITIONAL_BUILD_PROPERTIES += net.bt.name=Android +ADDITIONAL_SYSTEM_PROPERTIES += net.bt.name=Android # ------------------------------------------------------------ # Define a function that, given a list of module tags, returns @@ -391,12 +467,16 @@ endif # Typical build; include any Android.mk files we can find. # +# Bring in dex_preopt.mk +# This creates some modules so it needs to be included after +# should-install-to-system is defined (in order for base_rules.mk to function +# properly), but before readonly-final-product-vars is called. +include $(BUILD_SYSTEM)/dex_preopt.mk + # Strip and readonly a few more variables so they won't be modified. $(readonly-final-product-vars) -ADDITIONAL_DEFAULT_PROPERTIES := $(strip $(ADDITIONAL_DEFAULT_PROPERTIES)) -.KATI_READONLY := ADDITIONAL_DEFAULT_PROPERTIES -ADDITIONAL_BUILD_PROPERTIES := $(strip $(ADDITIONAL_BUILD_PROPERTIES)) -.KATI_READONLY := ADDITIONAL_BUILD_PROPERTIES +ADDITIONAL_SYSTEM_PROPERTIES := $(strip $(ADDITIONAL_SYSTEM_PROPERTIES)) +.KATI_READONLY := ADDITIONAL_SYSTEM_PROPERTIES ADDITIONAL_PRODUCT_PROPERTIES := $(strip $(ADDITIONAL_PRODUCT_PROPERTIES)) .KATI_READONLY := ADDITIONAL_PRODUCT_PROPERTIES @@ -432,11 +512,6 @@ subdir_makefiles_total := $(words int $(subdir_makefiles) post finish) $(foreach mk,$(subdir_makefiles),$(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] including $(mk) ...)$(eval include $(mk))) -ifneq (,$(PDK_FUSION_PLATFORM_ZIP)$(PDK_FUSION_PLATFORM_DIR)) -# Bring in the PDK platform.zip modules. -include $(BUILD_SYSTEM)/pdk_fusion_modules.mk -endif # PDK_FUSION_PLATFORM_ZIP || PDK_FUSION_PLATFORM_DIR - droid_targets : blueprint_tools endif # dont_bother @@ -472,6 +547,13 @@ $(call generate_all_enforce_rro_packages) endif # ------------------------------------------------------------------- +# Sort ALL_MODULES to remove duplicate entries. +# ------------------------------------------------------------------- +ALL_MODULES := $(sort $(ALL_MODULES)) +# Cannot set to readonly because Makefile extends ALL_MODULES +# .KATI_READONLY := ALL_MODULES + +# ------------------------------------------------------------------- # Fix up CUSTOM_MODULES to refer to installed files rather than # just bare module names. Leave unknown modules alone in case # they're actually full paths to a particular file. @@ -492,96 +574,158 @@ CUSTOM_MODULES := \ # brought in as requirements of other modules. # # Resolve the required module name to 32-bit or 64-bit variant. -# Get a list of corresponding 32-bit module names, if one exists. -define get-32-bit-modules -$(sort $(foreach m,$(1),\ - $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\ - $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX)))) -endef -# Get a list of corresponding 32-bit module names, if one exists; -# otherwise return the original module name -define get-32-bit-modules-if-we-can -$(sort $(foreach m,$(1),\ - $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\ - $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX), \ - $(m)))) -endef -# TODO: we can probably check to see if these modules are actually host -# modules -define get-host-32-bit-modules -$(sort $(foreach m,$(1),\ - $(if $(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),\ - $(m)$(HOST_2ND_ARCH_MODULE_SUFFIX)))) -endef -# Get a list of corresponding 32-bit module names, if one exists; -# otherwise return the original module name -define get-host-32-bit-modules-if-we-can -$(sort $(foreach m,$(1),\ - $(if $(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),\ - $(m)$(HOST_2ND_ARCH_MODULE_SUFFIX),\ - $(m)))) +# Get a list of corresponding module names for the second arch, if they exist. +# $(1): TARGET, HOST or HOST_CROSS +# $(2): A list of module names +define get-modules-for-2nd-arch +$(strip \ + $(foreach m,$(2), \ + $(if $(filter true,$(ALL_MODULES.$(m)$($(1)_2ND_ARCH_MODULE_SUFFIX).FOR_2ND_ARCH)), \ + $(m)$($(1)_2ND_ARCH_MODULE_SUFFIX) \ + ) \ + ) \ +) endef -# If a module is for a cross host os, the required modules must be for -# that OS too. -# If a module is built for 32-bit, the required modules must be 32-bit too; -# Otherwise if the module is an executable or shared library, -# the required modules must be 64-bit; -# otherwise we require both 64-bit and 32-bit variant, if one exists. -define target-select-bitness-of-required-modules -$(foreach m,$(ALL_MODULES),\ - $(eval r := $(ALL_MODULES.$(m).REQUIRED_FROM_TARGET))\ - $(if $(r),\ - $(if $(ALL_MODULES.$(m).FOR_2ND_ARCH),\ - $(eval r_r := $(call get-32-bit-modules-if-we-can,$(r))),\ - $(if $(filter EXECUTABLES SHARED_LIBRARIES NATIVE_TESTS,$(ALL_MODULES.$(m).CLASS)),\ - $(eval r_r := $(r)),\ - $(eval r_r := $(r) $(call get-32-bit-modules,$(r)))\ - )\ - )\ - $(eval ALL_MODULES.$(m).REQUIRED_FROM_TARGET := $(strip $(r_r)))\ - )\ +# Resolves module bitness for PRODUCT_PACKAGES and PRODUCT_HOST_PACKAGES. +# The returned list of module names can be used to access +# ALL_MODULES.<module>.<*> variables. +# Name resolution for PRODUCT_PACKAGES / PRODUCT_HOST_PACKAGES: +# foo:32 resolves to foo_32; +# foo:64 resolves to foo; +# foo resolves to both foo and foo_32 (if foo_32 is defined). +# +# Name resolution for HOST_CROSS modules: +# foo:32 resolves to foo; +# foo:64 resolves to foo_64; +# foo resolves to both foo and foo_64 (if foo_64 is defined). +# +# $(1): TARGET, HOST or HOST_CROSS +# $(2): A list of simple module names with :32 and :64 suffix +define resolve-bitness-for-modules +$(strip \ + $(eval modules_32 := $(patsubst %:32,%,$(filter %:32,$(2)))) \ + $(eval modules_64 := $(patsubst %:64,%,$(filter %:64,$(2)))) \ + $(eval modules_both := $(filter-out %:32 %:64,$(2))) \ + $(eval ### if 2ND_HOST_CROSS_IS_64_BIT, then primary/secondary are reversed for HOST_CROSS modules) \ + $(if $(filter HOST_CROSS_true,$(1)_$(2ND_HOST_CROSS_IS_64_BIT)), \ + $(eval modules_1st_arch := $(modules_32)) \ + $(eval modules_2nd_arch := $(modules_64)), \ + $(eval modules_1st_arch := $(modules_64)) \ + $(eval modules_2nd_arch := $(modules_32))) \ + $(eval ### Note for 32-bit product, 32 and 64 will be added as their original module names.) \ + $(eval modules := $(modules_1st_arch)) \ + $(if $($(1)_2ND_ARCH), \ + $(eval modules += $(call get-modules-for-2nd-arch,$(1),$(modules_2nd_arch))), \ + $(eval modules += $(modules_2nd_arch))) \ + $(eval ### For the rest we add both) \ + $(eval modules += $(modules_both)) \ + $(if $($(1)_2ND_ARCH), \ + $(eval modules += $(call get-modules-for-2nd-arch,$(1),$(modules_both)))) \ + $(modules) \ ) endef -$(call target-select-bitness-of-required-modules) - -define host-select-bitness-of-required-modules -$(foreach m,$(ALL_MODULES),\ - $(eval r := $(ALL_MODULES.$(m).REQUIRED_FROM_HOST))\ - $(if $(r),\ - $(if $(ALL_MODULES.$(m).FOR_2ND_ARCH),\ - $(eval r_r := $(call get-host-32-bit-modules-if-we-can,$(r))),\ - $(if $(filter EXECUTABLES SHARED_LIBRARIES NATIVE_TESTS,$(ALL_MODULES.$(m).CLASS)),\ - $(eval r_r := $(r)),\ - $(eval r_r := $(r) $(call get-host-32-bit-modules,$(r)))\ - )\ - )\ - $(eval ALL_MODULES.$(m).REQUIRED_FROM_HOST := $(strip $(r_r)))\ - )\ + +# Resolve the required module names to 32-bit or 64-bit variant for: +# ALL_MODULES.<*>.REQUIRED_FROM_TARGET +# ALL_MODULES.<*>.REQUIRED_FROM_HOST +# ALL_MODULES.<*>.REQUIRED_FROM_HOST_CROSS +# +# If a module is for cross host OS, the required modules are also for that OS. +# Required modules explicitly suffixed with :32 or :64 resolve to that bitness. +# Otherwise if the requiring module is native and the required module is shared +# library or native test, then the required module resolves to the same bitness. +# Otherwise the required module resolves to both variants, if they exist. +# $(1): TARGET, HOST or HOST_CROSS +define select-bitness-of-required-modules +$(foreach m,$(ALL_MODULES), \ + $(eval r := $(ALL_MODULES.$(m).REQUIRED_FROM_$(1))) \ + $(if $(r), \ + $(if $(filter HOST_CROSS,$(1)), \ + $(if $(ALL_MODULES.$(m).FOR_HOST_CROSS),,$(error Only expected REQUIRED_FROM_HOST_CROSS on FOR_HOST_CROSS modules - $(m))) \ + $(eval r := $(addprefix host_cross_,$(r)))) \ + $(eval module_is_native := \ + $(filter EXECUTABLES SHARED_LIBRARIES NATIVE_TESTS,$(ALL_MODULES.$(m).CLASS))) \ + $(eval r_r := \ + $(foreach r_i,$(r), \ + $(if $(filter %:32 %:64,$(r_i)), \ + $(eval r_m := $(call resolve-bitness-for-modules,$(1),$(r_i))), \ + $(eval r_m := \ + $(eval r_i_2nd := $(call get-modules-for-2nd-arch,$(1),$(r_i))) \ + $(eval required_is_shared_library_or_native_test := \ + $(filter SHARED_LIBRARIES NATIVE_TESTS, \ + $(ALL_MODULES.$(r_i).CLASS) $(ALL_MODULES.$(r_i_2nd).CLASS))) \ + $(if $(and $(module_is_native),$(required_is_shared_library_or_native_test)), \ + $(if $(ALL_MODULES.$(m).FOR_2ND_ARCH),$(r_i_2nd),$(r_i)), \ + $(r_i) $(r_i_2nd)))) \ + $(eval r_m := $(foreach r_j,$(r_m),$(if $(ALL_MODULES.$(r_j).PATH),$(r_j)))) \ + $(if $(r_m),,$(eval _nonexistent_required += $(1)$(comma)$(m)$(comma)$(1)$(comma)$(r_i))) \ + $(r_m))) \ + $(eval ALL_MODULES.$(m).REQUIRED_FROM_$(1) := $(sort $(r_r))) \ + ) \ ) endef -$(call host-select-bitness-of-required-modules) - -define host-cross-select-bitness-of-required-modules -$(foreach m,$(ALL_MODULES),\ - $(eval r := $(ALL_MODULES.$(m).REQUIRED_FROM_HOST_CROSS))\ - $(if $(r),\ - $(if $(ALL_MODULES.$(m).FOR_HOST_CROSS),,$(error Only expected REQUIRED_FROM_HOST_CROSS on FOR_HOST_CROSS modules - $(m)))\ - $(eval r := $(addprefix host_cross_,$(r)))\ - $(if $(ALL_MODULES.$(m).FOR_2ND_ARCH),\ - $(eval r_r := $(call get-host-32-bit-modules-if-we-can,$(r))),\ - $(if $(filter EXECUTABLES SHARED_LIBRARIES NATIVE_TESTS,$(ALL_MODULES.$(m).CLASS)),\ - $(eval r_r := $(r)),\ - $(eval r_r := $(r) $(call get-host-32-bit-modules,$(r)))\ - )\ - )\ - $(eval ALL_MODULES.$(m).REQUIRED_FROM_HOST_CROSS := $(strip $(r_r)))\ - )\ + +# Resolve the required module names to 32-bit or 64-bit variant for: +# ALL_MODULES.<*>.TARGET_REQUIRED_FROM_HOST +# ALL_MODULES.<*>.HOST_REQUIRED_FROM_TARGET +# +# This is like select-bitness-of-required-modules, but it doesn't have +# complicated logic for various module types. +# Calls resolve-bitness-for-modules to resolve module names. +# $(1): TARGET or HOST +# $(2): HOST or TARGET +define select-bitness-of-target-host-required-modules +$(foreach m,$(ALL_MODULES), \ + $(eval r := $(ALL_MODULES.$(m).$(1)_REQUIRED_FROM_$(2))) \ + $(if $(r), \ + $(eval r_r := \ + $(foreach r_i,$(r), \ + $(eval r_m := $(call resolve-bitness-for-modules,$(1),$(r_i))) \ + $(eval r_m := $(foreach r_j,$(r_m),$(if $(ALL_MODULES.$(r_j).PATH),$(r_j)))) \ + $(if $(r_m),,$(eval _nonexistent_required += $(2)$(comma)$(m)$(comma)$(1)$(comma)$(r_i))) \ + $(r_m))) \ + $(eval ALL_MODULES.$(m).$(1)_REQUIRED_FROM_$(2) := $(sort $(r_r))) \ + ) \ ) endef -$(call host-cross-select-bitness-of-required-modules) -r_r := + +_nonexistent_required := +$(call select-bitness-of-required-modules,TARGET) +$(call select-bitness-of-required-modules,HOST) +$(call select-bitness-of-required-modules,HOST_CROSS) +$(call select-bitness-of-target-host-required-modules,TARGET,HOST) +$(call select-bitness-of-target-host-required-modules,HOST,TARGET) +_nonexistent_required := $(sort $(_nonexistent_required)) + +check_missing_required_modules := true +ifneq (,$(filter true,$(ALLOW_MISSING_DEPENDENCIES) $(BUILD_BROKEN_MISSING_REQUIRED_MODULES))) + check_missing_required_modules := +endif # ALLOW_MISSING_DEPENDENCIES == true || BUILD_BROKEN_MISSING_REQUIRED_MODULES == true + +# Some executables are skipped in ASAN SANITIZE_TARGET build, thus breaking their dependencies. +ifneq (,$(filter address,$(SANITIZE_TARGET))) + check_missing_required_modules := +endif # SANITIZE_TARGET has ASAN + +# HOST OS darwin build is broken, disable this check for darwin for now. +# TODO(b/162102724): Remove this when darwin host has no broken dependency. +ifneq (,$(filter $(HOST_OS),darwin)) + check_missing_required_modules := +endif # HOST_OS == darwin + +ifeq (true,$(check_missing_required_modules)) +ifneq (,$(_nonexistent_required)) + $(warning Missing required dependencies:) + $(foreach r_i,$(_nonexistent_required), \ + $(eval r := $(subst $(comma),$(space),$(r_i))) \ + $(info $(word 1,$(r)) module $(word 2,$(r)) requires non-existent $(word 3,$(r)) module: $(word 4,$(r))) \ + ) + $(warning Set BUILD_BROKEN_MISSING_REQUIRED_MODULES := true to bypass this check if this is intentional) + $(error Build failed) +endif # _nonexistent_required != empty +endif # check_missing_required_modules == true define add-required-deps $(1): | $(2) @@ -652,10 +796,13 @@ $(foreach m,$(ALL_MODULES), \ $(eval req_files := )\ $(foreach req_mod,$(req_mods), \ $(eval req_file := $(filter $(TARGET_OUT_ROOT)/%, $(call module-installed-files,$(req_mod)))) \ - $(if $(strip $(req_file)),\ - ,\ - $(error $(m).LOCAL_TARGET_REQUIRED_MODULES : illegal value $(req_mod) : not a device module. If you want to specify host modules to be required to be installed along with your host module, add those module names to LOCAL_REQUIRED_MODULES instead)\ - )\ + $(if $(filter true,$(ALLOW_MISSING_DEPENDENCIES)), \ + , \ + $(if $(strip $(req_file)), \ + , \ + $(error $(m).LOCAL_TARGET_REQUIRED_MODULES : illegal value $(req_mod) : not a device module. If you want to specify host modules to be required to be installed along with your host module, add those module names to LOCAL_REQUIRED_MODULES instead) \ + ) \ + ) \ $(eval req_files := $(req_files)$(space)$(req_file))\ )\ $(eval req_files := $(strip $(req_files)))\ @@ -678,10 +825,13 @@ $(foreach m,$(ALL_MODULES), \ $(eval req_files := )\ $(foreach req_mod,$(req_mods), \ $(eval req_file := $(filter $(HOST_OUT)/%, $(call module-installed-files,$(req_mod)))) \ - $(if $(strip $(req_file)),\ - ,\ - $(error $(m).LOCAL_HOST_REQUIRED_MODULES : illegal value $(req_mod) : not a host module. If you want to specify target modules to be required to be installed along with your target module, add those module names to LOCAL_REQUIRED_MODULES instead)\ - )\ + $(if $(filter true,$(ALLOW_MISSING_DEPENDENCIES)), \ + , \ + $(if $(strip $(req_file)), \ + , \ + $(error $(m).LOCAL_HOST_REQUIRED_MODULES : illegal value $(req_mod) : not a host module. If you want to specify target modules to be required to be installed along with your target module, add those module names to LOCAL_REQUIRED_MODULES instead) \ + ) \ + ) \ $(eval req_files := $(req_files)$(space)$(req_file))\ )\ $(eval req_files := $(strip $(req_files)))\ @@ -800,9 +950,10 @@ $(foreach m,$($(if $(2),$($(1)2ND_ARCH_VAR_PREFIX))$(1)DEPENDENCIES_ON_SHARED_LI $($(if $(2),$($(1)2ND_ARCH_VAR_PREFIX))TARGET_OUT_INTERMEDIATES)/SHARED_LIBRARIES/%,\ $(call module-built-files,$(mod)))))\ \ - $(if $(r),\ + $(if $(and $(r),$(deps)),\ $(eval stamp := $(dir $(r))check_elf_files.timestamp)\ - $(eval $(call add-elf-file-check-shared-lib,$(stamp),$(deps)))\ + $(if $(CHECK_ELF_FILES.$(stamp)),\ + $(eval $(call add-elf-file-check-shared-lib,$(stamp),$(deps))))\ )) endef @@ -832,7 +983,6 @@ add-required-deps := # - TARGET # - HOST # - HOST_CROSS -# - AUX-<variant-name> # 3: Whether to use the common intermediates directory or not # - _ # - COMMON @@ -859,14 +1009,8 @@ add-required-deps := link_type_error := -define link-type-prefix-base -$(word 2,$(subst :,$(space),$(1))) -endef define link-type-prefix -$(if $(filter AUX-%,$(link-type-prefix-base)),$(patsubst AUX-%,AUX,$(link-type-prefix-base)),$(link-type-prefix-base)) -endef -define link-type-aux-variant -$(if $(filter AUX-%,$(link-type-prefix-base)),$(patsubst AUX-%,%,$(link-type-prefix-base))) +$(word 2,$(subst :,$(space),$(1))) endef define link-type-common $(patsubst _,,$(word 3,$(subst :,$(space),$(1)))) @@ -884,7 +1028,7 @@ define link-type-os $(strip $(eval _p := $(link-type-prefix))\ $(if $(filter HOST HOST_CROSS,$(_p)),\ $($(_p)_OS),\ - $(if $(filter AUX,$(_p)),AUX,android))) + android)) endef define link-type-arch $($(link-type-prefix)_$(link-type-2ndarchprefix)ARCH) @@ -1023,7 +1167,9 @@ define resolve-product-relative-paths $(subst $(_product_path_placeholder),$(TARGET_COPY_OUT_PRODUCT),\ $(subst $(_system_ext_path_placeholder),$(TARGET_COPY_OUT_SYSTEM_EXT),\ $(subst $(_odm_path_placeholder),$(TARGET_COPY_OUT_ODM),\ - $(foreach p,$(1),$(call append-path,$(PRODUCT_OUT),$(p)$(2))))))) + $(subst $(_vendor_dlkm_path_placeholder),$(TARGET_COPY_OUT_VENDOR_DLKM),\ + $(subst $(_odm_dlkm_path_placeholder),$(TARGET_COPY_OUT_ODM_DLKM),\ + $(foreach p,$(1),$(call append-path,$(PRODUCT_OUT),$(p)$(2))))))))) endef # Returns modules included automatically as a result of certain BoardConfig @@ -1049,8 +1195,7 @@ endef # foo resolves to both foo and foo_32 (if foo_32 is defined). # # Name resolution for LOCAL_REQUIRED_MODULES: -# If a module is built for 2nd arch, its required module resolves to -# 32-bit variant, if it exits. See the select-bitness-of-required-modules definition. +# See the select-bitness-of-required-modules definition. # $(1): product makefile define product-installed-files $(eval _pif_modules := \ @@ -1066,15 +1211,7 @@ define product-installed-files $(eval _pif_overrides := $(call module-overrides,$(_pif_modules))) \ $(eval _pif_modules := $(filter-out $(_pif_overrides), $(_pif_modules))) \ $(eval ### Resolve the :32 :64 module name) \ - $(eval _pif_modules_32 := $(patsubst %:32,%,$(filter %:32, $(_pif_modules)))) \ - $(eval _pif_modules_64 := $(patsubst %:64,%,$(filter %:64, $(_pif_modules)))) \ - $(eval _pif_modules_rest := $(filter-out %:32 %:64,$(_pif_modules))) \ - $(eval ### Note for 32-bit product, 32 and 64 will be added as their original module names.) \ - $(eval _pif_modules := $(call get-32-bit-modules-if-we-can, $(_pif_modules_32))) \ - $(eval _pif_modules += $(_pif_modules_64)) \ - $(eval ### For the rest we add both) \ - $(eval _pif_modules += $(call get-32-bit-modules, $(_pif_modules_rest))) \ - $(eval _pif_modules += $(_pif_modules_rest)) \ + $(eval _pif_modules := $(sort $(call resolve-bitness-for-modules,TARGET,$(_pif_modules)))) \ $(call expand-required-modules,_pif_modules,$(_pif_modules),$(_pif_overrides)) \ $(filter-out $(HOST_OUT_ROOT)/%,$(call module-installed-files, $(_pif_modules))) \ $(call resolve-product-relative-paths,\ @@ -1085,18 +1222,12 @@ endef # This does support the :32 / :64 syntax, but does not support module overrides. define host-installed-files $(eval _hif_modules := $(call get-product-var,$(1),PRODUCT_HOST_PACKAGES)) \ - $(eval ### Resolve the :32 :64 module name) \ - $(eval _hif_modules_32 := $(patsubst %:32,%,$(filter %:32, $(_hif_modules)))) \ - $(eval _hif_modules_64 := $(patsubst %:64,%,$(filter %:64, $(_hif_modules)))) \ - $(eval _hif_modules_rest := $(filter-out %:32 %:64,$(_hif_modules))) \ - $(eval _hif_modules := $(call get-host-32-bit-modules-if-we-can, $(_hif_modules_32))) \ - $(eval _hif_modules += $(_hif_modules_64)) \ - $(eval ### For the rest we add both) \ - $(eval _hif_modules += $(call get-host-32-bit-modules, $(_hif_modules_rest))) \ - $(eval _hif_modules += $(_hif_modules_rest)) \ $(eval ### Split host vs host cross modules) \ $(eval _hcif_modules := $(filter host_cross_%,$(_hif_modules))) \ $(eval _hif_modules := $(filter-out host_cross_%,$(_hif_modules))) \ + $(eval ### Resolve the :32 :64 module name) \ + $(eval _hif_modules := $(sort $(call resolve-bitness-for-modules,HOST,$(_hif_modules)))) \ + $(eval _hcif_modules := $(sort $(call resolve-bitness-for-modules,HOST_CROSS,$(_hcif_modules)))) \ $(call expand-required-host-modules,_hif_modules,$(_hif_modules),HOST) \ $(call expand-required-host-modules,_hcif_modules,$(_hcif_modules),HOST_CROSS) \ $(filter $(HOST_OUT)/%,$(call module-installed-files, $(_hif_modules))) \ @@ -1124,11 +1255,10 @@ ifdef FULL_BUILD # Strip :32 and :64 suffixes _modules := $(patsubst %:32,%,$(_modules)) _modules := $(patsubst %:64,%,$(_modules)) - # Sanity check all modules in PRODUCT_PACKAGES exist. We check for the + # Quickly check all modules in PRODUCT_PACKAGES exist. We check for the # existence if either <module> or the <module>_32 variant. - _nonexistent_modules := $(filter-out $(ALL_MODULES),$(_modules)) - _nonexistent_modules := $(foreach m,$(_nonexistent_modules),\ - $(if $(call get-32-bit-modules,$(m)),,$(m))) + _nonexistent_modules := $(foreach m,$(_modules), \ + $(if $(or $(ALL_MODULES.$(m).PATH),$(call get-modules-for-2nd-arch,TARGET,$(m))),,$(m))) $(call maybe-print-list-and-error,$(filter-out $(_allow_list),$(_nonexistent_modules)),\ $(INTERNAL_PRODUCT) includes non-existent modules in PRODUCT_PACKAGES) $(call maybe-print-list-and-error,$(filter-out $(_nonexistent_modules),$(_allow_list)),\ @@ -1151,17 +1281,19 @@ ifdef FULL_BUILD endif endif - # Some modules produce only host installed files when building with TARGET_BUILD_APPS - ifeq ($(TARGET_BUILD_APPS),) - _modules := $(foreach m,$(PRODUCT_PACKAGES) \ - $(PRODUCT_PACKAGES_DEBUG) \ - $(PRODUCT_PACKAGES_DEBUG_ASAN) \ - $(PRODUCT_PACKAGES_ENG) \ - $(PRODUCT_PACKAGES_TESTS),\ + # Modules may produce only host installed files in unbundled builds. + ifeq (,$(TARGET_BUILD_UNBUNDLED)) + _modules := $(call resolve-bitness-for-modules,TARGET, \ + $(PRODUCT_PACKAGES) \ + $(PRODUCT_PACKAGES_DEBUG) \ + $(PRODUCT_PACKAGES_DEBUG_ASAN) \ + $(PRODUCT_PACKAGES_ENG) \ + $(PRODUCT_PACKAGES_TESTS)) + _host_modules := $(foreach m,$(_modules), \ $(if $(ALL_MODULES.$(m).INSTALLED),\ $(if $(filter-out $(HOST_OUT_ROOT)/%,$(ALL_MODULES.$(m).INSTALLED)),,\ $(m)))) - $(call maybe-print-list-and-error,$(sort $(_modules)),\ + $(call maybe-print-list-and-error,$(sort $(_host_modules)),\ Host modules should be in PRODUCT_HOST_PACKAGES$(comma) not PRODUCT_PACKAGES) endif @@ -1276,6 +1408,10 @@ $(file >$(HOST_OUT)/.installable_test_files,$(sort \ test_files := endif +# Dedpulicate compatibility suite dist files across modules and packages before +# copying them to their requested locations. Assign the eval result to an unused +# var to prevent Make from trying to make a sense of it. +_unused := $(call copy-many-files, $(sort $(ALL_COMPATIBILITY_DIST_FILES))) # Don't include any GNU General Public License shared objects or static # libraries in SDK images. GPL executables (not static/dynamic libraries) @@ -1415,6 +1551,12 @@ systemextimage: $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) .PHONY: odmimage odmimage: $(INSTALLED_ODMIMAGE_TARGET) +.PHONY: vendor_dlkmimage +vendor_dlkmimage: $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) + +.PHONY: odm_dlkmimage +odm_dlkmimage: $(INSTALLED_ODM_DLKMIMAGE_TARGET) + .PHONY: systemotherimage systemotherimage: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) @@ -1433,8 +1575,11 @@ bootimage_test_harness: $(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET) .PHONY: vbmetaimage vbmetaimage: $(INSTALLED_VBMETAIMAGE_TARGET) -.PHONY: auxiliary -auxiliary: $(INSTALLED_AUX_TARGETS) +.PHONY: vbmetasystemimage +vbmetasystemimage: $(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET) + +.PHONY: vbmetavendorimage +vbmetavendorimage: $(INSTALLED_VBMETA_VENDORIMAGE_TARGET) # Build files and then package it into the rom formats .PHONY: droidcore @@ -1447,6 +1592,8 @@ droidcore: $(filter $(HOST_OUT_ROOT)/%,$(modules_to_install)) \ $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) \ $(INSTALLED_RECOVERYIMAGE_TARGET) \ $(INSTALLED_VBMETAIMAGE_TARGET) \ + $(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET) \ + $(INSTALLED_VBMETA_VENDORIMAGE_TARGET) \ $(INSTALLED_USERDATAIMAGE_TARGET) \ $(INSTALLED_CACHEIMAGE_TARGET) \ $(INSTALLED_BPTIMAGE_TARGET) \ @@ -1455,6 +1602,8 @@ droidcore: $(filter $(HOST_OUT_ROOT)/%,$(modules_to_install)) \ $(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) \ $(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET) \ $(INSTALLED_ODMIMAGE_TARGET) \ + $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) \ + $(INSTALLED_ODM_DLKMIMAGE_TARGET) \ $(INSTALLED_SUPERIMAGE_EMPTY_TARGET) \ $(INSTALLED_PRODUCTIMAGE_TARGET) \ $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \ @@ -1464,6 +1613,10 @@ droidcore: $(filter $(HOST_OUT_ROOT)/%,$(modules_to_install)) \ $(INSTALLED_FILES_JSON_VENDOR) \ $(INSTALLED_FILES_FILE_ODM) \ $(INSTALLED_FILES_JSON_ODM) \ + $(INSTALLED_FILES_FILE_VENDOR_DLKM) \ + $(INSTALLED_FILES_JSON_VENDOR_DLKM) \ + $(INSTALLED_FILES_FILE_ODM_DLKM) \ + $(INSTALLED_FILES_JSON_ODM_DLKM) \ $(INSTALLED_FILES_FILE_PRODUCT) \ $(INSTALLED_FILES_JSON_PRODUCT) \ $(INSTALLED_FILES_FILE_SYSTEM_EXT) \ @@ -1481,7 +1634,6 @@ droidcore: $(filter $(HOST_OUT_ROOT)/%,$(modules_to_install)) \ $(INSTALLED_FILES_FILE_RECOVERY) \ $(INSTALLED_FILES_JSON_RECOVERY) \ $(INSTALLED_ANDROID_INFO_TXT_TARGET) \ - auxiliary \ soong_docs # dist_files only for putting your library into the dist directory with a full build. @@ -1508,6 +1660,14 @@ ifneq ($(TARGET_BUILD_APPS),) $(if $(ALL_MODULES.$(m).BUNDLE),$(ALL_MODULES.$(m).BUNDLE):$(m)-base.zip)) $(call dist-for-goals,apps_only, $(apps_only_bundle_files)) + # Dist the lint reports if they exist. + apps_only_lint_report_files := $(foreach m,$(unbundled_build_modules),\ + $(foreach report,$(ALL_MODULES.$(m).LINT_REPORTS),\ + $(report):$(m)-$(notdir $(report)))) + .PHONY: lint-check + lint-check: $(foreach f, $(apps_only_lint_report_files), $(call word-colon,1,$(f))) + $(call dist-for-goals,lint-check, $(apps_only_lint_report_files)) + # For uninstallable modules such as static Java library, we have to dist the built file, # as <module_name>.<suffix> apps_only_dist_built_files := $(foreach m,$(unbundled_build_modules),$(if $(ALL_MODULES.$(m).INSTALLED),,\ @@ -1524,6 +1684,9 @@ ifneq ($(TARGET_BUILD_APPS),) $(PROGUARD_DICT_ZIP) : $(apps_only_installed_files) $(call dist-for-goals,apps_only, $(PROGUARD_DICT_ZIP)) + $(PROGUARD_USAGE_ZIP) : $(apps_only_installed_files) + $(call dist-for-goals,apps_only, $(PROGUARD_USAGE_ZIP)) + $(SYMBOLS_ZIP) : $(apps_only_installed_files) $(call dist-for-goals,apps_only, $(SYMBOLS_ZIP)) @@ -1543,7 +1706,7 @@ $(eval $(call combine-notice-files, html, \ $(apps_only_installed_files))) -else # TARGET_BUILD_APPS +else ifeq (,$(TARGET_BUILD_UNBUNDLED)) $(call dist-for-goals, droidcore, \ $(INTERNAL_UPDATE_PACKAGE_TARGET) \ $(INTERNAL_OTA_PACKAGE_TARGET) \ @@ -1552,6 +1715,7 @@ else # TARGET_BUILD_APPS $(BUILT_OTATOOLS_PACKAGE) \ $(SYMBOLS_ZIP) \ $(PROGUARD_DICT_ZIP) \ + $(PROGUARD_USAGE_ZIP) \ $(COVERAGE_ZIP) \ $(APPCOMPAT_ZIP) \ $(INSTALLED_FILES_FILE) \ @@ -1560,6 +1724,10 @@ else # TARGET_BUILD_APPS $(INSTALLED_FILES_JSON_VENDOR) \ $(INSTALLED_FILES_FILE_ODM) \ $(INSTALLED_FILES_JSON_ODM) \ + $(INSTALLED_FILES_FILE_VENDOR_DLKM) \ + $(INSTALLED_FILES_JSON_VENDOR_DLKM) \ + $(INSTALLED_FILES_FILE_ODM_DLKM) \ + $(INSTALLED_FILES_JSON_ODM_DLKM) \ $(INSTALLED_FILES_FILE_PRODUCT) \ $(INSTALLED_FILES_JSON_PRODUCT) \ $(INSTALLED_FILES_FILE_SYSTEM_EXT) \ @@ -1568,7 +1736,11 @@ else # TARGET_BUILD_APPS $(INSTALLED_FILES_JSON_SYSTEMOTHER) \ $(INSTALLED_FILES_FILE_RECOVERY) \ $(INSTALLED_FILES_JSON_RECOVERY) \ - $(INSTALLED_BUILD_PROP_TARGET) \ + $(INSTALLED_BUILD_PROP_TARGET):build.prop \ + $(INSTALLED_VENDOR_BUILD_PROP_TARGET):build.prop-vendor \ + $(INSTALLED_PRODUCT_BUILD_PROP_TARGET):build.prop-product \ + $(INSTALLED_ODM_BUILD_PROP_TARGET):build.prop-odm \ + $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET):build.prop-system_ext \ $(BUILT_TARGET_FILES_PACKAGE) \ $(INSTALLED_ANDROID_INFO_TXT_TARGET) \ $(INSTALLED_MISC_INFO_TARGET) \ @@ -1580,13 +1752,11 @@ else # TARGET_BUILD_APPS $(call dist-for-goals, droidcore, $(f))) ifneq ($(ANDROID_BUILD_EMBEDDED),true) - ifneq ($(TARGET_BUILD_PDK),true) $(call dist-for-goals, droidcore, \ $(APPS_ZIP) \ $(INTERNAL_EMULATOR_PACKAGE_TARGET) \ ) endif - endif $(call dist-for-goals, droidcore, \ $(INSTALLED_FILES_FILE_ROOT) \ @@ -1639,10 +1809,15 @@ else # TARGET_BUILD_APPS $(call dist-for-goals, dist_files, $(api_xmls)) api_xmls := + ifdef CLANG_COVERAGE + $(foreach f,$(SOONG_NDK_API_XML), \ + $(call dist-for-goals,droidcore,$(f):ndk_apis/$(notdir $(f)))) + endif + # Building a full system-- the default is to build droidcore droid_targets: droidcore dist_files -endif # TARGET_BUILD_APPS +endif # !TARGET_BUILD_UNBUNDLED .PHONY: docs docs: $(ALL_DOCS) @@ -1703,9 +1878,9 @@ modules: .PHONY: dump-files dump-files: - $(info product_target_FILES for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):) - $(foreach p,$(sort $(product_target_FILES)),$(info : $(p))) - @echo Successfully dumped product file list + @echo "Target files for $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) ($(INTERNAL_PRODUCT)):" + @echo $(sort $(patsubst $(PRODUCT_OUT)/%,%,$(filter $(PRODUCT_OUT)/%,$(modules_to_install)))) | tr -s ' ' '\n' + @echo Successfully dumped product target file list. .PHONY: nothing nothing: diff --git a/core/native_benchmark.mk b/core/native_benchmark.mk deleted file mode 100644 index 073d8dd2e2..0000000000 --- a/core/native_benchmark.mk +++ /dev/null @@ -1,15 +0,0 @@ -########################################### -## A thin wrapper around BUILD_EXECUTABLE -## Common flags for native benchmarks are added. -########################################### -$(call record-module-type,NATIVE_BENCHMARK) - -LOCAL_STATIC_LIBRARIES += libgoogle-benchmark - -ifndef LOCAL_MULTILIB -ifndef LOCAL_32_BIT_ONLY -LOCAL_MULTILIB := both -endif -endif - -include $(BUILD_EXECUTABLE) diff --git a/core/native_test_config_template.xml b/core/native_test_config_template.xml index ef1818f776..ea982cf2f9 100644 --- a/core/native_test_config_template.xml +++ b/core/native_test_config_template.xml @@ -22,11 +22,11 @@ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> <option name="cleanup" value="true" /> - <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" /> + <option name="push" value="{MODULE}->{TEST_INSTALL_BASE}/{MODULE}" /> </target_preparer> <test class="com.android.tradefed.testtype.GTest" > - <option name="native-test-device-path" value="/data/local/tmp" /> + <option name="native-test-device-path" value="{TEST_INSTALL_BASE}" /> <option name="module-name" value="{MODULE}" /> </test> </configuration> diff --git a/core/ninja_config.mk b/core/ninja_config.mk index 591937c0da..6fccacda29 100644 --- a/core/ninja_config.mk +++ b/core/ninja_config.mk @@ -15,7 +15,6 @@ PARSE_TIME_MAKE_GOALS := \ $(dont_bother_goals) \ all \ ECLIPSE-% \ - AUX-% \ brillo_tests \ btnod \ build-art% \ @@ -25,25 +24,17 @@ PARSE_TIME_MAKE_GOALS := \ continuous_native_tests \ cts \ custom_images \ - deps-license \ dicttool_aosp \ dump-products \ eng \ - fusion \ oem_image \ online-system-api-sdk-docs \ - pdk \ - platform \ - platform-java \ product-graph \ samplecode \ sdk \ sdk_addon \ sdk_repo \ - snod \ stnod \ - systemimage-nodeps \ - target-files-package \ test-art% \ user \ userdataimage \ diff --git a/core/notice_files.mk b/core/notice_files.mk index 22f8e41844..721a03411f 100644 --- a/core/notice_files.mk +++ b/core/notice_files.mk @@ -6,7 +6,7 @@ $(call record-module-type,NOTICE_FILE) ifneq ($(LOCAL_NOTICE_FILE),) notice_file:=$(strip $(LOCAL_NOTICE_FILE)) else -notice_file:=$(strip $(wildcard $(LOCAL_PATH)/NOTICE)) +notice_file:=$(strip $(wildcard $(LOCAL_PATH)/LICENSE $(LOCAL_PATH)/LICENCE $(LOCAL_PATH)/NOTICE)) endif ifeq ($(LOCAL_MODULE_CLASS),GYP) @@ -105,7 +105,7 @@ $(installed_notice_file): PRIVATE_INSTALLED_MODULE := $(module_installed_filenam $(installed_notice_file): $(notice_file) @echo Notice file: $< -- $@ $(hide) mkdir -p $(dir $@) - $(hide) cat $< > $@ + $(hide) awk 'FNR==1 && NR > 1 {print "\n"} {print}' $^ > $@ ifdef LOCAL_INSTALLED_MODULE # Make LOCAL_INSTALLED_MODULE depend on NOTICE files if they exist diff --git a/core/package.mk b/core/package.mk index 6bde48553d..591f7aafdb 100644 --- a/core/package.mk +++ b/core/package.mk @@ -41,15 +41,7 @@ else endif LOCAL_NO_2ND_ARCH_MODULE_SUFFIX := true - -# if TARGET_PREFER_32_BIT_APPS is set, try to build 32-bit first -ifdef TARGET_2ND_ARCH -ifeq ($(TARGET_PREFER_32_BIT_APPS),true) -LOCAL_2ND_ARCH_VAR_PREFIX := $(TARGET_2ND_ARCH_VAR_PREFIX) -else LOCAL_2ND_ARCH_VAR_PREFIX := -endif -endif # check if preferred arch is supported include $(BUILD_SYSTEM)/module_arch_supported.mk @@ -57,13 +49,7 @@ ifeq ($(my_module_arch_supported),true) # first arch is supported include $(BUILD_SYSTEM)/package_internal.mk else ifneq (,$(TARGET_2ND_ARCH)) -# check if the non-preferred arch is the primary or secondary -ifeq ($(TARGET_PREFER_32_BIT_APPS),true) -LOCAL_2ND_ARCH_VAR_PREFIX := -else LOCAL_2ND_ARCH_VAR_PREFIX := $(TARGET_2ND_ARCH_VAR_PREFIX) -endif - # check if non-preferred arch is supported include $(BUILD_SYSTEM)/module_arch_supported.mk ifeq ($(my_module_arch_supported),true) diff --git a/core/package_internal.mk b/core/package_internal.mk index 692ff49fcc..a97e401b52 100644 --- a/core/package_internal.mk +++ b/core/package_internal.mk @@ -377,9 +377,11 @@ ifeq ($(need_compile_res),true) # they want to use this module's R.java file. $(LOCAL_BUILT_MODULE): $(R_file_stamp) +ifneq ($(full_classes_jar),) # The R.java file must exist by the time the java source # list is generated $(java_source_list_file): $(R_file_stamp) +endif endif # need_compile_res @@ -399,7 +401,7 @@ ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true) # resources. ifeq ($(LOCAL_SDK_RES_VERSION),core_current) # core_current doesn't contain any framework resources. -else ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS_USE_PREBUILT_SDK),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),) +else ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_USE_PREBUILT_SDKS),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),) # for released sdk versions, the platform resources were built into android.jar. framework_res_package_export := \ $(call resolve-prebuilt-sdk-jar-path,$(LOCAL_SDK_RES_VERSION)) @@ -527,7 +529,7 @@ endif # We skip it for unbundled app builds where we cannot build veridex. module_run_appcompat := ifeq (true,$(non_system_module)) -ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK))) # ! unbundled app build +ifeq (,$(TARGET_BUILD_APPS)) # ! unbundled app build ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true) module_run_appcompat := true endif @@ -627,7 +629,7 @@ $(my_bundle_module): $(MERGE_ZIPS) $(SOONG_ZIP) $(ZIP2ZIP) endif # full_classes_jar $(MERGE_ZIPS) $@ $@.parts/*.zip rm -rf $@.parts -ALL_MODULES.$(LOCAL_MODULE).BUNDLE := $(my_bundle_module) +ALL_MODULES.$(my_register_name).BUNDLE := $(my_bundle_module) ifdef TARGET_BUILD_APPS ifdef LOCAL_DPI_VARIANTS diff --git a/core/pathmap.mk b/core/pathmap.mk index af33f5de35..dacbe2195d 100644 --- a/core/pathmap.mk +++ b/core/pathmap.mk @@ -40,7 +40,6 @@ pathmap_INCL := \ libhardware:hardware/libhardware/include \ libhardware_legacy:hardware/libhardware_legacy/include \ libril:hardware/ril/include \ - recovery:bootable/recovery \ system-core:system/core/include \ audio:system/media/audio/include \ audio-effects:system/media/audio_effects/include \ diff --git a/core/pdk_config.mk b/core/pdk_config.mk deleted file mode 100644 index 922e0ef2d6..0000000000 --- a/core/pdk_config.mk +++ /dev/null @@ -1,190 +0,0 @@ -# This file defines the rule to fuse the platform.zip into the current PDK build. -PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR := -PDK_PLATFORM_JAVA_ZIP_JAVA_HOST_LIB_DIR := \ - host/common/obj/JAVA_LIBRARIES/bouncycastle-host_intermediates \ - host/common/obj/JAVA_LIBRARIES/compatibility-host-util_intermediates \ - host/common/obj/JAVA_LIBRARIES/cts-tradefed-harness_intermediates \ - host/common/obj/JAVA_LIBRARIES/hosttestlib_intermediates -PDK_PLATFORM_JAVA_ZIP_CONTENTS := - -ifneq (,$(filter platform-java, $(MAKECMDGOALS))$(PDK_FUSION_PLATFORM_ZIP)$(PDK_FUSION_PLATFORM_DIR)) -# additional items to add to platform.zip for platform-java build -# For these dirs, add classes.jar and javalib.jar from the dir to platform.zip -# all paths under out dir -PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR += \ - target/common/obj/JAVA_LIBRARIES/android.test.runner_intermediates \ - target/common/obj/JAVA_LIBRARIES/android-common_intermediates \ - target/common/obj/JAVA_LIBRARIES/android-ex-camera2_intermediates \ - target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates \ - target/common/obj/JAVA_LIBRARIES/bouncycastle_intermediates \ - target/common/obj/JAVA_LIBRARIES/conscrypt_intermediates \ - target/common/obj/JAVA_LIBRARIES/core-oj_intermediates \ - target/common/obj/JAVA_LIBRARIES/core-libart_intermediates \ - target/common/obj/JAVA_LIBRARIES/core-icu4j_intermediates \ - target/common/obj/JAVA_LIBRARIES/ext_intermediates \ - target/common/obj/JAVA_LIBRARIES/framework-minus-apex_intermediates \ - target/common/obj/JAVA_LIBRARIES/hwbinder_intermediates \ - target/common/obj/JAVA_LIBRARIES/ims-common_intermediates \ - target/common/obj/JAVA_LIBRARIES/okhttp_intermediates \ - target/common/obj/JAVA_LIBRARIES/telephony-common_intermediates \ - target/common/obj/JAVA_LIBRARIES/voip-common_intermediates \ - -# not java libraries -PDK_PLATFORM_JAVA_ZIP_CONTENTS += \ - target/common/obj/APPS/framework-res_intermediates/package-export.apk \ - target/common/obj/APPS/framework-res_intermediates/src/R.stamp -endif # platform-java or FUSION build - -PDK_PLATFORM_JAVA_ZIP_JAVA_LIB_DIR := \ - $(PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR) \ - $(PDK_PLATFORM_JAVA_ZIP_JAVA_HOST_LIB_DIR) - -PDK_PLATFORM_JAVA_ZIP_CONTENTS += $(foreach lib_dir,$(PDK_PLATFORM_JAVA_ZIP_JAVA_LIB_DIR),\ - $(lib_dir)/classes.jar $(lib_dir)/classes-header.jar \ - $(lib_dir)/javalib.jar $(lib_dir)/classes*.dex \ - $(lib_dir)/classes.dex.toc ) - -# check and override java support level -ifneq ($(TARGET_BUILD_PDK)$(PDK_FUSION_PLATFORM_ZIP)$(PDK_FUSION_PLATFORM_DIR),) - ifneq ($(wildcard external/proguard),) - TARGET_BUILD_JAVA_SUPPORT_LEVEL := sdk - else # no proguard - TARGET_BUILD_JAVA_SUPPORT_LEVEL := - endif - # platform support is set after checking platform.zip -endif # PDK - -ifneq (,$(PDK_FUSION_PLATFORM_DIR)$(PDK_FUSION_PLATFORM_ZIP)) - -_pdk_fusion_intermediates := -_pdk_fusion_stamp := -_pdk_fusion_file_list := -_pdk_fusion_java_file_list := -PDK_FUSION_SYMLINK_STAMP := - -ifdef PDK_FUSION_PLATFORM_DIR - _pdk_fusion_intermediates := $(PDK_FUSION_PLATFORM_DIR) - _pdk_fusion_file_list := $(sort \ - $(shell cd $(PDK_FUSION_PLATFORM_DIR); find * -type f)) - _pdk_fusion_java_file_list := $(filter target/common/%,$(_pdk_fusion_file_list)) - _pdk_fusion_file_list := $(filter-out target/common/%,$(_pdk_fusion_file_list)) - - PDK_FUSION_SYMLINK_STAMP := $(call intermediates-dir-for, PACKAGING, pdk_fusion)/pdk_symlinks.stamp - - symlink_list := $(sort \ - $(shell cd $(PDK_FUSION_PLATFORM_DIR); find * -type l)) -$(PDK_FUSION_SYMLINK_STAMP): PRIVATE_SYMLINKS := $(foreach s,$(symlink_list),\ - $(s):$(shell readlink $(PDK_FUSION_PLATFORM_DIR)/$(s))) -$(PDK_FUSION_SYMLINK_STAMP): - $(foreach s,$(PRIVATE_SYMLINKS),\ - mkdir -p $(PRODUCT_OUT)/$(dir $(call word-colon,1,$(s))) && \ - ln -sf $(call word-colon,2,$(s)) $(PRODUCT_OUT)/$(call word-colon,1,$(s)) &&) true - touch $@ - - symlink_list := -endif # PDK_FUSION_PLATFORM_DIR - -ifdef PDK_FUSION_PLATFORM_ZIP - _pdk_fusion_intermediates := $(call intermediates-dir-for, PACKAGING, pdk_fusion) - _pdk_fusion_stamp := $(_pdk_fusion_intermediates)/pdk_fusion.stamp - - _pdk_fusion_file_list := $(shell unzip -Z -1 $(PDK_FUSION_PLATFORM_ZIP) \ - '*[^/]' -x 'target/common/*' 2>/dev/null) - _pdk_fusion_java_file_list := \ - $(shell unzip -Z -1 $(PDK_FUSION_PLATFORM_ZIP) 'target/common/*' 2>/dev/null) - _pdk_fusion_files := $(addprefix $(_pdk_fusion_intermediates)/,\ - $(_pdk_fusion_file_list) $(_pdk_fusion_java_file_list)) - -$(_pdk_fusion_stamp) : $(PDK_FUSION_PLATFORM_ZIP) - @echo "Unzip $(dir $@) <- $<" - $(hide) rm -rf $(dir $@) && mkdir -p $(dir $@) - $(hide) unzip -qo $< -d $(dir $@) - $(call split-long-arguments,-touch,$(_pdk_fusion_files)) - $(hide) touch $@ - -$(_pdk_fusion_files) : $(_pdk_fusion_stamp) -endif # PDK_FUSION_PLATFORM_ZIP - -ifneq ($(_pdk_fusion_java_file_list),) - # This represents whether java build can use platform API or not - # This should not be used in Android.mk - TARGET_BUILD_PDK_JAVA_PLATFORM := true - ifneq ($(TARGET_BUILD_JAVA_SUPPORT_LEVEL),) - TARGET_BUILD_JAVA_SUPPORT_LEVEL := platform - endif -endif - -# Implicit pattern rules to copy the fusion files to the system image directory. -# Note that if there is already explicit rule in the build system to generate a file, -# the pattern rule will be just ignored by make. -# That's desired by us: we want only absent files from the platform zip package. -# Copy with the last-modified time preserved, never follow symbolic links. -$(PRODUCT_OUT)/% : $(_pdk_fusion_intermediates)/% $(_pdk_fusion_stamp) - @mkdir -p $(dir $@) - $(hide) rm -rf $@ - $(hide) cp -fpPR $< $@ - -# implicit rules for host java files -$(HOST_COMMON_OUT_ROOT)/% : $(_pdk_fusion_intermediates)/host/common/% $(_pdk_fusion_stamp) - @mkdir -p $(dir $@) - $(hide) cp -fpPR $< $@ - -ifeq (true,$(TARGET_BUILD_PDK_JAVA_PLATFORM)) - PDK_FUSION_OUT_DIR := $(OUT_DIR) - - define JAVA_dependency_template - $(call add-dependency,$(PDK_FUSION_OUT_DIR)/$(strip $(1)),\ - $(foreach d,$(filter $(2),$(_pdk_fusion_java_file_list)),$(PDK_FUSION_OUT_DIR)/$(d))) - endef - - # needs explicit dependency as package-export.apk is not explicitly pulled - $(eval $(call JAVA_dependency_template,\ - target/common/obj/APPS/framework-res_intermediates/src/R.stamp,\ - target/common/obj/APPS/framework-res_intermediates/package-export.apk)) - - # javalib.jar should pull classes.jar as classes.jar is not explicitly pulled. - $(foreach lib_dir,$(PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR),\ - $(eval $(call JAVA_dependency_template,$(lib_dir)/javalib.jar,\ - $(lib_dir)/classes.jar))) - -# implicit rules for all other target files -$(TARGET_COMMON_OUT_ROOT)/% : $(_pdk_fusion_intermediates)/target/common/% $(_pdk_fusion_stamp) - @mkdir -p $(dir $@) - $(hide) cp -fpPR $< $@ -endif # TARGET_BUILD_PDK_JAVA_PLATFORM - -ALL_PDK_FUSION_FILES := $(addprefix $(PRODUCT_OUT)/, $(_pdk_fusion_file_list)) - -endif # PDK_FUSION_PLATFORM_ZIP || PDK_FUSION_PLATFORM_DIR - -ifeq ($(TARGET_BUILD_PDK),true) - $(info PDK TARGET_BUILD_JAVA_SUPPORT_LEVEL $(TARGET_BUILD_JAVA_SUPPORT_LEVEL)) - ifeq ($(TARGET_BUILD_PDK_JAVA_PLATFORM),) - # SDK used for Java build under PDK - PDK_BUILD_SDK_VERSION := $(lastword $(TARGET_AVAILABLE_SDK_VERSIONS)) - $(info PDK Build uses SDK $(PDK_BUILD_SDK_VERSION)) - else # PDK_JAVA - $(info PDK Build uses the current platform API) - endif # PDK_JAVA -endif # BUILD_PDK - -ifneq (,$(filter platform platform-java, $(MAKECMDGOALS))$(filter true,$(TARGET_BUILD_PDK))) - # files under $(PRODUCT_OUT)/symbols to help debugging. - # Source not included to PDK due to dependency issue, so provide symbols instead. - - PDK_SYMBOL_FILES_LIST := - ifeq ($(TARGET_IS_64_BIT),true) - PDK_SYMBOL_FILES_LIST += system/bin/app_process64 - ifdef TARGET_2ND_ARCH - PDK_SYMBOL_FILES_LIST += system/bin/app_process32 - endif - else - PDK_SYMBOL_FILES_LIST += system/bin/app_process32 - endif - - ifneq (,$(PDK_FUSION_PLATFORM_ZIP)$(PDK_FUSION_PLATFORM_DIR)) - # symbols should be explicitly pulled for fusion build - $(foreach f,$(filter $(PDK_SYMBOL_FILES_LIST), $(_pdk_fusion_file_list)),\ - $(eval $(call add-dependency,$(PRODUCT_OUT)/$(f),$(PRODUCT_OUT)/symbols/$(f)))) - endif # PLATFORM_ZIP || PLATFORM_DIR -endif # platform.zip/dir build or PDK diff --git a/core/pdk_fusion_modules.mk b/core/pdk_fusion_modules.mk deleted file mode 100644 index 235acf9378..0000000000 --- a/core/pdk_fusion_modules.mk +++ /dev/null @@ -1,86 +0,0 @@ -# Auto-generate module defitions from platform.zip. -# We use these rules to rebuild .odex files of the .jar/.apk inside the platform.zip. -# - -ifdef PDK_FUSION_PLATFORM_ZIP -pdk_dexpreopt_config_mk := $(TARGET_OUT_INTERMEDIATES)/pdk_dexpreopt_config.mk - -$(shell rm -f $(pdk_dexpreopt_config_mk) && mkdir -p $(dir $(pdk_dexpreopt_config_mk)) && \ - unzip -qo $(PDK_FUSION_PLATFORM_ZIP) -d $(dir $(pdk_dexpreopt_config_mk)) pdk_dexpreopt_config.mk 2>/dev/null) -endif - -ifdef PDK_FUSION_PLATFORM_DIR -pdk_dexpreopt_config_mk := $(PDK_FUSION_PLATFORM_DIR)/pdk_dexpreopt_config.mk -endif - --include $(pdk_dexpreopt_config_mk) - -# Define a PDK prebuilt module that comes from platform.zip. -# Must be called with $(eval) -define prebuilt-pdk-java-module -include $(CLEAR_VARS) -LOCAL_MODULE:=$(1) -LOCAL_MODULE_CLASS:=$(2) -# Use LOCAL_PREBUILT_MODULE_FILE instead of LOCAL_SRC_FILES so we don't need to deal with LOCAL_PATH. -LOCAL_PREBUILT_MODULE_FILE:=$(3) -LOCAL_DEX_PREOPT:=$(4) -LOCAL_MULTILIB:=$(5) -LOCAL_DEX_PREOPT_FLAGS:=$(6) -LOCAL_BUILT_MODULE_STEM:=$(7) -LOCAL_MODULE_SUFFIX:=$(suffix $(7)) -LOCAL_PRIVILEGED_MODULE:=$(8) -LOCAL_VENDOR_MODULE:=$(9) -LOCAL_MODULE_TARGET_ARCH:=$(10) -LOCAL_REPLACE_PREBUILT_APK_INSTALLED:=$(11) -LOCAL_CERTIFICATE:=PRESIGNED -include $(BUILD_PREBUILT) - -# The source prebuilts are extracted in the rule of _pdk_fusion_stamp. -# Use a touch rule to establish the dependency. -ifndef PDK_FUSION_PLATFORM_DIR -$(3) $(11) : $(_pdk_fusion_stamp) - $(hide) if [ ! -f $$@ ]; then \ - echo 'Error: $$@ does not exist. Check your platform.zip.' 1>&2; \ - exit 1; \ - fi - $(hide) touch $$@ -endif -endef - -# We don't have a LOCAL_PATH for the auto-generated modules, so let it be the $(BUILD_SYSTEM). -LOCAL_PATH := $(BUILD_SYSTEM) - -##### Java libraries. -# Only set up rules for modules that aren't built from source. -pdk_prebuilt_libraries := $(foreach l,$(PDK.DEXPREOPT.JAVA_LIBRARIES),\ - $(if $(MODULE.TARGET.JAVA_LIBRARIES.$(l)),,$(l))) - -$(foreach l,$(pdk_prebuilt_libraries), $(eval \ - $(call prebuilt-pdk-java-module,\ - $(l),\ - JAVA_LIBRARIES,\ - $(_pdk_fusion_intermediates)/$(PDK.DEXPREOPT.$(l).SRC),\ - $(PDK.DEXPREOPT.$(l).DEX_PREOPT),\ - $(PDK.DEXPREOPT.$(l).MULTILIB),\ - $(PDK.DEXPREOPT.$(l).DEX_PREOPT_FLAGS),\ - javalib.jar,\ - ))) - -###### Apps. -pdk_prebuilt_apps := $(foreach a,$(PDK.DEXPREOPT.APPS),\ - $(if $(MODULE.TARGET.APPS.$(a)),,$(a))) - -$(foreach a,$(pdk_prebuilt_apps), $(eval \ - $(call prebuilt-pdk-java-module,\ - $(a),\ - APPS,\ - $(_pdk_fusion_intermediates)/$(PDK.DEXPREOPT.$(a).SRC),\ - $(PDK.DEXPREOPT.$(a).DEX_PREOPT),\ - $(PDK.DEXPREOPT.$(a).MULTILIB),\ - $(PDK.DEXPREOPT.$(a).DEX_PREOPT_FLAGS),\ - package.apk,\ - $(PDK.DEXPREOPT.$(a).PRIVILEGED_MODULE),\ - $(PDK.DEXPREOPT.$(a).VENDOR_MODULE),\ - $(PDK.DEXPREOPT.$(a).TARGET_ARCH),\ - $(_pdk_fusion_intermediates)/$(PDK.DEXPREOPT.$(a).STRIPPED_SRC),\ - ))) diff --git a/core/product.mk b/core/product.mk index f8ba5936f8..624501ea85 100644 --- a/core/product.mk +++ b/core/product.mk @@ -145,25 +145,27 @@ _product_single_value_vars += \ PRODUCT_SYSTEM_BRAND \ PRODUCT_SYSTEM_MANUFACTURER \ -# A list of property assignments, like "key = value", with zero or more -# whitespace characters on either side of the '='. +# PRODUCT_<PARTITION>_PROPERTIES are lists of property assignments +# that go to <partition>/build.prop. Each property assignment is +# "key = value" with zero or more whitespace characters on either +# side of the '='. +_product_list_vars += \ + PRODUCT_SYSTEM_PROPERTIES \ + PRODUCT_SYSTEM_EXT_PROPERTIES \ + PRODUCT_VENDOR_PROPERTIES \ + PRODUCT_ODM_PROPERTIES \ + PRODUCT_PRODUCT_PROPERTIES + +# TODO(b/117892318) deprecate these: +# ... in favor or PRODUCT_SYSTEM_PROPERTIES +_product_list_vars += PRODUCT_SYSTEM_DEFAULT_PROPERTIES +# ... in favor of PRODUCT_VENDOR_PROPERTIES _product_list_vars += PRODUCT_PROPERTY_OVERRIDES - -# A list of property assignments, like "key = value", with zero or more -# whitespace characters on either side of the '='. -# used for adding properties to default.prop _product_list_vars += PRODUCT_DEFAULT_PROPERTY_OVERRIDES -# A list of property assignments, like "key = value", with zero or more -# whitespace characters on either side of the '='. -# used for adding properties to build.prop of product partition -_product_list_vars += PRODUCT_PRODUCT_PROPERTIES - -# A list of property assignments, like "key = value", with zero or more -# whitespace characters on either side of the '='. -# used for adding properties to build.prop of system_ext and odm partitions -_product_list_vars += PRODUCT_SYSTEM_EXT_PROPERTIES -_product_list_vars += PRODUCT_ODM_PROPERTIES +# TODO(b/117892318) consider deprecating these too +_product_list_vars += PRODUCT_SYSTEM_PROPERTY_BLACKLIST +_product_list_vars += PRODUCT_VENDOR_PROPERTY_BLACKLIST # The characteristics of the product, which among other things is passed to aapt _product_single_value_vars += PRODUCT_CHARACTERISTICS @@ -226,19 +228,12 @@ _product_list_vars += PRODUCT_SUPPORTS_BOOT_SIGNER _product_list_vars += PRODUCT_SUPPORTS_VBOOT _product_list_vars += PRODUCT_SUPPORTS_VERITY _product_list_vars += PRODUCT_SUPPORTS_VERITY_FEC -_product_list_vars += PRODUCT_OEM_PROPERTIES - -# A list of property assignments, like "key = value", with zero or more -# whitespace characters on either side of the '='. -# used for adding properties to default.prop of system partition -_product_list_vars += PRODUCT_SYSTEM_DEFAULT_PROPERTIES - -_product_list_vars += PRODUCT_SYSTEM_PROPERTY_BLACKLIST -_product_list_vars += PRODUCT_VENDOR_PROPERTY_BLACKLIST _product_list_vars += PRODUCT_SYSTEM_SERVER_APPS _product_list_vars += PRODUCT_SYSTEM_SERVER_JARS # List of system_server jars delivered via apex. Format = <apex name>:<jar name>. _product_list_vars += PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS +# If true, then suboptimal order of system server jars does not cause an error. +_product_list_vars += PRODUCT_BROKEN_SUBOPTIMAL_ORDER_OF_SYSTEM_SERVER_JARS # Additional system server jars to be appended at the end of the common list. # This is necessary to avoid jars reordering due to makefile inheritance order. @@ -256,6 +251,8 @@ _product_single_value_vars += PRODUCT_VENDOR_VERITY_PARTITION _product_single_value_vars += PRODUCT_PRODUCT_VERITY_PARTITION _product_single_value_vars += PRODUCT_SYSTEM_EXT_VERITY_PARTITION _product_single_value_vars += PRODUCT_ODM_VERITY_PARTITION +_product_single_value_vars += PRODUCT_VENDOR_DLKM_VERITY_PARTITION +_product_single_value_vars += PRODUCT_ODM_DLKM_VERITY_PARTITION _product_single_value_vars += PRODUCT_SYSTEM_SERVER_DEBUG_INFO _product_single_value_vars += PRODUCT_OTHER_JAVA_DEBUG_INFO @@ -283,6 +280,8 @@ _product_single_value_vars += PRODUCT_VENDOR_BASE_FS_PATH _product_single_value_vars += PRODUCT_PRODUCT_BASE_FS_PATH _product_single_value_vars += PRODUCT_SYSTEM_EXT_BASE_FS_PATH _product_single_value_vars += PRODUCT_ODM_BASE_FS_PATH +_product_single_value_vars += PRODUCT_VENDOR_DLKM_BASE_FS_PATH +_product_single_value_vars += PRODUCT_ODM_DLKM_BASE_FS_PATH # The first API level this product shipped with _product_single_value_vars += PRODUCT_SHIPPING_API_LEVEL @@ -324,7 +323,7 @@ _product_list_vars += PRODUCT_EXTRA_VNDK_VERSIONS # VNDK version of product partition. It can be 'current' if the product # partitions uses PLATFORM_VNDK_VERSION. -_product_single_value_var += PRODUCT_PRODUCT_VNDK_VERSION +_product_single_value_vars += PRODUCT_PRODUCT_VNDK_VERSION # Whether the list of allowed of actionable compatible properties should be disabled or not _product_single_value_vars += PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE @@ -374,6 +373,8 @@ _product_single_value_vars += PRODUCT_BUILD_VENDOR_IMAGE _product_single_value_vars += PRODUCT_BUILD_PRODUCT_IMAGE _product_single_value_vars += PRODUCT_BUILD_SYSTEM_EXT_IMAGE _product_single_value_vars += PRODUCT_BUILD_ODM_IMAGE +_product_single_value_vars += PRODUCT_BUILD_VENDOR_DLKM_IMAGE +_product_single_value_vars += PRODUCT_BUILD_ODM_DLKM_IMAGE _product_single_value_vars += PRODUCT_BUILD_CACHE_IMAGE _product_single_value_vars += PRODUCT_BUILD_RAMDISK_IMAGE _product_single_value_vars += PRODUCT_BUILD_USERDATA_IMAGE diff --git a/core/product_config.mk b/core/product_config.mk index a16af05cf4..6170b5b77a 100644 --- a/core/product_config.mk +++ b/core/product_config.mk @@ -166,7 +166,7 @@ $(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\ $(if $(filter-out $(makefile),$(PRODUCTS)),$(eval $(call import-products,$(makefile))))\ ) -# Sanity check +# Quick check $(check-all-products) ifneq ($(filter dump-products, $(MAKECMDGOALS)),) @@ -201,7 +201,7 @@ endif # EMMA_INSTRUMENT $(call strip-product-vars) ############################################################################# -# Sanity check and assign default values +# Quick check and assign default values TARGET_DEVICE := $(PRODUCT_DEVICE) @@ -231,6 +231,10 @@ PRODUCT_AAPT_CONFIG := $(subst $(space),$(comma),$(PRODUCT_AAPT_CONFIG)) # Extra boot jars must be appended at the end after common boot jars. PRODUCT_BOOT_JARS += $(PRODUCT_BOOT_JARS_EXTRA) +# Add 'platform:' prefix to unqualified boot jars +PRODUCT_BOOT_JARS := $(foreach pair,$(PRODUCT_BOOT_JARS), \ + $(if $(findstring :,$(pair)),,platform:)$(pair)) + # The extra system server jars must be appended at the end after common system server jars. PRODUCT_SYSTEM_SERVER_JARS += $(PRODUCT_SYSTEM_SERVER_JARS_EXTRA) @@ -271,11 +275,9 @@ ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE endif $(foreach pair,$(PRODUCT_UPDATABLE_BOOT_JARS), \ - $(if $(findstring $(call word-colon,2,$(pair)),$(PRODUCT_BOOT_JARS)), \ - $(error A jar in PRODUCT_UPDATABLE_BOOT_JARS must not be in PRODUCT_BOOT_JARS, \ - but $(call word-colon,2,$(pair)) is) \ - ) \ -) + $(eval jar := $(call word-colon,2,$(pair))) \ + $(if $(findstring $(jar), $(PRODUCT_BOOT_JARS)), \ + $(error A jar in PRODUCT_UPDATABLE_BOOT_JARS must not be in PRODUCT_BOOT_JARS, but $(jar) is))) ENFORCE_SYSTEM_CERTIFICATE := $(PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT) ENFORCE_SYSTEM_CERTIFICATE_ALLOW_LIST := $(PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_ALLOW_LIST) @@ -356,6 +358,12 @@ endif $(KATI_obsolete_var OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS \ ,Use PRODUCT_EXTRA_VNDK_VERSIONS instead) +# If build command defines OVERRIDE_PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE, +# override PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE with it unless it is +# defined as `false`. If the value is `false` clear +# PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE +# OVERRIDE_PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE can be used for +# testing only. ifdef OVERRIDE_PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE ifeq (false,$(OVERRIDE_PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE)) PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := @@ -365,11 +373,35 @@ ifdef OVERRIDE_PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE else ifeq ($(PRODUCT_SHIPPING_API_LEVEL),) # No shipping level defined else ifeq ($(call math_gt,$(PRODUCT_SHIPPING_API_LEVEL),29),true) + # Enforce product interface if PRODUCT_SHIPPING_API_LEVEL is greater than 29. PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true endif $(KATI_obsolete_var OVERRIDE_PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE,Use PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE instead) +# If build command defines PRODUCT_USE_PRODUCT_VNDK_OVERRIDE as `false`, +# PRODUCT_PRODUCT_VNDK_VERSION will not be defined automatically. +# PRODUCT_USE_PRODUCT_VNDK_OVERRIDE can be used for testing only. +PRODUCT_USE_PRODUCT_VNDK := false +ifneq ($(PRODUCT_USE_PRODUCT_VNDK_OVERRIDE),) + PRODUCT_USE_PRODUCT_VNDK := $(PRODUCT_USE_PRODUCT_VNDK_OVERRIDE) +else ifeq ($(PRODUCT_SHIPPING_API_LEVEL),) + # No shipping level defined +else ifeq ($(call math_gt,$(PRODUCT_SHIPPING_API_LEVEL),29),true) + # Enforce product interface for VNDK if PRODUCT_SHIPPING_API_LEVEL is greater + # than 29. + PRODUCT_USE_PRODUCT_VNDK := true +endif + +ifeq ($(PRODUCT_USE_PRODUCT_VNDK),true) + ifndef PRODUCT_PRODUCT_VNDK_VERSION + PRODUCT_PRODUCT_VNDK_VERSION := current + endif +endif + +$(KATI_obsolete_var PRODUCT_USE_PRODUCT_VNDK,Use PRODUCT_PRODUCT_VNDK_VERSION instead) +$(KATI_obsolete_var PRODUCT_USE_PRODUCT_VNDK_OVERRIDE,Use PRODUCT_PRODUCT_VNDK_VERSION instead) + define product-overrides-config $$(foreach rule,$$(PRODUCT_$(1)_OVERRIDES),\ $$(if $$(filter 2,$$(words $$(subst :,$$(space),$$(rule)))),,\ @@ -397,6 +429,8 @@ $(foreach image, \ PRODUCT \ SYSTEM_EXT \ ODM \ + VENDOR_DLKM \ + ODM_DLKM \ CACHE \ RAMDISK \ USERDATA \ diff --git a/core/rbe.mk b/core/rbe.mk index 019ac04efd..91606d4004 100644 --- a/core/rbe.mk +++ b/core/rbe.mk @@ -19,39 +19,45 @@ ifneq ($(filter-out false,$(USE_RBE)),) ifdef RBE_DIR rbe_dir := $(RBE_DIR) else - rbe_dir := $(HOME)/rbe + rbe_dir := prebuilts/remoteexecution-client/live/ endif ifdef RBE_CXX_EXEC_STRATEGY cxx_rbe_exec_strategy := $(RBE_CXX_EXEC_STRATEGY) else - cxx_rbe_exec_strategy := "local" + cxx_rbe_exec_strategy := local + endif + + ifdef RBE_CXX_COMPARE + cxx_compare := $(RBE_CXX_COMPARE) + else + cxx_compare := false endif ifdef RBE_JAVAC_EXEC_STRATEGY javac_exec_strategy := $(RBE_JAVAC_EXEC_STRATEGY) else - javac_exec_strategy := "local" + javac_exec_strategy := remote_local_fallback endif ifdef RBE_R8_EXEC_STRATEGY r8_exec_strategy := $(RBE_R8_EXEC_STRATEGY) else - r8_exec_strategy := "local" + r8_exec_strategy := remote_local_fallback endif ifdef RBE_D8_EXEC_STRATEGY d8_exec_strategy := $(RBE_D8_EXEC_STRATEGY) else - d8_exec_strategy := "local" + d8_exec_strategy := remote_local_fallback endif - platform := "container-image=docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62" - cxx_platform := $(platform)",Pool=default" - java_r8_d8_platform := $(platform)",Pool=java16" + platform := container-image=docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62 + cxx_platform := $(platform),Pool=default + java_r8_d8_platform := $(platform),Pool=java16 RBE_WRAPPER := $(rbe_dir)/rewrapper - RBE_CXX := --labels=type=compile,lang=cpp,compiler=clang --env_var_whitelist=PWD --exec_strategy=$(cxx_rbe_exec_strategy) --platform="$(cxx_platform)" + RBE_CXX := --labels=type=compile,lang=cpp,compiler=clang --env_var_allowlist=PWD --exec_strategy=$(cxx_rbe_exec_strategy) --platform=$(cxx_platform) --compare=$(cxx_compare) # Append rewrapper to existing *_WRAPPER variables so it's possible to # use both ccache and rewrapper. @@ -59,15 +65,15 @@ ifneq ($(filter-out false,$(USE_RBE)),) CXX_WRAPPER := $(strip $(CXX_WRAPPER) $(RBE_WRAPPER) $(RBE_CXX)) ifdef RBE_JAVAC - JAVAC_WRAPPER := $(strip $(JAVAC_WRAPPER) $(RBE_WRAPPER) --labels=type=compile,lang=java,compiler=javac --exec_strategy=$(javac_exec_strategy) --platform="$(java_r8_d8_platform)") + JAVAC_WRAPPER := $(strip $(JAVAC_WRAPPER) $(RBE_WRAPPER) --labels=type=compile,lang=java,compiler=javac --exec_strategy=$(javac_exec_strategy) --platform=$(java_r8_d8_platform)) endif ifdef RBE_R8 - R8_WRAPPER := $(strip $(RBE_WRAPPER) --labels=type=compile,compiler=r8 --exec_strategy=$(r8_exec_strategy) --platform="$(java_r8_d8_platform)" --inputs=out/soong/host/linux-x86/framework/r8-compat-proguard.jar,build/make/core/proguard_basic_keeps.flags --toolchain_inputs=prebuilts/jdk/jdk11/linux-x86/bin/java) + R8_WRAPPER := $(strip $(RBE_WRAPPER) --labels=type=compile,compiler=r8 --exec_strategy=$(r8_exec_strategy) --platform=$(java_r8_d8_platform) --inputs=out/soong/host/linux-x86/framework/r8-compat-proguard.jar,build/make/core/proguard_basic_keeps.flags --toolchain_inputs=prebuilts/jdk/jdk11/linux-x86/bin/java) endif ifdef RBE_D8 - D8_WRAPPER := $(strip $(RBE_WRAPPER) --labels=type=compile,compiler=d8 --exec_strategy=$(d8_exec_strategy) --platform="$(java_r8_d8_platform)" --inputs=out/soong/host/linux-x86/framework/d8.jar --toolchain_inputs=prebuilts/jdk/jdk11/linux-x86/bin/java) + D8_WRAPPER := $(strip $(RBE_WRAPPER) --labels=type=compile,compiler=d8 --exec_strategy=$(d8_exec_strategy) --platform=$(java_r8_d8_platform) --inputs=out/soong/host/linux-x86/framework/d8.jar --toolchain_inputs=prebuilts/jdk/jdk11/linux-x86/bin/java) endif rbe_dir := diff --git a/core/robolectric_test_config_template.xml b/core/robolectric_test_config_template.xml new file mode 100644 index 0000000000..e79abd56ab --- /dev/null +++ b/core/robolectric_test_config_template.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- This test config file is auto-generated. --> +<configuration description="Runs {MODULE}"> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-junit" /> + + <option name="java-folder" value="prebuilts/jdk/jdk9/linux-x86/" /> + <option name="exclude-paths" value="java" /> + <option name="use-robolectric-resources" value="true" /> + + {EXTRA_CONFIGS} + + <test class="com.android.tradefed.testtype.IsolatedHostTest" > + <option name="jar" value="{MODULE}.jar" /> + </test> +</configuration> diff --git a/core/shared_library_internal.mk b/core/shared_library_internal.mk index 219772a1e6..12b7f44f44 100644 --- a/core/shared_library_internal.mk +++ b/core/shared_library_internal.mk @@ -51,8 +51,8 @@ my_target_crtbegin_so_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT_crt my_target_crtend_so_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT_crtend_so) endif ifneq ($(LOCAL_SDK_VERSION),) -my_target_crtbegin_so_o := $(wildcard $(my_ndk_sysroot_lib)/crtbegin_so.o) -my_target_crtend_so_o := $(wildcard $(my_ndk_sysroot_lib)/crtend_so.o) +my_target_crtbegin_so_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT_crtbegin_so.sdk.$(my_ndk_crt_version)) +my_target_crtend_so_o := $(SOONG_$(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJECT_crtend_so.sdk.$(my_ndk_crt_version)) endif $(linked_module): PRIVATE_TARGET_LIBCRT_BUILTINS := $(my_target_libcrt_builtins) $(linked_module): PRIVATE_TARGET_LIBATOMIC := $(my_target_libatomic) diff --git a/core/shared_test_lib.mk b/core/shared_test_lib.mk deleted file mode 100644 index 1ea9fe790e..0000000000 --- a/core/shared_test_lib.mk +++ /dev/null @@ -1 +0,0 @@ -$(error BUILD_SHARED_TEST_LIBRARY is obsolete) diff --git a/core/soong_android_app_set.mk b/core/soong_android_app_set.mk index c88489427a..ef9eaced5f 100644 --- a/core/soong_android_app_set.mk +++ b/core/soong_android_app_set.mk @@ -1,13 +1,13 @@ # App prebuilt coming from Soong. # Extra inputs: -# LOCAL_APK_SET_MASTER_FILE +# LOCAL_APK_SET_INSTALL_FILE ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK)) $(call pretty-error,soong_apk_set.mk may only be used from Soong) endif -LOCAL_BUILT_MODULE_STEM := $(LOCAL_APK_SET_MASTER_FILE) -LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_APK_SET_MASTER_FILE) +LOCAL_BUILT_MODULE_STEM := $(LOCAL_APK_SET_INSTALL_FILE) +LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_APK_SET_INSTALL_FILE) ####################################### include $(BUILD_SYSTEM)/base_rules.mk @@ -15,19 +15,19 @@ include $(BUILD_SYSTEM)/base_rules.mk ## Extract master APK from APK set into given directory # $(1) APK set -# $(2) master APK entry (e.g., splits/base-master.apk +# $(2) APK entry to install (e.g., splits/base.apk -define extract-master-from-apk-set +define extract-install-file-from-apk-set $(LOCAL_BUILT_MODULE): $(1) @echo "Extracting $$@" unzip -pq $$< $(2) >$$@ endef -$(eval $(call extract-master-from-apk-set,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_APK_SET_MASTER_FILE))) +$(eval $(call extract-install-file-from-apk-set,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_APK_SET_INSTALL_FILE))) # unzip returns 11 it there was nothing to extract, which is expected, -# $(LOCAL_APK_SET_MASTER_FILE) has is already there. -LOCAL_POST_INSTALL_CMD := unzip -qo -j -d $(dir $(LOCAL_INSTALLED_MODULE)) \ - $(LOCAL_PREBUILT_MODULE_FILE) -x $(LOCAL_APK_SET_MASTER_FILE) || [[ $$? -eq 11 ]] +# $(LOCAL_APK_SET_INSTALL_FILE) has is already there. +LOCAL_POST_INSTALL_CMD := unzip -qoDD -j -d $(dir $(LOCAL_INSTALLED_MODULE)) \ + $(LOCAL_PREBUILT_MODULE_FILE) -x $(LOCAL_APK_SET_INSTALL_FILE) || [[ $$? -eq 11 ]] $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD) PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES)) diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk index 01e980029b..50ac93a96b 100644 --- a/core/soong_app_prebuilt.mk +++ b/core/soong_app_prebuilt.mk @@ -7,10 +7,12 @@ # LOCAL_SOONG_HEADER_JAR # LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR # LOCAL_SOONG_PROGUARD_DICT +# LOCAL_SOONG_PROGUARD_USAGE # LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE # LOCAL_SOONG_RRO_DIRS # LOCAL_SOONG_JNI_LIBS_$(TARGET_ARCH) # LOCAL_SOONG_JNI_LIBS_$(TARGET_2ND_ARCH) +# LOCAL_SOONG_JNI_LIBS_SYMBOLS ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK)) $(call pretty-error,soong_app_prebuilt.mk may only be used from Soong) @@ -51,7 +53,7 @@ endif # We skip it for unbundled app builds where we cannot build veridex. module_run_appcompat := ifeq (true,$(non_system_module)) -ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK))) # ! unbundled app build +ifeq (,$(TARGET_BUILD_APPS)) # ! unbundled app build ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true) module_run_appcompat := true endif @@ -84,6 +86,13 @@ ifdef LOCAL_SOONG_PROGUARD_DICT $(intermediates.COMMON)/proguard_dictionary) endif +ifdef LOCAL_SOONG_PROGUARD_USAGE_ZIP + $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_USAGE_ZIP),\ + $(intermediates.COMMON)/proguard_usage.zip)) + $(call add-dependency,$(LOCAL_BUILT_MODULE),\ + $(intermediates.COMMON)/proguard_usage.zip) +endif + ifdef LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE resource_export_package := $(intermediates.COMMON)/package-export.apk resource_export_stamp := $(intermediates.COMMON)/src/R.stamp @@ -118,6 +127,11 @@ $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \ $(call create-suite-dependencies) endif +# install symbol files of JNI libraries +my_jni_lib_symbols_copy_files := $(foreach f,$(LOCAL_SOONG_JNI_LIBS_SYMBOLS),\ + $(call word-colon,1,$(f)):$(patsubst $(PRODUCT_OUT)/%,$(TARGET_OUT_UNSTRIPPED)/%,$(call word-colon,2,$(f)))) +$(LOCAL_BUILT_MODULE): $(call copy-many-files, $(my_jni_lib_symbols_copy_files)) + # embedded JNI will already have been handled by soong my_embed_jni := my_prebuilt_jni_libs := @@ -167,7 +181,11 @@ endif PACKAGES.$(LOCAL_MODULE).PARTITION := $(actual_partition_tag) ifdef LOCAL_SOONG_BUNDLE - ALL_MODULES.$(LOCAL_MODULE).BUNDLE := $(LOCAL_SOONG_BUNDLE) + ALL_MODULES.$(my_register_name).BUNDLE := $(LOCAL_SOONG_BUNDLE) +endif + +ifdef LOCAL_SOONG_LINT_REPORTS + ALL_MODULES.$(my_register_name).LINT_REPORTS := $(LOCAL_SOONG_LINT_REPORTS) endif ifndef LOCAL_IS_HOST_MODULE diff --git a/core/soong_cc_prebuilt.mk b/core/soong_cc_prebuilt.mk index 51549bd2a5..a0315a5429 100644 --- a/core/soong_cc_prebuilt.mk +++ b/core/soong_cc_prebuilt.mk @@ -112,7 +112,12 @@ endif my_check_same_vndk_variants := ifeq ($(LOCAL_CHECK_SAME_VNDK_VARIANTS),true) ifeq ($(filter hwaddress address, $(SANITIZE_TARGET)),) - my_check_same_vndk_variants := true + ifneq ($(CLANG_COVERAGE),true) + # Do not compare VNDK variant for special cases e.g. coverage builds. + ifneq ($(SKIP_VNDK_VARIANTS_CHECK),true) + my_check_same_vndk_variants := true + endif + endif endif endif @@ -137,8 +142,16 @@ ifeq ($(my_check_same_vndk_variants),true) $(LOCAL_BUILT_MODULE): $(same_vndk_variants_stamp) endif +# Use copy-or-link-prebuilt-to-target for host executables and shared libraries, +# to preserve symlinks to the source trees. They can then run directly from the +# prebuilt directories where the linker can load their dependencies using +# relative RUNPATHs. $(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE) +ifeq ($(LOCAL_IS_HOST_MODULE) $(if $(filter EXECUTABLES SHARED_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),true,),true true) + $(copy-or-link-prebuilt-to-target) +else $(transform-prebuilt-to-target) +endif ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),) $(hide) chmod +x $@ endif diff --git a/core/soong_config.mk b/core/soong_config.mk index 51b7e384a4..ad2e816627 100644 --- a/core/soong_config.mk +++ b/core/soong_config.mk @@ -39,9 +39,9 @@ $(call add_json_str, Platform_base_os, $(PLATFORM_BASE_OS)) $(call add_json_str, Platform_min_supported_target_sdk_version, $(PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION)) $(call add_json_bool, Allow_missing_dependencies, $(ALLOW_MISSING_DEPENDENCIES)) -$(call add_json_bool, Unbundled_build, $(TARGET_BUILD_APPS)) -$(call add_json_bool, Unbundled_build_sdks_from_source, $(UNBUNDLED_BUILD_SDKS_FROM_SOURCE)) -$(call add_json_bool, Pdk, $(filter true,$(TARGET_BUILD_PDK))) +$(call add_json_bool, Unbundled_build, $(TARGET_BUILD_UNBUNDLED)) +$(call add_json_bool, Unbundled_build_apps, $(TARGET_BUILD_APPS)) +$(call add_json_bool, Always_use_prebuilt_sdks, $(TARGET_BUILD_USE_PREBUILT_SDKS)) $(call add_json_bool, Debuggable, $(filter userdebug eng,$(TARGET_BUILD_VARIANT))) $(call add_json_bool, Eng, $(filter eng,$(TARGET_BUILD_VARIANT))) @@ -115,29 +115,24 @@ $(call add_json_list, JavaCoverageExcludePaths, $(JAVA_COVERAGE_EXCLUDE $(call add_json_bool, GcovCoverage, $(filter true,$(NATIVE_COVERAGE))) $(call add_json_bool, ClangCoverage, $(filter true,$(CLANG_COVERAGE))) -# TODO(b/158212027): Remove `$(COVERAGE_PATHS)` from this list when all users have been moved to -# `NATIVE_COVERAGE_PATHS`. -$(call add_json_list, NativeCoveragePaths, $(COVERAGE_PATHS) $(NATIVE_COVERAGE_PATHS)) -# TODO(b/158212027): Remove `$(COVERAGE_EXCLUDE_PATHS)` from this list when all users have been -# moved to `NATIVE_COVERAGE_EXCLUDE_PATHS`. -$(call add_json_list, NativeCoverageExcludePaths, $(COVERAGE_EXCLUDE_PATHS) $(NATIVE_COVERAGE_EXCLUDE_PATHS)) +$(call add_json_list, NativeCoveragePaths, $(NATIVE_COVERAGE_PATHS)) +$(call add_json_list, NativeCoverageExcludePaths, $(NATIVE_COVERAGE_EXCLUDE_PATHS)) $(call add_json_bool, SamplingPGO, $(filter true,$(SAMPLING_PGO))) $(call add_json_bool, ArtUseReadBarrier, $(call invert_bool,$(filter false,$(PRODUCT_ART_USE_READ_BARRIER)))) $(call add_json_bool, Binder32bit, $(BINDER32BIT)) $(call add_json_str, BtConfigIncludeDir, $(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR)) -$(call add_json_list, DeviceKernelHeaders, $(TARGET_PROJECT_SYSTEM_INCLUDES)) -$(call add_json_bool, DevicePrefer32BitApps, $(filter true,$(TARGET_PREFER_32_BIT_APPS))) -$(call add_json_bool, DevicePrefer32BitExecutables, $(filter true,$(TARGET_PREFER_32_BIT_EXECUTABLES))) +$(call add_json_list, DeviceKernelHeaders, $(TARGET_DEVICE_KERNEL_HEADERS) $(TARGET_BOARD_KERNEL_HEADERS) $(TARGET_PRODUCT_KERNEL_HEADERS)) $(call add_json_str, DeviceVndkVersion, $(BOARD_VNDK_VERSION)) $(call add_json_str, Platform_vndk_version, $(PLATFORM_VNDK_VERSION)) $(call add_json_str, ProductVndkVersion, $(PRODUCT_PRODUCT_VNDK_VERSION)) $(call add_json_list, ExtraVndkVersions, $(PRODUCT_EXTRA_VNDK_VERSIONS)) -$(call add_json_bool, BoardVndkRuntimeDisable, $(BOARD_VNDK_RUNTIME_DISABLE)) $(call add_json_list, DeviceSystemSdkVersions, $(BOARD_SYSTEMSDK_VERSIONS)) $(call add_json_list, Platform_systemsdk_versions, $(PLATFORM_SYSTEMSDK_VERSIONS)) $(call add_json_bool, Malloc_not_svelte, $(call invert_bool,$(filter true,$(MALLOC_SVELTE)))) +$(call add_json_bool, Malloc_zero_contents, $(MALLOC_ZERO_CONTENTS)) +$(call add_json_bool, Malloc_pattern_fill_contents, $(MALLOC_PATTERN_FILL_CONTENTS)) $(call add_json_str, Override_rs_driver, $(OVERRIDE_RS_DRIVER)) $(call add_json_bool, UncompressPrivAppDex, $(call invert_bool,$(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS)))) @@ -158,6 +153,8 @@ $(call add_json_bool, Uml, $(filter true,$(TARGET_ $(call add_json_bool, Use_lmkd_stats_log, $(filter true,$(TARGET_LMKD_STATS_LOG))) $(call add_json_str, VendorPath, $(TARGET_COPY_OUT_VENDOR)) $(call add_json_str, OdmPath, $(TARGET_COPY_OUT_ODM)) +$(call add_json_str, VendorDlkmPath, $(TARGET_COPY_OUT_VENDOR_DLKM)) +$(call add_json_str, OdmDlkmPath, $(TARGET_COPY_OUT_ODM_DLKM)) $(call add_json_str, ProductPath, $(TARGET_COPY_OUT_PRODUCT)) $(call add_json_str, SystemExtPath, $(TARGET_COPY_OUT_SYSTEM_EXT)) $(call add_json_bool, MinimizeJavaDebugInfo, $(filter true,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO))) @@ -175,6 +172,8 @@ $(call add_json_list, PgoAdditionalProfileDirs, $(PGO_ADDITIONAL_PROFIL $(call add_json_list, BoardVendorSepolicyDirs, $(BOARD_VENDOR_SEPOLICY_DIRS) $(BOARD_SEPOLICY_DIRS)) $(call add_json_list, BoardOdmSepolicyDirs, $(BOARD_ODM_SEPOLICY_DIRS)) +$(call add_json_list, BoardVendorDlkmSepolicyDirs, $(BOARD_VENDOR_DLKM_SEPOLICY_DIRS)) +$(call add_json_list, BoardOdmDlkmSepolicyDirs, $(BOARD_ODM_DLKM_SEPOLICY_DIRS)) $(call add_json_list, BoardPlatPublicSepolicyDirs, $(BOARD_PLAT_PUBLIC_SEPOLICY_DIR)) $(call add_json_list, BoardPlatPrivateSepolicyDirs, $(BOARD_PLAT_PRIVATE_SEPOLICY_DIR)) $(call add_json_list, BoardSepolicyM4Defs, $(BOARD_SEPOLICY_M4DEFS)) @@ -211,11 +210,15 @@ $(foreach namespace,$(SOONG_CONFIG_NAMESPACES),\ $(call end_json_map) $(call add_json_bool, EnforceProductPartitionInterface, $(PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE)) +$(call add_json_str, DeviceCurrentApiLevelForVendorModules, $(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES)) $(call add_json_bool, InstallExtraFlattenedApexes, $(PRODUCT_INSTALL_EXTRA_FLATTENED_APEXES)) $(call add_json_bool, BoardUsesRecoveryAsBoot, $(BOARD_USES_RECOVERY_AS_BOOT)) +$(call add_json_list, BoardKernelBinaries, $(BOARD_KERNEL_BINARIES)) +$(call add_json_list, BoardKernelModuleInterfaceVersions, $(BOARD_KERNEL_MODULE_INTERFACE_VERSIONS)) + $(call json_end) $(file >$(SOONG_VARIABLES).tmp,$(json_contents)) diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk index bfde9446cd..5444d960c9 100644 --- a/core/soong_java_prebuilt.mk +++ b/core/soong_java_prebuilt.mk @@ -58,6 +58,14 @@ ifdef LOCAL_SOONG_PROGUARD_DICT $(intermediates.COMMON)/proguard_dictionary) endif +ifdef LOCAL_SOONG_PROGUARD_USAGE + $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_USAGE_ZIP),\ + $(intermediates.COMMON)/proguard_usage.zip)) + $(call add-dependency,$(LOCAL_BUILT_MODULE),\ + $(intermediates.COMMON)/proguard_usage.zip) +endif + + ifdef LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE my_res_package := $(intermediates.COMMON)/package-res.apk @@ -91,18 +99,21 @@ endif # LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE ifdef LOCAL_SOONG_DEX_JAR ifndef LOCAL_IS_HOST_MODULE - ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),) # is_boot_jar + boot_jars := $(foreach pair,$(PRODUCT_BOOT_JARS), $(call word-colon,2,$(pair))) + ifneq ($(filter $(LOCAL_MODULE),$(boot_jars)),) # is_boot_jar ifeq (true,$(WITH_DEXPREOPT)) - # For libart, the boot jars' odex files are replaced by $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE). - # We use this installed_odex trick to get boot.art installed. - installed_odex := $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE) - # Append the odex for the 2nd arch if we have one. - installed_odex += $($(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE) - ALL_MODULES.$(my_register_name).INSTALLED += $(installed_odex) - # Make sure to install the .odex and .vdex when you run "make <module_name>" - $(my_all_targets): $(installed_odex) - # Copy $(LOCAL_BUILT_MODULE) and its dependencies when installing boot.art - $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE): $(LOCAL_BUILT_MODULE) + # $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE_MODULE) contains modules that installs + # all of bootjars' dexpreopt files (.art, .oat, .vdex, ...) + # Add them to the required list so they are installed alongside this module. + ALL_MODULES.$(my_register_name).REQUIRED_FROM_TARGET += \ + $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE_MODULE) \ + $(2ND_DEFAULT_DEX_PREOPT_INSTALLED_IMAGE_MODULE) + # Copy $(LOCAL_BUILT_MODULE) and its dependencies when installing boot.art + # so that dependencies of $(LOCAL_BUILT_MODULE) (which may include + # jacoco-report-classes.jar) are copied for every build. + $(foreach m,$(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE_MODULE) $(2ND_DEFAULT_DEX_PREOPT_INSTALLED_IMAGE_MODULE), \ + $(eval $(call add-dependency,$(firstword $(call module-installed-files,$(m))),$(LOCAL_BUILT_MODULE))) \ + ) endif endif # is_boot_jar @@ -132,7 +143,7 @@ ALL_MODULES.$(my_register_name).CLASSES_JAR := $(full_classes_jar) $(my_register_name): $(my_installed) ifdef LOCAL_SOONG_AAR - ALL_MODULES.$(LOCAL_MODULE).AAR := $(LOCAL_SOONG_AAR) + ALL_MODULES.$(my_register_name).AAR := $(LOCAL_SOONG_AAR) endif javac-check : $(full_classes_jar) diff --git a/core/soong_rust_prebuilt.mk b/core/soong_rust_prebuilt.mk index 4a9eb4ab6f..de6bafdc7e 100644 --- a/core/soong_rust_prebuilt.mk +++ b/core/soong_rust_prebuilt.mk @@ -57,7 +57,11 @@ ifdef LOCAL_INSTALLED_MODULE endif $(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE) +ifeq ($(LOCAL_IS_HOST_MODULE) $(if $(filter EXECUTABLES SHARED_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),true,),true true) + $(copy-or-link-prebuilt-to-target) +else $(transform-prebuilt-to-target) +endif ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),) $(hide) chmod +x $@ endif @@ -75,6 +79,23 @@ ifndef LOCAL_IS_HOST_MODULE endif endif + +ifeq ($(NATIVE_COVERAGE),true) + ifneq (,$(strip $(LOCAL_PREBUILT_COVERAGE_ARCHIVE))) + $(eval $(call copy-one-file,$(LOCAL_PREBUILT_COVERAGE_ARCHIVE),$(intermediates)/$(LOCAL_MODULE).zip)) + ifneq ($(LOCAL_UNINSTALLABLE_MODULE),true) + ifdef LOCAL_IS_HOST_MODULE + my_coverage_path := $($(my_prefix)OUT_COVERAGE)/$(patsubst $($(my_prefix)OUT)/%,%,$(my_module_path)) + else + my_coverage_path := $(TARGET_OUT_COVERAGE)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_module_path)) + endif + my_coverage_path := $(my_coverage_path)/$(patsubst %.so,%,$(my_installed_module_stem)).zip + $(eval $(call copy-one-file,$(LOCAL_PREBUILT_COVERAGE_ARCHIVE),$(my_coverage_path))) + $(LOCAL_BUILT_MODULE): $(my_coverage_path) + endif + endif +endif + # A product may be configured to strip everything in some build variants. # We do the stripping as a post-install command so that LOCAL_BUILT_MODULE # is still with the symbols and we don't need to clean it (and relink) when diff --git a/core/static_java_library.mk b/core/static_java_library.mk index 7eef167e11..7a873229d7 100644 --- a/core/static_java_library.mk +++ b/core/static_java_library.mk @@ -111,7 +111,7 @@ endif framework_res_package_export := # Please refer to package.mk ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true) -ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS_USE_PREBUILT_SDK),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),) +ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_USE_PREBUILT_SDKS),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),) framework_res_package_export := \ $(call resolve-prebuilt-sdk-jar-path,$(LOCAL_SDK_RES_VERSION)) else @@ -209,7 +209,7 @@ $(built_aar) : $(aar_classes_jar) $(full_android_manifest) $(intermediates.COMMO $(call jar-args-sorted-files-in-directory,$(dir $@)aar) # Register the aar file. -ALL_MODULES.$(LOCAL_MODULE).AAR := $(built_aar) +ALL_MODULES.$(my_register_name).AAR := $(built_aar) endif # need_compile_res # Reset internal variables. diff --git a/core/static_test_lib.mk b/core/static_test_lib.mk deleted file mode 100644 index a0e2970698..0000000000 --- a/core/static_test_lib.mk +++ /dev/null @@ -1,9 +0,0 @@ -############################################# -## A thin wrapper around BUILD_STATIC_LIBRARY -## Common flags for native tests are added. -############################################# -$(call record-module-type,STATIC_TEST_LIBRARY) - -include $(BUILD_SYSTEM)/target_test_internal.mk - -include $(BUILD_STATIC_LIBRARY) diff --git a/core/sysprop.mk b/core/sysprop.mk new file mode 100644 index 0000000000..73dbec792a --- /dev/null +++ b/core/sysprop.mk @@ -0,0 +1,431 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# sysprop.mk defines rules for generating <partition>/[etc/]build.prop files + +# ----------------------------------------------------------------- +# property_overrides_split_enabled +property_overrides_split_enabled := +ifeq ($(BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED), true) + property_overrides_split_enabled := true +endif + +BUILDINFO_SH := build/make/tools/buildinfo.sh +POST_PROCESS_PROPS := $(HOST_OUT_EXECUTABLES)/post_process_props$(HOST_EXECUTABLE_SUFFIX) + +# Emits a set of sysprops common to all partitions to a file. +# $(1): Partition name +# $(2): Output file name +define generate-common-build-props + echo "####################################" >> $(2);\ + echo "# from generate-common-build-props" >> $(2);\ + echo "# These properties identify this partition image." >> $(2);\ + echo "####################################" >> $(2);\ + $(if $(filter system,$(1)),\ + echo "ro.product.$(1).brand=$(PRODUCT_SYSTEM_BRAND)" >> $(2);\ + echo "ro.product.$(1).device=$(PRODUCT_SYSTEM_DEVICE)" >> $(2);\ + echo "ro.product.$(1).manufacturer=$(PRODUCT_SYSTEM_MANUFACTURER)" >> $(2);\ + echo "ro.product.$(1).model=$(PRODUCT_SYSTEM_MODEL)" >> $(2);\ + echo "ro.product.$(1).name=$(PRODUCT_SYSTEM_NAME)" >> $(2);\ + ,\ + echo "ro.product.$(1).brand=$(PRODUCT_BRAND)" >> $(2);\ + echo "ro.product.$(1).device=$(TARGET_DEVICE)" >> $(2);\ + echo "ro.product.$(1).manufacturer=$(PRODUCT_MANUFACTURER)" >> $(2);\ + echo "ro.product.$(1).model=$(PRODUCT_MODEL)" >> $(2);\ + echo "ro.product.$(1).name=$(TARGET_PRODUCT)" >> $(2);\ + )\ + echo "ro.$(1).build.date=`$(DATE_FROM_FILE)`" >> $(2);\ + echo "ro.$(1).build.date.utc=`$(DATE_FROM_FILE) +%s`" >> $(2);\ + echo "ro.$(1).build.fingerprint=$(BUILD_FINGERPRINT_FROM_FILE)" >> $(2);\ + echo "ro.$(1).build.id=$(BUILD_ID)" >> $(2);\ + echo "ro.$(1).build.tags=$(BUILD_VERSION_TAGS)" >> $(2);\ + echo "ro.$(1).build.type=$(TARGET_BUILD_VARIANT)" >> $(2);\ + echo "ro.$(1).build.version.incremental=$(BUILD_NUMBER_FROM_FILE)" >> $(2);\ + echo "ro.$(1).build.version.release=$(PLATFORM_VERSION)" >> $(2);\ + echo "ro.$(1).build.version.sdk=$(PLATFORM_SDK_VERSION)" >> $(2);\ + +endef + +# Rule for generating <partition>/[etc/]build.prop file +# +# $(1): partition name +# $(2): path to the output +# $(3): path to the input *.prop files. The contents of the files are directly +# emitted to the output +# $(4): list of variable names each of which contains name=value pairs +# $(5): optional list of prop names to force remove from the output. Properties from both +# $(3) and (4) are affected. +define build-properties +ALL_DEFAULT_INSTALLED_MODULES += $(2) + +$(eval # Properties can be assigned using `prop ?= value` or `prop = value` syntax.) +$(eval # Eliminate spaces around the ?= and = separators.) +$(foreach name,$(strip $(4)),\ + $(eval _temp := $$(call collapse-pairs,$$($(name)),?=))\ + $(eval _resolved_$(name) := $$(call collapse-pairs,$$(_temp),=))\ +) + +$(eval # Implement the legacy behavior when BUILD_BROKEN_DUP_SYSPROP is on.) +$(eval # Optional assignments are all converted to normal assignments and) +$(eval # when their duplicates the first one wins) +$(if $(filter true,$(BUILD_BROKEN_DUP_SYSPROP)),\ + $(foreach name,$(strip $(4)),\ + $(eval _temp := $$(subst ?=,=,$$(_resolved_$(name))))\ + $(eval _resolved_$(name) := $$(call uniq-pairs-by-first-component,$$(_resolved_$(name)),=))\ + )\ + $(eval _option := --allow-dup)\ +) + +$(2): $(POST_PROCESS_PROPS) $(INTERNAL_BUILD_ID_MAKEFILE) $(API_FINGERPRINT) $(3) + $(hide) echo Building $$@ + $(hide) mkdir -p $$(dir $$@) + $(hide) rm -f $$@ && touch $$@ + $(hide) $$(call generate-common-build-props,$(call to-lower,$(strip $(1))),$$@) + $(hide) $(foreach file,$(strip $(3)),\ + if [ -f "$(file)" ]; then\ + echo "" >> $$@;\ + echo "####################################" >> $$@;\ + echo "# from $(file)" >> $$@;\ + echo "####################################" >> $$@;\ + cat $(file) >> $$@;\ + fi;) + $(hide) $(foreach name,$(strip $(4)),\ + echo "" >> $$@;\ + echo "####################################" >> $$@;\ + echo "# from variable $(name)" >> $$@;\ + echo "####################################" >> $$@;\ + $$(foreach line,$$(_resolved_$(name)),\ + echo "$$(line)" >> $$@;\ + )\ + ) + $(hide) $(POST_PROCESS_PROPS) $$(_option) $$@ $(5) + $(hide) echo "# end of file" >> $$@ +endef + +# ----------------------------------------------------------------- +# Define fingerprint, thumbprint, and version tags for the current build +# +# BUILD_VERSION_TAGS is a comma-separated list of tags chosen by the device +# implementer that further distinguishes the build. It's basically defined +# by the device implementer. Here, we are adding a mandatory tag that +# identifies the signing config of the build. +BUILD_VERSION_TAGS := $(BUILD_VERSION_TAGS) +ifeq ($(TARGET_BUILD_TYPE),debug) + BUILD_VERSION_TAGS += debug +endif +# The "test-keys" tag marks builds signed with the old test keys, +# which are available in the SDK. "dev-keys" marks builds signed with +# non-default dev keys (usually private keys from a vendor directory). +# Both of these tags will be removed and replaced with "release-keys" +# when the target-files is signed in a post-build step. +ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/make/target/product/security/testkey) +BUILD_KEYS := test-keys +else +BUILD_KEYS := dev-keys +endif +BUILD_VERSION_TAGS += $(BUILD_KEYS) +BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS))) + +# BUILD_FINGERPRINT is used used to uniquely identify the combined build and +# product; used by the OTA server. +ifeq (,$(strip $(BUILD_FINGERPRINT))) + ifeq ($(strip $(HAS_BUILD_NUMBER)),false) + BF_BUILD_NUMBER := $(BUILD_USERNAME)$$($(DATE_FROM_FILE) +%m%d%H%M) + else + BF_BUILD_NUMBER := $(file <$(BUILD_NUMBER_FILE)) + endif + BUILD_FINGERPRINT := $(PRODUCT_BRAND)/$(TARGET_PRODUCT)/$(TARGET_DEVICE):$(PLATFORM_VERSION)/$(BUILD_ID)/$(BF_BUILD_NUMBER):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS) +endif +# unset it for safety. +BF_BUILD_NUMBER := + +BUILD_FINGERPRINT_FILE := $(PRODUCT_OUT)/build_fingerprint.txt +ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) >$(BUILD_FINGERPRINT_FILE) && grep " " $(BUILD_FINGERPRINT_FILE))) + $(error BUILD_FINGERPRINT cannot contain spaces: "$(file <$(BUILD_FINGERPRINT_FILE))") +endif +BUILD_FINGERPRINT_FROM_FILE := $$(cat $(BUILD_FINGERPRINT_FILE)) +# unset it for safety. +BUILD_FINGERPRINT := + +# BUILD_THUMBPRINT is used to uniquely identify the system build; used by the +# OTA server. This purposefully excludes any product-specific variables. +ifeq (,$(strip $(BUILD_THUMBPRINT))) + BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS) +endif + +BUILD_THUMBPRINT_FILE := $(PRODUCT_OUT)/build_thumbprint.txt +ifneq (,$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_THUMBPRINT) >$(BUILD_THUMBPRINT_FILE) && grep " " $(BUILD_THUMBPRINT_FILE))) + $(error BUILD_THUMBPRINT cannot contain spaces: "$(file <$(BUILD_THUMBPRINT_FILE))") +endif +BUILD_THUMBPRINT_FROM_FILE := $$(cat $(BUILD_THUMBPRINT_FILE)) +# unset it for safety. +BUILD_THUMBPRINT := + +# ----------------------------------------------------------------- +# Define human readable strings that describe this build +# + +# BUILD_ID: detail info; has the same info as the build fingerprint +BUILD_DESC := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER_FROM_FILE) $(BUILD_VERSION_TAGS) + +# BUILD_DISPLAY_ID is shown under Settings -> About Phone +ifeq ($(TARGET_BUILD_VARIANT),user) + # User builds should show: + # release build number or branch.buld_number non-release builds + + # Dev. branches should have DISPLAY_BUILD_NUMBER set + ifeq (true,$(DISPLAY_BUILD_NUMBER)) + BUILD_DISPLAY_ID := $(BUILD_ID).$(BUILD_NUMBER_FROM_FILE) $(BUILD_KEYS) + else + BUILD_DISPLAY_ID := $(BUILD_ID) $(BUILD_KEYS) + endif +else + # Non-user builds should show detailed build information + BUILD_DISPLAY_ID := $(BUILD_DESC) +endif + +# TARGET_BUILD_FLAVOR and ro.build.flavor are used only by the test +# harness to distinguish builds. Only add _asan for a sanitized build +# if it isn't already a part of the flavor (via a dedicated lunch +# config for example). +TARGET_BUILD_FLAVOR := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) +ifneq (, $(filter address, $(SANITIZE_TARGET))) +ifeq (,$(findstring _asan,$(TARGET_BUILD_FLAVOR))) +TARGET_BUILD_FLAVOR := $(TARGET_BUILD_FLAVOR)_asan +endif +endif + +KNOWN_OEM_THUMBPRINT_PROPERTIES := \ + ro.product.brand \ + ro.product.name \ + ro.product.device +OEM_THUMBPRINT_PROPERTIES := $(filter $(KNOWN_OEM_THUMBPRINT_PROPERTIES),\ + $(PRODUCT_OEM_PROPERTIES)) +KNOWN_OEM_THUMBPRINT_PROPERTIES:= + +# ----------------------------------------------------------------- +# system/build.prop +# +# Note: parts of this file that can't be generated by the build-properties +# macro are manually created as separate files and then fed into the macro + +# Accepts a whitespace separated list of product locales such as +# (en_US en_AU en_GB...) and returns the first locale in the list with +# underscores replaced with hyphens. In the example above, this will +# return "en-US". +define get-default-product-locale +$(strip $(subst _,-, $(firstword $(1)))) +endef + +gen_from_buildinfo_sh := $(call intermediates-dir-for,PACKAGING,system_build_prop)/buildinfo.prop +$(gen_from_buildinfo_sh): $(INTERNAL_BUILD_ID_MAKEFILE) $(API_FINGERPRINT) + $(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \ + TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \ + TARGET_DEVICE="$(TARGET_DEVICE)" \ + PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \ + PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \ + PRIVATE_BUILD_DESC="$(BUILD_DESC)" \ + BUILD_ID="$(BUILD_ID)" \ + BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \ + DATE="$(DATE_FROM_FILE)" \ + BUILD_USERNAME="$(BUILD_USERNAME)" \ + BUILD_HOSTNAME="$(BUILD_HOSTNAME)" \ + BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \ + BOARD_BUILD_SYSTEM_ROOT_IMAGE="$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)" \ + PLATFORM_VERSION="$(PLATFORM_VERSION)" \ + PLATFORM_VERSION_LAST_STABLE="$(PLATFORM_VERSION_LAST_STABLE)" \ + PLATFORM_SECURITY_PATCH="$(PLATFORM_SECURITY_PATCH)" \ + PLATFORM_BASE_OS="$(PLATFORM_BASE_OS)" \ + PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \ + PLATFORM_PREVIEW_SDK_VERSION="$(PLATFORM_PREVIEW_SDK_VERSION)" \ + PLATFORM_PREVIEW_SDK_FINGERPRINT="$$(cat $(API_FINGERPRINT))" \ + PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \ + PLATFORM_VERSION_ALL_CODENAMES="$(PLATFORM_VERSION_ALL_CODENAMES)" \ + PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION="$(PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION)" \ + BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \ + $(if $(OEM_THUMBPRINT_PROPERTIES),BUILD_THUMBPRINT="$(BUILD_THUMBPRINT_FROM_FILE)") \ + TARGET_CPU_ABI_LIST="$(TARGET_CPU_ABI_LIST)" \ + TARGET_CPU_ABI_LIST_32_BIT="$(TARGET_CPU_ABI_LIST_32_BIT)" \ + TARGET_CPU_ABI_LIST_64_BIT="$(TARGET_CPU_ABI_LIST_64_BIT)" \ + TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \ + TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \ + bash $(BUILDINFO_SH) > $@ + +ifneq ($(PRODUCT_OEM_PROPERTIES),) +import_oem_prop := $(call intermediates-dir-for,ETC,system_build_prop)/oem.prop + +$(import_oem_prop): + $(hide) echo "#" >> $@; \ + echo "# PRODUCT_OEM_PROPERTIES" >> $@; \ + echo "#" >> $@; + $(hide) $(foreach prop,$(PRODUCT_OEM_PROPERTIES), \ + echo "import /oem/oem.prop $(prop)" >> $@;) +else +import_oem_prop := +endif + +ifdef TARGET_SYSTEM_PROP +system_prop_file := $(TARGET_SYSTEM_PROP) +else +system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop) +endif + +_prop_files_ := \ + $(import_oem_prop) \ + $(gen_from_buildinfo_sh) \ + $(system_prop_file) + +# Order matters here. When there are duplicates, the last one wins. +# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter +_prop_vars_ := \ + ADDITIONAL_SYSTEM_PROPERTIES \ + PRODUCT_SYSTEM_PROPERTIES + +# TODO(b/117892318): deprecate this +_prop_vars_ += \ + PRODUCT_SYSTEM_DEFAULT_PROPERTIES + +ifndef property_overrides_split_enabled +_prop_vars_ += \ + ADDITIONAL_VENDOR_PROPERTIES \ + PRODUCT_VENDOR_PROPERTIES +endif + +_blacklist_names_ := \ + $(PRODUCT_SYSTEM_PROPERTY_BLACKLIST) \ + ro.product.first_api_level + +INSTALLED_BUILD_PROP_TARGET := $(TARGET_OUT)/build.prop + +$(eval $(call build-properties,system,$(INSTALLED_BUILD_PROP_TARGET),\ +$(_prop_files_),$(_prop_vars_),\ +$(_blacklist_names_))) + +# ----------------------------------------------------------------- +# vendor/build.prop +# +_prop_files_ := $(if $(TARGET_VENDOR_PROP),\ + $(TARGET_VENDOR_PROP),\ + $(wildcard $(TARGET_DEVICE_DIR)/vendor.prop)) + +android_info_prop := $(call intermediates-dir-for,ETC,android_info_prop)/android_info.prop +$(android_info_prop): $(INSTALLED_ANDROID_INFO_TXT_TARGET) + cat $< | grep 'require version-' | sed -e 's/require version-/ro.build.expect./g' > $@ + +_prop_files_ += $(android_info_pro) + +ifdef property_overrides_split_enabled +# Order matters here. When there are duplicates, the last one wins. +# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter +_prop_vars_ := \ + ADDITIONAL_VENDOR_PROPERTIES \ + PRODUCT_VENDOR_PROPERTIES + +# TODO(b/117892318): deprecate this +_prop_vars_ += \ + PRODUCT_DEFAULT_PROPERTY_OVERRIDES \ + PRODUCT_PROPERTY_OVERRIDES +else +_prop_vars_ := +endif + +INSTALLED_VENDOR_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR)/build.prop +$(eval $(call build-properties,\ + vendor,\ + $(INSTALLED_VENDOR_BUILD_PROP_TARGET),\ + $(_prop_files_),\ + $(_prop_vars_),\ + $(PRODUCT_VENDOR_PROPERTY_BLACKLIST))) + +# ----------------------------------------------------------------- +# product/etc/build.prop +# + +_prop_files_ := $(if $(TARGET_PRODUCT_PROP),\ + $(TARGET_PRODUCT_PROP),\ + $(wildcard $(TARGET_DEVICE_DIR)/product.prop)) + +# Order matters here. When there are duplicates, the last one wins. +# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter +_prop_vars_ := \ + ADDITIONAL_PRODUCT_PROPERTIES \ + PRODUCT_PRODUCT_PROPERTIES + +INSTALLED_PRODUCT_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT)/etc/build.prop +$(eval $(call build-properties,\ + product,\ + $(INSTALLED_PRODUCT_BUILD_PROP_TARGET),\ + $(_prop_files_),\ + $(_prop_vars_),\ + $(empty))) + +# ---------------------------------------------------------------- +# odm/etc/build.prop +# +_prop_files_ := $(if $(TARGET_ODM_PROP),\ + $(TARGET_ODM_PROP),\ + $(wildcard $(TARGET_DEVICE_DIR)/odm.prop)) + +# Order matters here. When there are duplicates, the last one wins. +# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter +_prop_vars_ := \ + ADDITIONAL_ODM_PROPERTIES \ + PRODUCT_ODM_PROPERTIES + +INSTALLED_ODM_BUILD_PROP_TARGET := $(TARGET_OUT_ODM)/etc/build.prop +$(eval $(call build-properties,\ + odm,\ + $(INSTALLED_ODM_BUILD_PROP_TARGET),\ + $(_prop_files),\ + $(_prop_vars_),\ + $(empty))) + +# ---------------------------------------------------------------- +# vendor_dlkm/etc/build.prop +# + +INSTALLED_VENDOR_DLKM_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR_DLKM)/etc/build.prop +$(eval $(call build-properties,\ + vendor_dlkm,\ + $(INSTALLED_VENDOR_DLKM_BUILD_PROP_TARGET))) + +# ---------------------------------------------------------------- +# odm_dlkm/etc/build.prop +# + +INSTALLED_ODM_DLKM_BUILD_PROP_TARGET := $(TARGET_OUT_ODM_DLKM)/etc/build.prop +$(eval $(call build-properties,\ + odm_dlkm,\ + $(INSTALLED_ODM_DLKM_BUILD_PROP_TARGET))) + +# ----------------------------------------------------------------- +# system_ext/etc/build.prop +# +_prop_files_ := $(if $(TARGET_SYSTEM_EXT_PROP),\ + $(TARGET_SYSTEM_EXT_PROP),\ + $(wildcard $(TARGET_DEVICE_DIR)/system_ext.prop)) + +# Order matters here. When there are duplicates, the last one wins. +# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter +_prop_vars_ := PRODUCT_SYSTEM_EXT_PROPERTIES + +INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET := $(TARGET_OUT_SYSTEM_EXT)/etc/build.prop +$(eval $(call build-properties,\ + system_ext,\ + $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET),\ + $(_prop_files_),\ + $(_prop_vars_),\ + $(empty))) diff --git a/core/tasks/boot_jars_package_check.mk b/core/tasks/boot_jars_package_check.mk index 825bbc37d7..c9a8e27614 100644 --- a/core/tasks/boot_jars_package_check.mk +++ b/core/tasks/boot_jars_package_check.mk @@ -17,25 +17,31 @@ # ifneq ($(SKIP_BOOT_JARS_CHECK),true) -ifneq ($(TARGET_BUILD_PDK),true) ifdef PRODUCT_BOOT_JARS intermediates := $(call intermediates-dir-for, PACKAGING, boot-jars-package-check,,COMMON) stamp := $(intermediates)/stamp -# The actual names for the updatable jars are <jar_name>.<apex_name> e.g., updatable-media.com.android.media -updatable_boot_jars := $(foreach pair,$(PRODUCT_UPDATABLE_BOOT_JARS),\ - $(eval apex := $(call word-colon,1,$(pair)))\ - $(eval jar := $(call word-colon,2,$(pair)))\ - $(jar).$(apex)\ -) -#TODO(jiyong) merge art_boot_jars into updatable_boot_jars -art_boot_jars := $(addsuffix .com.android.art.release,$(filter $(ART_APEX_JARS),$(PRODUCT_BOOT_JARS))) - -platform_boot_jars := $(filter-out $(ART_APEX_JARS),$(PRODUCT_BOOT_JARS)) - -built_boot_jars := $(foreach j, $(updatable_boot_jars) $(art_boot_jars) $(platform_boot_jars), \ +# Convert the colon-separated components <apex>:<jar> to <jar>.<apex> names +# (e.g. com.android.media:updatable-media -> updatable-media.com.android.media). +# Special cases: +# - for the "platform" or "system_ext" apex drop the .<apex> suffix +# - for the ART apex select release variant +boot_jars := $(foreach pair,$(PRODUCT_BOOT_JARS) $(PRODUCT_UPDATABLE_BOOT_JARS), \ + $(eval apex := $(call word-colon,1,$(pair))) \ + $(eval jar := $(call word-colon,2,$(pair))) \ + $(eval q := :) \ + $(eval sfx := $(q).$(apex)$(q)) \ + $(eval sfx := $(subst $(q).platform$(q),$(q)$(q),$(sfx))) \ + $(eval sfx := $(subst $(q).system_ext$(q),$(q)$(q),$(sfx))) \ + $(eval sfx := $(subst $(q).com.android.art$(q),$(q).com.android.art.release$(q),$(sfx))) \ + $(eval sfx := $(patsubst $(q)%$(q),%,$(sfx))) \ + $(jar)$(sfx)) + +# Convert boot jar names to build paths. +built_boot_jars := $(foreach j, $(boot_jars), \ $(call intermediates-dir-for, JAVA_LIBRARIES, $(j),,COMMON)/classes.jar) + script := build/make/core/tasks/check_boot_jars/check_boot_jars.py allowed_file := build/make/core/tasks/check_boot_jars/package_allowed_list.txt @@ -54,5 +60,4 @@ check-boot-jars : $(stamp) droidcore : check-boot-jars endif # PRODUCT_BOOT_JARS -endif # TARGET_BUILD_PDK not true endif # SKIP_BOOT_JARS_CHECK not true diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk index f3b4368775..cd5fa8e3b3 100644 --- a/core/tasks/cts.mk +++ b/core/tasks/cts.mk @@ -16,6 +16,7 @@ test_suite_name := cts test_suite_tradefed := cts-tradefed test_suite_dynamic_config := test/suite_harness/tools/cts-tradefed/DynamicConfig.xml test_suite_readme := test/suite_harness/tools/cts-tradefed/README +include_test_suite_notice := true include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk diff --git a/core/tasks/deps_licenses.mk b/core/tasks/deps_licenses.mk deleted file mode 100644 index daf986f606..0000000000 --- a/core/tasks/deps_licenses.mk +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright (C) 2015 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Print modules and their transitive dependencies with license files. -# To invoke, run "make deps-license PROJ_PATH=<proj-path-patterns> DEP_PATH=<dep-path-patterns>". -# PROJ_PATH restricts the paths of the source modules; DEP_PATH restricts the paths of the dependency modules. -# Both can be makefile patterns supported by makefile function $(filter). -# Example: "make deps-license packages/app/% external/%" prints all modules in packages/app/ with their dpendencies in external/. -# The printout lines look like "<module_name> :: <module_paths> :: <license_files>". - -ifneq (,$(filter deps-license,$(MAKECMDGOALS))) -ifndef PROJ_PATH -$(error To "make deps-license" you must specify PROJ_PATH and DEP_PATH.) -endif -ifndef DEP_PATH -$(error To "make deps-license" you must specify PROJ_PATH and DEP_PATH.) -endif - -# Expand a module's dependencies transitively. -# $(1): the variable name to hold the result. -# $(2): the initial module name. -define get-module-all-dependencies -$(eval _gmad_new := $(sort $(filter-out $($(1)),\ - $(foreach m,$(2),$(ALL_DEPS.$(m).ALL_DEPS)))))\ -$(if $(_gmad_new),$(eval $(1) += $(_gmad_new))\ - $(call get-module-all-dependencies,$(1),$(_gmad_new))) -endef - -define print-deps-license -$(foreach m, $(sort $(ALL_DEPS.MODULES)),\ - $(eval m_p := $(sort $(ALL_MODULES.$(m).PATH) $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).PATH)))\ - $(if $(filter $(PROJ_PATH),$(m_p)),\ - $(eval deps :=)\ - $(eval $(call get-module-all-dependencies,deps,$(m)))\ - $(info $(m) :: $(m_p) :: $(ALL_DEPS.$(m).LICENSE))\ - $(foreach d,$(deps),\ - $(eval d_p := $(sort $(ALL_MODULES.$(d).PATH) $(ALL_MODULES.$(d)$(TARGET_2ND_ARCH_MODULE_SUFFIX).PATH)))\ - $(if $(filter $(DEP_PATH),$(d_p)),\ - $(info $(space)$(space)$(space)$(space)$(d) :: $(d_p) :: $(ALL_DEPS.$(d).LICENSE)))))) -endef - -.PHONY: deps-license -deps-license: - @$(call print-deps-license) - -endif diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk index cb84a5ca74..a820a28f25 100644 --- a/core/tasks/general-tests.mk +++ b/core/tasks/general-tests.mk @@ -14,12 +14,10 @@ .PHONY: general-tests -# TODO(b/149249068): Remove vts10-tradefed.jar after all VTS tests are converted general_tests_tools := \ $(HOST_OUT_JAVA_LIBRARIES)/cts-tradefed.jar \ $(HOST_OUT_JAVA_LIBRARIES)/compatibility-host-util.jar \ $(HOST_OUT_JAVA_LIBRARIES)/vts-tradefed.jar \ - $(HOST_OUT_JAVA_LIBRARIES)/vts10-tradefed.jar intermediates_dir := $(call intermediates-dir-for,PACKAGING,general-tests) general_tests_zip := $(PRODUCT_OUT)/general-tests.zip diff --git a/core/tasks/ide.mk b/core/tasks/ide.mk index e557e6016f..a3aa0cdc03 100644 --- a/core/tasks/ide.mk +++ b/core/tasks/ide.mk @@ -40,8 +40,7 @@ ifdef eclipse_project_goals endif source_paths := $(foreach m,$(eclipse_project_modules),$(ALL_MODULES.$(m).PATH)) \ - $(foreach m,$(eclipse_project_modules),$(ALL_MODULES.$(m).INTERMEDIATE_SOURCE_DIR)) \ - $(INTERNAL_SDK_SOURCE_DIRS) + $(foreach m,$(eclipse_project_modules),$(ALL_MODULES.$(m).INTERMEDIATE_SOURCE_DIR)) source_paths := $(sort $(source_paths)) .classpath: PRIVATE_MODULES := $(eclipse_project_modules) diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk index f6cec15252..cf32d652c5 100644 --- a/core/tasks/module-info.mk +++ b/core/tasks/module-info.mk @@ -14,11 +14,12 @@ $(MODULE_INFO_JSON): '"compatibility_suites": [$(foreach w,$(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)),"$(w)", )], ' \ '"auto_test_config": [$(ALL_MODULES.$(m).auto_test_config)], ' \ '"module_name": "$(ALL_MODULES.$(m).MODULE_NAME)", ' \ - '"test_config": [$(if $(ALL_MODULES.$(m).TEST_CONFIG),"$(ALL_MODULES.$(m).TEST_CONFIG)")], ' \ + '"test_config": [$(foreach w,$(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)),"$(w)", )], ' \ '"dependencies": [$(foreach w,$(sort $(ALL_DEPS.$(m).ALL_DEPS)),"$(w)", )], ' \ '"srcs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SRCS)),"$(w)", )], ' \ '"srcjars": [$(foreach w,$(sort $(ALL_MODULES.$(m).SRCJARS)),"$(w)", )], ' \ '"classes_jar": [$(foreach w,$(sort $(ALL_MODULES.$(m).CLASSES_JAR)),"$(w)", )], ' \ + '"test_mainline_modules": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_MAINLINE_MODULES)),"$(w)", )], ' \ '},\n' \ ) | sed -e 's/, *\]/]/g' -e 's/, *\}/ }/g' -e '$$s/,$$//' >> $@ $(hide) echo '}' >> $@ diff --git a/core/tasks/platform_availability_check.mk b/core/tasks/platform_availability_check.mk index 043d130440..f252ff5301 100644 --- a/core/tasks/platform_availability_check.mk +++ b/core/tasks/platform_availability_check.mk @@ -26,11 +26,31 @@ $(strip $(foreach m,$(product_MODULES),\ $(if $(filter true,$(ALL_MODULES.$(m).NOT_AVAILABLE_FOR_PLATFORM)),\ $(m)))))) -_violators_with_path := $(foreach m,$(sort $(_modules_not_available_for_platform)),\ +ifndef ALLOW_MISSING_DEPENDENCIES + _violators_with_path := $(foreach m,$(sort $(_modules_not_available_for_platform)),\ $(m):$(word 1,$(ALL_MODULES.$(m).PATH))\ -) + ) -$(call maybe-print-list-and-error,$(_violators_with_path),\ + $(call maybe-print-list-and-error,$(_violators_with_path),\ Following modules are requested to be installed. But are not available \ for platform because they do not have "//apex_available:platform" or \ they depend on other modules that are not available for platform) + +else + +# Don't error out immediately when ALLOW_MISSING_DEPENDENCIES is set. +# Instead, add a dependency on a rule that prints the error message. + define not_available_for_platform_rule + not_installable_file := $(patsubst $(OUT_DIR)/%,$(OUT_DIR)/NOT_AVAILABLE_FOR_PLATFORM/%,$(1))) + $(1): $$(not_installable_file) + $$(not_installable_file): + $(call echo-error,$(2),Module is requested to be installed but is not \ +available for platform because it does not have "//apex_available:platform" or \ +it depends on other modules that are not available for platform.) + exit 1 + endef + + $(foreach m,$(_modules_not_available_for_platform),\ + $(foreach i,$(ALL_MODULES.$(m).INSTALLED),\ + $(eval $(call not_available_for_platform_rule,$(i),$(m))))) +endif diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk index 89b0b9b1bf..f394b96682 100644 --- a/core/tasks/tools/compatibility.mk +++ b/core/tasks/tools/compatibility.mk @@ -26,10 +26,12 @@ # Output variables: # compatibility_zip: the path to the output zip file. -out_dir := $(HOST_OUT)/$(test_suite_name)/android-$(test_suite_name) +test_suite_subdir := android-$(test_suite_name) +out_dir := $(HOST_OUT)/$(test_suite_name)/$(test_suite_subdir) test_artifacts := $(COMPATIBILITY.$(test_suite_name).FILES) test_tools := $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar \ $(HOST_OUT_JAVA_LIBRARIES)/tradefed.jar \ + $(HOST_OUT_JAVA_LIBRARIES)/tradefed-no-fwk.jar \ $(HOST_OUT_JAVA_LIBRARIES)/tradefed-test-framework.jar \ $(HOST_OUT_JAVA_LIBRARIES)/loganalysis.jar \ $(HOST_OUT_JAVA_LIBRARIES)/compatibility-host-util.jar \ @@ -43,24 +45,65 @@ test_tools := $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar \ test_tools += $(test_suite_tools) +# The JDK to package into the test suite zip file. Always package the linux JDK. +test_suite_jdk_dir := $(ANDROID_JAVA_HOME)/../linux-x86 +test_suite_jdk := $(call intermediates-dir-for,PACKAGING,$(test_suite_name)_jdk,HOST)/jdk.zip +$(test_suite_jdk): PRIVATE_JDK_DIR := $(test_suite_jdk_dir) +$(test_suite_jdk): PRIVATE_SUBDIR := $(test_suite_subdir) +$(test_suite_jdk): $(shell find $(test_suite_jdk_dir) -type f | sort) +$(test_suite_jdk): $(SOONG_ZIP) + $(SOONG_ZIP) -o $@ -P $(PRIVATE_SUBDIR)/jdk -C $(PRIVATE_JDK_DIR) -D $(PRIVATE_JDK_DIR) + # Include host shared libraries host_shared_libs := $(call copy-many-files, $(COMPATIBILITY.$(test_suite_name).HOST_SHARED_LIBRARY.FILES)) +compatibility_zip_deps := \ + $(test_artifacts) \ + $(test_tools) \ + $(test_suite_prebuilt_tools) \ + $(test_suite_dynamic_config) \ + $(test_suite_jdk) \ + $(MERGE_ZIPS) \ + $(SOONG_ZIP) \ + $(host_shared_libs) \ + +compatibility_zip_resources := $(out_dir)/tools $(out_dir)/testcases + +# Test Suite NOTICE files +test_suite_notice_txt := $(out_dir)/NOTICE.txt +test_suite_notice_html := $(out_dir)/NOTICE.html + +$(eval $(call combine-notice-files, html, \ + $(test_suite_notice_txt), \ + $(test_suite_notice_html), \ + "Notices for files contained in the test suites filesystem image in this directory:", \ + $(HOST_OUT_NOTICE_FILES) $(TARGET_OUT_NOTICE_FILES), \ + $(compatibility_zip_deps))) + +ifeq ($(include_test_suite_notice),true) + compatibility_zip_deps += $(test_suite_notice_txt) + compatibility_zip_resources += $(test_suite_notice_txt) +endif + compatibility_zip := $(out_dir).zip -$(compatibility_zip): PRIVATE_NAME := android-$(test_suite_name) $(compatibility_zip): PRIVATE_OUT_DIR := $(out_dir) $(compatibility_zip): PRIVATE_TOOLS := $(test_tools) $(test_suite_prebuilt_tools) $(compatibility_zip): PRIVATE_SUITE_NAME := $(test_suite_name) $(compatibility_zip): PRIVATE_DYNAMIC_CONFIG := $(test_suite_dynamic_config) -$(compatibility_zip): $(test_artifacts) $(test_tools) $(test_suite_prebuilt_tools) $(test_suite_dynamic_config) $(SOONG_ZIP) $(host_shared_libs) | $(ADB) $(ACP) +$(compatibility_zip): PRIVATE_RESOURCES := $(compatibility_zip_resources) +$(compatibility_zip): PRIVATE_JDK := $(test_suite_jdk) +$(compatibility_zip): $(compatibility_zip_deps) | $(ADB) $(ACP) # Make dir structure - $(hide) mkdir -p $(PRIVATE_OUT_DIR)/tools $(PRIVATE_OUT_DIR)/testcases - $(hide) echo $(BUILD_NUMBER_FROM_FILE) > $(PRIVATE_OUT_DIR)/tools/version.txt + mkdir -p $(PRIVATE_OUT_DIR)/tools $(PRIVATE_OUT_DIR)/testcases + rm -f $@ $@.tmp $@.jdk + echo $(BUILD_NUMBER_FROM_FILE) > $(PRIVATE_OUT_DIR)/tools/version.txt # Copy tools - $(hide) cp $(PRIVATE_TOOLS) $(PRIVATE_OUT_DIR)/tools + cp $(PRIVATE_TOOLS) $(PRIVATE_OUT_DIR)/tools $(if $(PRIVATE_DYNAMIC_CONFIG),$(hide) cp $(PRIVATE_DYNAMIC_CONFIG) $(PRIVATE_OUT_DIR)/testcases/$(PRIVATE_SUITE_NAME).dynamic) - $(hide) find $(PRIVATE_OUT_DIR)/tools $(PRIVATE_OUT_DIR)/testcases | sort >$@.list - $(hide) $(SOONG_ZIP) -d -o $@ -C $(dir $@) -l $@.list + find $(PRIVATE_RESOURCES) | sort >$@.list + $(SOONG_ZIP) -d -o $@.tmp -C $(dir $@) -l $@.list + $(MERGE_ZIPS) $@ $@.tmp $(PRIVATE_JDK) + rm -f $@.tmp # Reset all input variables test_suite_name := @@ -69,4 +112,7 @@ test_suite_dynamic_config := test_suite_readme := test_suite_prebuilt_tools := test_suite_tools := +include_test_suite_notice := +test_suite_jdk := +test_suite_jdk_dir := host_shared_libs := diff --git a/core/tasks/tools/package-modules.mk b/core/tasks/tools/package-modules.mk index 7c4266ce4f..2b43f0fed3 100644 --- a/core/tasks/tools/package-modules.mk +++ b/core/tasks/tools/package-modules.mk @@ -16,7 +16,16 @@ # my_makefile := $(lastword $(filter-out $(lastword $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) -my_staging_dir := $(call intermediates-dir-for,PACKAGING,$(my_package_name)) + +include $(CLEAR_VARS) +LOCAL_MODULE := $(my_package_name) +LOCAL_MODULE_CLASS := PACKAGING +LOCAL_MODULE_STEM := $(my_package_name).zip +LOCAL_UNINSTALLABLE_MODULE := true +include $(BUILD_SYSTEM)/base_rules.mk +my_staging_dir := $(intermediates) +my_package_zip := $(LOCAL_BUILT_MODULE) + my_built_modules := $(foreach p,$(my_copy_pairs),$(call word-colon,1,$(p))) my_copy_pairs := $(foreach p,$(my_copy_pairs),$(call word-colon,1,$(p)):$(my_staging_dir)/$(call word-colon,2,$(p))) my_pickup_files := @@ -80,7 +89,6 @@ ifneq ($(my_missing_error),) $(error done) endif -my_package_zip := $(my_staging_dir)/$(my_package_name).zip $(my_package_zip): PRIVATE_COPY_PAIRS := $(my_copy_pairs) $(my_package_zip): PRIVATE_PICKUP_FILES := $(my_pickup_files) $(my_package_zip) : $(my_built_modules) diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk index b4c5a3bc61..4d7d67eb4d 100644 --- a/core/tasks/vendor_module_check.mk +++ b/core/tasks/vendor_module_check.mk @@ -108,10 +108,10 @@ ifneq (,$(filter path all, $(_restrictions))) $(foreach m, $(_vendor_check_modules), \ $(if $(filter-out ,$(ALL_MODULES.$(m).INSTALLED)),\ - $(if $(filter $(TARGET_OUT_VENDOR)/% $(TARGET_OUT_ODM)/% $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED)),,\ + $(if $(filter $(TARGET_OUT_VENDOR)/% $(TARGET_OUT_ODM)/% $(TARGET_OUT_VENDOR_DLKM)/% $(TARGET_OUT_ODM_DLKM)/% $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED)),,\ $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) \ in product "$(TARGET_PRODUCT)" being installed to \ - $(ALL_MODULES.$(m).INSTALLED) which is not in the vendor tree or odm tree)))) + $(ALL_MODULES.$(m).INSTALLED) which is not in the vendor, odm, vendor_dlkm or odm_dlkm tree)))) endif diff --git a/core/tasks/vndk.mk b/core/tasks/vndk.mk index a2973b4c8e..ebe9bd4736 100644 --- a/core/tasks/vndk.mk +++ b/core/tasks/vndk.mk @@ -20,18 +20,11 @@ ifeq ($(BOARD_VNDK_VERSION),current) # PLATFORM_VNDK_VERSION must be set. ifneq (,$(PLATFORM_VNDK_VERSION)) -# BOARD_VNDK_RUNTIME_DISABLE must not be set to 'true'. -ifneq ($(BOARD_VNDK_RUNTIME_DISABLE),true) - .PHONY: vndk vndk: $(SOONG_VNDK_SNAPSHOT_ZIP) $(call dist-for-goals, vndk, $(SOONG_VNDK_SNAPSHOT_ZIP)) -else # BOARD_VNDK_RUNTIME_DISABLE is set to 'true' -error_msg := "CANNOT generate VNDK snapshot. BOARD_VNDK_RUNTIME_DISABLE must not be set to 'true'." -endif # BOARD_VNDK_RUNTIME_DISABLE - else # PLATFORM_VNDK_VERSION is NOT set error_msg := "CANNOT generate VNDK snapshot. PLATFORM_VNDK_VERSION must be set." endif # PLATFORM_VNDK_VERSION diff --git a/core/test_config_common.mk b/core/test_config_common.mk deleted file mode 100644 index 487f9f2277..0000000000 --- a/core/test_config_common.mk +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_MODULE_CLASS := TEST_CONFIG - -# Output test config files to testcases directory. -ifeq (,$(filter general-tests, $(LOCAL_COMPATIBILITY_SUITE))) - LOCAL_COMPATIBILITY_SUITE += general-tests -endif - -LOCAL_MODULE_SUFFIX := .config - -my_test_config_file := $(wildcard $(LOCAL_PATH)/$(LOCAL_MODULE).xml) -LOCAL_SRC_FILES := - -include $(BUILD_SYSTEM)/base_rules.mk - -# The test config is not in a standalone XML file. -ifndef my_test_config_file - -ifndef LOCAL_TEST_CONFIG_OPTIONS - $(call pretty-error,LOCAL_TEST_CONFIG_OPTIONS must be set if the test XML file is not provided.) -endif - -my_base_test_config_file := $(LOCAL_PATH)/AndroidTest.xml -my_test_config_file := $(dir $(LOCAL_BUILT_MODULE))AndroidTest.xml - -$(my_test_config_file) : PRIVATE_test_config_options := $(LOCAL_TEST_CONFIG_OPTIONS) -$(my_test_config_file) : $(my_base_test_config_file) - @echo "Create $(notdir $@) with options: $(PRIVATE_test_config_options)." - $(eval _option_xml := \ - $(foreach option,$(PRIVATE_test_config_options), \ - $(eval p := $(subst :,$(space),$(option))) \ - <option name="$(word 1,$(p))" value="$(word 2,$(p))" \/>\n)) - $(hide) sed 's&</configuration>&$(_option_xml)</configuration>&' $< > $@ - -endif # my_test_config_file - -$(LOCAL_BUILT_MODULE) : $(my_test_config_file) - $(copy-file-to-target) - -my_base_test_config_file := -my_test_config_file := diff --git a/core/version_defaults.mk b/core/version_defaults.mk index c28c2fa0c5..b507ca9224 100644 --- a/core/version_defaults.mk +++ b/core/version_defaults.mk @@ -39,9 +39,9 @@ ifdef INTERNAL_BUILD_ID_MAKEFILE include $(INTERNAL_BUILD_ID_MAKEFILE) endif -DEFAULT_PLATFORM_VERSION := RP1A -MIN_PLATFORM_VERSION := RP1A -MAX_PLATFORM_VERSION := RP1A +DEFAULT_PLATFORM_VERSION := SP1A +MIN_PLATFORM_VERSION := SP1A +MAX_PLATFORM_VERSION := SP1A ALLOWED_VERSIONS := $(call allowed-platform-versions,\ $(MIN_PLATFORM_VERSION),\ @@ -93,7 +93,7 @@ PLATFORM_VERSION_LAST_STABLE := 11 # These are the current development codenames, if the build is not a final # release build. If this is a final release build, it is simply "REL". -PLATFORM_VERSION_CODENAME.RP1A := REL +PLATFORM_VERSION_CODENAME.SP1A := S ifndef PLATFORM_VERSION_CODENAME PLATFORM_VERSION_CODENAME := $(PLATFORM_VERSION_CODENAME.$(TARGET_PLATFORM_VERSION)) @@ -240,7 +240,7 @@ ifndef PLATFORM_SECURITY_PATCH # It must be of the form "YYYY-MM-DD" on production devices. # It must match one of the Android Security Patch Level strings of the Public Security Bulletins. # If there is no $PLATFORM_SECURITY_PATCH set, keep it empty. - PLATFORM_SECURITY_PATCH := 2020-09-01 + PLATFORM_SECURITY_PATCH := 2020-09-05 endif .KATI_READONLY := PLATFORM_SECURITY_PATCH diff --git a/envsetup.sh b/envsetup.sh index 793f4b6cfa..abe1eabb2f 100644 --- a/envsetup.sh +++ b/envsetup.sh @@ -8,7 +8,7 @@ Invoke ". build/envsetup.sh" from your shell to add the following functions to y Selects <product_name> as the product to build, and <build_variant> as the variant to build, and stores those selections in the environment to be read by subsequent invocations of 'm' etc. -- tapas: tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [eng|userdebug|user] +- tapas: tapas [<App1> <App2> ...] [arm|x86|arm64|x86_64] [eng|userdebug|user] - croot: Changes directory to the top of the tree, or a subdirectory thereof. - m: Makes from the top of the tree. - mm: Builds and installs all of the modules in the current directory, and their @@ -33,7 +33,7 @@ Invoke ". build/envsetup.sh" from your shell to add the following functions to y - allmod: List all modules. - gomod: Go to the directory containing a module. - pathmod: Get the directory containing a module. -- refreshmod: Refresh list of modules for allmod/gomod. +- refreshmod: Refresh list of modules for allmod/gomod/pathmod. Environment options: - SANITIZE_HOST: Set to 'address' to use ASAN for all host modules. @@ -119,13 +119,13 @@ function get_build_var() if [ "$BUILD_VAR_CACHE_READY" = "true" ] then eval "echo \"\${var_cache_$1}\"" - return + return 0 fi local T=$(gettop) if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." >&2 - return + return 1 fi (\cd $T; build/soong/soong_ui.bash --dumpvar-mode $1) } @@ -218,8 +218,6 @@ function setpaths() arm64) toolchaindir=aarch64/aarch64-linux-android-$targetgccversion/bin; toolchaindir2=arm/arm-linux-androideabi-$targetgccversion2/bin ;; - mips|mips64) toolchaindir=mips/mips64el-linux-android-$targetgccversion/bin - ;; *) echo "Can't find toolchain for unknown architecture: $ARCH" toolchaindir=xxxxxxxxx @@ -578,10 +576,25 @@ function add_lunch_combo() function print_lunch_menu() { local uname=$(uname) - local choices=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES) + local choices + choices=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null) + local ret=$? + echo echo "You're building on" $uname echo + + if [ $ret -ne 0 ] + then + echo "Warning: Cannot display lunch menu." + echo + echo "Note: You can invoke lunch with an explicit target:" + echo + echo " usage: lunch [target]" >&2 + echo + return + fi + echo "Lunch menu... pick a combo:" local i=1 @@ -599,7 +612,12 @@ function lunch() { local answer - if [ "$1" ] ; then + if [[ $# -gt 1 ]]; then + echo "usage: lunch [target]" >&2 + return 1 + fi + + if [ "$1" ]; then answer=$1 else print_lunch_menu @@ -632,7 +650,6 @@ function lunch() export TARGET_BUILD_APPS= local product variant_and_version variant version - product=${selection%%-*} # Trim everything after first dash variant_and_version=${selection#*-} # Trim everything up to first dash if [ "$variant_and_version" != "$selection" ]; then @@ -657,7 +674,6 @@ function lunch() then return 1 fi - export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT) export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT) if [ -n "$version" ]; then @@ -667,10 +683,10 @@ function lunch() fi export TARGET_BUILD_TYPE=release - echo + [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || echo set_stuff_for_environment - printconfig + [[ -n "${ANDROID_QUIET_BUILD:-}" ]] || printconfig destroy_build_var_cache } @@ -696,10 +712,10 @@ function _lunch() function tapas() { local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)" - local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|arm64|x86_64|mips64)$' | xargs)" + local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|arm64|x86_64)$' | xargs)" local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)" local density="$(echo $* | xargs -n 1 echo | \grep -E '^(ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)" - local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|mips|arm64|x86_64|mips64|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)" + local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|arm|x86|arm64|x86_64|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)" if [ "$showHelp" != "" ]; then $(gettop)/build/make/tapasHelp.sh @@ -722,10 +738,8 @@ function tapas() local product=aosp_arm case $arch in x86) product=aosp_x86;; - mips) product=aosp_mips;; arm64) product=aosp_arm64;; x86_64) product=aosp_x86_64;; - mips64) product=aosp_mips64;; esac if [ -z "$variant" ]; then variant=eng @@ -949,7 +963,7 @@ case `uname -s` in Darwin) function sgrep() { - find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cc|cpp|hpp|S|java|xml|sh|mk|aidl|vts)' \ + find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cc|cpp|hpp|S|java|xml|sh|mk|aidl|vts|proto)' \ -exec grep --color -n "$@" {} + } @@ -957,7 +971,7 @@ case `uname -s` in *) function sgrep() { - find . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.\(c\|h\|cc\|cpp\|hpp\|S\|java\|xml\|sh\|mk\|aidl\|vts\)' \ + find . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.\(c\|h\|cc\|cpp\|hpp\|S\|java\|xml\|sh\|mk\|aidl\|vts\|proto\)' \ -exec grep --color -n "$@" {} + } ;; @@ -1599,6 +1613,41 @@ function source_vendorsetup() { done } +function showcommands() { + local T=$(gettop) + if [[ -z "$TARGET_PRODUCT" ]]; then + >&2 echo "TARGET_PRODUCT not set. Run lunch." + return + fi + case $(uname -s) in + Darwin) + PREBUILT_NAME=darwin-x86 + ;; + Linux) + PREBUILT_NAME=linux-x86 + ;; + *) + >&2 echo Unknown host $(uname -s) + return + ;; + esac + if [[ -z "$OUT_DIR" ]]; then + if [[ -z "$OUT_DIR_COMMON_BASE" ]]; then + OUT_DIR=out + else + OUT_DIR=${OUT_DIR_COMMON_BASE}/${PWD##*/} + fi + fi + if [[ "$1" == "--regenerate" ]]; then + shift 1 + NINJA_ARGS="-t commands $@" m + else + (cd $T && prebuilts/build-tools/$PREBUILT_NAME/bin/ninja \ + -f $OUT_DIR/combined-${TARGET_PRODUCT}.ninja \ + -t commands "$@") + fi +} + validate_current_shell source_vendorsetup addcompletions @@ -43,7 +43,11 @@ Common goals are: senod Quickly rebuild the system_ext image from built packages Stands for "SystemExt, NO Dependencies" onod Quickly rebuild the odm image from built packages - Stands for "ODM, NO Dependencies" + Stands for "Odm, NO Dependencies" + vdnod Quickly rebuild the vendor_dlkm image from built packages + Stands for "VendorDlkm, NO Dependencies" + odnod Quickly rebuild the odm_dlkm image from built packages + Stands for "OdmDlkm, NO Dependencies" So, for example, you could run: diff --git a/rbesetup.sh b/rbesetup.sh index 7e9b2ea4e9..724ad7dc56 100644 --- a/rbesetup.sh +++ b/rbesetup.sh @@ -4,7 +4,7 @@ source build/envsetup.sh # for the build to be executed with RBE. function use_rbe() { local RBE_LOG_DIR="/tmp" - local RBE_BINARIES_DIR="prebuilts/remoteexecution-client/latest/" + local RBE_BINARIES_DIR="prebuilts/remoteexecution-client/latest" local DOCKER_IMAGE="gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62" # Do not set an invocation-ID and let reproxy auto-generate one. @@ -23,3 +23,26 @@ function use_rbe() { RBE_re_proxy="${RBE_BINARIES_DIR}/reproxy" \ $@ } + +# This function detects if the uploader is available and sets the path of it to +# ANDROID_ENABLE_METRICS_UPLOAD. +function _export_metrics_uploader() { + local uploader_path="$(gettop)/vendor/google/misc/metrics_uploader_prebuilt/metrics_uploader.sh" + if [ -x "${uploader_path}" ]; then + export ANDROID_ENABLE_METRICS_UPLOAD="${uploader_path}" + fi +} + +# This function sets RBE specific environment variables needed for the build to +# executed by RBE. This file should be sourced once per checkout of Android code. +function _set_rbe_vars() { + unset USE_GOMA + export USE_RBE="true" + export RBE_CXX_EXEC_STRATEGY="remote_local_fallback" + export RBE_JAVAC=1 + export RBE_R8=1 + export RBE_D8=1 +} + +_export_metrics_uploader +_set_rbe_vars diff --git a/tapasHelp.sh b/tapasHelp.sh index 38b3e345bb..0f461304a3 100755 --- a/tapasHelp.sh +++ b/tapasHelp.sh @@ -6,7 +6,7 @@ SCRIPT_DIR="${PWD}" cd ../.. TOP="${PWD}" -message='usage: tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [eng|userdebug|user] +message='usage: tapas [<App1> <App2> ...] [arm|x86|arm64|x86_64] [eng|userdebug|user] tapas selects individual apps to be built by the Android build system. Unlike "lunch", "tapas" does not request the building of images for a device. diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk index 49f6edcde4..e34dc23339 100644 --- a/target/board/BoardConfigGsiCommon.mk +++ b/target/board/BoardConfigGsiCommon.mk @@ -11,7 +11,9 @@ TARGET_NO_KERNEL := true # This flag is set by mainline but isn't desired for GSI. BOARD_USES_SYSTEM_OTHER_ODEX := -# system.img is always ext4 with sparse option +# system.img is always ext4 and non-sparsed. +TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true + # GSI also includes make_f2fs to support userdata parition in f2fs # for some devices TARGET_USERIMAGES_USE_F2FS := true @@ -33,12 +35,19 @@ BOARD_USES_METADATA_PARTITION := true # updating the last seen rollback index in the tamper-evident storage. BOARD_AVB_ROLLBACK_INDEX := 0 -# Enable chain partition for system. -# GSI need to sign on system.img instead of vbmeta. +# Enable AVB chained partition for system. +# https://android.googlesource.com/platform/external/avb/+/master/README.md BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 +ifdef BUILDING_GSI +# super.img spec for GSI targets +BOARD_SUPER_PARTITION_SIZE := 3229614080 +BOARD_SUPER_PARTITION_GROUPS := gsi_dynamic_partitions +BOARD_GSI_DYNAMIC_PARTITIONS_PARTITION_LIST := system +BOARD_GSI_DYNAMIC_PARTITIONS_SIZE := 3221225472 +endif # Enable chain partition for boot, mainly for GKI images. BOARD_AVB_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem @@ -58,7 +67,7 @@ endif BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4 BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216 -# Setup a vendor image to let PRODUCT_PROPERTY_OVERRIDES does not affect GSI +# Setup a vendor image to let PRODUCT_VENDOR_PROPERTIES does not affect GSI BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4 # Disable 64 bit mediadrmserver diff --git a/target/board/emulator_arm/AndroidBoard.mk b/target/board/emulator_arm/AndroidBoard.mk new file mode 100644 index 0000000000..7911f6105f --- /dev/null +++ b/target/board/emulator_arm/AndroidBoard.mk @@ -0,0 +1 @@ +LOCAL_PATH := $(call my-dir) diff --git a/target/board/emulator_arm/BoardConfig.mk b/target/board/emulator_arm/BoardConfig.mk new file mode 100644 index 0000000000..287824fa7b --- /dev/null +++ b/target/board/emulator_arm/BoardConfig.mk @@ -0,0 +1,37 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# arm emulator specific definitions +TARGET_ARCH := arm +TARGET_ARCH_VARIANT := armv7-a-neon +TARGET_CPU_VARIANT := generic +TARGET_CPU_ABI := armeabi-v7a +TARGET_CPU_ABI2 := armeabi + +include build/make/target/board/BoardConfigGsiCommon.mk +include build/make/target/board/BoardConfigEmuCommon.mk + +BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800 + +# Wifi. +BOARD_WLAN_DEVICE := emulator +BOARD_HOSTAPD_DRIVER := NL80211 +BOARD_WPA_SUPPLICANT_DRIVER := NL80211 +BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated +BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated +WPA_SUPPLICANT_VERSION := VER_0_8_X +WIFI_DRIVER_FW_PATH_PARAM := "/dev/null" +WIFI_DRIVER_FW_PATH_STA := "/dev/null" +WIFI_DRIVER_FW_PATH_AP := "/dev/null" diff --git a/core/target_test_config.mk b/target/board/emulator_arm/device.mk index 61f5d2b2e3..af023eb25c 100644 --- a/core/target_test_config.mk +++ b/target/board/emulator_arm/device.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2017 The Android Open Source Project +# Copyright (C) 2020 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,10 +14,5 @@ # limitations under the License. # -# -# Common rules for building a TradeFed test XML file for target side tests. -# - -$(call record-module-type,TARGET_TEST_CONFIG) - -include $(BUILD_SYSTEM)/test_config_common.mk +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps. diff --git a/target/board/emulator_arm/system_ext.prop b/target/board/emulator_arm/system_ext.prop new file mode 100644 index 0000000000..64829f3ce4 --- /dev/null +++ b/target/board/emulator_arm/system_ext.prop @@ -0,0 +1,5 @@ +# +# system.prop for generic sdk +# + +rild.libpath=/vendor/lib/libreference-ril.so diff --git a/target/board/emulator_arm64/device.mk b/target/board/emulator_arm64/device.mk index 57675d02de..73dc2f4c4f 100644 --- a/target/board/emulator_arm64/device.mk +++ b/target/board/emulator_arm64/device.mk @@ -26,7 +26,3 @@ endif PRODUCT_COPY_FILES += \ $(LOCAL_KERNEL):kernel - -# Adjust the Dalvik heap to be appropriate for a tablet. -$(call inherit-product-if-exists, frameworks/base/build/tablet-dalvik-heap.mk) -$(call inherit-product-if-exists, frameworks/native/build/tablet-dalvik-heap.mk) diff --git a/target/board/emulator_x86/BoardConfig.mk b/target/board/emulator_x86/BoardConfig.mk new file mode 100644 index 0000000000..8f79166b48 --- /dev/null +++ b/target/board/emulator_x86/BoardConfig.mk @@ -0,0 +1,40 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# x86 emulator specific definitions +TARGET_CPU_ABI := x86 +TARGET_ARCH := x86 +TARGET_ARCH_VARIANT := x86 + +TARGET_PRELINK_MODULE := false + +include build/make/target/board/BoardConfigGsiCommon.mk +include build/make/target/board/BoardConfigEmuCommon.mk + +# Resize to 4G to accommodate ASAN and CTS +BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296 + +BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86 + +# Wifi. +BOARD_WLAN_DEVICE := emulator +BOARD_HOSTAPD_DRIVER := NL80211 +BOARD_WPA_SUPPLICANT_DRIVER := NL80211 +BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated +BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated +WPA_SUPPLICANT_VERSION := VER_0_8_X +WIFI_DRIVER_FW_PATH_PARAM := "/dev/null" +WIFI_DRIVER_FW_PATH_STA := "/dev/null" +WIFI_DRIVER_FW_PATH_AP := "/dev/null" diff --git a/target/board/emulator_x86/device.mk b/target/board/emulator_x86/device.mk new file mode 100644 index 0000000000..8a9d8da921 --- /dev/null +++ b/target/board/emulator_x86/device.mk @@ -0,0 +1,27 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps. + +ifdef NET_ETH0_STARTONBOOT + PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1 +endif + +# Ensure we package the BIOS files too. +PRODUCT_HOST_PACKAGES += \ + bios.bin \ + vgabios-cirrus.bin \ diff --git a/target/board/emulator_x86/system_ext.prop b/target/board/emulator_x86/system_ext.prop new file mode 100644 index 0000000000..64829f3ce4 --- /dev/null +++ b/target/board/emulator_x86/system_ext.prop @@ -0,0 +1,5 @@ +# +# system.prop for generic sdk +# + +rild.libpath=/vendor/lib/libreference-ril.so diff --git a/target/board/emulator_x86_64/BoardConfig.mk b/target/board/emulator_x86_64/BoardConfig.mk new file mode 100755 index 0000000000..b9cbd8a243 --- /dev/null +++ b/target/board/emulator_x86_64/BoardConfig.mk @@ -0,0 +1,42 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# x86_64 emulator specific definitions +TARGET_CPU_ABI := x86_64 +TARGET_ARCH := x86_64 +TARGET_ARCH_VARIANT := x86_64 + +TARGET_2ND_CPU_ABI := x86 +TARGET_2ND_ARCH := x86 +TARGET_2ND_ARCH_VARIANT := x86_64 + +TARGET_PRELINK_MODULE := false +include build/make/target/board/BoardConfigGsiCommon.mk +include build/make/target/board/BoardConfigEmuCommon.mk + +BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800 + +BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86 + +# Wifi. +BOARD_WLAN_DEVICE := emulator +BOARD_HOSTAPD_DRIVER := NL80211 +BOARD_WPA_SUPPLICANT_DRIVER := NL80211 +BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated +BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated +WPA_SUPPLICANT_VERSION := VER_0_8_X +WIFI_DRIVER_FW_PATH_PARAM := "/dev/null" +WIFI_DRIVER_FW_PATH_STA := "/dev/null" +WIFI_DRIVER_FW_PATH_AP := "/dev/null" diff --git a/target/board/emulator_x86_64/device.mk b/target/board/emulator_x86_64/device.mk new file mode 100755 index 0000000000..8a9d8da921 --- /dev/null +++ b/target/board/emulator_x86_64/device.mk @@ -0,0 +1,27 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps. + +ifdef NET_ETH0_STARTONBOOT + PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1 +endif + +# Ensure we package the BIOS files too. +PRODUCT_HOST_PACKAGES += \ + bios.bin \ + vgabios-cirrus.bin \ diff --git a/target/board/emulator_x86_64/system_ext.prop b/target/board/emulator_x86_64/system_ext.prop new file mode 100644 index 0000000000..ed9d1731c7 --- /dev/null +++ b/target/board/emulator_x86_64/system_ext.prop @@ -0,0 +1,5 @@ +# +# system.prop for generic sdk +# + +rild.libpath=/vendor/lib64/libreference-ril.so diff --git a/target/board/emulator_x86_64_arm64/BoardConfig.mk b/target/board/emulator_x86_64_arm64/BoardConfig.mk new file mode 100755 index 0000000000..26b61a6787 --- /dev/null +++ b/target/board/emulator_x86_64_arm64/BoardConfig.mk @@ -0,0 +1,59 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# x86_64 emulator specific definitions +TARGET_CPU_ABI := x86_64 +TARGET_ARCH := x86_64 +TARGET_ARCH_VARIANT := x86_64 + +TARGET_2ND_CPU_ABI := x86 +TARGET_2ND_ARCH := x86 +TARGET_2ND_ARCH_VARIANT := x86_64 + +TARGET_NATIVE_BRIDGE_ARCH := arm64 +TARGET_NATIVE_BRIDGE_ARCH_VARIANT := armv8-a +TARGET_NATIVE_BRIDGE_CPU_VARIANT := generic +TARGET_NATIVE_BRIDGE_ABI := arm64-v8a + +TARGET_NATIVE_BRIDGE_2ND_ARCH := arm +TARGET_NATIVE_BRIDGE_2ND_ARCH_VARIANT := armv7-a-neon +TARGET_NATIVE_BRIDGE_2ND_CPU_VARIANT := generic +TARGET_NATIVE_BRIDGE_2ND_ABI := armeabi-v7a armeabi + +BUILD_BROKEN_DUP_RULES := true + +TARGET_PRELINK_MODULE := false + +include build/make/target/board/BoardConfigMainlineCommon.mk +include build/make/target/board/BoardConfigEmuCommon.mk + +# the settings differ from BoardConfigMainlineCommon.mk +BOARD_USES_SYSTEM_OTHER_ODEX := + +# Resize to 4G to accommodate ASAN and CTS +BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296 + +BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86 + +# Wifi. +BOARD_WLAN_DEVICE := emulator +BOARD_HOSTAPD_DRIVER := NL80211 +BOARD_WPA_SUPPLICANT_DRIVER := NL80211 +BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated +BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated +WPA_SUPPLICANT_VERSION := VER_0_8_X +WIFI_DRIVER_FW_PATH_PARAM := "/dev/null" +WIFI_DRIVER_FW_PATH_STA := "/dev/null" +WIFI_DRIVER_FW_PATH_AP := "/dev/null" diff --git a/target/board/emulator_x86_64_arm64/device.mk b/target/board/emulator_x86_64_arm64/device.mk new file mode 100755 index 0000000000..af023eb25c --- /dev/null +++ b/target/board/emulator_x86_64_arm64/device.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps. diff --git a/target/board/emulator_x86_64_arm64/system_ext.prop b/target/board/emulator_x86_64_arm64/system_ext.prop new file mode 100644 index 0000000000..ed9d1731c7 --- /dev/null +++ b/target/board/emulator_x86_64_arm64/system_ext.prop @@ -0,0 +1,5 @@ +# +# system.prop for generic sdk +# + +rild.libpath=/vendor/lib64/libreference-ril.so diff --git a/target/board/emulator_x86_arm/BoardConfig.mk b/target/board/emulator_x86_arm/BoardConfig.mk new file mode 100644 index 0000000000..21fdbc8e99 --- /dev/null +++ b/target/board/emulator_x86_arm/BoardConfig.mk @@ -0,0 +1,52 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# x86 emulator specific definitions +TARGET_CPU_ABI := x86 +TARGET_ARCH := x86 +TARGET_ARCH_VARIANT := x86 + +TARGET_NATIVE_BRIDGE_ARCH := arm +TARGET_NATIVE_BRIDGE_ARCH_VARIANT := armv7-a-neon +TARGET_NATIVE_BRIDGE_CPU_VARIANT := generic +TARGET_NATIVE_BRIDGE_ABI := armeabi-v7a armeabi + +BUILD_BROKEN_DUP_RULES := true + +# +# The inclusion order below is important. +# The settings in latter makefiles overwrite those in the former. +# +include build/make/target/board/BoardConfigMainlineCommon.mk +include build/make/target/board/BoardConfigEmuCommon.mk + +# the settings differ from BoardConfigMainlineCommon.mk +BOARD_USES_SYSTEM_OTHER_ODEX := + +# Resize to 4G to accommodate ASAN and CTS +BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296 + +BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86 + +# Wifi. +BOARD_WLAN_DEVICE := emulator +BOARD_HOSTAPD_DRIVER := NL80211 +BOARD_WPA_SUPPLICANT_DRIVER := NL80211 +BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated +BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated +WPA_SUPPLICANT_VERSION := VER_0_8_X +WIFI_DRIVER_FW_PATH_PARAM := "/dev/null" +WIFI_DRIVER_FW_PATH_STA := "/dev/null" +WIFI_DRIVER_FW_PATH_AP := "/dev/null" diff --git a/target/board/emulator_x86_arm/device.mk b/target/board/emulator_x86_arm/device.mk new file mode 100644 index 0000000000..af023eb25c --- /dev/null +++ b/target/board/emulator_x86_arm/device.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu +PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps. diff --git a/target/board/emulator_x86_arm/system_ext.prop b/target/board/emulator_x86_arm/system_ext.prop new file mode 100644 index 0000000000..64829f3ce4 --- /dev/null +++ b/target/board/emulator_x86_arm/system_ext.prop @@ -0,0 +1,5 @@ +# +# system.prop for generic sdk +# + +rild.libpath=/vendor/lib/libreference-ril.so diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk index 8624ed72b3..87c16daade 100644 --- a/target/board/generic/BoardConfig.mk +++ b/target/board/generic/BoardConfig.mk @@ -30,6 +30,8 @@ TARGET_CPU_ABI := armeabi-v7a TARGET_CPU_ABI2 := armeabi include build/make/target/board/BoardConfigGsiCommon.mk + +ifndef BUILDING_GSI include build/make/target/board/BoardConfigEmuCommon.mk BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800 @@ -44,3 +46,4 @@ WPA_SUPPLICANT_VERSION := VER_0_8_X WIFI_DRIVER_FW_PATH_PARAM := "/dev/null" WIFI_DRIVER_FW_PATH_STA := "/dev/null" WIFI_DRIVER_FW_PATH_AP := "/dev/null" +endif diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk index cfb15f0656..76242c90b2 100644 --- a/target/board/generic/device.mk +++ b/target/board/generic/device.mk @@ -16,12 +16,3 @@ PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps. - -# NFC: -# Provide default libnfc-nci.conf file for devices that does not have one in -# vendor/etc because aosp system image (of aosp_$arch products) is going to -# be used as GSI. -# May need to remove the following for newly launched devices in P since this -# NFC configuration file should be in vendor/etc, instead of system/etc -PRODUCT_COPY_FILES += \ - device/generic/common/nfc/libnfc-nci.conf:system/etc/libnfc-nci.conf diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk index ba696230f4..c45a8abd9c 100644 --- a/target/board/generic_arm64/BoardConfig.mk +++ b/target/board/generic_arm64/BoardConfig.mk @@ -60,15 +60,27 @@ BOARD_USES_RECOVERY_AS_BOOT := true BOARD_KERNEL-4.19-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920 BOARD_KERNEL-5.4_BOOTIMAGE_PARTITION_SIZE := 67108864 +BOARD_KERNEL-5.4-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 67108864 BOARD_KERNEL-5.4-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920 +BOARD_KERNEL-5.4-GZ-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 47185920 BOARD_KERNEL-5.4-LZ4_BOOTIMAGE_PARTITION_SIZE := 53477376 +BOARD_KERNEL-5.4-LZ4-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 53477376 +BOARD_KERNEL-MAINLINE_BOOTIMAGE_PARTITION_SIZE := 67108864 +BOARD_KERNEL-MAINLINE-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920 +BOARD_KERNEL-MAINLINE-LZ4_BOOTIMAGE_PARTITION_SIZE := 53477376 + BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800 BOARD_RAMDISK_USE_LZ4 := true BOARD_BOOT_HEADER_VERSION := 3 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION) -BOARD_KERNEL_BINARIES := kernel-4.19-gz kernel-5.4 kernel-5.4-gz kernel-5.4-lz4 +BOARD_KERNEL_BINARIES := kernel-4.19-gz kernel-5.4 kernel-5.4-gz kernel-5.4-lz4 \ + kernel-mainline kernel-mainline-gz kernel-mainline-lz4 +ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) +BOARD_KERNEL_BINARIES += kernel-5.4-allsyms kernel-5.4-gz-allsyms kernel-5.4-lz4-allsyms +endif +BOARD_KERNEL_MODULE_INTERFACE_VERSIONS := 5.4-android12-0 # Some vendors still haven't cleaned up all device specific directories under # root! diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk index d96bfc2cf1..1585fbd894 100644 --- a/target/board/generic_arm64/device.mk +++ b/target/board/generic_arm64/device.mk @@ -18,8 +18,14 @@ PRODUCT_COPY_FILES += \ kernel/prebuilts/4.19/arm64/Image.gz:kernel-4.19-gz \ device/google/cuttlefish_kernel/5.4-arm64/kernel-5.4:kernel-5.4 \ device/google/cuttlefish_kernel/5.4-arm64/kernel-5.4-gz:kernel-5.4-gz \ - device/google/cuttlefish_kernel/5.4-arm64/kernel-5.4-lz4:kernel-5.4-lz4 + device/google/cuttlefish_kernel/5.4-arm64/kernel-5.4-lz4:kernel-5.4-lz4 \ + kernel/prebuilts/mainline/arm64/kernel-mainline:kernel-mainline \ + kernel/prebuilts/mainline/arm64/kernel-mainline-gz:kernel-mainline-gz \ + kernel/prebuilts/mainline/arm64/kernel-mainline-lz4:kernel-mainline-lz4 -# Adjust the Dalvik heap to be appropriate for a tablet. -$(call inherit-product-if-exists, frameworks/base/build/tablet-dalvik-heap.mk) -$(call inherit-product-if-exists, frameworks/native/build/tablet-dalvik-heap.mk) +ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) +PRODUCT_COPY_FILES += \ + device/google/cuttlefish_kernel/5.4-arm64/kernel-5.4:kernel-5.4-allsyms \ + device/google/cuttlefish_kernel/5.4-arm64/kernel-5.4-gz:kernel-5.4-gz-allsyms \ + device/google/cuttlefish_kernel/5.4-arm64/kernel-5.4-lz4:kernel-5.4-lz4-allsyms +endif diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk index 83d7eccc7a..c40c15b23b 100644 --- a/target/board/generic_x86/BoardConfig.mk +++ b/target/board/generic_x86/BoardConfig.mk @@ -21,6 +21,7 @@ TARGET_ARCH_VARIANT := x86 TARGET_PRELINK_MODULE := false include build/make/target/board/BoardConfigGsiCommon.mk +ifndef BUILDING_GSI include build/make/target/board/BoardConfigEmuCommon.mk # Resize to 4G to accomodate ASAN and CTS @@ -38,3 +39,4 @@ WPA_SUPPLICANT_VERSION := VER_0_8_X WIFI_DRIVER_FW_PATH_PARAM := "/dev/null" WIFI_DRIVER_FW_PATH_STA := "/dev/null" WIFI_DRIVER_FW_PATH_AP := "/dev/null" +endif diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk index 2b10a3dfa1..5ad008f119 100644 --- a/target/board/generic_x86/device.mk +++ b/target/board/generic_x86/device.mk @@ -18,7 +18,7 @@ PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps. ifdef NET_ETH0_STARTONBOOT - PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1 + PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1 endif # Ensure we package the BIOS files too. diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk index 07bbc071ac..660ec6e7fe 100755 --- a/target/board/generic_x86_64/BoardConfig.mk +++ b/target/board/generic_x86_64/BoardConfig.mk @@ -24,6 +24,7 @@ TARGET_2ND_ARCH_VARIANT := x86_64 TARGET_PRELINK_MODULE := false include build/make/target/board/BoardConfigGsiCommon.mk +ifndef BUILDING_GSI include build/make/target/board/BoardConfigEmuCommon.mk BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800 @@ -40,3 +41,4 @@ WPA_SUPPLICANT_VERSION := VER_0_8_X WIFI_DRIVER_FW_PATH_PARAM := "/dev/null" WIFI_DRIVER_FW_PATH_STA := "/dev/null" WIFI_DRIVER_FW_PATH_AP := "/dev/null" +endif diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk index 2b10a3dfa1..5ad008f119 100755 --- a/target/board/generic_x86_64/device.mk +++ b/target/board/generic_x86_64/device.mk @@ -18,7 +18,7 @@ PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps. ifdef NET_ETH0_STARTONBOOT - PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1 + PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1 endif # Ensure we package the BIOS files too. diff --git a/target/board/gsi_system_ext.prop b/target/board/gsi_system_ext.prop index dd3227efb2..780aadc0ae 100644 --- a/target/board/gsi_system_ext.prop +++ b/target/board/gsi_system_ext.prop @@ -12,8 +12,3 @@ persist.sys.disable_rescue=true # TODO(b/78105955): disable privapp_permissions checking before the bug solved ro.control_privapp_permissions=disable - -# TODO(b/136212765): the default for LMK -ro.lmk.kill_heaviest_task=true -ro.lmk.kill_timeout_ms=100 -ro.lmk.use_minfree_levels=true diff --git a/target/board/gsi_system_ext_user.prop b/target/board/gsi_system_ext_user.prop index db6d880b7a..217bd012ad 100644 --- a/target/board/gsi_system_ext_user.prop +++ b/target/board/gsi_system_ext_user.prop @@ -9,8 +9,3 @@ persist.sys.disable_rescue=true # TODO(b/78105955): disable privapp_permissions checking before the bug solved ro.control_privapp_permissions=disable - -# TODO(b/136212765): the default for LMK -ro.lmk.kill_heaviest_task=true -ro.lmk.kill_timeout_ms=100 -ro.lmk.use_minfree_levels=true diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk index 4121bc10e2..8c069ba36c 100644 --- a/target/product/AndroidProducts.mk +++ b/target/product/AndroidProducts.mk @@ -55,13 +55,16 @@ PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/full.mk \ $(LOCAL_DIR)/full_x86.mk \ $(LOCAL_DIR)/generic.mk \ + $(LOCAL_DIR)/generic_system_arm64.mk \ + $(LOCAL_DIR)/generic_system_x86.mk \ + $(LOCAL_DIR)/generic_system_x86_64.mk \ + $(LOCAL_DIR)/generic_system_x86_arm.mk \ $(LOCAL_DIR)/generic_x86.mk \ $(LOCAL_DIR)/gsi_arm64.mk \ - $(LOCAL_DIR)/mainline_arm64.mk \ $(LOCAL_DIR)/mainline_system_arm64.mk \ $(LOCAL_DIR)/mainline_system_x86.mk \ - $(LOCAL_DIR)/mainline_system_x86_arm.mk \ $(LOCAL_DIR)/mainline_system_x86_64.mk \ + $(LOCAL_DIR)/mainline_system_x86_arm.mk \ $(LOCAL_DIR)/sdk_arm64.mk \ $(LOCAL_DIR)/sdk.mk \ $(LOCAL_DIR)/sdk_phone_arm64.mk \ diff --git a/target/product/OWNERS b/target/product/OWNERS index 1c74859834..259c8f43e9 100644 --- a/target/product/OWNERS +++ b/target/product/OWNERS @@ -1 +1 @@ -per-file runtime_libart.mk = agampe@google.com, calin@google.com, mast@google.com, ngeoffray@google.com, oth@google.com, rpl@google.com, sehr@google.com, vmarko@google.com +per-file runtime_libart.mk = calin@google.com, mast@google.com, ngeoffray@google.com, oth@google.com, rpl@google.com, vmarko@google.com diff --git a/target/product/aosp_arm.mk b/target/product/aosp_arm.mk index 0cec14b176..90acc17fee 100644 --- a/target/product/aosp_arm.mk +++ b/target/product/aosp_arm.mk @@ -26,7 +26,7 @@ PRODUCT_USE_DYNAMIC_PARTITIONS := true # # All components inherited here go to system image # -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking for excat this product name ifeq (aosp_arm,$(TARGET_PRODUCT)) diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk index e88a36683c..38f82a2d60 100644 --- a/target/product/aosp_arm64.mk +++ b/target/product/aosp_arm64.mk @@ -30,7 +30,7 @@ # All components inherited here go to system image # $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking for excat this product name ifeq (aosp_arm64,$(TARGET_PRODUCT)) @@ -49,7 +49,7 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk) # -# All components inherited here go to vendor image +# All components inherited here go to vendor or vendor_boot image # $(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk) $(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk) diff --git a/target/product/aosp_arm64_ab.mk b/target/product/aosp_arm64_ab.mk index 75b9cc4f4b..5510e1b78c 100644 --- a/target/product/aosp_arm64_ab.mk +++ b/target/product/aosp_arm64_ab.mk @@ -14,7 +14,7 @@ # limitations under the License. # -# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at +# PRODUCT_VENDOR_PROPERTIES cannot be used here because sysprops will be at # /vendor/[build|default].prop when build split is on. In order to have sysprops # on the generic system image, place them in build/make/target/board/ # gsi_system.prop. @@ -29,7 +29,7 @@ # (The system image of Legacy GSI is not CSI) # $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking for excat this product name ifeq (aosp_arm64_ab,$(TARGET_PRODUCT)) diff --git a/target/product/aosp_arm_ab.mk b/target/product/aosp_arm_ab.mk index 80ebdb1518..7e06044050 100644 --- a/target/product/aosp_arm_ab.mk +++ b/target/product/aosp_arm_ab.mk @@ -14,7 +14,7 @@ # limitations under the License. # -# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at +# PRODUCT_VENDOR_PROPERTIES cannot be used here because sysprops will be at # /vendor/[build|default].prop when build split is on. In order to have sysprops # on the generic system image, place them in build/make/target/board/ # gsi_system.prop. @@ -28,7 +28,7 @@ # All components inherited here go to system image # (The system image of Legacy GSI is not CSI) # -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking for excat this product name ifeq (aosp_arm_ab,$(TARGET_PRODUCT)) diff --git a/target/product/aosp_product.mk b/target/product/aosp_product.mk index e3819e6115..e396ad11ff 100644 --- a/target/product/aosp_product.mk +++ b/target/product/aosp_product.mk @@ -23,9 +23,9 @@ $(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk) # Additional settings used in all AOSP builds PRODUCT_PRODUCT_PROPERTIES += \ - ro.config.ringtone=Ring_Synth_04.ogg \ - ro.config.notification_sound=pixiedust.ogg \ - ro.com.android.dataroaming=true \ + ro.config.ringtone?=Ring_Synth_04.ogg \ + ro.config.notification_sound?=pixiedust.ogg \ + ro.com.android.dataroaming?=true \ # More AOSP packages PRODUCT_PACKAGES += \ @@ -38,8 +38,3 @@ PRODUCT_PACKAGES += \ # Provide a APN configuration to GSI product PRODUCT_COPY_FILES += \ device/sample/etc/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml - -# NFC: -# Provide a libnfc-nci.conf to GSI product -PRODUCT_COPY_FILES += \ - device/generic/common/nfc/libnfc-nci.conf:$(TARGET_COPY_OUT_PRODUCT)/etc/libnfc-nci.conf diff --git a/target/product/aosp_x86.mk b/target/product/aosp_x86.mk index 51b5dafb0f..7db2c0ff0c 100644 --- a/target/product/aosp_x86.mk +++ b/target/product/aosp_x86.mk @@ -26,7 +26,7 @@ PRODUCT_USE_DYNAMIC_PARTITIONS := true # # All components inherited here go to system image # -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking for excat this product name ifeq (aosp_x86,$(TARGET_PRODUCT)) diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk index 9b26716beb..5d782644dc 100644 --- a/target/product/aosp_x86_64.mk +++ b/target/product/aosp_x86_64.mk @@ -32,7 +32,7 @@ PRODUCT_USE_DYNAMIC_PARTITIONS := true # All components inherited here go to system image # $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking for excat this product name ifeq (aosp_x86_64,$(TARGET_PRODUCT)) diff --git a/target/product/aosp_x86_64_ab.mk b/target/product/aosp_x86_64_ab.mk index 9d23fc7b08..c31545ddf6 100644 --- a/target/product/aosp_x86_64_ab.mk +++ b/target/product/aosp_x86_64_ab.mk @@ -14,7 +14,7 @@ # limitations under the License. # -# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at +# PRODUCT_VENDOR_PROPERTIES cannot be used here because sysprops will be at # /vendor/[build|default].prop when build split is on. In order to have sysprops # on the generic system image, place them in build/make/target/board/ # gsi_system.prop. @@ -29,7 +29,7 @@ # (The system image of Legacy GSI is not CSI) # $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking for excat this product name ifeq (aosp_x86_64_ab,$(TARGET_PRODUCT)) diff --git a/target/product/aosp_x86_ab.mk b/target/product/aosp_x86_ab.mk index 6b6a4c61ad..2f02dd1bc2 100644 --- a/target/product/aosp_x86_ab.mk +++ b/target/product/aosp_x86_ab.mk @@ -14,7 +14,7 @@ # limitations under the License. # -# PRODUCT_PROPERTY_OVERRIDES cannot be used here because sysprops will be at +# PRODUCT_VENDOR_PROPERTIES cannot be used here because sysprops will be at # /vendor/[build|default].prop when build split is on. In order to have sysprops # on the generic system image, place them in build/make/target/board/ # gsi_system.prop. @@ -29,7 +29,7 @@ # (The system image of Legacy GSI is not CSI) # $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking for excat this product name ifeq (aosp_x86_ab,$(TARGET_PRODUCT)) diff --git a/target/product/aosp_x86_arm.mk b/target/product/aosp_x86_arm.mk index deba3d98dd..f96e068b56 100644 --- a/target/product/aosp_x86_arm.mk +++ b/target/product/aosp_x86_arm.mk @@ -19,7 +19,7 @@ PRODUCT_USE_DYNAMIC_PARTITIONS := true # # All components inherited here go to system image # -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking ifeq (aosp_x86_arm,$(TARGET_PRODUCT)) diff --git a/target/product/base_system.mk b/target/product/base_system.mk index 4569bceff9..ccff4a6c85 100644 --- a/target/product/base_system.mk +++ b/target/product/base_system.mk @@ -51,6 +51,7 @@ PRODUCT_PACKAGES += \ cmd \ com.android.adbd \ com.android.conscrypt \ + com.android.cronet \ com.android.extservices \ com.android.i18n \ com.android.ipsec \ @@ -68,7 +69,6 @@ PRODUCT_PACKAGES += \ com.android.wifi \ ContactsProvider \ content \ - crash_dump \ CtsShimPrebuilt \ CtsShimPrivPrebuilt \ debuggerd\ @@ -193,6 +193,7 @@ PRODUCT_PACKAGES += \ libwilhelm \ linker \ linkerconfig \ + llkd \ lmkd \ LocalTransport \ locksettings \ @@ -212,7 +213,7 @@ PRODUCT_PACKAGES += \ mtpd \ ndc \ netd \ - NetworkStack \ + NetworkStackNext \ org.apache.http.legacy \ otacerts \ PackageInstaller \ @@ -324,6 +325,7 @@ PRODUCT_BOOT_JARS := \ $(ART_APEX_JARS) \ framework-minus-apex \ ext \ + com.android.i18n:core-icu4j \ telephony-common \ voip-common \ ims-common @@ -354,10 +356,12 @@ PRODUCT_BOOT_JARS += android.test.base endif PRODUCT_COPY_FILES += system/core/rootdir/init.zygote32.rc:system/etc/init/hw/init.zygote32.rc -PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote32 +PRODUCT_SYSTEM_PROPERTIES += ro.zygote?=zygote32 -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += debug.atrace.tags.enableflags=0 -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += persist.traced.enable=1 +PRODUCT_SYSTEM_PROPERTIES += debug.atrace.tags.enableflags=0 +PRODUCT_SYSTEM_PROPERTIES += persist.traced.enable=1 + +PRODUCT_PROPERTY_OVERRIDES += ro.gfx.angle.supported=true # Packages included only for eng or userdebug builds, previously debug tagged PRODUCT_PACKAGES_DEBUG := \ diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk index 471340b2d1..b955841f64 100644 --- a/target/product/base_vendor.mk +++ b/target/product/base_vendor.mk @@ -66,11 +66,11 @@ PRODUCT_PACKAGES += \ passwd_vendor \ selinux_policy_nonsystem \ shell_and_utilities_vendor \ - vndservice \ # Base module when shipping api level is less than or equal to 29 PRODUCT_PACKAGES_SHIPPING_API_LEVEL_29 += \ android.hardware.configstore@1.1-service \ + vndservice \ vndservicemanager \ # VINTF data for vendor image diff --git a/target/product/core_64_bit.mk b/target/product/core_64_bit.mk index f9baa270a5..7fa6ed2b7f 100644 --- a/target/product/core_64_bit.mk +++ b/target/product/core_64_bit.mk @@ -27,7 +27,7 @@ PRODUCT_COPY_FILES += system/core/rootdir/init.zygote64_32.rc:system/etc/init/hw # Set the zygote property to select the 64-bit primary, 32-bit secondary script # This line must be parsed before the one in core_minimal.mk -PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote64_32 +PRODUCT_SYSTEM_PROPERTIES += ro.zygote=zygote64_32 TARGET_SUPPORTS_32_BIT_APPS := true TARGET_SUPPORTS_64_BIT_APPS := true diff --git a/target/product/core_64_bit_only.mk b/target/product/core_64_bit_only.mk index 8901a50434..63beea9943 100644 --- a/target/product/core_64_bit_only.mk +++ b/target/product/core_64_bit_only.mk @@ -24,7 +24,7 @@ PRODUCT_COPY_FILES += system/core/rootdir/init.zygote64.rc:system/etc/init/hw/in # Set the zygote property to select the 64-bit script. # This line must be parsed before the one in core_minimal.mk -PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote64 +PRODUCT_SYSTEM_PROPERTIES += ro.zygote=zygote64 TARGET_SUPPORTS_32_BIT_APPS := false TARGET_SUPPORTS_64_BIT_APPS := true diff --git a/target/product/emulated_storage.mk b/target/product/emulated_storage.mk index ea5d9ad94d..7d380d9ba7 100644 --- a/target/product/emulated_storage.mk +++ b/target/product/emulated_storage.mk @@ -15,9 +15,9 @@ # PRODUCT_QUOTA_PROJID := 1 -PRODUCT_PROPERTY_OVERRIDES += external_storage.projid.enabled=1 +PRODUCT_VENDOR_PROPERTIES += external_storage.projid.enabled=1 PRODUCT_FS_CASEFOLD := 1 -PRODUCT_PROPERTY_OVERRIDES += external_storage.casefold.enabled=1 +PRODUCT_VENDOR_PROPERTIES += external_storage.casefold.enabled=1 -PRODUCT_PROPERTY_OVERRIDES += external_storage.sdcardfs.enabled=0 +PRODUCT_VENDOR_PROPERTIES += external_storage.sdcardfs.enabled=0 diff --git a/target/product/emulator.mk b/target/product/emulator.mk index 93c861f84c..36da1f7034 100644 --- a/target/product/emulator.mk +++ b/target/product/emulator.mk @@ -47,7 +47,7 @@ $(call inherit-product-if-exists, device/generic/goldfish/vendor.mk) #responding, disble it for now. #still keep it on internal master as it is still working #once it is fixed in aosp, remove this block of comment. -#PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \ +#PRODUCT_VENDOR_PROPERTIES += \ #config.disable_location=true # enable Google-specific location features, diff --git a/target/product/emulator_vendor.mk b/target/product/emulator_vendor.mk index a935d58b15..89c3f3ab69 100644 --- a/target/product/emulator_vendor.mk +++ b/target/product/emulator_vendor.mk @@ -39,7 +39,7 @@ $(call inherit-product-if-exists, device/generic/goldfish/vendor.mk) #responding, disble it for now. #still keep it on internal master as it is still working #once it is fixed in aosp, remove this block of comment. -#PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \ +#PRODUCT_VENDOR_PROPERTIES += \ #config.disable_location=true # enable Google-specific location features, diff --git a/target/product/full.mk b/target/product/full.mk index b356f9d424..adb54ab662 100644 --- a/target/product/full.mk +++ b/target/product/full.mk @@ -19,6 +19,7 @@ # build quite specifically for the emulator, and might not be # entirely appropriate to inherit from for on-device configurations. +$(call inherit-product-if-exists, device/generic/goldfish/arm32-vendor.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/emulator.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk) $(call inherit-product, $(SRC_TARGET_DIR)/board/generic/device.mk) diff --git a/target/product/full_base.mk b/target/product/full_base.mk index ffd3cde11a..a8e1e913f7 100644 --- a/target/product/full_base.mk +++ b/target/product/full_base.mk @@ -43,9 +43,9 @@ PRODUCT_PACKAGES += \ netutils-wrapper-1.0 # Additional settings used in all AOSP builds -PRODUCT_PROPERTY_OVERRIDES := \ - ro.config.ringtone=Ring_Synth_04.ogg \ - ro.config.notification_sound=pixiedust.ogg +PRODUCT_VENDOR_PROPERTIES := \ + ro.config.ringtone?=Ring_Synth_04.ogg \ + ro.config.notification_sound?=pixiedust.ogg # Put en_US first in the list, so make it default. PRODUCT_LOCALES := en_US diff --git a/target/product/full_base_telephony.mk b/target/product/full_base_telephony.mk index af4097d87a..d8a54cd7f3 100644 --- a/target/product/full_base_telephony.mk +++ b/target/product/full_base_telephony.mk @@ -19,9 +19,9 @@ # build quite specifically for the emulator, and might not be # entirely appropriate to inherit from for on-device configurations. -PRODUCT_PROPERTY_OVERRIDES := \ - keyguard.no_require_sim=true \ - ro.com.android.dataroaming=true +PRODUCT_VENDOR_PROPERTIES := \ + keyguard.no_require_sim?=true \ + ro.com.android.dataroaming?=true PRODUCT_COPY_FILES := \ device/sample/etc/apns-full-conf.xml:system/etc/apns-conf.xml \ diff --git a/target/product/full_x86.mk b/target/product/full_x86.mk index 55c450a80f..2f40c03d16 100644 --- a/target/product/full_x86.mk +++ b/target/product/full_x86.mk @@ -28,7 +28,7 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk) $(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk) ifdef NET_ETH0_STARTONBOOT - PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1 + PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1 endif # Ensure we package the BIOS files too. diff --git a/target/product/generic_system.mk b/target/product/generic_system.mk new file mode 100644 index 0000000000..12f58ad3d9 --- /dev/null +++ b/target/product/generic_system.mk @@ -0,0 +1,148 @@ +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This makefile is the basis of a generic system image for a handheld device. +$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk) +# Add adb keys to debuggable AOSP builds (if they exist) +$(call inherit-product-if-exists, vendor/google/security/adb/vendor_key.mk) + +# Enable updating of APEXes +$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk) + +# Shared java libs +PRODUCT_PACKAGES += \ + com.android.nfc_extras \ + +# Applications +PRODUCT_PACKAGES += \ + LiveWallpapersPicker \ + PartnerBookmarksProvider \ + PresencePolling \ + RcsService \ + SafetyRegulatoryInfo \ + Stk \ + Tag \ + TimeZoneUpdater \ + +# OTA support +PRODUCT_PACKAGES += \ + recovery-refresh \ + update_engine \ + update_verifier \ + +# Wrapped net utils for /vendor access. +PRODUCT_PACKAGES += netutils-wrapper-1.0 + +# Charger images +PRODUCT_PACKAGES += charger_res_images + +# system_other support +PRODUCT_PACKAGES += \ + cppreopts.sh \ + otapreopt_script \ + +# Bluetooth libraries +PRODUCT_PACKAGES += \ + audio.a2dp.default \ + audio.hearing_aid.default \ + +# For ringtones that rely on forward lock encryption +PRODUCT_PACKAGES += libfwdlockengine + +# System libraries commonly depended on by things on the system_ext or product partitions. +# These lists will be pruned periodically. +PRODUCT_PACKAGES += \ + android.hardware.biometrics.fingerprint@2.1 \ + android.hardware.radio@1.0 \ + android.hardware.radio@1.1 \ + android.hardware.radio@1.2 \ + android.hardware.radio@1.3 \ + android.hardware.radio@1.4 \ + android.hardware.radio.config@1.0 \ + android.hardware.radio.deprecated@1.0 \ + android.hardware.secure_element@1.0 \ + android.hardware.wifi@1.0 \ + libaudio-resampler \ + libaudiohal \ + libdrm \ + liblogwrap \ + liblz4 \ + libminui \ + libnl \ + libprotobuf-cpp-full \ + +# These libraries are empty and have been combined into libhidlbase, but are still depended +# on by things off /system. +# TODO(b/135686713): remove these +PRODUCT_PACKAGES += \ + libhidltransport \ + libhwbinder \ + +PRODUCT_PACKAGES_DEBUG += \ + avbctl \ + bootctl \ + tinycap \ + tinyhostless \ + tinymix \ + tinypcminfo \ + tinyplay \ + update_engine_client \ + +PRODUCT_HOST_PACKAGES += \ + tinyplay + +# Enable configurable audio policy +PRODUCT_PACKAGES += \ + libaudiopolicyengineconfigurable \ + libpolicy-subsystem + +# Include all zygote init scripts. "ro.zygote" will select one of them. +PRODUCT_COPY_FILES += \ + system/core/rootdir/init.zygote32.rc:system/etc/init/hw/init.zygote32.rc \ + system/core/rootdir/init.zygote64.rc:system/etc/init/hw/init.zygote64.rc \ + system/core/rootdir/init.zygote64_32.rc:system/etc/init/hw/init.zygote64_32.rc \ + +# Enable dynamic partition size +PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true + +PRODUCT_ENFORCE_RRO_TARGETS := * + +# TODO(b/150820813) Settings depends on static overlay, remove this after eliminating the dependency. +PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS := Settings + +PRODUCT_NAME := generic_system +PRODUCT_BRAND := generic + +# Define /system partition-specific product properties to identify that /system +# partition is generic_system. +PRODUCT_SYSTEM_NAME := mainline +PRODUCT_SYSTEM_BRAND := Android +PRODUCT_SYSTEM_MANUFACTURER := Android +PRODUCT_SYSTEM_MODEL := mainline +PRODUCT_SYSTEM_DEVICE := generic + +_base_mk_allowed_list := + +_my_allowed_list := $(_base_mk_allowed_list) + +# For mainline, system.img should be mounted at /, so we include ROOT here. +_my_paths := \ + $(TARGET_COPY_OUT_ROOT)/ \ + $(TARGET_COPY_OUT_SYSTEM)/ \ + +$(call require-artifacts-in-path, $(_my_paths), $(_my_allowed_list)) diff --git a/target/product/generic_system_arm64.mk b/target/product/generic_system_arm64.mk new file mode 100644 index 0000000000..b8b12c3214 --- /dev/null +++ b/target/product/generic_system_arm64.mk @@ -0,0 +1,46 @@ +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# All components inherited here go to system image +# +$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) +$(call enforce-product-packages-exist,) + +# Enable mainline checking +PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true + +PRODUCT_BUILD_CACHE_IMAGE := false +PRODUCT_BUILD_ODM_IMAGE := false +PRODUCT_BUILD_VENDOR_DLKM_IMAGE := false +PRODUCT_BUILD_ODM_DLKM_IMAGE := false +PRODUCT_BUILD_PRODUCT_IMAGE := false +PRODUCT_BUILD_RAMDISK_IMAGE := false +PRODUCT_BUILD_SYSTEM_IMAGE := true +PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false +PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false +PRODUCT_BUILD_USERDATA_IMAGE := false +PRODUCT_BUILD_VENDOR_IMAGE := false + +PRODUCT_SHIPPING_API_LEVEL := 29 + +# TODO(b/137033385): change this back to "all" +PRODUCT_RESTRICT_VENDOR_FILES := owner + +PRODUCT_NAME := generic_system_arm64 +PRODUCT_DEVICE := mainline_arm64 +PRODUCT_BRAND := generic diff --git a/target/product/generic_system_x86.mk b/target/product/generic_system_x86.mk new file mode 100644 index 0000000000..dddcb7e2ed --- /dev/null +++ b/target/product/generic_system_x86.mk @@ -0,0 +1,45 @@ +# +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# All components inherited here go to system image +# +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) +$(call enforce-product-packages-exist,) + +# Enable mainline checking +PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true + +PRODUCT_BUILD_CACHE_IMAGE := false +PRODUCT_BUILD_ODM_IMAGE := false +PRODUCT_BUILD_VENDOR_DLKM_IMAGE := false +PRODUCT_BUILD_ODM_DLKM_IMAGE := false +PRODUCT_BUILD_PRODUCT_IMAGE := false +PRODUCT_BUILD_RAMDISK_IMAGE := false +PRODUCT_BUILD_SYSTEM_IMAGE := true +PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false +PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false +PRODUCT_BUILD_USERDATA_IMAGE := false +PRODUCT_BUILD_VENDOR_IMAGE := false + +PRODUCT_SHIPPING_API_LEVEL := 29 + +# TODO(b/137033385): change this back to "all" +PRODUCT_RESTRICT_VENDOR_FILES := owner + +PRODUCT_NAME := generic_system_x86 +PRODUCT_DEVICE := mainline_x86 +PRODUCT_BRAND := generic diff --git a/target/product/generic_system_x86_64.mk b/target/product/generic_system_x86_64.mk new file mode 100644 index 0000000000..1ca967835a --- /dev/null +++ b/target/product/generic_system_x86_64.mk @@ -0,0 +1,45 @@ +# +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# All components inherited here go to system image +# +$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) +$(call enforce-product-packages-exist,) + +# Enable mainline checking +PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true + +PRODUCT_BUILD_CACHE_IMAGE := false +PRODUCT_BUILD_ODM_IMAGE := false +PRODUCT_BUILD_VENDOR_DLKM_IMAGE := false +PRODUCT_BUILD_ODM_DLKM_IMAGE := false +PRODUCT_BUILD_PRODUCT_IMAGE := false +PRODUCT_BUILD_RAMDISK_IMAGE := false +PRODUCT_BUILD_SYSTEM_IMAGE := true +PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false +PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false +PRODUCT_BUILD_USERDATA_IMAGE := false +PRODUCT_BUILD_VENDOR_IMAGE := false + +PRODUCT_SHIPPING_API_LEVEL := 29 + +PRODUCT_RESTRICT_VENDOR_FILES := all + +PRODUCT_NAME := generic_system_x86_64 +PRODUCT_DEVICE := mainline_x86_64 +PRODUCT_BRAND := generic diff --git a/target/product/generic_system_x86_arm.mk b/target/product/generic_system_x86_arm.mk new file mode 100644 index 0000000000..a62fb9b8ad --- /dev/null +++ b/target/product/generic_system_x86_arm.mk @@ -0,0 +1,45 @@ +# +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# All components inherited here go to system image +# +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) +$(call enforce-product-packages-exist,) + +# Enable mainline checking +PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true + +PRODUCT_BUILD_CACHE_IMAGE := false +PRODUCT_BUILD_ODM_IMAGE := false +PRODUCT_BUILD_VENDOR_DLKM_IMAGE := false +PRODUCT_BUILD_ODM_DLKM_IMAGE := false +PRODUCT_BUILD_PRODUCT_IMAGE := false +PRODUCT_BUILD_RAMDISK_IMAGE := false +PRODUCT_BUILD_SYSTEM_IMAGE := true +PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false +PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false +PRODUCT_BUILD_USERDATA_IMAGE := false +PRODUCT_BUILD_VENDOR_IMAGE := false + +PRODUCT_SHIPPING_API_LEVEL := 29 + +# TODO(b/137033385): change this back to "all" +PRODUCT_RESTRICT_VENDOR_FILES := owner + +PRODUCT_NAME := generic_system_x86_arm +PRODUCT_DEVICE := mainline_x86_arm +PRODUCT_BRAND := generic diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk index ca171dff5c..7f19615edf 100644 --- a/target/product/go_defaults_common.mk +++ b/target/product/go_defaults_common.mk @@ -18,7 +18,7 @@ # Set lowram options and enable traced by default -PRODUCT_PROPERTY_OVERRIDES += \ +PRODUCT_VENDOR_PROPERTIES += \ ro.config.low_ram=true \ # Speed profile services and wifi-service to reduce RAM and storage. diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk index c491d4a593..b4df5fef97 100644 --- a/target/product/gsi/Android.mk +++ b/target/product/gsi/Android.mk @@ -31,10 +31,6 @@ check-vndk-abi-dump-list-timestamp := $(call intermediates-dir-for,PACKAGING,vnd ifeq ($(TARGET_IS_64_BIT)|$(TARGET_2ND_ARCH),true|) # TODO(b/110429754) remove this condition when we support 64-bit-only device check-vndk-list: ; -else ifeq ($(TARGET_BUILD_PDK),true) -# b/118634643: don't check VNDK lib list when building PDK. Some libs (libandroid_net.so -# and some render-script related ones) can't be built in PDK due to missing frameworks/base. -check-vndk-list: ; else ifeq ($(TARGET_SKIP_CURRENT_VNDK),true) check-vndk-list: ; else ifeq ($(BOARD_VNDK_VERSION),) @@ -211,3 +207,13 @@ LOCAL_SYSTEM_EXT_MODULE := true LOCAL_MODULE_RELATIVE_PATH := init include $(BUILD_PREBUILT) + + +include $(CLEAR_VARS) +LOCAL_MODULE := init.vndk-nodef.rc +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_CLASS := ETC +LOCAL_SYSTEM_EXT_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := init + +include $(BUILD_PREBUILT) diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt index 0589517711..baf1382164 100644 --- a/target/product/gsi/current.txt +++ b/target/product/gsi/current.txt @@ -54,197 +54,32 @@ VNDK-SP: libunwindstack.so VNDK-SP: libutils.so VNDK-SP: libutilscallstack.so VNDK-SP: libz.so -VNDK-core: android.frameworks.automotive.display@1.0.so -VNDK-core: android.frameworks.cameraservice.common@2.0.so -VNDK-core: android.frameworks.cameraservice.device@2.0.so -VNDK-core: android.frameworks.cameraservice.service@2.0.so -VNDK-core: android.frameworks.cameraservice.service@2.1.so -VNDK-core: android.frameworks.displayservice@1.0.so -VNDK-core: android.frameworks.schedulerservice@1.0.so -VNDK-core: android.frameworks.sensorservice@1.0.so -VNDK-core: android.frameworks.stats@1.0.so -VNDK-core: android.hardware.atrace@1.0.so VNDK-core: android.hardware.audio.common@2.0.so -VNDK-core: android.hardware.audio.common@4.0.so -VNDK-core: android.hardware.audio.common@5.0.so -VNDK-core: android.hardware.audio.common@6.0.so -VNDK-core: android.hardware.audio.effect@2.0.so -VNDK-core: android.hardware.audio.effect@4.0.so -VNDK-core: android.hardware.audio.effect@5.0.so -VNDK-core: android.hardware.audio.effect@6.0.so -VNDK-core: android.hardware.audio@2.0.so -VNDK-core: android.hardware.audio@4.0.so -VNDK-core: android.hardware.audio@5.0.so -VNDK-core: android.hardware.audio@6.0.so -VNDK-core: android.hardware.authsecret@1.0.so -VNDK-core: android.hardware.automotive.audiocontrol@1.0.so -VNDK-core: android.hardware.automotive.audiocontrol@2.0.so -VNDK-core: android.hardware.automotive.can@1.0.so -VNDK-core: android.hardware.automotive.evs@1.0.so -VNDK-core: android.hardware.automotive.evs@1.1.so VNDK-core: android.hardware.automotive.occupant_awareness-V1-ndk_platform.so -VNDK-core: android.hardware.automotive.sv@1.0.so -VNDK-core: android.hardware.automotive.vehicle@2.0.so -VNDK-core: android.hardware.biometrics.face@1.0.so -VNDK-core: android.hardware.biometrics.fingerprint@2.1.so -VNDK-core: android.hardware.biometrics.fingerprint@2.2.so -VNDK-core: android.hardware.bluetooth.a2dp@1.0.so -VNDK-core: android.hardware.bluetooth.audio@2.0.so -VNDK-core: android.hardware.bluetooth@1.0.so -VNDK-core: android.hardware.bluetooth@1.1.so -VNDK-core: android.hardware.boot@1.0.so -VNDK-core: android.hardware.boot@1.1.so -VNDK-core: android.hardware.broadcastradio@1.0.so -VNDK-core: android.hardware.broadcastradio@1.1.so -VNDK-core: android.hardware.broadcastradio@2.0.so -VNDK-core: android.hardware.camera.common@1.0.so -VNDK-core: android.hardware.camera.device@1.0.so -VNDK-core: android.hardware.camera.device@3.2.so -VNDK-core: android.hardware.camera.device@3.3.so -VNDK-core: android.hardware.camera.device@3.4.so -VNDK-core: android.hardware.camera.device@3.5.so -VNDK-core: android.hardware.camera.device@3.6.so -VNDK-core: android.hardware.camera.metadata@3.2.so -VNDK-core: android.hardware.camera.metadata@3.3.so -VNDK-core: android.hardware.camera.metadata@3.4.so -VNDK-core: android.hardware.camera.metadata@3.5.so -VNDK-core: android.hardware.camera.provider@2.4.so -VNDK-core: android.hardware.camera.provider@2.5.so -VNDK-core: android.hardware.camera.provider@2.6.so -VNDK-core: android.hardware.cas.native@1.0.so -VNDK-core: android.hardware.cas@1.0.so -VNDK-core: android.hardware.cas@1.1.so -VNDK-core: android.hardware.cas@1.2.so VNDK-core: android.hardware.configstore-utils.so VNDK-core: android.hardware.configstore@1.0.so VNDK-core: android.hardware.configstore@1.1.so VNDK-core: android.hardware.confirmationui-support-lib.so -VNDK-core: android.hardware.confirmationui@1.0.so -VNDK-core: android.hardware.contexthub@1.0.so -VNDK-core: android.hardware.contexthub@1.1.so -VNDK-core: android.hardware.drm@1.0.so -VNDK-core: android.hardware.drm@1.1.so -VNDK-core: android.hardware.drm@1.2.so -VNDK-core: android.hardware.drm@1.3.so -VNDK-core: android.hardware.dumpstate@1.0.so -VNDK-core: android.hardware.dumpstate@1.1.so -VNDK-core: android.hardware.fastboot@1.0.so -VNDK-core: android.hardware.gatekeeper@1.0.so -VNDK-core: android.hardware.gnss.measurement_corrections@1.0.so -VNDK-core: android.hardware.gnss.measurement_corrections@1.1.so -VNDK-core: android.hardware.gnss.visibility_control@1.0.so -VNDK-core: android.hardware.gnss@1.0.so -VNDK-core: android.hardware.gnss@1.1.so -VNDK-core: android.hardware.gnss@2.0.so -VNDK-core: android.hardware.gnss@2.1.so VNDK-core: android.hardware.graphics.allocator@2.0.so VNDK-core: android.hardware.graphics.allocator@3.0.so VNDK-core: android.hardware.graphics.allocator@4.0.so VNDK-core: android.hardware.graphics.bufferqueue@1.0.so VNDK-core: android.hardware.graphics.bufferqueue@2.0.so -VNDK-core: android.hardware.graphics.composer@2.1.so -VNDK-core: android.hardware.graphics.composer@2.2.so -VNDK-core: android.hardware.graphics.composer@2.3.so -VNDK-core: android.hardware.graphics.composer@2.4.so -VNDK-core: android.hardware.health.storage@1.0.so -VNDK-core: android.hardware.health@1.0.so -VNDK-core: android.hardware.health@2.0.so -VNDK-core: android.hardware.health@2.1.so VNDK-core: android.hardware.identity-V2-ndk_platform.so -VNDK-core: android.hardware.input.classifier@1.0.so -VNDK-core: android.hardware.input.common@1.0.so -VNDK-core: android.hardware.ir@1.0.so VNDK-core: android.hardware.keymaster-V2-ndk_platform.so -VNDK-core: android.hardware.keymaster@3.0.so -VNDK-core: android.hardware.keymaster@4.0.so -VNDK-core: android.hardware.keymaster@4.1.so VNDK-core: android.hardware.light-V1-ndk_platform.so -VNDK-core: android.hardware.light@2.0.so -VNDK-core: android.hardware.media.bufferpool@1.0.so VNDK-core: android.hardware.media.bufferpool@2.0.so -VNDK-core: android.hardware.media.c2@1.0.so -VNDK-core: android.hardware.media.c2@1.1.so VNDK-core: android.hardware.media.omx@1.0.so VNDK-core: android.hardware.media@1.0.so VNDK-core: android.hardware.memtrack@1.0.so -VNDK-core: android.hardware.neuralnetworks@1.0.so -VNDK-core: android.hardware.neuralnetworks@1.1.so -VNDK-core: android.hardware.neuralnetworks@1.2.so -VNDK-core: android.hardware.neuralnetworks@1.3.so -VNDK-core: android.hardware.nfc@1.0.so -VNDK-core: android.hardware.nfc@1.1.so -VNDK-core: android.hardware.nfc@1.2.so -VNDK-core: android.hardware.oemlock@1.0.so VNDK-core: android.hardware.power-V1-ndk_platform.so -VNDK-core: android.hardware.power.stats@1.0.so -VNDK-core: android.hardware.power@1.0.so -VNDK-core: android.hardware.power@1.1.so -VNDK-core: android.hardware.power@1.2.so -VNDK-core: android.hardware.power@1.3.so -VNDK-core: android.hardware.radio.config@1.0.so -VNDK-core: android.hardware.radio.config@1.1.so -VNDK-core: android.hardware.radio.config@1.2.so -VNDK-core: android.hardware.radio.deprecated@1.0.so -VNDK-core: android.hardware.radio@1.0.so -VNDK-core: android.hardware.radio@1.1.so -VNDK-core: android.hardware.radio@1.2.so -VNDK-core: android.hardware.radio@1.3.so -VNDK-core: android.hardware.radio@1.4.so -VNDK-core: android.hardware.radio@1.5.so VNDK-core: android.hardware.rebootescrow-V1-ndk_platform.so -VNDK-core: android.hardware.secure_element@1.0.so -VNDK-core: android.hardware.secure_element@1.1.so -VNDK-core: android.hardware.secure_element@1.2.so -VNDK-core: android.hardware.sensors@1.0.so -VNDK-core: android.hardware.sensors@2.0.so -VNDK-core: android.hardware.sensors@2.1.so VNDK-core: android.hardware.soundtrigger@2.0-core.so VNDK-core: android.hardware.soundtrigger@2.0.so -VNDK-core: android.hardware.soundtrigger@2.1.so -VNDK-core: android.hardware.soundtrigger@2.2.so -VNDK-core: android.hardware.soundtrigger@2.3.so -VNDK-core: android.hardware.tetheroffload.config@1.0.so -VNDK-core: android.hardware.tetheroffload.control@1.0.so -VNDK-core: android.hardware.thermal@1.0.so -VNDK-core: android.hardware.thermal@1.1.so -VNDK-core: android.hardware.thermal@2.0.so -VNDK-core: android.hardware.tv.cec@1.0.so -VNDK-core: android.hardware.tv.cec@2.0.so -VNDK-core: android.hardware.tv.input@1.0.so -VNDK-core: android.hardware.tv.tuner@1.0.so -VNDK-core: android.hardware.usb.gadget@1.0.so -VNDK-core: android.hardware.usb.gadget@1.1.so -VNDK-core: android.hardware.usb@1.0.so -VNDK-core: android.hardware.usb@1.1.so -VNDK-core: android.hardware.usb@1.2.so VNDK-core: android.hardware.vibrator-V1-ndk_platform.so -VNDK-core: android.hardware.vibrator@1.0.so -VNDK-core: android.hardware.vibrator@1.1.so -VNDK-core: android.hardware.vibrator@1.2.so -VNDK-core: android.hardware.vibrator@1.3.so -VNDK-core: android.hardware.vr@1.0.so -VNDK-core: android.hardware.weaver@1.0.so -VNDK-core: android.hardware.wifi.hostapd@1.0.so -VNDK-core: android.hardware.wifi.hostapd@1.1.so -VNDK-core: android.hardware.wifi.hostapd@1.2.so -VNDK-core: android.hardware.wifi.offload@1.0.so -VNDK-core: android.hardware.wifi.supplicant@1.0.so -VNDK-core: android.hardware.wifi.supplicant@1.1.so -VNDK-core: android.hardware.wifi.supplicant@1.2.so -VNDK-core: android.hardware.wifi.supplicant@1.3.so -VNDK-core: android.hardware.wifi@1.0.so -VNDK-core: android.hardware.wifi@1.1.so -VNDK-core: android.hardware.wifi@1.2.so -VNDK-core: android.hardware.wifi@1.3.so -VNDK-core: android.hardware.wifi@1.4.so -VNDK-core: android.hidl.allocator@1.0.so -VNDK-core: android.hidl.memory.block@1.0.so VNDK-core: android.hidl.token@1.0-utils.so VNDK-core: android.hidl.token@1.0.so -VNDK-core: android.system.net.netd@1.0.so -VNDK-core: android.system.net.netd@1.1.so VNDK-core: android.system.suspend@1.0.so -VNDK-core: android.system.wifi.keystore@1.0.so VNDK-core: libadf.so VNDK-core: libaudioroute.so VNDK-core: libaudioutils.so diff --git a/target/product/gsi/init.gsi.rc b/target/product/gsi/init.gsi.rc index c6faba78d9..f482843220 100644 --- a/target/product/gsi/init.gsi.rc +++ b/target/product/gsi/init.gsi.rc @@ -1,3 +1,5 @@ # # Android init script for GSI required initialization # + +import /system/system_ext/etc/init/init.vndk-${ro.vndk.version:-nodef}.rc diff --git a/target/product/gsi/init.legacy-gsi.rc b/target/product/gsi/init.legacy-gsi.rc deleted file mode 100644 index 00dd576fc1..0000000000 --- a/target/product/gsi/init.legacy-gsi.rc +++ /dev/null @@ -1,3 +0,0 @@ -# If ro.vndk.version is not defined, import init.vndk-27.rc. -import /system/etc/init/gsi/init.vndk-${ro.vndk.version:-27}.rc - diff --git a/target/product/gsi/init.vndk-27.rc b/target/product/gsi/init.vndk-27.rc deleted file mode 100644 index d464a2f396..0000000000 --- a/target/product/gsi/init.vndk-27.rc +++ /dev/null @@ -1,3 +0,0 @@ -on early-init - # Set ro.vndk.version to 27 so that O-MR1-VENDOR can run latest GSI. - setprop ro.vndk.version 27 diff --git a/target/product/gsi/init.vndk-nodef.rc b/target/product/gsi/init.vndk-nodef.rc new file mode 100644 index 0000000000..efeef117be --- /dev/null +++ b/target/product/gsi/init.vndk-nodef.rc @@ -0,0 +1,3 @@ +on early-init + # Must define BOARD_VNDK_VERSION + exec - root -- /system/bin/reboot bootloader diff --git a/target/product/gsi_arm64.mk b/target/product/gsi_arm64.mk index adf7ca541c..1043a85e03 100644 --- a/target/product/gsi_arm64.mk +++ b/target/product/gsi_arm64.mk @@ -18,7 +18,7 @@ # All components inherited here go to system image # $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # Enable mainline checking PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk index d3521fc944..241b6ba146 100644 --- a/target/product/gsi_release.mk +++ b/target/product/gsi_release.mk @@ -24,6 +24,8 @@ # - etc. # +BUILDING_GSI := true + # Exclude all files under system/product and system/system_ext PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \ system/product/% \ @@ -52,7 +54,8 @@ PRODUCT_PACKAGES += com.android.apex.cts.shim.v1_with_prebuilts.flattened # GSI specific tasks on boot PRODUCT_PACKAGES += \ gsi_skip_mount.cfg \ - init.gsi.rc + init.gsi.rc \ + init.vndk-nodef.rc \ -# Support addtional P and Q VNDK packages -PRODUCT_EXTRA_VNDK_VERSIONS := 28 29 +# Support additional P, Q and R VNDK packages +PRODUCT_EXTRA_VNDK_VERSIONS := 28 29 30 diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk index 77c103d7ee..c2608c412a 100644 --- a/target/product/handheld_system.mk +++ b/target/product/handheld_system.mk @@ -43,7 +43,6 @@ PRODUCT_PACKAGES += \ CaptivePortalLogin \ CertInstaller \ clatd \ - clatd.conf \ DocumentsUI \ DownloadProviderUi \ EasterEgg \ @@ -83,7 +82,7 @@ PRODUCT_SYSTEM_SERVER_APPS += \ PRODUCT_COPY_FILES += \ frameworks/av/media/libeffects/data/audio_effects.conf:system/etc/audio_effects.conf -PRODUCT_PROPERTY_OVERRIDES += \ - ro.carrier=unknown \ - ro.config.notification_sound=OnTheHunt.ogg \ - ro.config.alarm_alert=Alarm_Classic.ogg +PRODUCT_VENDOR_PROPERTIES += \ + ro.carrier?=unknown \ + ro.config.notification_sound?=OnTheHunt.ogg \ + ro.config.alarm_alert?=Alarm_Classic.ogg diff --git a/target/product/legacy_gsi_release.mk b/target/product/legacy_gsi_release.mk index c1646bba3b..09b96fb529 100644 --- a/target/product/legacy_gsi_release.mk +++ b/target/product/legacy_gsi_release.mk @@ -16,22 +16,8 @@ include $(SRC_TARGET_DIR)/product/gsi_release.mk -PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \ - system/etc/init/init.legacy-gsi.rc \ - system/etc/init/gsi/init.vndk-27.rc \ - system/etc/ld.config.vndk_lite.txt \ - # Legacy GSI support additional O-MR1 interface PRODUCT_EXTRA_VNDK_VERSIONS += 27 -# Support for the O-MR1 devices -PRODUCT_COPY_FILES += \ - build/make/target/product/gsi/init.legacy-gsi.rc:system/etc/init/init.legacy-gsi.rc \ - build/make/target/product/gsi/init.vndk-27.rc:system/etc/init/gsi/init.vndk-27.rc - -# Namespace configuration file for non-enforcing VNDK -PRODUCT_PACKAGES += \ - ld.config.vndk_lite.txt - # Legacy GSI relax the compatible property checking PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := false diff --git a/target/product/mainline.mk b/target/product/mainline.mk deleted file mode 100644 index 22436e66b3..0000000000 --- a/target/product/mainline.mk +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (C) 2019 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This makefile is intended to serve as a base for completely AOSP based -# mainline devices, It contain the mainline system partition and sensible -# defaults for the system_ext, product and vendor partitions. -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) - -$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_vendor.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_product.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_vendor.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_product.mk) - -$(call inherit-product, frameworks/base/data/sounds/AllAudio.mk) - -PRODUCT_PROPERTY_OVERRIDES += \ - ro.config.ringtone=Ring_Synth_04.ogg \ - ro.com.android.dataroaming=true \ - -PRODUCT_PACKAGES += \ - PhotoTable \ - WallpaperPicker \ - -PRODUCT_COPY_FILES += device/sample/etc/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml diff --git a/target/product/mainline_arm64.mk b/target/product/mainline_arm64.mk deleted file mode 100644 index 52b3222958..0000000000 --- a/target/product/mainline_arm64.mk +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright (C) 2018 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline.mk) -whitelist := product_manifest.xml -$(call enforce-product-packages-exist,$(whitelist)) - -PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed - -# Modules that should probably be moved to /product -PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \ - system/bin/healthd \ - system/etc/init/healthd.rc \ - system/etc/vintf/manifest/manifest_healthd.xml \ - -PRODUCT_SHIPPING_API_LEVEL := 29 - -PRODUCT_RESTRICT_VENDOR_FILES := all - -PRODUCT_NAME := mainline_arm64 -PRODUCT_DEVICE := mainline_arm64 -PRODUCT_BRAND := generic diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk index a787707a04..0b6eaf02dc 100644..120000 --- a/target/product/mainline_system.mk +++ b/target/product/mainline_system.mk @@ -1,143 +1 @@ -# -# Copyright (C) 2018 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# This makefile is the basis of a generic system image for a handheld device. -$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk) -# Add adb keys to debuggable AOSP builds (if they exist) -$(call inherit-product-if-exists, vendor/google/security/adb/vendor_key.mk) - -# Enable updating of APEXes -$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk) - -# Shared java libs -PRODUCT_PACKAGES += \ - com.android.nfc_extras \ - -# Applications -PRODUCT_PACKAGES += \ - LiveWallpapersPicker \ - PartnerBookmarksProvider \ - PresencePolling \ - RcsService \ - SafetyRegulatoryInfo \ - Stk \ - Tag \ - TimeZoneUpdater \ - -# Binaries -PRODUCT_PACKAGES += llkd - -# OTA support -PRODUCT_PACKAGES += \ - recovery-refresh \ - update_engine \ - update_verifier \ - -# Wrapped net utils for /vendor access. -PRODUCT_PACKAGES += netutils-wrapper-1.0 - -# Charger images -PRODUCT_PACKAGES += charger_res_images - -# system_other support -PRODUCT_PACKAGES += \ - cppreopts.sh \ - otapreopt_script \ - -# Bluetooth libraries -PRODUCT_PACKAGES += \ - audio.a2dp.default \ - audio.hearing_aid.default \ - -# For ringtones that rely on forward lock encryption -PRODUCT_PACKAGES += libfwdlockengine - -# System libraries commonly depended on by things on the system_ext or product partitions. -# These lists will be pruned periodically. -PRODUCT_PACKAGES += \ - android.hardware.biometrics.fingerprint@2.1 \ - android.hardware.radio@1.0 \ - android.hardware.radio@1.1 \ - android.hardware.radio@1.2 \ - android.hardware.radio@1.3 \ - android.hardware.radio@1.4 \ - android.hardware.radio.config@1.0 \ - android.hardware.radio.deprecated@1.0 \ - android.hardware.secure_element@1.0 \ - android.hardware.wifi@1.0 \ - libaudio-resampler \ - libaudiohal \ - libdrm \ - liblogwrap \ - liblz4 \ - libminui \ - libnl \ - libprotobuf-cpp-full \ - -# These libraries are empty and have been combined into libhidlbase, but are still depended -# on by things off /system. -# TODO(b/135686713): remove these -PRODUCT_PACKAGES += \ - libhidltransport \ - libhwbinder \ - -PRODUCT_PACKAGES_DEBUG += \ - avbctl \ - bootctl \ - tinyplay \ - tinycap \ - tinymix \ - tinypcminfo \ - update_engine_client \ - -PRODUCT_HOST_PACKAGES += \ - tinyplay - -# Include all zygote init scripts. "ro.zygote" will select one of them. -PRODUCT_COPY_FILES += \ - system/core/rootdir/init.zygote32.rc:system/etc/init/hw/init.zygote32.rc \ - system/core/rootdir/init.zygote64.rc:system/etc/init/hw/init.zygote64.rc \ - system/core/rootdir/init.zygote32_64.rc:system/etc/init/hw/init.zygote32_64.rc \ - system/core/rootdir/init.zygote64_32.rc:system/etc/init/hw/init.zygote64_32.rc \ - -# Enable dynamic partition size -PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true - -PRODUCT_ENFORCE_RRO_TARGETS := * - -PRODUCT_NAME := mainline_system -PRODUCT_BRAND := generic - -# Define /system partition-specific product properties to identify that /system -# partition is mainline_system. -PRODUCT_SYSTEM_NAME := mainline -PRODUCT_SYSTEM_BRAND := Android -PRODUCT_SYSTEM_MANUFACTURER := Android -PRODUCT_SYSTEM_MODEL := mainline -PRODUCT_SYSTEM_DEVICE := generic - -_base_mk_allowed_list := - -_my_allowed_list := $(_base_mk_allowed_list) - -# For mainline, system.img should be mounted at /, so we include ROOT here. -_my_paths := \ - $(TARGET_COPY_OUT_ROOT)/ \ - $(TARGET_COPY_OUT_SYSTEM)/ \ - -$(call require-artifacts-in-path, $(_my_paths), $(_my_allowed_list)) +generic_system.mk
\ No newline at end of file diff --git a/target/product/mainline_system_arm64.mk b/target/product/mainline_system_arm64.mk index 679af0a06d..5fa13ce6c0 100644 --- a/target/product/mainline_system_arm64.mk +++ b/target/product/mainline_system_arm64.mk @@ -14,28 +14,10 @@ # limitations under the License. # -# -# All components inherited here go to system image -# -$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) -$(call enforce-product-packages-exist,) - -# Enable mainline checking -PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true - -PRODUCT_BUILD_CACHE_IMAGE := false -PRODUCT_BUILD_ODM_IMAGE := false -PRODUCT_BUILD_PRODUCT_IMAGE := false -PRODUCT_BUILD_RAMDISK_IMAGE := false -PRODUCT_BUILD_SYSTEM_IMAGE := true -PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false -PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false -PRODUCT_BUILD_USERDATA_IMAGE := false -PRODUCT_BUILD_VENDOR_IMAGE := false +# Do not modify this file. It's just alias of generic_system_arm64.mk +# Will be removed when renaming from mainline_system to generic_system +# complete -PRODUCT_SHIPPING_API_LEVEL := 29 +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system_arm64.mk) PRODUCT_NAME := mainline_system_arm64 -PRODUCT_DEVICE := mainline_arm64 -PRODUCT_BRAND := generic diff --git a/target/product/mainline_system_x86.mk b/target/product/mainline_system_x86.mk index e1f862c88d..3fb1963e98 100644 --- a/target/product/mainline_system_x86.mk +++ b/target/product/mainline_system_x86.mk @@ -14,27 +14,10 @@ # limitations under the License. # -# -# All components inherited here go to system image -# -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) -$(call enforce-product-packages-exist,) - -# Enable mainline checking -PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true - -PRODUCT_BUILD_CACHE_IMAGE := false -PRODUCT_BUILD_ODM_IMAGE := false -PRODUCT_BUILD_PRODUCT_IMAGE := false -PRODUCT_BUILD_RAMDISK_IMAGE := false -PRODUCT_BUILD_SYSTEM_IMAGE := true -PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false -PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false -PRODUCT_BUILD_USERDATA_IMAGE := false -PRODUCT_BUILD_VENDOR_IMAGE := false +# Do not modify this file. It's just alias of generic_system_x86.mk +# Will be removed when renaming from mainline_system to generic_system +# complete -PRODUCT_SHIPPING_API_LEVEL := 29 +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system_x86.mk) PRODUCT_NAME := mainline_system_x86 -PRODUCT_DEVICE := mainline_x86 -PRODUCT_BRAND := generic diff --git a/target/product/mainline_system_x86_64.mk b/target/product/mainline_system_x86_64.mk index 8806d3edbb..eab99c55e6 100644 --- a/target/product/mainline_system_x86_64.mk +++ b/target/product/mainline_system_x86_64.mk @@ -14,28 +14,10 @@ # limitations under the License. # -# -# All components inherited here go to system image -# -$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) -$(call enforce-product-packages-exist,) - -# Enable mainline checking -PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true - -PRODUCT_BUILD_CACHE_IMAGE := false -PRODUCT_BUILD_ODM_IMAGE := false -PRODUCT_BUILD_PRODUCT_IMAGE := false -PRODUCT_BUILD_RAMDISK_IMAGE := false -PRODUCT_BUILD_SYSTEM_IMAGE := true -PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false -PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false -PRODUCT_BUILD_USERDATA_IMAGE := false -PRODUCT_BUILD_VENDOR_IMAGE := false +# Do not modify this file. It's just alias of generic_system_x86_64.mk +# Will be removed when renaming from mainline_system to generic_system +# complete -PRODUCT_SHIPPING_API_LEVEL := 29 +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system_x86_64.mk) PRODUCT_NAME := mainline_system_x86_64 -PRODUCT_DEVICE := mainline_x86_64 -PRODUCT_BRAND := generic diff --git a/target/product/mainline_system_x86_arm.mk b/target/product/mainline_system_x86_arm.mk index 04fb6523a5..483fb58dac 100644 --- a/target/product/mainline_system_x86_arm.mk +++ b/target/product/mainline_system_x86_arm.mk @@ -14,27 +14,10 @@ # limitations under the License. # -# -# All components inherited here go to system image -# -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) -$(call enforce-product-packages-exist,) - -# Enable mainline checking -PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true - -PRODUCT_BUILD_CACHE_IMAGE := false -PRODUCT_BUILD_ODM_IMAGE := false -PRODUCT_BUILD_PRODUCT_IMAGE := false -PRODUCT_BUILD_RAMDISK_IMAGE := false -PRODUCT_BUILD_SYSTEM_IMAGE := true -PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false -PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false -PRODUCT_BUILD_USERDATA_IMAGE := false -PRODUCT_BUILD_VENDOR_IMAGE := false +# Do not modify this file. It's just alias of generic_system_x86_arm.mk +# Will be removed when renaming from mainline_system to generic_system +# complete -PRODUCT_SHIPPING_API_LEVEL := 29 +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system_x86_arm.mk) PRODUCT_NAME := mainline_system_x86_arm -PRODUCT_DEVICE := mainline_x86_arm -PRODUCT_BRAND := generic diff --git a/target/product/media_system.mk b/target/product/media_system.mk index 26fb7f34ba..1004dc57f3 100644 --- a/target/product/media_system.mk +++ b/target/product/media_system.mk @@ -74,11 +74,11 @@ PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,\ # On userdebug builds, collect more tombstones by default. ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ - tombstoned.max_tombstone_count=50 +PRODUCT_VENDOR_PROPERTIES += \ + tombstoned.max_tombstone_count?=50 endif -PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \ +PRODUCT_VENDOR_PROPERTIES += \ ro.logd.size.stats=64K \ log.tag.stats_log=I diff --git a/target/product/profile_boot_common.mk b/target/product/profile_boot_common.mk index a40b3e9449..fa2e163e1e 100644 --- a/target/product/profile_boot_common.mk +++ b/target/product/profile_boot_common.mk @@ -23,7 +23,7 @@ PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION := build/make/target/product/empt DEX_PREOPT_DEFAULT := nostripping # Boot image property overrides. -PRODUCT_PROPERTY_OVERRIDES += \ +PRODUCT_VENDOR_PROPERTIES += \ dalvik.vm.profilesystemserver=true \ dalvik.vm.profilebootclasspath=true diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk index ad361dc09e..1bd2af7f1f 100644 --- a/target/product/runtime_libart.mk +++ b/target/product/runtime_libart.mk @@ -40,7 +40,7 @@ PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \ hiddenapi-package-whitelist.xml \ -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ +PRODUCT_SYSTEM_PROPERTIES += \ dalvik.vm.image-dex2oat-Xms=64m \ dalvik.vm.image-dex2oat-Xmx=64m \ dalvik.vm.dex2oat-Xms=64m \ @@ -50,50 +50,50 @@ PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ dalvik.vm.dexopt.secondary=true \ dalvik.vm.appimageformat=lz4 -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ +PRODUCT_SYSTEM_PROPERTIES += \ ro.dalvik.vm.native.bridge=0 # Different dexopt types for different package update/install times. # On eng builds, make "boot" reasons only extract for faster turnaround. ifeq (eng,$(TARGET_BUILD_VARIANT)) - PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ - pm.dexopt.first-boot=extract \ - pm.dexopt.boot=extract + PRODUCT_SYSTEM_PROPERTIES += \ + pm.dexopt.first-boot?=extract \ + pm.dexopt.boot?=extract else - PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ - pm.dexopt.first-boot=quicken \ - pm.dexopt.boot=verify + PRODUCT_SYSTEM_PROPERTIES += \ + pm.dexopt.first-boot?=quicken \ + pm.dexopt.boot?=verify endif # The install filter is speed-profile in order to enable the use of # profiles from the dex metadata files. Note that if a profile is not provided # or if it is empty speed-profile is equivalent to (quicken + empty app image). -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ - pm.dexopt.install=speed-profile \ - pm.dexopt.bg-dexopt=speed-profile \ - pm.dexopt.ab-ota=speed-profile \ - pm.dexopt.inactive=verify \ - pm.dexopt.shared=speed +PRODUCT_SYSTEM_PROPERTIES += \ + pm.dexopt.install?=speed-profile \ + pm.dexopt.bg-dexopt?=speed-profile \ + pm.dexopt.ab-ota?=speed-profile \ + pm.dexopt.inactive?=verify \ + pm.dexopt.shared?=speed # Pass file with the list of updatable boot class path packages to dex2oat. -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ +PRODUCT_SYSTEM_PROPERTIES += \ dalvik.vm.dex2oat-updatable-bcp-packages-file=/system/etc/updatable-bcp-packages.txt # Enable resolution of startup const strings. -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ +PRODUCT_SYSTEM_PROPERTIES += \ dalvik.vm.dex2oat-resolve-startup-strings=true # Specify default block size of 512K to enable parallel image decompression. -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ +PRODUCT_SYSTEM_PROPERTIES += \ dalvik.vm.dex2oat-max-image-block-size=524288 # Enable minidebuginfo generation unless overridden. -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ +PRODUCT_SYSTEM_PROPERTIES += \ dalvik.vm.minidebuginfo=true \ dalvik.vm.dex2oat-minidebuginfo=true # Enable iorapd by default -PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \ +PRODUCT_SYSTEM_PROPERTIES += \ ro.iorapd.enable=true PRODUCT_USES_DEFAULT_ART_CONFIG := true diff --git a/target/product/sdk_phone_arm64.mk b/target/product/sdk_phone_arm64.mk index 3ab0c57fe4..761de05d4c 100644 --- a/target/product/sdk_phone_arm64.mk +++ b/target/product/sdk_phone_arm64.mk @@ -14,7 +14,6 @@ # limitations under the License. # QEMU_USE_SYSTEM_EXT_PARTITIONS := true - PRODUCT_USE_DYNAMIC_PARTITIONS := true # This is a build configuration for a full-featured build of the @@ -22,11 +21,16 @@ PRODUCT_USE_DYNAMIC_PARTITIONS := true # build quite specifically for the emulator, and might not be # entirely appropriate to inherit from for on-device configurations. +# Enable mainline checking for exact this product name +ifeq (sdk_phone_arm64,$(TARGET_PRODUCT)) +PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed +endif + # # All components inherited here go to system image # $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) # # All components inherited here go to system_ext image diff --git a/target/product/sdk_phone_armv7.mk b/target/product/sdk_phone_armv7.mk index 77b8b50644..5081a87b5f 100644 --- a/target/product/sdk_phone_armv7.mk +++ b/target/product/sdk_phone_armv7.mk @@ -14,8 +14,40 @@ # limitations under the License. # QEMU_USE_SYSTEM_EXT_PARTITIONS := true +PRODUCT_USE_DYNAMIC_PARTITIONS := true -$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_arm.mk) +# This is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + +# Enable mainline checking for exact this product name +ifeq (sdk_phone_armv7,$(TARGET_PRODUCT)) +PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed +endif + +# +# All components inherited here go to system image +# +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) + +# +# All components inherited here go to system_ext image +# +$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk) + +# +# All components inherited here go to product image +# +$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk) + +# +# All components inherited here go to vendor image +# +$(call inherit-product-if-exists, device/generic/goldfish/arm32-vendor.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/board/emulator_arm/device.mk) # Define the host tools and libs that are parts of the SDK. $(call inherit-product, sdk/build/product_sdk.mk) @@ -29,4 +61,5 @@ PRODUCT_PACKAGES += \ # Overrides PRODUCT_BRAND := Android PRODUCT_NAME := sdk_phone_armv7 -PRODUCT_DEVICE := generic +PRODUCT_DEVICE := emulator_arm +PRODUCT_MODEL := Android SDK built for arm diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk index 9df26a9c0a..63671dcd31 100644 --- a/target/product/sdk_phone_x86.mk +++ b/target/product/sdk_phone_x86.mk @@ -16,12 +16,17 @@ QEMU_USE_SYSTEM_EXT_PARTITIONS := true PRODUCT_USE_DYNAMIC_PARTITIONS := true +# This is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + # # All components inherited here go to system image # -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) -# Enable mainline checking for excat this product name +# Enable mainline checking for exact this product name ifeq (sdk_phone_x86,$(TARGET_PRODUCT)) PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed endif @@ -42,9 +47,7 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk) # $(call inherit-product-if-exists, device/generic/goldfish/x86-vendor.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk) - -$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/board/emulator_x86/device.mk) # Define the host tools and libs that are parts of the SDK. -include sdk/build/product_sdk.mk @@ -53,5 +56,5 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86.mk) # Overrides PRODUCT_BRAND := Android PRODUCT_NAME := sdk_phone_x86 -PRODUCT_DEVICE := generic_x86 +PRODUCT_DEVICE := emulator_x86 PRODUCT_MODEL := Android SDK built for x86 diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk index 862c66e599..c5a6245aed 100644 --- a/target/product/sdk_phone_x86_64.mk +++ b/target/product/sdk_phone_x86_64.mk @@ -16,13 +16,18 @@ QEMU_USE_SYSTEM_EXT_PARTITIONS := true PRODUCT_USE_DYNAMIC_PARTITIONS := true +# This is a build configuration for a full-featured build of the +# Open-Source part of the tree. It's geared toward a US-centric +# build quite specifically for the emulator, and might not be +# entirely appropriate to inherit from for on-device configurations. + # # All components inherited here go to system image # $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_system.mk) -# Enable mainline checking for excat this product name +# Enable mainline checking for exact this product name ifeq (sdk_phone_x86_64,$(TARGET_PRODUCT)) PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed endif @@ -43,7 +48,7 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk) # $(call inherit-product-if-exists, device/generic/goldfish/x86_64-vendor.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/board/emulator_x86_64/device.mk) # Define the host tools and libs that are parts of the SDK. -include sdk/build/product_sdk.mk @@ -52,5 +57,5 @@ $(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk) # Overrides PRODUCT_BRAND := Android PRODUCT_NAME := sdk_phone_x86_64 -PRODUCT_DEVICE := generic_x86_64 +PRODUCT_DEVICE := emulator_x86_64 PRODUCT_MODEL := Android SDK built for x86_64 diff --git a/target/product/updatable_apex.mk b/target/product/updatable_apex.mk index a84a0d2ba3..c8dc8b0027 100644 --- a/target/product/updatable_apex.mk +++ b/target/product/updatable_apex.mk @@ -20,6 +20,6 @@ ifneq ($(OVERRIDE_TARGET_FLATTEN_APEX),true) # com.android.apex.cts.shim.v1_prebuilt overrides CtsShimPrebuilt # and CtsShimPrivPrebuilt since they are packaged inside the APEX. PRODUCT_PACKAGES += com.android.apex.cts.shim.v1_prebuilt - PRODUCT_PROPERTY_OVERRIDES := ro.apex.updatable=true + PRODUCT_VENDOR_PROPERTIES := ro.apex.updatable=true TARGET_FLATTEN_APEX := false endif diff --git a/target/product/userspace_reboot.mk b/target/product/userspace_reboot.mk index 3f881af7e6..f235d146e3 100644 --- a/target/product/userspace_reboot.mk +++ b/target/product/userspace_reboot.mk @@ -16,4 +16,4 @@ # Inherit this when the target supports userspace reboot -PRODUCT_PROPERTY_OVERRIDES := init.userspace_reboot.is_supported=true +PRODUCT_VENDOR_PROPERTIES := init.userspace_reboot.is_supported=true diff --git a/target/product/virtual_ab_ota.mk b/target/product/virtual_ab_ota.mk index 1774de42e4..e4c45758ba 100644 --- a/target/product/virtual_ab_ota.mk +++ b/target/product/virtual_ab_ota.mk @@ -16,6 +16,6 @@ PRODUCT_VIRTUAL_AB_OTA := true -PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.enabled=true +PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.enabled=true PRODUCT_PACKAGES += e2fsck_ramdisk diff --git a/target/product/virtual_ab_ota_plus_non_ab.mk b/target/product/virtual_ab_ota_plus_non_ab.mk index 325d75e3e7..99a10ed9c3 100644 --- a/target/product/virtual_ab_ota_plus_non_ab.mk +++ b/target/product/virtual_ab_ota_plus_non_ab.mk @@ -18,4 +18,4 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk) PRODUCT_OTA_FORCE_NON_AB_PACKAGE := true -PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.allow_non_ab=true +PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.allow_non_ab=true diff --git a/target/product/virtual_ab_ota_retrofit.mk b/target/product/virtual_ab_ota_retrofit.mk index 3e857412e7..3416a4fd81 100644 --- a/target/product/virtual_ab_ota_retrofit.mk +++ b/target/product/virtual_ab_ota_retrofit.mk @@ -18,4 +18,4 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk) PRODUCT_VIRTUAL_AB_OTA_RETROFIT := true -PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.retrofit=true +PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.retrofit=true diff --git a/tools/Android.bp b/tools/Android.bp index 8c7eb38373..e0f3739280 100644 --- a/tools/Android.bp +++ b/tools/Android.bp @@ -24,3 +24,55 @@ python_binary_host { }, }, } + +python_binary_host { + name: "post_process_props", + srcs: ["post_process_props.py"], + version: { + py2: { + enabled: false, + }, + py3: { + enabled: true, + }, + }, +} + +python_test_host { + name: "post_process_props_unittest", + main: "test_post_process_props.py", + srcs: [ + "post_process_props.py", + "test_post_process_props.py", + ], + version: { + py2: { + enabled: false, + }, + py3: { + enabled: true, + }, + }, + test_config: "post_process_props_unittest.xml", + test_suites: ["general-tests"], +} + +python_binary_host { + name: "extract_kernel", + srcs: ["extract_kernel.py"], + version: { + py2: { + enabled: true, + }, + py3: { + enabled: false, + }, + }, +} + +genrule_defaults { + name: "extract_kernel_release_defaults", + tools: ["extract_kernel", "lz4"], + out: ["kernel_release.txt"], + cmd: "$(location) --tools lz4:$(location lz4) --input $(in) --output-release > $(out)" +} diff --git a/tools/buildinfo_common.sh b/tools/buildinfo_common.sh deleted file mode 100755 index 673e06f3da..0000000000 --- a/tools/buildinfo_common.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -partition="$1" - -if [ "$#" -ne 1 ]; then - echo "Usage: $0 <partition>" 1>&2 - exit 1 -fi - -echo "# begin common build properties" -echo "# autogenerated by $0" - -echo "ro.${partition}.build.date=`$DATE`" -echo "ro.${partition}.build.date.utc=`$DATE +%s`" -echo "ro.${partition}.build.fingerprint=$BUILD_FINGERPRINT" -echo "ro.${partition}.build.id=$BUILD_ID" -echo "ro.${partition}.build.tags=$BUILD_VERSION_TAGS" -echo "ro.${partition}.build.type=$TARGET_BUILD_TYPE" -echo "ro.${partition}.build.version.incremental=$BUILD_NUMBER" -echo "ro.${partition}.build.version.release=$PLATFORM_VERSION_LAST_STABLE" -echo "ro.${partition}.build.version.release_or_codename=$PLATFORM_VERSION" -echo "ro.${partition}.build.version.sdk=$PLATFORM_SDK_VERSION" - -echo "ro.product.${partition}.brand=$PRODUCT_BRAND" -echo "ro.product.${partition}.device=$PRODUCT_DEVICE" -echo "ro.product.${partition}.manufacturer=$PRODUCT_MANUFACTURER" -echo "ro.product.${partition}.model=$PRODUCT_MODEL" -echo "ro.product.${partition}.name=$PRODUCT_NAME" - -echo "# end common build properties" diff --git a/tools/check_elf_file.py b/tools/check_elf_file.py index de855c6a7e..372404b90b 100755 --- a/tools/check_elf_file.py +++ b/tools/check_elf_file.py @@ -174,7 +174,7 @@ class ELFParser(object): @classmethod def open(cls, elf_file_path, llvm_readobj): """Open and parse the ELF file.""" - # Parse the ELF header for simple sanity checks. + # Parse the ELF header to check the magic word. header = cls._read_elf_header(elf_file_path) if not header or header.ei_magic != _ELF_MAGIC: raise ELFInvalidMagicError() diff --git a/tools/check_identical_lib.sh b/tools/check_identical_lib.sh index c3aa41a722..c9f436f0bb 100755 --- a/tools/check_identical_lib.sh +++ b/tools/check_identical_lib.sh @@ -26,7 +26,19 @@ function strip_lib() { strip_lib ${CORE} ${stripped_core} strip_lib ${VENDOR} ${stripped_vendor} if ! cmp -s ${stripped_core} ${stripped_vendor}; then - echo "VNDK library not in vndkMustUseVendorVariantList but has different core and vendor variant: $(basename ${CORE})" - echo "If the two variants need to have different runtime behavior, consider using libvndksupport." + echo "ERROR: VNDK library $(basename ${CORE%.so}) has different core and" \ + "vendor variants! This means that the copy used in the system.img/etc" \ + "and vendor.img/etc images are different. In order to preserve space on" \ + "some devices, it is helpful if they are the same. Frequently, " \ + "libraries are different because they or their dependencies compile" \ + "things based on the macro '__ANDROID_VNDK__' or they specify custom" \ + "options under 'target: { vendor: { ... } }'. Here are some possible" \ + "resolutions:" + echo "ERROR: 1). Remove differences, possibly using the libvndksupport" \ + "function android_is_in_vendor_process in order to turn this into a" \ + "runtime difference." + echo "ERROR: 2). Add the library to the VndkMustUseVendorVariantList" \ + "variable in build/soong/cc/config/vndk.go, which is used to" \ + "acknowledge this difference." exit 1 fi diff --git a/tools/droiddoc/templates-ndk/assets/GPL-LICENSE.txt b/tools/droiddoc/templates-ndk/assets/GPL-LICENSE.txt deleted file mode 100644 index 66a0f18dbf..0000000000 --- a/tools/droiddoc/templates-ndk/assets/GPL-LICENSE.txt +++ /dev/null @@ -1,278 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES.
\ No newline at end of file diff --git a/tools/droiddoc/templates-ndk/assets/LICENSE.txt b/tools/droiddoc/templates-ndk/assets/LICENSE.txt deleted file mode 100644 index e84328beda..0000000000 --- a/tools/droiddoc/templates-ndk/assets/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2011 John Resig, http://jquery.com/ - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file diff --git a/tools/droiddoc/templates-ndk/assets/android-developer-docs.css b/tools/droiddoc/templates-ndk/assets/android-developer-docs.css deleted file mode 100644 index cd610f74e7..0000000000 --- a/tools/droiddoc/templates-ndk/assets/android-developer-docs.css +++ /dev/null @@ -1,2768 +0,0 @@ -/* file: android-developer-core.css - author: smain - date: september 2008 - info: core developer styles (developer.android.com) - Required by jdiff -*/ - - -/* RESET STYLES */ - -html,body,div,h1,h2,h3,h4,h5,h6,p,img, -dl,dt,dd,ol,ul,li,table,caption,tbody, -tfoot,thead,tr,th,td,form,fieldset, -embed,object,applet { - margin: 0; - padding: 0; - border: 0; -} - -/* BASICS */ - -html, body { - overflow:hidden; /* keeps scrollbar off IE */ - background-color:#fff; -} - -body { - font-family:arial,sans-serif; - color:#000; - font-size:13px; - color:#333; - background-image:url(images/bg_fade.jpg); - background-repeat:repeat-x; -} - -a, a code { - color:#006699; -} - -a:active, -a:active code { - color:#f00; -} - -a:visited, -a:visited code { - color:#006699; -} - -input, select, -textarea, option, label { - font-family:inherit; - font-size:inherit; - padding:0; - margin:0; - vertical-align:middle; -} - -option { - padding:0 4px; -} - -p, form { - padding:0; - margin:0 0 1em; -} - -code, pre { - color:#007000; - font-family:monospace; - line-height:1em; -} - -var { - color:#007000; - font-style:italic; -} - -pre { - border:1px solid #ccc; - background-color:#fafafa; - padding:10px; - margin:0 0 1em 1em; - overflow:auto; - line-height:inherit; /* fixes vertical scrolling in webkit */ -} - -h1,h2,h3,h4,h5 { - margin:1em 0; - padding:0; -} - -p,ul,ol,dl,dd,dt,li { - line-height:1.3em; -} - -ul,ol { - margin:0 0 .8em; - padding:0 0 0 2em; -} - -li { - padding:0 0 .5em; -} - -dl { - margin:0 0 1em 0; - padding:0; -} - -dt { - margin:0; - padding:0; -} - -dd { - margin:0 0 1em; - padding:0 0 0 2em; -} - -li p { - margin:.5em 0 0; -} - -dd p { - margin:1em 0 0; -} - -li pre, li table, li img { - margin:.5em 0 0 1em; -} - -dd pre, -#jd-content dd table, -#jd-content dd img { - margin:1em 0 0 1em; -} - -li ul, -li ol, -dd ul, -dd ol { - margin:0; - padding: 0 0 0 2em; -} - -li li, -dd li { - margin:0; - padding:.5em 0 0; -} - -dl dl, -ol dl, -ul dl { - margin:0 0 1em; - padding:0; -} - -table { - font-size:1em; - margin:0 0 1em; - padding:0; - border-collapse:collapse; - border-width:0; - empty-cells:show; -} - -td,th { - border:1px solid #ccc; - padding:6px 12px; - text-align:left; - vertical-align:top; - background-color:inherit; -} - -th { - background-color:#dee8f1; -} - -td > p:last-child { - margin:0; -} - -hr.blue { - background-color:#DDF0F2; - border:none; - height:5px; - margin:20px 0 10px; -} - -blockquote { - margin: 0 0 1em 1em; - padding: 0 4em 0 1em; - border-left:2px solid #eee; -} -/* LAYOUT */ - -#body-content { - /* "Preliminary" watermark for preview releases and interim builds. - background:transparent url(images/preliminary.png) repeat scroll 0 0; */ - margin:0; - position:relative; - width:100%; -} - -#header { - height: 114px; - position:relative; - z-index:100; - min-width:675px; /* min width for the tabs, before they wrap */ - padding:0 10px; - border-bottom:3px solid #94b922; -} - -#headerLeft{ - padding: 25px 0 0; -} - -#headerLeft img{ - height:50px; - width:180px; -} - -#headerRight { - position:absolute; - right:0; - top:0; - text-align:right; -} - -/* Tabs in the header */ - -#header ul { - list-style: none; - margin: 7px 0 0; - padding: 0; - height: 29px; -} - -#header li { - float: left; - margin: 0px 2px 0px 0px; - padding:0; -} - -#header li a { - text-decoration: none; - display: block; - background-image: url(images/bg_images_sprite.png); - background-position: 0 -58px; - background-repeat: no-repeat; - color: #666; - font-size: 13px; - font-weight: bold; - width: 94px; - height: 29px; - text-align: center; - margin: 0px; -} - -#header li a:hover { - background-image: url(images/bg_images_sprite.png); - background-position: 0 -29px; - background-repeat: no-repeat; -} - -#header li a span { - position:relative; - top:7px; -} - -#header li a span+span { - display:none; -} - -/* tab highlighting */ - -.home #home-link a, -.guide #guide-link a, -.reference #reference-link a, -.sdk #sdk-link a, -.resources #resources-link a, -.videos #videos-link a { - background-image: url(images/bg_images_sprite.png); - background-position: 0 0; - background-repeat: no-repeat; - color: #fff; - font-weight: bold; - cursor:default; -} - -.home #home-link a:hover, -.guide #guide-link a:hover, -.reference #reference-link a:hover, -.sdk #sdk-link a:hover, -.resources #resources-link a:hover, -.videos #videos-link a:hover { - background-image: url(images/bg_images_sprite.png); - background-position: 0 0; -} - -#headerLinks { - margin:10px 10px 0 0; - height:13px; - font-size: 11px; - vertical-align: top; -} - -#headerLinks a { - color: #7FA9B5; -} - -#headerLinks img { - vertical-align:middle; -} - -#language { - margin:0 10px 0 4px; -} - -#search { - height:45px; - margin:15px 10px 0 0; -} - -/* MAIN BODY */ - -#mainBodyFluid { - margin: 20px 10px; - color:#333; -} - -#mainBodyFixed { - margin: 20px 10px; - color: #333; - width:930px; - position:relative; -} - -#mainBodyFixed h3, -#mainBodyFluid h3 { - color:#336666; - font-size:1.25em; - margin: 0em 0em 0em 0em; - padding-bottom:.5em; -} - -#mainBodyFixed h2, -#mainBodyFluid h2 { - color:#336666; - font-size:1.25em; - margin: 0; - padding-bottom:.5em; -} - -#mainBodyFixed h1, -#mainBodyFluid h1 { - color:#435A6E; - font-size:1.7em; - margin: 1em 0; -} - -#mainBodyFixed .green, -#mainBodyFluid .green, -#jd-content .green { - color:#7BB026; - background-color:none; -} - -#mainBodyLeft { - float: left; - width: 600px; - margin-right: 20px; - color: #333; - position:relative; -} - -div.indent { - margin-left: 40px; - margin-right: 70px; -} - -#mainBodyLeft p { - color: #333; - font-size: 13px; -} - -#mainBodyLeft p.blue { - color: #669999; -} - -#mainBodyLeft #communityDiv { - float: left; - background-image:url(images/bg_community_leftDiv.jpg); - background-repeat: no-repeat; - width: 581px; - height: 347px; - padding: 20px 0px 0px 20px; -} - -#mainBodyRight { - float: left; - width: 300px; - color: #333; -} - -#mainBodyRight p { - padding-right: 50px; - color: #333; -} - -#mainBodyRight table { - width: 100%; -} - -#mainBodyRight td { - border:0px solid #666; - padding:0px 5px; - text-align:left; -} - -#mainBodyRight td p { - margin:0 0 1em 0; -} - -#mainBodyRight .blueBorderBox { - border:5px solid #ddf0f2; - padding:18px 18px 18px 18px; - text-align:left; -} - -#mainBodyFixed .seperator { - background-image:url(images/hr_gray_side.jpg); - background-repeat:no-repeat; - width: 100%; - float: left; - clear: both; -} - -#mainBodyBottom { - float: left; - width: 100%; - clear:both; - color: #333; -} - -#mainBodyBottom .seperator { - background-image:url(images/hr_gray_main.jpg); - background-repeat:no-repeat; - width: 100%; - float: left; - clear: both; -} - -/* FOOTER */ - -#footer { - float: left; - width:90%; - margin: 20px; - color: #aaa; - font-size: 11px; -} - -#footer a { - color: #aaa; - font-size: 11px; -} - -#footer a:hover { - text-decoration: underline; - color:#aaa; -} - -#footerlinks { - margin-top:2px; -} - -#footerlinks a, -#footerlinks a:visited { - color:#006699; -} - -/* SEARCH FILTER */ - -#search_autocomplete { - color:#aaa; -} - -#search-button { - display:inline; -} - -#search_filtered_div { - position:absolute; - margin-top:-1px; - z-index:101; - border:1px solid #BCCDF0; - background-color:#fff; -} - -#search_filtered { - min-width:100%; -} -#search_filtered td{ - background-color:#fff; - border-bottom: 1px solid #669999; - line-height:1.5em; -} - -#search_filtered .jd-selected { - background-color: #94b922; - cursor:pointer; -} -#search_filtered .jd-selected, -#search_filtered .jd-selected a { - color:#fff; -} - -.no-display { - display: none; -} - -.jd-autocomplete { - font-family: Arial, sans-serif; - padding-left: 6px; - padding-right: 6px; - padding-top: 1px; - padding-bottom: 1px; - font-size: 0.81em; - border: none; - margin: 0; - line-height: 1.05em; -} - -.show-row { - display: table-row; -} -.hide-row { - display: hidden; -} - -/* SEARCH */ - -/* restrict global search form width */ -#searchForm { - width:350px; -} - -#searchTxt { - width:200px; -} - -/* disable twiddle and size selectors for left column */ -#leftSearchControl div { - width: 100%; -} - -#leftSearchControl .gsc-twiddle { - background-image : none; -} - -#leftSearchControl td, #searchForm td { - border: 0px solid #000; -} - -#leftSearchControl .gsc-resultsHeader .gsc-title { - padding-left : 0px; - font-weight : bold; - font-size : 13px; - color:#006699; - display : none; -} - -#leftSearchControl .gsc-resultsHeader div.gsc-results-selector { - display : none; -} - -#leftSearchControl .gsc-resultsRoot { - padding-top : 6px; -} - -#leftSearchControl div.gs-visibleUrl-long { - display : block; - color:#006699; -} - -.gsc-webResult div.gs-visibleUrl-short, -table.gsc-branding, -.gsc-clear-button { - display : none; -} - -.gsc-cursor-box .gsc-cursor div.gsc-cursor-page, -.gsc-cursor-box .gsc-trailing-more-results a.gsc-trailing-more-results, -#leftSearchControl a, -#leftSearchControl a b { - color:#006699; -} - -.gsc-resultsHeader { - display: none; -} - -/* Disable built in search forms */ -.gsc-control form.gsc-search-box { - display : none; -} -table.gsc-search-box { - margin:6px 0 0 0; - border-collapse:collapse; -} - -td.gsc-input { - padding:0 2px; - width:100%; - vertical-align:middle; -} - -input.gsc-input { - border:1px solid #BCCDF0; - width:99%; - padding-left:2px; - font-size:.95em; -} - -td.gsc-search-button { - text-align: right; - padding:0; - vertical-align:top; -} - -#search-button { - margin:0 0 0 2px; - font-size:11px; -} - -/* search result tabs */ - -#doc-content .gsc-control { - position:relative; -} - -#doc-content .gsc-tabsArea { - position:relative; - white-space:nowrap; -} - -#doc-content .gsc-tabHeader { - padding: 3px 6px; - position:relative; - width:auto; -} - -#doc-content .gsc-tabHeader.gsc-tabhActive { - border-top: 2px solid #94B922; -} - -#doc-content h2#searchTitle { - padding:0; -} - -#doc-content .gsc-resultsbox-visible { - padding:1em 0 0 6px; -} - -/* CAROUSEL */ - -#homeMiddle { - padding: 0px 0px 0px 0px; - float: left; - width: 584px; - height: 627px; - position:relative; -} - -#topAnnouncement { - background:url(images/home/bg_home_announcement.png) no-repeat 0 0; -} - -#homeTitle { - padding:15px 15px 0; - height:30px; -} - -#homeTitle h2 { - padding:0; -} - -#announcement-block { - padding:0 15px 0; - overflow:hidden; - background: url(images/hr_gray_side.jpg) no-repeat 15px 0; - zoom:1; -} - -#announcement-block>* { - padding:15px 0 0; -} - -#announcement-block img { - float:left; - margin:0 30px 0 0; -} - -#announcement { - float:left; - margin:0; -} - -#carousel { - background:url(images/home/bg_home_carousel.png) no-repeat 0 0; - position:relative; - height:400px; -} - -#carouselMain { - background: url(images/home/bg_home_carousel_board.png) 0 0 no-repeat; - height:auto; - padding: 25px 21px 0; - overflow:hidden; - position:relative; - zoom:1; /*IE6*/ -} - -#carouselMain img { - margin:0; -} - -#carouselMain .bulletinDesc h3 { - margin:0; - padding:0; -} - -#carouselMain .bulletinDesc p { - margin:0; - padding:0.7em 0 0; -} - -#carouselWheel { - background: url(images/home/bg_home_carousel_wheel.png) 0 0 no-repeat; - padding-top:40px; - height:150px; -} - -.clearer { clear:both; } - -a#arrow-left, a#arrow-right { - float:left; - width:42px; - height:42px; - background-image:url(images/home/carousel_buttons_sprite.png); - background-repeat:no-repeat; -} -a#arrow-left { - margin:35px 3px 0 10px; -} -a#arrow-right { - margin:35px 10px 0 0; -} -a.arrow-left-off, -a#arrow-left.arrow-left-off:hover { - background-position:0 0; -} -a.arrow-right-off, -a#arrow-right.arrow-right-off:hover { - background-position:-42px 0; -} -a#arrow-left:hover { - background-position:0 -42px; -} -a#arrow-right:hover { - background-position:-42px -42px; -} -a.arrow-left-on { - background-position:0 0; -} -a.arrow-right-on { - background-position:-42px 0; -} -a.arrow-right-off, -a.arrow-left-off { - cursor:default; -} - -.app-list-container { - margin:0 20px; - position:relative; - width:100%; -} - -div#list-clip { - height:110px; - width:438px; - overflow:hidden; - position:relative; - float:left; -} - -div#app-list { - left:0; - z-index:1; - position:absolute; - margin:11px 0 0; - _margin-top:13px; - width:1000%; -} - -#app-list a { - display:block; - float:left; - height:90px; - width:90px; - margin:0 24px 0; - padding:3px; - background:#99cccc; - -webkit-border-radius:7px; - -moz-border-radius:7px; - border-radius:7px; - text-decoration:none; - text-align:center; - font-size:11px; - line-height:11px; -} - -#app-list a span { - position:relative; - top:-4px; -} - -#app-list img { - width:90px; - height:70px; - margin:0; -} - -#app-list a.selected, -#app-list a:active.selected, -#app-list a:hover.selected { - background:#A4C639; - color:#fff; - cursor:default; - text-decoration:none; -} - -#app-list a:hover, -#app-list a:active { - background:#ff9900; -} - -#app-list a:hover span, -#app-list a:active span { - text-decoration:underline; -} - -#droid-name { - padding-top:.5em; - color:#666; - padding-bottom:.25em; -} - -/*IE6*/ -* html #app-list a { zoom: 1; margin:0 24px 0 15px;} - -* html #list-clip { - width:430px !important; -} - -/*carousel bulletin layouts*/ -/*460px width*/ -/*185px height*/ -.img-left { - float:left; - width:230px; - overflow:hidden; - padding:8px 0 8px 8px; -} -.desc-right { - float:left; - width:270px; - padding:10px; -} -.img-right { - float:right; - width:220px; - overflow:hidden; - padding:8px 8px 8px 0; -} -.desc-left { - float:right; - width:280px; - padding:10px; - text-align:right; -} -.img-top { - padding:20px 20px 0; -} -.desc-bottom { - padding:10px; -} - - -/* VIDEO PAGE */ - -#mainBodyLeft.videoPlayer { - width:570px; -} - -#mainBodyRight.videoPlayer { - width:330px; -} - -/* player */ - -#videoPlayerBox { - background-color: #DAF3FC; - border-radius:7px; - -moz-border-radius:7px; - -webkit-border-radius:7px; - width:530px; - padding:20px; - border:1px solid #d3ecf5; - box-shadow:2px 3px 1px #eee; - -moz-box-shadow:2px 3px 1px #eee; - -webkit-box-shadow:2px 3px 1px #eee; -} - -#videoBorder { - background-color: #FFF; - min-height:399px; - height:auto !important; - border:1px solid #ccdada; - border-radius:7px 7px 0 0; - -moz-border-radius:7px 7px 0 0; - -webkit-border-top-left-radius:7px; - -webkit-border-top-right-radius:7px; -} - -#videoPlayerTitle { - width:500px; - padding:15px 15px 0; -} - -#videoPlayerTitle h2 { - font-weight:bold; - font-size:1.2em; - color:#336666; - margin:0; - padding:0; -} - -#objectWrapper { - padding:15px 15px; - height:334px; - width:500px; -} - -/* playlist tabs */ - -ul#videoTabs { - list-style-type:none; - padding:0; - clear:both; - margin:0; - padding: 20px 0 0 15px; - zoom:1; /* IE7/8, otherwise top-padding is double */ -} - -ul#videoTabs li { - display:inline; - padding:0; - margin:0 3px 0 0; - line-height:2em; -} - -ul#videoTabs li a { - border-radius:7px 7px 0 0; - -moz-border-radius:7px 7px 0 0; - -webkit-border-top-left-radius:7px; - -webkit-border-top-right-radius:7px; - background:#95c0d0; - color:#fff; - text-decoration:none; - padding:.45em 1.5em; - font-weight:bold; -} - -ul#videoTabs li.selected a { - font-weight:bold; - text-decoration:none; - color:#555; - background:#daf3fc; - border-bottom:1px solid #daf3fc; -} - -ul#videoTabs li:hover a { - background:#85acba; -} - -ul#videoTabs li.selected:hover a { - background:#daf3fc; -} - -/* playlists */ - -#videos { - background:#daf3fc; - margin-bottom:1.5em; - padding:15px; - border-radius:5px; - -moz-border-radius:5px; - -webkit-border-radius:5px; - box-shadow:2px 3px 1px #eee; - -moz-box-shadow:2px 3px 1px #eee; - -webkit-box-shadow:2px 3px 1px #eee; -} - -#videos div { - display:none; -} - -#videos div.selected { - display:block; -} - -ul.videoPreviews { - list-style:none; - padding:0; - margin:0; - zoom:1; /* IE, otherwise, layout doesn't update when showing 'more' */ -} - -ul.videoPreviews li { - margin:0 0 5px; - padding:0; - overflow:hidden; - position:relative; -} - -#mainBodyFixed ul.videoPreviews h3 { - font-size: 12px; - margin:0 0 1em 130px; - padding:0; - font-weight:bold; - color:inherit; -} - -ul.videoPreviews a { - margin:1px; - padding:10px; - text-decoration:none; - height:90px; - display:block; - border-radius:5px; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color:transparent; -} - -ul.videoPreviews a:hover { - background-color:#FFF; - border:none; /* IE8, otherwise, bg doesn't work */ -} - -ul.videoPreviews a.selected { - background-color: #FF9900; -} - -ul.videoPreviews img { - float:left; - clear:left; - margin:0; -} - -ul.videoPreviews h3 { - font-size:12px; - font-weight:bold; - text-decoration:none; - margin:0 0 1em 130px; - padding:0; -} - -ul.videoPreviews p { - font-size: 12px; - text-decoration:none; - margin:0 0 1.2em 130px; -} - -ul.videoPreviews p.full { - display:none; -} - -ul.videoPreviews span.more { - padding:0 0 0 12px; - background:url(images/arrow_bluelink_down.png) 0 2px no-repeat; -} - -ul.videoPreviews span.less { - padding:0 0 0 12px; - background:url(images/arrow_bluelink_up.png) 0 2px no-repeat; - display:none; -} - -ul.videoPreviews p.toggle { - position:absolute; - margin:0; - margin-top:-23px; /* instead of bottom:23px, because IE won't do it correctly */ - left:140px; -} - -ul.videoPreviews p.toggle a { - height:auto; - margin:0; - padding:0; - zoom:1; /* IE6, otherwise the margin considers the img on redraws */ -} - -ul.videoPreviews p.toggle a:hover { - text-decoration:underline; - background:transparent; /* IE6, otherwise it inherits white */ -} - -/* featured videos */ - -#mainBodyRight h2 { - padding:0 0 5px; -} - -#mainBodyRight ul.videoPreviews { - margin:10px 0 0; -} - -#mainBodyRight ul.videoPreviews li { - font-size:11px; - line-height:13px; - margin:0 0 5px; - padding:0; -} - -#mainBodyRight ul.videoPreviews h3 { - padding:0; - margin:0; - font-size:100%; -} - -#mainBodyRight ul.videoPreviews a { - text-decoration:none; - height:108px; - border:1px solid #FFF; -} - -#mainBodyRight ul.videoPreviews a:hover { - border:1px solid #CCDADA; -} - -#mainBodyRight ul.videoPreviews a.selected { - border:1px solid #FFF; -} - -#mainBodyRight ul.videoPreviews p { - line-height:1.2em; - padding:0; - margin:4px 0 0 130px; -} - -#mainBodyRight ul.videoPreviews img { - margin-top:5px; -} - -/* Pretty printing styles. Used with prettify.js. */ - -.str { color: #080; } -.kwd { color: #008; } -.com { color: #800; } -.typ { color: #606; } -.lit { color: #066; } -.pun { color: #660; } -.pln { color: #000; } -dl.tag-list dt code, -.tag { color: #008; } -dl.atn-list dt code, -.atn { color: #828; } -.atv { color: #080; } -.dec { color: #606; } - -@media print { - .str { color: #060; } - .kwd { color: #006; font-weight: bold; } - .com { color: #600; font-style: italic; } - .typ { color: #404; font-weight: bold; } - .lit { color: #044; } - .pun { color: #440; } - .pln { color: #000; } - .tag { color: #006; font-weight: bold; } - .atn { color: #404; } - .atv { color: #060; } -} - - -#title { - border-bottom: 4px solid #ccc; - display:none; -} - -#title h1 { - color:#336666; - margin:0; - padding: 5px 10px; - font-size: 1em; - line-height: 15px; -} - -#title h1 .small{ - color:#000; - margin:0; - font-size: 13px; - padding:0 0 0 15px; -} - -/* SIDE NAVIGATION */ - -#side-nav { - padding:0 6px 0 0; - background-color: #fff; - font-size:12px; -} - -#resize-packages-nav { -/* keeps the resize handle below the h-scroll handle */ - height:270px; - overflow:hidden; - max-height:100%; -} - -#packages-nav { - height:270px; - max-height:inherit; - position:relative; - overflow:auto; -} - -#classes-nav, -#devdoc-nav { - overflow:auto; - position:relative; -} - -#side-nav ul { - list-style: none; - margin: 0; - padding:5px 0; -} - -#side-nav ul ul { - margin: .5em 0 0 0; - padding: 0; -} - -#side-nav li { - padding:0; - padding:1px 0 1px 0; - zoom:1; -} - -#side-nav li span.heading, -#side-nav li h2 { - display:block; - font-size:12px; - font-weight: bold; - margin:.5em 0 0 0; - padding: 3px 0 1px 9px; -} - -#side-nav li a { - display: inline-block; /* needed to apply padding to line-wraps */ - text-decoration:none; - padding: 0 0 0 18px; - zoom:1; -} - -#side-nav li a span+span { - display:none; -} - -#side-nav li a:hover { - text-decoration:underline; -} - -#side-nav li a+a { - padding: 0; -} -/*second level (nested) list*/ -#side-nav li li li a { - padding: 0 0 0 28px; -} -/*third level (nested) list*/ -#side-nav li li li li a { - padding: 0 0 0 38px; -} - -#side-nav .selected { - background-color: #435a6e; - color: #fff; - font-weight:bold; -} - -#side-nav .selected a { - color: #fff; - text-decoration:none; -} - -#side-nav strong { - display:block; -} - -#side-nav .toggle-list .toggle-img { - margin:0; - padding:0; - position:absolute; - top:0; - left:0; - height:16px; - width:15px; - outline-style:none; -} -/* second-level toggle */ -#side-nav .toggle-list .toggle-list .toggle-img { - left:10px; -} - -#side-nav .closed .toggle-img, -#side-nav .open .closed .toggle-img { - background:url('images/triangle-closed-small.png') 7px 4px no-repeat; -} -#side-nav .open .toggle-img { - background:url('images/triangle-opened-small.png') 7px 4px no-repeat; -} - -#side-nav .toggle-list { - position:relative; -} - -#side-nav .toggle-list ul { - margin:0; - display:none; -} - -#side-nav .toggle-list div { - display:block; -} - -#index-links .selected { - background-color: #fff; - color: #000; - font-weight:normal; - text-decoration:none; -} - -#index-links { - padding:7px 0 4px 10px; -} - -/* nav tree */ - -#nav-tree ul { - padding:5px 0 1.5em; -} - -#side-nav #nav-tree ul li a, -#side-nav #nav-tree ul li span.no-children { - padding: 0 0 0 0; - margin: 0; -} - -#nav-tree .plus { - margin: 0 3px 0 0; -} - -#nav-tree ul ul { - list-style: none; - margin: 0; - padding: 0 0 0 0; -} - -#nav-tree ul li { - margin: 0; - padding: 0 0 0 0; - white-space: nowrap; -} - -#nav-tree .children_ul { - margin:0; -} - -#nav-tree a.nolink { - color: black; - text-decoration: none; -} - -#nav-tree span.label { - width: 100%; -} - -#nav-tree { - overflow-x: auto; - overflow-y: scroll; -} - -#nav-swap { - font-size:10px; - line-height:10px; - margin-left:1em; - text-decoration:none; - display:block; -} - -#tree-link { - -} - -/* DOCUMENT BODY */ - -#doc-content { - overflow:auto; -} - -#jd-header { - background-color: #E2E2E2; - padding: 7px 15px; -} - -#jd-header h1 { - margin: 0 0 10px; - font-size:1.7em; -} - -#jd-header .crumb { - font-size:.9em; - line-height:1em; - color:#777; -} - -#jd-header .crumb a, -#jd-header .crumb a:visited { - text-decoration:none; - color:#777; -} - -#jd-header .crumb a:hover { - text-decoration:underline; -} - -#jd-header table { - margin:0; - padding:0; -} - -#jd-header td { - border:none; - padding:0; - vertical-align:top; -} - -#jd-header.guide-header { - background-color:#fff; - color:#435a6e; - height:50px; -} - -#jd-descr { - position:relative; -} - -/* summary tables for reference pages */ -.jd-sumtable { - margin: .5em 1em 1em 1em; - width:95%; /* consistent table widths; within IE's quirks */ - font-size:.9em; -} - -.jd-sumtable a { - text-decoration:none; -} - -.jd-sumtable a:hover { - text-decoration:underline; -} - -/* the link inside a sumtable for "Show All/Hide All" */ -.toggle-all { - display:block; - float:right; - font-weight:normal; - font-size:0.9em; -} - -/* adjustments for in/direct subclasses tables */ -.jd-sumtable-subclasses { - margin: 1em 0 0 0; - max-width:968px; -} - -/* extra space between end of method name and open-paren */ -.sympad { - margin-right: 2px; -} - -/* right alignment for the return type in sumtable */ -.jd-sumtable .jd-typecol { - text-align:right; -} - -/* adjustments for the expando table-in-table */ -.jd-sumtable-expando { - margin:.5em 0; - padding:0; -} - -/* a div that holds a short description */ -.jd-descrdiv { - padding:3px 1em 0 1em; - margin:0; - border:0; -} - -/* page-top-right container for reference pages (holds -links to summary tables) */ -#api-info-block { - font-size:.8em; - padding:6px 10px; - font-weight:normal; - float:right; - text-align:right; - color:#999; - max-width:70%; -} - -#api-level-toggle { - padding:0 10px; - font-size:11px; - float:right; -} - -#api-level-toggle label.disabled { - color:#999; -} - -div.api-level { - font-size:.8em; - font-weight:normal; - color:#999; - float:right; - padding:0 7px 0; - margin-top:-25px; -} - -#api-info-block div.api-level { - font-size:1.3em; - font-weight:bold; - float:none; - color:#444; - padding:0; - margin:0; -} - -/* Force link colors for IE6 */ -div.api-level a { - color:#999; -} -#api-info-block div.api-level a:link { - color:#444; -} -#api-level-toggle a { - color:#999; -} - -div#deprecatedSticker { - display:none; - z-index:99; - position:fixed; - right:15px; - top:114px; - margin:0; - padding:1em; - background:#FFF; - border:1px solid #dddd00; - box-shadow:-5px 5px 10px #ccc; - -moz-box-shadow:-5px 5px 10px #ccc; - -webkit-box-shadow:-5px 5px 10px #ccc; -} - -div#naMessage { - display:none; - width:555px; - height:0; - margin:0 auto; -} - -div#naMessage div { - z-index:99; - width:450px; - position:fixed; - margin:50px 0; - padding:4em 4em 3em; - background:#FFF; - border:1px solid #dddd00; - box-shadow:-10px 10px 40px #888; - -moz-box-shadow:-10px 10px 40px #888; - -webkit-box-shadow:-10px 10px 40px #888; -} -/* IE6 can't position fixed */ -* html div#naMessage div { position:absolute; } - -div#naMessage strong { - font-size:1.1em; -} - -.absent, -.absent a:link, -.absent a:visited, -.absent a:hover, -.absent * { - color:#bbb !important; - cursor:default !important; - text-decoration:none !important; -} - -#api-level-toggle a, -.api-level a { - color:inherit; - text-decoration:none; -} - -#api-level-toggle a:hover, -.api-level a:hover { - color:inherit; - text-decoration:underline !important; - cursor:pointer !important; -} - -#side-nav li.absent.selected, -#side-nav li.absent.selected *, -#side-nav div.label.absent.selected, -#side-nav div.label.absent.selected * { - background-color:#eaeaea !important; -} -/* IE6 quirk (won't chain classes, so just keep background blue) */ -* html #side-nav li.selected, -* html #side-nav li.selected *, -* html #side-nav div.label.selected, -* html #side-nav div.label.selected * { - background-color: #435a6e !important; -} - - -.absent h4.jd-details-title, -.absent h4.jd-details-title * { - background-color:#f6f6f6 !important; -} - -.absent img { - opacity: .3; - filter: alpha(opacity=30); - -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; -} - - -/* applies to a div containing links to summary tables */ -.sum-details-links { - padding:0; - font-weight:normal; -} - -.sum-details-links a { - text-decoration:none; -} - -.sum-details-links a:hover { - text-decoration:underline; -} - - -/* inheritance table */ -.jd-inheritance-table { - border-spacing:0; - margin:0; - padding:0; - font-size:.9em; -} -.jd-inheritance-table td { - border: none; - margin: 0; - padding: 0; -} -.jd-inheritance-table .jd-inheritance-space { - font-weight:bold; - width:1em; -} -.jd-inheritance-table .jd-inheritance-interface-cell { - padding-left: 17px; -} - -#jd-content { - padding: 18px 15px; -} - -hr { - background-color:#ccc; - border-color:#fff; - margin:2em 0 1em; -} - -/* DOC CLASSES */ - -#jd-content h1 { -/*sdk page*/ - font-size:1.6em; - color:#336666; - margin:0 0 .5em; -} - -#jd-content h2 { - font-size:1.45em; - color:#111; - border-top:2px solid #ccc; - padding: .5em 0 0; - margin: 2em 0 1em 0; -} - -#jd-content h3 { - font-size:1.3em; - color:#3a3a3a; - padding: 0; - margin: 1.5em 0 .65em 0; -} - -#jd-content h4 { - font-size:1.1em; - color:#3a3a3a; - padding: 0; - margin: 1.25em 0 .65em 0; -} - -#jd-content h5 { - font-size:1.0em; - color:#3a3a3a; - padding: 0; - margin: 1em 0 .65em 0; -} - -#jd-content .small-header { - font-size:1em; - color:#000; - font-weight:bold; - border:none; - padding:0; - margin:1em 0 .5em; - position:inherit; -} - -#jd-content table { - margin: 0 0 1em 1em; -} - -#jd-content img { - margin: 0 0 1em 1em; -} - -#jd-content li img, -#jd-content dd img { - margin:.5em 0 .5em 1em; -} - -.nolist { - list-style:none; - padding:0; - margin:0 0 1em 1em; -} - -.nolist li { - padding:0 0 2px; - margin:0; -} - -h4 .normal { - font-size:.9em; - font-weight:normal; -} - -.caps { - font-variant:small-caps; - font-size:1.2em; -} - -dl.tag-list dl.atn-list { - padding:0 0 0 2em; -} - -.jd-details { -/* border:1px solid #669999; - padding:4px; */ - margin:0 0 1em; -} - -/* API reference: a container for the -.tagdata blocks that make up the detailed -description */ -.jd-details-descr { - padding:0; - margin:.5em .25em; -} - -/* API reference: a block containing -a detailed description, a params table, -seealso list, etc */ -.jd-tagdata { - margin:.5em 1em; -} - -.jd-tagdata p { - margin:0 0 1em 1em; -} - -/* API reference: adjustments to -the detailed description block */ -.jd-tagdescr { - margin:.25em 0 .75em 0; - line-height:1em; -} - -.jd-tagdescr p { - margin:.5em 0; - padding:0; - -} - -.jd-tagdescr ol, -.jd-tagdescr ul { - margin:0 2.5em; - padding:0; -} - -.jd-tagdescr table, -.jd-tagdescr img { - margin:.25em 1em; -} - -.jd-tagdescr li { -margin:0 0 .25em 0; -padding:0; -} - -/* API reference: heading marking -the details section for constants, -attrs, methods, etc. */ -h4.jd-details-title { - font-size:1.15em; - background-color: #E2E2E2; - margin:1.5em 0 .6em; - padding:3px 95px 3px 3px; /* room for api-level */ -} - -h4.jd-tagtitle { - margin:0; -} - -/* API reference: heading for "Parameters", "See Also", etc., -in details sections */ -h5.jd-tagtitle { - margin:0 0 .25em 0; - font-size:1em; -} - -.jd-tagtable { - margin:0; -} - -.jd-tagtable td, -.jd-tagtable th { - border:none; - background-color:#fff; - vertical-align:top; - font-weight:normal; - padding:2px 10px; -} - -.jd-tagtable th { - font-style:italic; -} - -#jd-content table h2 { - background-color: #d6d6d6; - font-size: 1.1em; - margin:0 0 10px; - padding:5px; - left:0; - width:auto; -} - -div.design-announce { - border-top:1px solid #33B5E5; - border-bottom:1px solid #33B5E5; - padding:5px 10px 10px 55px; - margin:2em 0; - background:url('images/icon_design.png') 5px 13px no-repeat; -} - -div.design-announce p { - margin: .5em 0 0 0; -} - -div.special { - padding: .5em 1em 1em 1em; - margin: 0 0 1em; - background-color: #DAF3FC; - border:1px solid #d3ecf5; - border-radius:5px; - -moz-border-radius:5px; - -webkit-border-radius:5px; -} - -div.special p { - margin: .5em 0 0 0; -} - -div.special ol { - margin: 0; -} - -div.special ol li { - margin: 0; - padding: 0; -} - -#jd-content div.special h2, -#jd-content div.special h3 { - color:#669999; - font-size:1.2em; - border:none; - margin:0 0 .5em; - padding:0; -} - -#jd-content div.special.reference h2, -#jd-content div.special.reference h3, -#jd-content div.special.reference h4 { - color:#000; - font-size:1em; - border:none; - font-weight:bold; - margin:.5em 0; - padding:0; -} - -p.note, div.note, -p.caution, div.caution, -p.warning, div.warning { - margin: 1em; - padding: 0 0 0 .5em; - border-left: 4px solid; -} - -p.special-note, -div.special-note { - background-color:#EBF3DB; - padding:10px 20px; - margin:0 0 1em; -} - -p.note, -div.note { - border-color: #99aacc; -} - -p.warning, -div.warning { - border-color: #aa0033; -} - -p.caution, -div.caution { - border-color: #ffcf00; -} - -li .note, -li .caution, -li .warning { - margin: .5em 0 0 0; - padding: .2em .5em .2em .9em; -} - -/* Makes sure the first paragraph does not add top-whitespace within the box*/ -li .note>p:first-child, -li .caution>p:first-child, -li .warning>p:first-child { - margin-top:0; - padding-top:0; -} - -dl.xml dt { - font-variant:small-caps; - font-size:1.2em; -} - -dl.xml dl { - padding:0; -} - -dl.xml dl dt { - font-variant:normal; - font-size:1em; -} - -.listhead li { - font-weight: bold; -} - -.listhead li *, /*ie*/.listhead li li { - font-weight: normal; -} - -ol.no-style, -ul.no-style { - list-style:none; - padding-left:1em; -} - -.new, -.new-child { - font-size: .78em; - font-weight: bold; - color: #ff3d3d; - text-decoration: none; - vertical-align:top; - line-height:.9em; - white-space:nowrap; -} - -.toggle-list.open .new-child { - display:none; -} - -pre.classic { - background-color:transparent; - border:none; - padding:0; -} - -p.img-caption { - margin: -0.5em 0 1em 1em; /* matches default img left-margin */ -} - -div.figure { - float:right; - clear:right; - margin:1em 0 0 0; - padding:0 0 0 3em; - background-color:#fff; - /* width must be defined w/ an inline style matching the image width */ -} - -#jd-content -div.figure img { - margin: 0 0 1em; -} - -div.figure p.img-caption { - margin: -0.5em 0 1em 0; -} - -p.table-caption { - margin: 0 0 0.5em 1em; /* matches default table left-margin */ -} - - -/* toggle for misc content (such as long sample code) - see toggleContent() script in android-developer-docs.js */ -.toggle-content.closed .toggle-content-toggleme { - display:none; -} - -.toggle-content a[href="#"] { - text-decoration:none; - color:inherit; -} - -.toggle-content-toggleme { - padding-bottom:1px; /* fixes animation bounce due to margins */ -} - -#jd-content .toggle-content img.toggle-content-img { - margin:0; -} - - -/* BEGIN quickview sidebar element styles */ - -#qv-wrapper { - float: right; - width:310px; /* +35px padding */ - background-color:#fff; - margin:-48px 0 2px 0; - padding:0 0 20px 35px; -} - -#qv { - background-color:#fff; - border:4px solid #dee8f1; - margin:0; - padding:0 5px 5px; - width:292px; /* +10px padding; +8px border */ - font-size:.9em; -} - -#qv ol { - list-style:none; - padding: 0; -} - -#qv ol ol{ - list-style:none; - padding: 0 0 0 12px; - margin:0; -} - -#qv ul { - padding: 0 10px 0 2em; -} - -#qv li { - padding: 0 10px 3px; - line-height: 1.2em; -} - -#qv li li { - padding: 3px 10px 0; -} - -#qv ul li { - padding: 0 10px 0 0; -} - -#qv li.selected a { - color:#555; - text-decoration:none; -} - -#qv a, -#qv a code { - color:#cc6600; -} - -#qv p { - margin:8px 0 0; - padding:0 10px; -} - -#jd-content #qv h2 { - font-size:1.05em; - font-weight:bold; - margin:12px 0 .25em 0; - padding:0 10px; - background-color:transparent; - color:#7BB026; - border:none; - left:0; - z-index:1; -} - -#qv-extra #rule { - padding: 0 10px; - margin: 0; -} - -#qv-sub-rule { - padding: 5px 15px 10px; - margin: 0; -} - -#jd-content -#qv-sub-rule h2 { - margin: 0 0 .5em 0; -} - -/* END quickview sidebar element styles */ - -/* Begin sidebox sidebar element styles */ - -.sidebox-wrapper { - float:right; - clear:right; - width:310px; /* +35px padding */ - background-color:#fff; - margin:0; - padding:0 0 20px 35px; -} - -.sidebox { - border-left:1px solid #dee8f1; - background-color:#ffffee; - margin:0; - padding:8px 12px; - font-size:0.9em; - width:285px; /* +24px padding; +1px border */ -} - -.sidebox p { - margin-bottom: .75em; -} - -.sidebox ul { - padding: 0 0 0 1.5em; -} - -.sidebox li ul { - margin-top:0; - margin-bottom:.1em; -} - -.sidebox li { -padding:0 0 0 0em; -} - -#jd-content .sidebox h2, -#jd-content .sidebox h3, -#jd-content .sidebox h4, -#jd-content .sidebox h5 { - border:none; - font-size:1em; - margin:0; - padding:0 0 8px; - left:0; - z-index:0; -} - -.sidebox hr { - background-color:#ccc; - border:none; -} - -/* End sidebox sidebar element styles */ - -/* BEGIN developer training bar styles */ - -div#tb-wrapper { - float: right; - clear:right; - width:380px; /* +25px padding = 405 */ - background-color:#fff; - margin:0 0 2px 0; - padding:0 0 20px 25px; -} - -div#tb { - margin:0; - padding:0 15px; - width:350px; /* +15px padding = 380 */ - font-size:.9em; - background:#e9e9e9; - border:1px solid #aaa; - border-radius:5px; - -moz-border-radius:5px; - -webkit-border-radius:5px; - overflow:auto; -} - -div#tb h2 { - font-size:1.3em; - font-weight:bold; - margin:1em 0; - padding:0; - background-color:transparent; - border:none; - clear:both; -} - -div.download-box a.button { - color: #069; - font-size:1.1em; - font-weight:bold; - text-decoration:none; - height:27px; - line-height:27px; - text-align:center; - padding:5px 8px; - background-color: #fff; - border: 1px solid #aaa; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; -} - -div.download-box a.button:hover { - border-color: #09C; - background-color: #4CADCB; - background-image: -webkit-gradient(linear,left top,left bottom,from(#5dbcd9),to(#4cadcb)); - background-image: -webkit-linear-gradient(top,#5dbcd9,#4cadcb); - background-image: -moz-linear-gradient(top,#5dbcd9,#4cadcb); - background-image: -ms-linear-gradient(top,#5dbcd9,#4cadcb); - background-image: -o-linear-gradient(top,#5dbcd9,#4cadcb); - background-image: linear-gradient(top,#5dbcd9,#4cadcb); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#5dbcd9',EndColorStr='#4cadcb'); - color: #fff; -} - -div.download-box a.button:active { - background-color: #1E799A; - background-image: none; - border-color: #30B7E6; -} - -div.download-box p.filename { - font-size:0.85em; - color:#888; - margin:4px 0 1em 10px; -} - -/* End developer training bar */ - -/* Training nav bar (previous/next) */ - -div.training-nav-top { - float: right; - width:380px; /* +25px padding = 405 */ - margin:-58px 0 0 0; - padding:0 0 20px 25px; -} - -div.training-nav-bottom { - padding:1px; /* for weird FF bug (scrollbar appears) */ - margin:3em 0; - overflow:auto; -} - -div.training-nav-button-next a, -div.training-nav-button-previous a { - display:block; - width:160px; - height:55px; - padding:4px 7px; - border:1px solid #aaa; - border-radius:5px; - -moz-border-radius:5px; - -webkit-border-radius:5px; - text-decoration:none; - font-weight:bold; -} - -div.training-nav-button-next a:hover, -div.training-nav-button-previous a:hover { - border:1px solid #069; /* match link color */ -} - -div.training-nav-button-next a:active, -div.training-nav-button-previous a:active { - border:1px solid #f00; /* match link color */ -} - -div.training-nav-button-previous { - float:left; - text-align:left; -} - -div.training-nav-button-next { - float:right; - text-align:right; -} - -span.training-nav-button-title { - display:block; - font-size:.85em; - font-weight:normal; - line-height:1.3em; - margin:.5em 0 0; -} - -/* End training nav bar */ - -/* BEGIN image and caption styles (originally for UI Guidelines docs) */ - -table.image-caption { - padding:0; - margin:.5em 0; - border:0; -} - -td.image-caption-i { - font-size:92%; - padding:0 5px; - margin:0; - border:0; -} - -td.image-caption-i img { - padding:0 1em; - margin:0; -} - -.image-list { - width:24px; - text-align:center; -} - -td.image-caption-c { - font-size:92%; - padding:1em 2px 2px 2px; - margin:0; - border:0; - width:350px; -} - -.grad-rule-top { -background-image:url(images/grad-rule-qv.png); -background-repeat:no-repeat; -padding-top:1em; -margin-top:0; -} - -.image-caption-nested { - margin-top:0; - padding:0 0 0 1em; -} - -.image-caption-nested td { - padding:0 4px 2px 0; - margin:0; - border:0; -} - -/* END image and caption styles */ - -/* table of contents */ - -ol.toc { - margin: 0 0 1em 0; - padding: 0; - list-style: none; - font-size:95%; -} - -ol.toc li { - font-weight: bold; - margin: 0 0 .5em 1em; - padding: 0; -} - -ol.toc li p { - font-weight: normal; -} - -ol.toc li ol { - margin: 0; - padding: 0; -} - -ol.toc li li { - padding: 0; - margin: 0 0 0 1em; - font-weight: normal; - list-style: none; -} - -table ol.toc { - margin-left: 0; -} - -.columns td { - padding:0 5px; - border:none; -} - -/* link table */ -.jd-linktable { - margin: 0 0 1em; - border-bottom: 1px solid #888; -} -.jd-linktable th, -.jd-linktable td { - padding: 3px 5px; - vertical-align: top; - text-align: left; - border:none; -} -.jd-linktable tr { - background-color: #fff; -} -.jd-linktable td { - border-top: 1px solid #888; - background-color: inherit; -} -.jd-linktable td p { - padding: 0 0 5px; -} -.jd-linktable .jd-linkcol { -} -.jd-linktable .jd-descrcol { -} -.jd-linktable .jd-typecol { - text-align:right; -} -.jd-linktable .jd-valcol { -} -.jd-linktable .jd-commentrow { - border-top:none; - padding-left:25px; -} -.jd-deprecated-warning { - margin-top: 0; - margin-bottom: 10px; -} - -tr.alt-color { - background-color: #f6f6f6; -} - -/* expando trigger */ -#jd-content .jd-expando-trigger-img { - margin:0; -} - -/* jd-expando */ -.jd-inheritedlinks { - padding:0 0 0 13px -} - -/* SDK PAGE */ -table.download tr { - background-color:#d9d9d9; -} - -table.download tr.alt-color { - background-color:#ededed; -} - -table.download td, -table.download th { - border:2px solid #fff; - padding:10px 5px; -} - -table.download th { - background-color:#6d8293; - color:#fff; -} - -/* INLAY 180 COPY and 240PX EXTENSION */ -/* modified to 43px so that all browsers eliminate the package panel h-scroll */ -.g-tpl-240 .g-unit, -.g-unit .g-tpl-240 .g-unit, -.g-unit .g-unit .g-tpl-240 .g-unit { - display: block; - margin: 0 0 0 243px; - width: auto; - float: none; -} -.g-unit .g-unit .g-tpl-240 .g-first, -.g-unit .g-tpl-240 .g-first, -.g-tpl-240 .g-first { - display: block; - margin: 0; - width: 243px; - float: left; -} -/* 240px alt */ -.g-tpl-240-alt .g-unit, -.g-unit .g-tpl-240-alt .g-unit, -.g-unit .g-unit .g-tpl-240-alt .g-unit { - display: block; - margin: 0 243px 0 0; - width: auto; - float: none; -} -.g-unit .g-unit .g-tpl-240-alt .g-first, -.g-unit .g-tpl-240-alt .g-first, -.g-tpl-240-alt .g-first { - display: block; - margin: 0; - width: 243px; - float: right; -} - -/* 200px */ -.g-tpl-200 .g-unit, -.g-unit .g-tpl-200 .g-unit, -.g-unit .g-unit .g-tpl-200 .g-unit { - display: block; - margin: 0 0 0 200px; - width: auto; - float: none; -} -.g-unit .g-unit .g-tpl-200 .g-first, -.g-unit .g-tpl-200 .g-first, -.g-tpl-200 .g-first { - display: block; - margin: 0; - width: 200px; - float: left; -} -/* 200px alt */ -.g-tpl-200-alt .g-unit, -.g-unit .g-tpl-200-alt .g-unit, -.g-unit .g-unit .g-tpl-200-alt .g-unit { - display: block; - margin: 0 200px 0 0; - width: auto; - float: none; -} -.g-unit .g-unit .g-tpl-200-alt .g-first, -.g-unit .g-tpl-200-alt .g-first, -.g-tpl-200-alt .g-first { - display: block; - margin: 0; - width: 200px; - float: right; -} - -/* 190px */ -.g-tpl-190 .g-unit, -.g-unit .g-tpl-190 .g-unit, -.g-unit .g-unit .g-tpl-190 .g-unit { - display: block; - margin: 0 0 0 190px; - width: auto; - float: none; -} -.g-unit .g-unit .g-tpl-190 .g-first, -.g-unit .g-tpl-190 .g-first, -.g-tpl-190 .g-first { - display: block; - margin: 0; - width: 190px; - float: left; -} -/* 190px alt */ -.g-tpl-190-alt .g-unit, -.g-unit .g-tpl-190-alt .g-unit, -.g-unit .g-unit .g-tpl-190-alt .g-unit { - display: block; - margin: 0 190px 0 0; - width: auto; - float: none; -} -.g-unit .g-unit .g-tpl-190-alt .g-first, -.g-unit .g-tpl-190-alt .g-first, -.g-tpl-190-alt .g-first { - display: block; - margin: 0; - width: 190px; - float: right; -} - -/* 180px */ -.g-tpl-180 .g-unit, -.g-unit .g-tpl-180 .g-unit, -.g-unit .g-unit .g-tpl-180 .g-unit { - display: block; - margin: 0 0 0 180px; - width: auto; - float: none; -} -.g-unit .g-unit .g-tpl-180 .g-first, -.g-unit .g-tpl-180 .g-first, -.g-tpl-180 .g-first { - display: block; - margin: 0; - width: 180px; - float: left; -} -/* 180px alt */ -.g-tpl-180-alt .g-unit, -.g-unit .g-tpl-180-alt .g-unit, -.g-unit .g-unit .g-tpl-180-alt .g-unit { - display: block; - margin: 0 180px 0 0; - width: auto; - float: none; -} -.g-unit .g-unit .g-tpl-180-alt .g-first, -.g-unit .g-tpl-180-alt .g-first, -.g-tpl-180-alt .g-first { - display: block; - margin: 0; - width: 180px; - float: right; -} - - -/* JQUERY RESIZABLE STYLES */ -.ui-resizable { position: relative; } -.ui-resizable-handle { position: absolute; display: none; font-size: 0.1px; z-index:1; } -.ui-resizable .ui-resizable-handle { display: block; } -body .ui-resizable-disabled .ui-resizable-handle { display: none; } -body .ui-resizable-autohide .ui-resizable-handle { display: none; } -.ui-resizable-s { cursor: s-resize; height: 6px; width: 100%; bottom: 0px; left: 0px; - background: transparent url("images/resizable-s2.gif") repeat scroll center top; } -.ui-resizable-e { cursor: e-resize; width: 6px; right: 0px; top: 0px; height: 100%; - background: transparent url("images/resizable-e2.gif") repeat scroll right center; } - -@media print { - - body { - overflow:visible; - } - - #header { - height:60px; - } - - #headerLeft { - padding:0; - } - - #header-tabs, - #headerRight, - #side-nav, - #api-info-block { - display:none; - } - - #body-content { - position:inherit; - } - - #doc-content { - margin-left:0 !important; - height:auto !important; - width:auto !important; - overflow:inherit; - display:inline; - } - - #jd-header { - padding:10px 0; - } - - #jd-content { - padding:15px 0 0; - } - - #footer { - float:none; - margin:2em 0 0; - } - - h4.jd-details-title { - border-bottom:1px solid #666; - } - - pre { - /* these allow lines to break (if there's a white space) */ - overflow: visible; - text-wrap: unrestricted; - white-space: -moz-pre-wrap; /* Moz */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - white-space: pre-wrap; /* CSS3 */ - word-wrap: break-word; /* IE 5.5+ */ - } - - h1, h2, h3, h4, h5, h6 { - page-break-after: avoid; - } - - table, img { - page-break-inside: avoid; - } -} diff --git a/tools/droiddoc/templates-ndk/assets/css/default.css b/tools/droiddoc/templates-ndk/assets/css/default.css deleted file mode 100644 index 036c0eb378..0000000000 --- a/tools/droiddoc/templates-ndk/assets/css/default.css +++ /dev/null @@ -1,7440 +0,0 @@ -/* color definitions */ -/* 16 column layout */ -/* clearfix idiom */ -/* common mixins */ -/* page layout + top-level styles */ -::selection { - background-color: #0099cc; - color: #fff; } -::-webkit-selection { - background-color: #0099cc; - color: #fff; } -::-moz-selection { - background-color: #0099cc; - color: #fff; } - -html, body { - height: 100%; - margin: 0; - padding: 0; - background-color:#F9F9F9; - -webkit-font-smoothing: antialiased; - /* prevent subpixel antialiasing, which thickens the text */ - /* text-rendering: optimizeLegibility; */ - /* turned off ligatures due to bug 5945455 */ } - -body { - color: #222; - font: 14px/19px Roboto, sans-serif; - font-weight: 400; - letter-spacing:.1; - padding:0 10px; } - -#page-container { - width: 940px; - margin: 0 40px; } - -#page-header { - height: 80px; - margin-bottom: 20px; - font-size: 48px; - line-height: 48px; - font-weight: 100; - padding-left: 10px; } - #page-header a { - display: block; - position: relative; - top: 20px; - text-decoration: none; - color: #555555 !important; } - -#main-row { - display: inline-block; } - #main-row:after { - content: "."; - display: block; - height: 0; - clear: both; - visibility: hidden; } - * html #main-row { - height: 1px; } - -#page-footer { - margin-left: 190px; - margin-top: 80px; - color: #999999; - padding-bottom: 40px; - font-size: 12px; - line-height: 15px; } - #page-footer a { - color: #777777; } - #page-footer #copyright { - margin-bottom: 10px; } - -#nav-container { - width: 160px; - min-height: 10px; - margin-right: 20px; - float: left; } - -#nav { - margin:0; - padding:0 0 30px; -} - -#side-nav { - min-height:5px; /* silly way to avoid doc floating left when nav goes fixed */ - margin-bottom:1px; -} -#devdoc-nav { - outline:none; - width:auto; - margin: 20px 0 0; } - -#devdoc-nav h2 { - border:0; -} - -#devdoc-nav.fixed { - position: fixed; - margin:0; - top: 65px; /* sticky-header height + 20px gutter */ -} - -#devdoc-nav span.small { - font-size:12px; - font-weight:normal; -} - -#content { - width: 760px; - float: left; } - -a:hover, -acronym:hover { - color: #7aa1b0 !important; } - -a:focus, -a:active { - color: #33b5e5 !important; } - -a.external-link { - background:url('../images/styles/open_new_page.png') no-repeat 100% 50%; - padding-right:16px; -} - -img { - border: none; } -#jd-content img { - margin-bottom:15px; -} - -ul { - margin: 0; - padding: 0; } - -strong { - font-weight: 500; } - -em { - font-style: italic; } - -acronym, -.tooltip-link { - border-bottom: 1px dotted #555555; - cursor: help; } - -acronym:hover, -.tooltip-link:hover { - color: #7aa1b0; - border-bottom-color: #7aa1b0; } - -img.with-shadow, -video.with-shadow { - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); } - -/* disclosures mixin */ -/* content layout */ -.layout-content-row { - display: inline-block; - margin-bottom: 10px; } - * html .layout-content-row { - height: 1px; } - -.layout-content-col { - float: left; - margin-left: 20px; } - .layout-content-col:first-child { - margin-left: 0; } - .layout-content-col h3, - .layout-content-col h4 { - margin-top:0; } - -.layout-content-col.span-1 { - width: 40px; } - -.layout-content-col.span-2 { - width: 100px; } - -.layout-content-col.span-3 { - width: 160px; } - -.layout-content-col.span-4 { - width: 220px; } - -.layout-content-col.span-5 { - width: 280px; } - -.layout-content-col.span-6 { - width: 340px; } - -.layout-content-col.span-7 { - width: 400px; } - -.layout-content-col.span-8 { - width: 460px; } - -.layout-content-col.span-9 { - width: 520px; } - -.layout-content-col.span-10 { - width: 580px; } - -.layout-content-col.span-11 { - width: 640px; } - -.layout-content-col.span-12 { - width: 700px; } - -.layout-content-col.span-13 { - width: 760px; } - -.vspace.size-1 { - height: 10px; } - -.vspace.size-2 { - height: 20px; } - -.vspace.size-3 { - height: 30px; } - -.vspace.size-4 { - height: 40px; } - -.vspace.size-5 { - height: 50px; } - -.vspace.size-6 { - height: 60px; } - -.vspace.size-7 { - height: 70px; } - -.vspace.size-8 { - height: 80px; } - -.vspace.size-9 { - height: 90px; } - -.vspace.size-10 { - height: 100px; } - -.vspace.size-11 { - height: 110px; } - -.vspace.size-12 { - height: 120px; } - -.vspace.size-13 { - height: 130px; } - -.vspace.size-14 { - height: 140px; } - -.vspace.size-15 { - height: 150px; } - -.vspace.size-16 { - height: 160px; } - -/* nav */ -#nav { - /* section header divs */ - /* expanded section header divs */ - /* sublinks */ } - #nav li { - list-style-type: none; - font-size: 14px; - margin:0; - padding:0; - line-height: 15px; } - #nav a { - color: #555555; - text-decoration: none; - word-wrap:break-word; } - #nav .nav-section-header { - position: relative; - margin-bottom: 1px; - padding: 0 30px 0 0; } - #nav li.selected a, #nav li.selected > .nav-section-header > a { - color: #09C; - } - #nav li.selected ul li a { - /* don't highlight child items */ - color: #555555; } - #nav .nav-section .nav-section .nav-section-header { - /* no white line between second level sections */ - margin-bottom: 0; } - /* section header links */ - #nav > li > div > a { - display: block; - color: #333333; - font-weight: 500; - padding: 10px 0 10px 10px; } - #nav .nav-section-header:after { - content: ''; - background: transparent url(../images/styles/disclosure_down.png) no-repeat scroll 50% 50%; - width: 34px; - height: 34px; - display: block; - position: absolute; - top: 0; - right: 0; } - #nav .nav-section-header.empty { - padding:0; } - #nav .nav-section-header.empty:after { - display: none; } - /* nested nav headers */ - #nav .nav-section .nav-section { - position: relative; - padding: 0; - margin: 0; } - #nav .nav-section li a { - /* first gen child (2nd level li) */ - display:block; - font-weight: normal; - text-transform: none; - padding: 7px 5px 7px 10px; - } - #nav .nav-section li li a { - /* second gen child (3rd level li) */ - padding: 5px 5px 5px 10px; - } - #nav li.expanded .nav-section-header { - background:#e9e9e9; - background: rgba(0, 0, 0, 0.05); } - #nav li.expanded li .nav-section-header { - background: transparent; } - #nav li.expanded li ul { - /* 3rd level ul */ - padding:0 0 0 10px; - } - #nav li.expanded > .nav-section-header:after { - content: ''; - background: transparent url(../images/styles/disclosure_up.png) no-repeat scroll 50% 50%; - width: 34px; - height: 34px; } - #nav li.expanded li ul.tree-list-children { - padding: 0; - } - #nav li.expanded li ul.tree-list-children .tree-list-children { - padding:0 0 0 10px; - } - #nav li span.tree-list-subtitle { - display:inline-block; - padding:5px 0 0 10px; - color:#555; - text-transform:uppercase; - font-size:12px; - } - #nav li span.tree-list-subtitle:before { - content: '—'; - } - #nav li span.tree-list-subtitle:after { - content: '—'; - } - #nav li span.tree-list-subtitle.package { - padding-top:15px; - cursor:default; - } - #nav li span.tree-list-subtitle.package:before { - content: ''; - } - #nav li span.tree-list-subtitle.package:after { - content: ''; - } - #nav li ul.tree-list-children.classes { - padding-left:10px; - } - #nav li ul { - display:none; - overflow: hidden; - margin: 0; } - #nav li ul.animate-height-in { - -webkit-transition: height 0.25s ease-in; - -moz-transition: height 0.25s ease-in; - transition: height 0.25s ease-in; } - #nav li ul.animate-height-out { - -webkit-transition: height 0.25s ease-out; - -moz-transition: height 0.25s ease-out; - transition: height 0.25s ease-out; } - #nav li ul li { - padding: 0; } - #nav li li li { - padding: 0; } - #nav li.expanded ul { - } - #nav li ul > li { - padding:0; - } - #nav li ul > li:last-child { - padding-bottom:5px; - } - #nav li ul.tree-list-children > li:last-child { - padding-bottom:0; - } - #nav li.expanded ul > li { - background:#efefef; - background: rgba(0, 0, 0, 0.03); } - #nav li.expanded ul > li li { - background:inherit; } - #nav li ul.tree-list-children ul { - display:block; } - -#nav.samples-nav li li li { - font-size:13px; -} -#nav.samples-nav li li li a { - padding-top:3px; - padding-bottom:3px; -} -#nav.samples-nav li li ul > li:last-child { - padding-bottom:3px; -} - -.new, -.new-child { - font-size: .78em; - font-weight: bold; - color: #ff3d3d; - vertical-align:top; - white-space:nowrap; -} - -/* content header */ -.content-header { - height: 30px; - margin:36px 0 23px; /* same as h1 */ - padding:0 0 10px;} /* same as h1 */ -.content-header.just-links { - margin-bottom:0; - padding-bottom:0;} - -.content-header h1 { - margin:0; - padding:0; - width: 700px; -} -.content-header > div:first-child { - height:1px; /* set fixed height for the header div to ensure the - next/prev links align with toc on training classes */ -} - -.content-footer { - border-top: 1px solid #ccc; - margin-top: 10px; - padding-top:10px; - width:100%; } - -.content-footer .col-9 { - margin-left:0; -} -.content-footer .col-4 { - margin-right:0; -} -.content-footer.wrap { - width:940px; -} -.content-footer .plus-container { - margin:5px 0 0; - text-align:right; - float:right; -} - -a.back-link { - text-decoration: none; - text-transform: uppercase; -} - -.content-header .paging-links { - margin-top:-25px; -} -.paging-links { - position: relative; - height:30px; } - .paging-links a { - position: absolute; } - .paging-links a, - .training-nav-top a { - color: #555555; - text-decoration: none; - text-transform: uppercase; } - .paging-links .prev-page-link:before, - .training-nav-top .prev-page-link:before, - a.back-link:before { - content: ''; - background: transparent url(../images/styles/disclosure_left.png) no-repeat scroll 50% 50%; - width: 10px; - height: 10px; - display: inline-block; - margin-right: 5px; } - .training-nav-top .next-page-link, - .training-nav-top .start-class-link, - .training-nav-top .start-course-link { - right: 10px; } - .paging-links .prev-page-link { - left: -15px; } - .paging-links .next-page-link { - right: 0; } - .next-page-link:after, - .start-class-link:after, - .start-course-link:after, - .next-class-link:after, - .go-link:after { - content: ''; - background: transparent url(../images/styles/disclosure_right.png) no-repeat scroll 50% 50%; - width: 10px; - height: 10px; - display: inline-block; - margin-left: 5px; } - .prev-page-link.inline:before { - content: none; } - .next-page-link.inline:after { - content: none; } - - .content-footer .paging-links .next-page-link { - left:0; - } - - .training-nav-top a { - display:block; - float:left; - width:122px; - height:28px; - padding: 8px; - line-height:28px; - text-align:center; - border:1px solid #DADADA; - border-bottom:0; - } - - .training-nav-top a.next-page-link { - border-left:0; - width:123px; - } - - .paging-links a.disabled, - .training-nav-top a.disabled, - .content-footer a.disabled { - color:#bbb; - } - - .paging-links a.disabled:hover, - .training-nav-top a.disabled:hover, - .content-footer a.disabled:hover { - cursor:default; - color:#bbb !important; - } - - .training-nav-top a.start-class-link, - .training-nav-top a.start-course-link { - width:262px; - } - - .paging-links a.start-class-link { - width:100%; - } - - /* list of classes on course landing page */ - ol.class-list { - list-style:none; - margin-left:0; - } - ol.class-list>li { - margin:0 0 15px; - padding:5px 0 0; - overflow:hidden; - border-top:1px solid #ccc; - } - ol.class-list li a.title { - font-size:16px; - margin:0; - clear:left; - display:block; - height:32px; - padding:0 4px; - } - ol.class-list li a.title h2 { - color:inherit; - margin:0 0 10px; - display:block; - float:left; - width:675px; - } - ol.class-list li a.title span { - display:none; - float:left; - font-size:18px; - font-weight:bold; - background: transparent url(../images/styles/disclosure_right.png) no-repeat scroll 50% 50%; - width: 10px; - height: 32px; - } - ol.class-list li a.title:hover { - background:#ddd; - color:#258AAF !important; - } - ol.class-list li a.title:hover span { - display:block; - } - - #jd-content - ol.class-list li img { - float:left; - clear:left; - width:64px; - margin:0 20px 0 0; - } - ol.class-list li p.description { - float:left; - display:block; - width:250px; - margin:0; - } - ol.class-list li p.description.article { - width: 550px; - } - ol.class-list ol { - float:left; - width:320px; - margin:0 0 0 30px; - list-style:none; - margin:0 0 0 20px; - } - ol.class-list div.lessons li { - margin:0 0 6px; - line-height:16px; - } - - - .hide { - display:none !important; - } - - - - /* inner-doc tabs w/ title */ - -div#title-tabs-wrapper { - border-bottom:1px solid #ccc; - margin:20px 0 30px; -} -h1.with-title-tabs { - display:inline-block; - margin:0 0 -1px 0; - padding:0 60px 0 0; - border-bottom:1px solid #F9F9F9; -} -ul#title-tabs { - list-style:none; - padding:0; - height:29px; - margin:0; - font-size:16px; - line-height:26px; - display:inline-block; - vertical-align:bottom; -} -ul#title-tabs li { - display:block; - float:left; - margin-right:40px; - border-bottom: 3px solid transparent; -} -ul#title-tabs li.selected { - border-bottom: 3px solid #93C; -} -ul#title-tabs li a { - color:#333; -} -ul#title-tabs li a:hover, -ul#title-tabs li a:active { - color:#93C !important; -} - - - -/* content body */ -@-webkit-keyframes glowheader { - from { - background-color: #33b5e5; - color: #000; - border-bottom-color: #000; } - - to { - background-color: transparent; - color: #33b5e5; - border-bottom-color: #33b5e5; } } - -@-moz-keyframes glowheader { - from { - background-color: #33b5e5; - color: #000; - border-bottom-color: #000; } - - to { - background-color: transparent; - color: #33b5e5; - border-bottom-color: #33b5e5; } } - -@keyframes glowheader { - from { - background-color: #33b5e5; - color: #000; - border-bottom-color: #000; } - - to { - background-color: transparent; - color: #33b5e5; - border-bottom-color: #33b5e5; } } - -h1:target, -h2:target, -h3:target { - -webkit-animation-name: glowheader; - -moz-animation-name: glowheader; - animation-name: glowheader; - -webkit-animation-duration: 0.7s; - -moz-animation-duration: 0.7s; - animation-duration: 0.7s; - -webkit-animation-timing-function: ease-out; - -moz-animation-timing-function: ease-out; - animation-timing-function: ease-out; } - -.design ol h4 { - margin-bottom:0; -} -.design ol { - counter-reset: item; } - .design ol>li { - font-size: 14px; - line-height: 20px; - list-style-type: none; - position: relative; } - .design ol>li:before { - content: counter(item) ". "; - counter-increment: item; - position: absolute; - left: -20px; - top: 0; } - .design ol li.value-1:before { - content: "1. "; } - .design ol li.value-2:before { - content: "2. "; } - .design ol li.value-3:before { - content: "3. "; } - .design ol li.value-4:before { - content: "4. "; } - .design ol li.value-5:before { - content: "5. "; } - .design ol li.value-6:before { - content: "6. "; } - .design ol li.value-7:before { - content: "7. "; } - .design ol li.value-8:before { - content: "8. "; } - .design ol li.value-9:before { - content: "9. "; } - .design ol li.value-10:before { - content: "10. "; } -.design .with-callouts ol>li { - list-style-position: inside; - margin-left: 0; } - .design .with-callouts ol>li:before { - display: inline; - left: -20px; - float: left; - width: 17px; - color: #33b5e5; - font-weight: 500; } -.design .with-callouts ul>li { - list-style-position: outside; } - -/* special list items */ -li.no-bullet { - list-style-type: none !important; } -li.no-bullet *{ - margin:0; } - -.design li.with-icon { - position: relative; - margin-left: 20px; - min-height: 30px; } - .design li.with-icon p { - margin-left: 0 !important; } - .design li.with-icon:before { - position: absolute; - left: -40px; - top: 0; - content: ''; - width: 30px; - height: 30px; } - .design li.with-icon.tablet:before { - background-image: url(../images/styles/ico_phone_tablet.png); } - .design li.with-icon.web:before { - background-image: url(../images/styles/ico_web.png); } - .design li.with-icon.action:before { - background-image: url(../images/styles/ico_action.png); } - .design li.with-icon.use:before { - background-image: url(../images/styles/ico_use.png); } - -/* figures and callouts */ -.figure { - position: relative; } - .figure.pad-below { - margin-bottom: 20px; } - .figure .figure-callout { - position: absolute; - color: #fff; - font-weight: 500; - font-size: 16px; - line-height: 23px; - text-align: center; - background: transparent url(../images/styles/callout.png) no-repeat scroll 50% 50%; - padding-right: 2px; - width: 30px; - height: 29px; - z-index: 1000; } - .figure .figure-callout.top { - top: -9px; } - .figure .figure-callout.right { - right: -5px; } - -.figure-caption { - margin: 0 10px 20px 0; - font-size: 14px; - line-height: 20px; - font-style: italic; } - -/* rows of figures */ -.figure-row { - font-size: 0; - line-height: 0; - /* to prevent space between figures */ } - .figure-row .figure { - display: inline-block; - vertical-align: top; } - .figure-row .figure + .figure { - margin-left: 10px; - /* reintroduce space between figures */ } - -/* video containers */ -.framed-galaxynexus-land-span-13 { - background: transparent url(../images/styles/device_galaxynexus_blank_land_span13.png) no-repeat -scroll top left; - padding: 42px 122px 62px 126px; - overflow: hidden; } - .framed-galaxynexus-land-span-13, .framed-galaxynexus-land-span-13 video, -.framed-galaxynexus-land-span-13 img { - width: 512px; - height: 286px; } - - -.framed-galaxynexus-land-span-8{ - background: transparent url(../images/styles/device_galaxynexus_blank_land_span8.png) no-repeat -scroll top left; - padding: 26px 68px 38px 72px; - overflow: hidden; } - .framed-galaxynexus-land-span-8, .framed-galaxynexus-land-span-8 video, -.framed-galaxynexus-land-span-8 img { - width: 320px; - height: 180px; } - -.framed-galaxynexus-port-span-9 { - background: transparent url(../images/styles/device_galaxynexus_blank_port_span9.png) no-repeat -scroll top left; - padding: 95px 122px 107px 124px; - overflow: hidden; } - .framed-galaxynexus-port-span-9, .framed-galaxynexus-port-span-9 video, -.framed-galaxynexus-port-span-9 img { - width: 274px; - height: 488px; } - -.framed-galaxynexus-port-span-5 { - background: transparent url(../images/styles/device_galaxynexus_blank_port_span5.png) no-repeat -scroll top left; - padding: 75px 31px 76px 33px; - overflow: hidden; } - .framed-galaxynexus-port-span-5, .framed-galaxynexus-port-span-5 video, -.framed-galaxynexus-port-span-5 img { - width: 216px; - height: 384px; } - -.framed-nexus4-port-216 { - background: transparent url(../images/styles/device_nexus4_blank_port_432.png) no-repeat -scroll top left; - background-size:240px 465px; - padding: 52px 12px 52px 12px; - overflow: hidden; } - .framed-nexus4-port-216, .framed-nexus4-port-216 video, - .framed-nexus4-port-216 img { - width: 216px; - height: 360px; } - -.framed-nexus5-port-span-5 { - background: transparent url(../images/styles/device_nexus5_blank_port_span5.png) no-repeat - scroll top left; - padding: 52px 33px 69px 31px; - overflow: hidden; -} - -.framed-nexus5-port-span-5, -.framed-nexus5-port-span-5 video, -.framed-nexus5-port-span-5 img { - width: 216px; - height: 384px; -} - -.framed-nexus5-land-span-13 { - background: transparent url(../images/styles/device_nexus5_blank_land_span13.png) no-repeat scroll top left; - padding: 36px 119px 54px 108px; - overflow: hidden; -} - -.framed-nexus5-land-span-13, -.framed-nexus5-land-span-13 video, -.framed-nexus5-land-span-13 img { - width: 533px; - height: 300px; -} - -.framed-nexus5-port-span-5, -.framed-nexus5-port-span-5 video, -.framed-nexus5-port-span-5 img { - width: 216px; - height: 384px; -} - -/* wear device frames */ - -.framed-wear-square { - background: transparent url(../images/styles/device_wear_square.png) no-repeat scroll top left; - background-size: 302px 302px; - height:222px; - width:222px; - padding:40px; - overflow:hidden; -} - -.framed-wear-square-small { - background: transparent url(../images/styles/device_wear_square_small.png) no-repeat scroll top left; - background-size: 169px 200px; - height:147px; - width:147px; - padding:27px 11px; - overflow:hidden; -} - -#jd-content -.framed-wear-square img { - height:222px; - width: 222px; - padding:0; - margin:0; -} - -#jd-content -.framed-wear-square-small img { - height:147px; - width: 147px; - padding:0; - margin:0; -} - - - - - - -/* landing page disclosures */ -.landing-page-link { - text-decoration: none; - font-weight: 500; - color: #333333; } - .landing-page-link:after { - content: ''; - background: transparent url(../images/styles/disclosure_right.png) no-repeat scroll 50% 50%; - width: 10px; - height: 10px; - display: inline-block; - margin-left: 5px; } - -/* tooltips */ -.tooltip-box { - position: absolute; - background-color: rgba(0, 0, 0, 0.9); - border-radius: 2px; - font-size: 14px; - line-height: 20px; - color: #fff; - padding: 6px 10px; - max-width: 250px; - z-index: 10000; } - .tooltip-box.below:after { - position: absolute; - content: ''; - line-height: 0; - display: block; - top: -10px; - left: 5px; - border: 5px solid transparent; - border-bottom-color: rgba(0, 0, 0, 0.9); } - -/* video note */ -.video-instructions { - margin-top: 10px; - margin-bottom: 10px; } - .video-instructions:before { - content: ''; - background: transparent url(../images/styles/ico_movie_inline.png) no-repeat scroll top left; - display: inline-block; - width: 12px; - height: 12px; - margin-right: 8px; } - .video-instructions:after { - content: 'Click device screen to replay movie.'; } - -/* download buttons */ -.download-button { - display: block; - margin-bottom: 5px; - text-decoration: none; - background-color: #33b5e5; - color: #fff !important; - font-weight: 500; - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.12); - padding: 6px 12px; - border-radius: 2px; } - .download-button:hover, .download-button:focus { - background-color: #0099cc; - color: #fff !important; } - .download-button:active { - background-color: #006699; } - -/* UI tables and other things found in Writing style and Settings pattern */ -.ui-table { - width: 100%; - background-color: #282828; - color: #fff; - border-radius: 2px; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); - border-collapse: separate; } - .ui-table th, - .ui-table td { - padding: 5px 10px; - background-color: inherit; - border:0;} - .ui-table thead th { - font-weight: bold; } - .ui-table tfoot td { - border-top: 1px solid #494949; - border-right: 1px solid #494949; - text-align: center; } - .ui-table tfoot td:last-child { - border-right: 0; } - -.layout-with-list-item-margins { - margin-left: 30px !important; } - -.emulate-content-left-padding { - margin-left: 10px; } - -.do-dont-label { - margin-bottom: 10px; - padding-left: 20px; - background: transparent none no-repeat scroll 0px 3px; } - .do-dont-label.bad { - background-image: url(../images/styles/ico_wrong.png); } - .do-dont-label.good { - background-image: url(../images/styles/ico_good.png); } - - - - - - - - - - - - - - - - - - - -/***** PREVIOUSLY style.css ******************/ - - - - - -@media screen, projection, print { -[dir='rtl'] { - direction: rtl; -} -html { - line-height: 20px; -} -pre, table, input, textarea, code { - font-size: 1em; -} -address, abbr, cite { - font-style: normal; -} -[dir='rtl'] th { - text-align: right; -} -html[lang^=ja] blockquote, html[lang^=ja] q, html[lang^=ko] blockquote, html[lang^=ko] q, -html[lang^=zh] blockquote, html[lang^=zh] q { - font-style: normal; -} -q { - font-style: italic; -} -fieldset, iframe, img { - border: 0; -} -img { - -ms-interpolation-mode: bicubic; - vertical-align: middle; - max-width: 100%; -} -q { - quotes: none; -} -sup, sub { - font-size: 11px; - line-height: 0; -} -} - -@media screen, projection { - -table, fieldset { - margin: 0; -} -h1 { - color:#333; - font-size: 34px; - margin: 36px 0 27px; - padding:0 0 10px; - font-weight:300; -} -h1, h2 { - line-height: 30px; -} -h1.short { - margin-right:320px; -} -h1.short { - margin-right:320px; -} -h1.super { - font-size: 37px; -} -h2 { - color:#333; - font-size: 26px; - margin: 32px 0 20px; - padding:0; - font-weight:300; -} -h3 { - color:#333; - font-size: 21px; - font-weight:400; - margin:21px 0 14px 0; -} -h3, h4 { - line-height: 21px; -} -h4 { - font-size: 18px; - margin: 12px 0; - font-weight:500; -} -h5 { - font-size: 14px; -} -h5, h6 { - margin: 5px 0; -} -h6 { - font-size: 12px; -} -hr { /* applied to the bottom of h2 elements */ - height: 1px; - margin: 3px 0 12px; - border: 0; - background: #ccc; -} -p, pre, table, form { - margin: 0 0 15px; -} -small { - font-size: 11.5px; - color: #000; -} -ul, ol { - margin: 0 0 15px 18px; - padding: 0; -} -[dir='rtl'] ul, [dir='rtl'] ol { - margin: 10px 30px 10px 10px; -} -ul ul, ul ol, ol ul, ol ol { - margin-bottom: 0; - margin-top: 0; -} -li { - margin:0 0 5px; -} -dd { - margin:0 0 10px 30px; -} -dd p, -dd pre, -dd ul, -dd ol, -dd dl { - margin-top:10px; -} -li p, -li pre, -li ul, -li ol, -li dl { - margin-top:5px; - margin-bottom:5px; -} -dl dd dl:first-child { - margin-top:0; -} -pre strong, pre b, a strong, a b, a code { - color: inherit; -} -pre, code { - color: #060; - font: 13px/1.5 monospace; -} -code { - font-weight:bold; - font: 13px/14px monospace; -} - -legend { - display: none; -} -a:link, a:visited, .link-color { - color: #258aaf; - text-decoration: none; -} -a:focus, a:hover, a:active { - color: #33B5E5; - text-decoration: none; -} -a.white { - color: #fff; - text-decoration:underline; -} -a.white:hover, a.white:active { - color: #ccc !important; -} -strong, b { - font-weight:bold; - color: #222; -} -table { - border-collapse: collapse; - border-spacing: 0; - border:0; - margin: .5em 1em 1em 0; - width:100%; /* consistent table widths; within IE's quirks */ - background-color:#f7f7f7; -} -th, td { - padding: 4px 12px; - vertical-align: top; - text-align: left; -} -td { - background-color:inherit; - border:solid 1px #DDD; -} -td *:last-child { - margin-bottom:0; -} -th { - background-color: #999; - color: #fff; - border:solid 1px #DDD; - font-weight: normal; -} -tr:first-of-type th:first-of-type:empty { - visibility: hidden; -} - -/* -------------------------------------------------------------------------- -Footer -*/ -.line { - clear: both; - background: #acbc00; - background: -moz-linear-gradient(top, #acbc00 0, #acbc00 50%, #bdde00 50%, #bdde00 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #acbc00), -color-stop(50%, #acbc00), color-stop(50%, #bdde00), color-stop(100%, #bdde00)); - background: -webkit-linear-gradient(top, #acbc00 0, #acbc00 50%, #bdde00 50%, #bdde00 100%); - background: -o-linear-gradient(top, #acbc00 0, #acbc00 50%, #bdde00 50%, #bdde00 100%); - background: -ms-linear-gradient(top, #acbc00 0, #acbc00 50%, #bdde00 50%, #bdde00 100%); - background: linear-gradient(top, #acbc00 0, #acbc00 50%, #bdde00 50%, #bdde00 100%); - height: 2px; - margin-top: 150px; - position: relative; - z-index: 11; -} -#footer { - font-size:11px; - clear: both; - color: #999; - padding: 15px 0; - margin-top:10px; - width:auto; -} -#footer-local ul { - list-style: none; - margin: 5px 0 30px 0; -} -#footer-local li { - display: inline; -} -#footer-local li+li:before { - content: '|'; - padding: 0 3px; - color: #e5e5e5; -} -#footer-global { - padding: 10px 15px; - background: #f5f5f5; -} -#footer-global { - border-top: 1px solid #ebebeb; - font-size: 11.5px; - line-height: 1.8; - list-style: none; -} -#footer-global ul { - margin: 0; -} -#footer-global li { - display: inline; - font-weight: bold; -} -#footer-global li+li:before { - content: '¬?'; - padding: 0 3px; -} -* html #footer-global li { - margin: 0 13px 0 0; -} -* [dir='rtl'] #footer-global li { - margin: 0 0 0 13px; -} -*+html #footer-global li { - margin: 0 13px 0 0; -} -*+[dir='rtl'] #footer-global li { - margin: 0 0 0 13px; -} -#footer-global li a { - font-weight: normal; -} -.locales { - margin: 10px 0 0 0px; -} -[dir='rtl'] .locales { - background-position: right center; - float: left; - padding: 0 24px 0 0; -} -.locales form { - margin: 0; -} -.locales select, .sites select { - line-height: 3.08; - margin: 0px 0; - border: solid 1px #EBEBEB; - -webkit-appearance: none; - background: white url('../images/arrows-up-down.png') right center no-repeat; - height: 30px; - color: #222; - line-height: normal; - padding: 5px; - width: 230px; -} -} - -/* ============================================================================= - Print Only - ========================================================================== */ -@media print { - /* configure printed page */ - @page { - margin: 0.75in 1in; - widows: 4; - orphans: 4; - } - - /* reset spacing metrics */ - html, body, .wrap { - margin: 0 !important; - padding: 0 !important; - width: auto !important; - } - - /* leave enough space on the left for bullets */ - body { - padding-left: 20px !important; - } - #doc-col { - margin-left: 0; - } - - /* hide a bunch of non-content elements */ - #header, #footer, #nav-x, #side-nav, - .training-nav-top, .training-nav-bottom, - #doc-col .content-footer, - .nav-x, .nav-y, - .paging-links { - display: none !important; - } - - /* remove extra space above page titles */ - #doc-col .content-header { - margin-top: 0; - } - - /* bump up spacing above subheadings */ - h2 { - margin-top: 40px !important; - } - - /* print link URLs where possible and give links default text color */ - p a:after { - content: " (" attr(href) ")"; - font-size: 80%; - } - p a { - word-wrap: break-word; - } - a { - color: inherit; - } - - /* syntax highlighting rules */ - .str { color: #060; } - .kwd { color: #006; font-weight: bold; } - .com { color: #600; font-style: italic; } - .typ { color: #404; font-weight: bold; } - .lit { color: #044; } - .pun { color: #440; } - .pln { color: #000; } - .tag { color: #006; font-weight: bold; } - .atn { color: #404; } - .atv { color: #060; } -} - -/* ============================================================================= - Columns - ========================================================================== */ - -@media screen, projection, print { -.full { - padding: 2.5em 0; - border-top: solid 1px #ddd; - border-bottom: solid 1px #ddd; - background: #f7f7f7; -} -.wrap { - margin: 0 auto; - width: 940px; - clear: both; -} -.cols { - height: 1%; - margin: 0 -1.533742331288343558282%; - width: 103.06748466257669%} -*+html .cols { - margin-bottom: 20px; -} -.cols:after { - clear: both; - content: ' '; - display: block; - height: 0; - visibility: hidden; -} -.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, -.col-13, .col-14, .col-15, .col-16 { - display: inline; - float: left; - margin-left: 10px; - margin-right: 10px; -} -/* -* html .col-1, * html .col-2, * html .col-3, * html .col-4, * html .col-5, * html .col-6, * html -.col-7, * html .col-8, * html .col-9, * html .col-10, * html .col-11, * html .col-12 { - margin: 0; - padding: 0 1.4% 20px; -} -[dir='rtl'] .col-1, [dir='rtl'] .col-2, [dir='rtl'] .col-3, [dir='rtl'] .col-4, [dir='rtl'] .col-5, -[dir='rtl'] .col-6, [dir='rtl'] .col-7, [dir='rtl'] .col-8, [dir='rtl'] .col-9, [dir='rtl'] .col-10, -[dir='rtl'] .col-11, [dir='rtl'] .col-12 { - float: right; -} -*/ -.col-1 { width: 40px } -.col-2 { width: 100px } -.col-3 { width: 160px } -.col-4 { width: 220px } -.col-5 { width: 280px } -.col-6 { width: 340px } -.col-7 { width: 400px } -.col-8 { width: 460px } -.col-9 { width: 520px } -.col-10 { width: 580px } -.col-11 { width: 640px } -.col-12 { width: 700px } -.col-13 { width: 760px } -.col-14 { width: 820px } -.col-15 { width: 880px } -.col-16 { width: 940px } -} - -.col-right { - margin-right:0px; -} - -@media screen and (max-width:772px) { -.col-5, .col-6, .col-7 { - clear: both; - width: 97.0238096%} -} - -/* ============================================================================= - Layout - ========================================================================== */ -@media screen, projection, print { - -/* -------------------------------------------------------------------------- -Header, Login, Nav-X, Search -*/ -#header { - margin: 0; - padding: 0; -} -#header:before, #header:after { - content: ""; - display: table; - clear: both -} -.logo, .nav-x { - float: left; -} -.nav-x { - margin-top: -2px; - list-style-type: none; -} -.nav-x a { - color: #333; - font-size: 16px; -} -.about a.selected { - color: #9933CC; -} -.design a.selected { - color: #33b5e5; -} -.develop a.selected { - color: #F80; -} -.distribute a.selected { - color: #9C0; -} - - - -.nav-x li { - display: inline; - margin-right: 45px; -} -.search { - float: right; - position: relative; - width: 220px -} -.search .bottom, .search .left, .search .right { - position: absolute; - background-color: #a3a3a3; -} -.search .bottom { - width: 220px; - height: 1px; - top: 24px; - left: 0 -} -.search .left, .search .right { - height: 5px; - width: 1px -} -.search .left { top: 19px; left: 0 } -.search .right { top: 19px; right: 0 } -.search form { - float: left; - margin-top: 2px; - width: inherit; -} -.search .close, -#player-frame .close { - position: absolute; - right: 8px; - bottom: 4px; - width: 16px; - height: 16px; - margin: 0; - text-indent: -1000em; - background: url(../images/close.png) no-repeat 0 0; - z-index:9999; -} -.search .close:hover, .search .close:focus, -#player-frame .close:hover, #player-frame .close:focus { - background-position: -16px 0; - cursor:pointer; -} -#player-frame .close { - top: 6px; -} -.search form input { - color: #999; - font-size: 1em; - width: inherit; - border: none; - margin: 0; - padding:0 0 0 6px; - z-index: 1500; - background-color: transparent -} -.search:hover .bottom, .search:hover .left, .search:hover .right { - background-color: #33b5e5; -} -.search:hover .icon { - background-position: -8px 0 -} -.search form input:focus { - color: #222; - font-weight: bold; - outline:0; -} -/* Search Dropdown */ -.search-dropdown { - padding: 15px; - width: 192px; - border: solid 1px #c5c5c5; - background: #fff; - position: absolute; - top: 35px; - left: 0; - -moz-box-shadow: 0 0 10px rgba(0,0,0,0.2); - -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.2); - box-shadow: 0 0 10px rgba(0,0,0,0.2) -} -.search-dropdown ul, .search-dropdown ul li { - list-style-type: none; - margin: 0; - padding: 0 -} -.search-dropdown ul li { - clear: both -} -.search-dropdown img { - float: left; - margin: 0 10px 10px 0 -} -.search-dropdown h6 { - color: #222; - margin: 0; - line-height: normal -} -.search-dropdown .desc { - color: #999; - font-size: 11.5px; - line-height: normal; - margin: 0; -} -.search-dropdown li a:hover h6, .search-dropdown li a:hover .desc { - color: #33b5e5 -} -/* -------------------------------------------------------------------------- -Buttons -*/ -.button, a.button, .button-secondary, a.button-secondary { - border-image: initial; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - cursor: pointer; -} -.button, a.button { - display:inline-block; - background-color: #09c; - background-image: -webkit-gradient(linear, left top, left bottom, from(#2faddb), to(#09c)); - background-image: -webkit-linear-gradient(top, #2faddb, #09c); - background-image: -moz-linear-gradient(top, #2faddb, #09c); - background-image: -ms-linear-gradient(top, #2faddb, #09c); - background-image: -o-linear-gradient(top, #2faddb, #09c); - background-image: linear-gradient(top, #2faddb, #09c); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#2faddb', EndColorStr='#0099cc',GradientType=0); - border: 1px solid #3990ab; - color: #fff; -} -.button-secondary, a.button-secondary { - background-color: #f3f3f3; - border: 1px solid #dcdcdc; - color: #444; -} -a.button, a.button:visited, a.button-secondary, a.button-secondary:visited { - margin-right: 16px; - font-weight: 400; - min-width: 54px; - outline: 0; - padding: 8px 15px; - text-align: center; -} -.button, .button-secondary { - margin-right: 16px; - font-weight: 400; - min-width: 54px; - outline: 0; - padding: 0 15px; - text-align: center; -} -.button:hover, a.button:hover { - border-color: #09c; - background-color: #4cadcb; - background-image: -webkit-gradient(linear, left top, left bottom, from(#5dbcd9), to(#4cadcb)); - background-image: -webkit-linear-gradient(top, #5dbcd9, #4cadcb); - background-image: -moz-linear-gradient(top, #5dbcd9, #4cadcb); - background-image: -ms-linear-gradient(top, #5dbcd9, #4cadcb); - background-image: -o-linear-gradient(top, #5dbcd9, #4cadcb); - background-image: linear-gradient(top, #5dbcd9, #4cadcb); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#5dbcd9', -EndColorStr='#4cadcb',GradientType=0); - color: #fff !important; -} -.button:active, a.button:active { - background-color: #1e799a; - background-image: none; - border-color: #30b7e6; -} -a.button.big.subtitle { - line-height:18px; -} -.button-secondary:hover, a.button-secondary:hover { - border-color: #dbdbdb; - background-color: #f3f3f3; - background-image: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec)); - background-image: -webkit-linear-gradient(top, #f9f9f9, #ececec); - background-image: -moz-linear-gradient(top, #f9f9f9, #ececec); - background-image: -ms-linear-gradient(top, #f9f9f9, #ececec); - background-image: -o-linear-gradient(top, #f9f9f9, #ececec); - background-image: linear-gradient(top, #f9f9f9, #ececec); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f9f9f9', -EndColorStr='#ececec'); - color: #33B5E5 !important; -} -.button-secondary:active, a.button-secondary:active { - border-color: #dadada; - background: #ebebeb; /* Old browsers */ - /* IE9 SVG, needs conditional override of 'filter' to 'none' */ - background: -url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/ -Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0Jv -eD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+ -CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIg -eDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ViZWJl -YiIgc3RvcC1vcGFjaXR5PSIxIi8+ -CiAgICA8c3RvcCBvZmZzZXQ9IjEwJSIgc3RvcC1jb2xvcj0iI2Y5ZjlmOSIgc3RvcC1vcGFjaXR5PSIxIi8+ -CiAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iI2ZhZmFmYSIgc3RvcC1vcGFjaXR5PSIxIi8+ -CiAgICA8c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Y5ZjlmOSIgc3RvcC1vcGFjaXR5PSIxIi8+ -CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmNmY2ZjYiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFy -R3JhZGllbnQ+ -CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIg -Lz4KPC9zdmc+); - background: -moz-linear-gradient(top, #ebebeb 0%, #f9f9f9 5%, #fafafa 50%, #f9f9f9 90%, -#ffffff 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ebebeb), -color-stop(5%,#f9f9f9), color-stop(50%,#fafafa), color-stop(90%,#f9f9f9), color-stop(100%,#ffffff)); -/* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #ebebeb 0%,#f9f9f9 5%,#fafafa 50%,#f9f9f9 -90%,#ffffff 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #ebebeb 0%,#f9f9f9 5%,#fafafa 50%,#f9f9f9 90%,#ffffff -100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, #ebebeb 0%,#f9f9f9 5%,#fafafa 50%,#f9f9f9 90%,#ffffff -100%); /* IE10+ */ - background: linear-gradient(top, #ebebeb 0%,#f9f9f9 5%,#fafafa 50%,#f9f9f9 90%,#ffffff -100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ebebeb', -endColorstr='#ffffff',GradientType=0 ); /* IE6-8 */ - -webkit-box-shadow: inset 0px 0px 5px 2px rgba(0, 0, 0, .05); - -moz-box-shadow: inset 0px 0px 5px 2px rgba(0, 0, 0, .05); - box-shadow: inset 0px 0px 5px 2px rgba(0, 0, 0, .05); - color: #258AAF !important; -} -.button.big { - font-size:20px; - display:inline-block; -} -.button.big span.small { - font-size:14px; -} -.button-caption { - margin-top:10px; - font-size:12px; - font-style:italic; -} - -.button.disabled, -.button.disabled:hover, -.button.disabled:active { - background:#ebebeb; - color:#999 !important; - border-color:#999; - cursor:default; -} - -.training-nav-top a.button-secondary, -.training-nav-bottom a.button-secondary { - display:block; - float:left; - margin:0; - width:130px; - text-transform:uppercase; - font-weight:bold; - - background-color: #f3f3f3; - background-image: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec)); - background-image: -webkit-linear-gradient(top, #f9f9f9, #ececec); - background-image: -moz-linear-gradient(top, #f9f9f9, #ececec); - background-image: -ms-linear-gradient(top, #f9f9f9, #ececec); - background-image: -o-linear-gradient(top, #f9f9f9, #ececec); - background-image: linear-gradient(top, #f9f9f9, #ececec); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f9f9f9', -EndColorStr='#ececec'); - color: #33B5E5; -} - -.training-nav-top a.button-secondary:hover, -.training-nav-bottom a.button-secondary:hover { - background-color: #09c; - background-image: -webkit-gradient(linear, left top, left bottom, from(#2faddb), to(#09c)); - background-image: -webkit-linear-gradient(top, #2faddb, #09c); - background-image: -moz-linear-gradient(top, #2faddb, #09c); - background-image: -ms-linear-gradient(top, #2faddb, #09c); - background-image: -o-linear-gradient(top, #2faddb, #09c); - background-image: linear-gradient(top, #2faddb, #09c); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#2faddb', EndColorStr='#09c'); - border: 1px solid #3990ab; - color: #fff !important; -} - -.training-nav-top a.button-secondary.last, -.training-nav-bottom a.button-secondary.last { - border-left:0; -} - -.training-nav-top a.button-secondary.double-size, -.training-nav-bottom a.button-secondary.double-size { - width:291px; -} - -.training-nav-top, -.training-nav-bottom { - float:right; - margin:0 0 0 20px; -} - -.training-nav-top { - position:relative; - top:73px; -} - -.training-nav-bottom { - padding:0 0 20px; -} - -#tb-wrapper, -#qv-wrapper { - float:right; - clear:right; - margin:6px 0 0 30px; /* negative top-margin to counter the content-header bottom margin */ - padding:0 0 30px; -} - -#tb-wrapper { - margin:51px 0 0 20px; /* negative top-margin to counter the content-header bottom margin */ -} - -#tb, -#qv { - font-size:13px; - line-height:18px; - width:238px; - border:1px solid #ccc; - float:right; -} - -#tb { - width:278px; -} - -#tb h2, -#qv h2 { - margin:10px 15px; - padding:0; - text-transform:uppercase; - border-bottom:1px solid gainsboro; -} - -#tb *, -#qv * { - font-size:inherit; -} - -#tb .download-box, -#qv .download-box { - padding:0 0 0 15px; -} - -#tb .download-box .filename, -#qv .download-box .filename { - font-size:11px; - margin:4px 4px 10px; - color:#666; -} - - -/* Dev guide quicknav */ - -.sidebox-wrapper { - float:right; - clear:right; - margin:0 0 0 20px; - padding:0 0 20px; -} - -.sidebox { - width:226px; - font-size:13px; - line-height:18px; - border-left:4px solid #99CC00; - float:right; - padding:0 0 0 10px; - margin:0 0 1em 20px; -} - -.sidebox h2, -.sidebox h3, -.sidebox h4, -.sidebox h5 { - font-weight:bold; - margin:0 0 10px; - line-height: 16px; -} - -.sidebox * { - font-size:inherit; -} - -.sidebox > *:last-child { - margin-bottom:0; -} - -#tb ol, -#tb ul, -#qv ul { - margin:0 15px 10px 35px; -} - -#tb p { - margin:0 15px 10px; -} - -#qv ol { - list-style:none; - margin:0 15px 15px; - font-size:inherit; - line-height:inherit; -} - -#tb ol ol, -#tb ul ul, -#qv ol ol, -#qv ul ul, -.sidebox ol ol, -.sidebox ul ul { - margin-bottom:0; -} - -#qv ol ol { - margin:3px 0 3px 15px; -} - -.sidebox p, -#qv p, -#tb p { - margin: 0 0 10px; -} - -/* related resources blocks in checklists */ - -/* related resources sections that have dynamic content */ - - - -h3.rel-resources { -margin:1.25em auto; -} - -/* -------------------------------------------------------------------------- -Form -*/ -.article form { - margin: 0 0 20px; -} -.article form .form-required { - color: #dd4b39; -} -.article form fieldset { - margin: 0 0 20px; - padding: 0; -} -.article form legend { - display: block; - line-height: 1.5; - margin: 0; - padding: 0; -} -/* -.article form ol, .article form ul { - margin: 0 0 0 1em; - padding: 0 0 0 1em; -} -[dir='rtl'] .article form ol, [dir='rtl'] .article form ul { - margin: 0 1em 0 0; - padding: 0 1em 0 0; -} -.article form ol ul, .article form ul ul, [dir='rtl'] .article form ol ul, [dir='rtl'] .article form -ul ul { - list-style: none; - margin: 0; - padding: 0; -} -.article form li { - margin: 0 0 20px; -} -.article form li li { - margin: 0 0 5px; -} -*/ -.article form label { - display: block; - margin: 0 0 5px; - padding: 0; -} -.article form input[type='text'], .article form select, .article form textarea, .article form -.checkbox-group, .article form .radio-group { - margin-bottom: 15px; -} -.checkbox-group input { - width: 13px; - height: 13px; - background: #fff; - border: solid 1px #c6c6c6; - float: left; -} -.article form .checkbox-group, .article form .radio-group { - display: block -} -.article form select { - border: solid 1px #ebebeb; - border-top-color: #ddd; - -webkit-appearance: none; - background: #f3f3f3 url(../images/arrows-up-down.png) right center no-repeat; - height: 30px; - color: #222; - line-height: normal; - padding: 5px; - width: 130px; -} - -.article form .browse .browse-msg { - font-size: 11.5px; -} -.article form .browse .button-secondary { - height: auto; - line-height: 25px; - font-size: 11px; - padding: 0 8px; - margin: 0 10px 15px 0; -} -.article form input[type='text'], .article form textarea { - border: 1px solid #ebebeb; - border-top-color: #dcdcdc; - color: #222; - line-height: normal; - padding: 6px 10px; - width: 300px; -} -.article form textarea { - height: 150px; -} -.article form input[type='text']:focus, .article form textarea:focus { - border-color: #33B5E5; - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .2); - -o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .2); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .2); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .2); - outline: 0; -} -.article form input[disabled], .article form textarea[disabled], .article form label.form-disabled { - color: #999; -} -.article form input[type='text'][disabled], .article form textarea[disabled] { - background-color: #ebebeb; -} -form .form-error input[type='text'], form .form-error textarea { - border-color: #dd4b39; - margin-right: 20px; -} -.aside { - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; - margin: 10px 0; - padding: 20px; - color: #666; - position: relative; - background: #f9f9f9; -} -/* -.aside, .notification, .promo { - -moz-border-radius: 2px; - -webkit-border-radius: 2px; - border-radius: 2px; - margin: 10px 0; - padding: 10px; - position: relative; -} -.aside>:first-child, .notification>:first-child, .promo>:first-child { - margin-top: 0; -} -.aside>:last-child, .notification>:last-child, .promo>:last-child { - margin-bottom: 0; -} -.aside { - background: #f9f9f9; -} -.notification { - background: #fffbe4; - border-color: #f8f6e6; -} -.promo { - background: #f6f9ff; - border-color: #eff2f9; -} -*/ - -/* SDK TOS styles */ - -div.sdk-terms { - white-space: pre-wrap; - word-wrap: break-word; - font-family: inherit; - font-size: inherit; - padding: 10px; - height: 370px; - width: 738px; - border: 1px solid #444; - background: transparent; - overflow:auto; - margin:0 0 10px; -} - -div.sdk-terms.fullsize { - padding: 0; - height: auto; - width: auto; - border:none; -} - -div.sdk-terms h3, -div.sdk-terms h2 { - margin:0; -} - -div#sdk-terms-form { - padding:0 0 0 10px; -} - -div#sdk-terms-form input { - display:inline; - margin:4px 4px 4px 0; -} - - -/* -------------------------------------------------------------------------- -Code Style -*/ -pre { - margin:0 0 1em 0; - padding: 1em; - overflow: auto; - border: solid 1px #ddd; - background: #f7f7f7; -} -.str { color: #800; } /* Code string */ -.kwd { color: #008; } -.typ { color: #606; } -.lit { color: #066; } -.pun { color: #660; } -.pln { color: #000; } -.tag { color: #008; } -.atn { color: #828; } -.atv { color: #800; } /* XML string */ -.dec { color: #606; } - -/* -------------------------------------------------------------------------- -Three-Pane -*/ -/* Package Nav & Classes Nav */ -.three-pane { - position: relative; - border-top: solid 1px #ebebeb; -} -#packages-nav .js-pane, -#classes-nav .js-pane { - overflow:visible; -} -#packages-nav { - height:270px; - max-height: inherit; - overflow: hidden; - position: relative; -} -#classes-nav { - overflow: hidden; - position: relative; -} -#packages-nav ul, #classes-nav ul { - list-style-type: none; - margin: 10px 0 20px 0; - padding: 0; -} -#classes-nav li { - font-weight: bold; - margin: 5px 0; -} -#packages-nav li, -#classes-nav li li { - margin: 0; -} -#packages-nav li a, #packages-nav li a:active, #packages-nav li a:visited, -#classes-nav li a, #classes-nav li a:active, #classes-nav li a:visited { - padding: 0 0 0 4px; -} -#packages-nav li a, #packages-nav li a:active, #packages-nav li a:visited, -#classes-nav li li a, #classes-nav li li a:active, #classes-nav li li a:visited, -#nav-tree li a, #nav-tree li a:active, #nav-tree li a:visited { - color: #222; - font-weight: normal; -} -#packages-nav li a, #packages-nav li a:active, #packages-nav li a:visited, -#classes-nav li li a, #classes-nav li li a:active, #classes-nav li li a:visited { - display: block; -} -#packages-nav li.selected a, #packages-nav li.selected a:active, #packages-nav li.selected -a:visited, -#classes-nav li li.selected a, #classes-nav li li.selected a:active, #classes-nav li li.selected -a:visited, -#nav-tree li div.selected { - font-weight: 500; - color: #0099cc; - background-color:#fff; } - #packages-nav li.selected ul li a, - #classes-nav li.selected ul li a { - /* don't highlight child items */ - color: #555555; } -#nav-tree li div.selected a { - font-weight: 500; - color: #0099cc; -} -#nav-swap { - height:30px; - border-top:1px solid #ccc; -} -#nav-swap a { - display:inline-block; - height:100%; - color: #222; - font-size: 12px; - padding: 5px 0 5px 5px; -} - -#nav-swap .fullscreen { - float: right; - width: 24px; - height: 24px; - text-indent: -1000em; - padding:0; - margin:3px 5px 0; - background: url(../images/fullscreen.png) no-repeat -24px 0; -} -#nav-swap .fullscreen.disabled { - background-position: 0 0; -} -#nav-swap .fullscreen:hover, -#nav-swap .fullscreen:focus { - cursor:pointer; -} - - -/* nav tree */ -#side-nav, #swapper, -#nav-tree, #tree-list { - overflow:hidden; - margin-left:0; -} - -#devdoc-nav { - overflow:visible !important; /* To keep the "to top" button visible */ -} - -#nav-tree ul { - list-style:none; - padding:0; - margin:10px 0; -} - -#nav-tree ul li div { - padding:0 0 0 4px; -} - -#side-nav #nav-tree ul li a, -#side-nav #nav-tree ul li span.no-children { - padding: 0; - margin: 0; -} - -#nav-tree .plus { - margin: 0 3px 0 0; -} - -#nav-tree ul ul { - list-style: none; - margin: 0; - padding: 0 0 0 0; -} - -#nav-tree ul li { - margin: 0; - padding: 0 0 0 0; - white-space: nowrap; -} - -#nav-tree .children_ul { - padding:0; - margin:0; -} -#nav-tree .children_ul li div { - padding:0 0 0 10px; -} -#nav-tree .children_ul .children_ul li div { - padding:0 0 0 20px; -} - -#nav-tree a.nolink { - color: #222; - text-decoration: none; -} - -#nav-tree span.label { - width: 100%; -} - -#nav-tree { - overflow-x: auto; - overflow-y: scroll; - outline:0; -} - - -/* Content */ -#doc-col { - margin-right:0; -} - -/* Uncomment this for preview release watermark -#doc-col { - background: url('../images/preview.png') repeat; -} -*/ - -#doc-content-container { - margin-left: 291px -} -#doc-header, #doc-content { - padding: 1em 2em; -} -#doc-header { - background: #f7f7f7; -} -#doc-header h1 { - line-height: 0; - margin-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; - padding: 8px 0; - margin: 0; - border-bottom: 1px solid #CCC; - background:#e9e9e9; - background: rgba(0, 0, 0, 0.05); /* matches #nav li.expanded */ - -} -#api-nav-title { - padding:0 5px; - white-space:nowrap; -} - -#api-level-toggle { - float:right; - padding:0 5px; -} - -#api-level-toggle label { - margin:0; - vertical-align:top; - line-height: 19px; - font-size:13px; - height: 19px; -} - -#api-level-toggle .select-wrapper { - width: 35px; - display: inline-block; - overflow: hidden; -} -#api-level-toggle select { - border: 0; - appearance:none; - -moz-appearance:none; - -webkit-appearance: none; - background: transparent url(../images/arrows-up-down.png) 23px 5px no-repeat; - color: #222; - height: 19px; - line-height: 19px; - padding: 0; - margin:1px 0 0 0; - width:150%; - font-size:13px; - vertical-align:top; - outline:0; -} - - -/* Toggle for revision notes and stuff */ -div.toggle-content.closed .toggle-content-toggleme { - display:none; -} - -#jd-content img.toggle-content-img { - margin:0 5px 5px 0; -} - -div.toggle-content-toggleme { - padding:0 0 0 15px; -} - - -/* API LEVEL FILTERED MEMBERS */ - -.absent, -.absent a:link, -.absent a:visited, -.absent a:hover, -.absent * { - color:#bbb !important; - cursor:default !important; - text-decoration:none !important; -} -#devdoc-nav li.absent.selected, -#devdoc-nav li.absent.selected *, -#devdoc-nav div.label.absent.selected, -#devdoc-nav div.label.absent.selected * { - background-color:#eaeaea !important; -} -.absent h4.jd-details-title, -.absent h4.jd-details-title * { - background-color:#f6f6f6 !important; -} -.absent img { - opacity: .3; - filter: alpha(opacity=30); - -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; -} - - - - - - - - - -/* JQUERY RESIZABLE STYLES */ -.ui-resizable { position: relative; } -.ui-resizable-handle { position: absolute; display: none; font-size: 0.1px; z-index:1; } -.ui-resizable .ui-resizable-handle { display: block; border-bottom: 1px solid #e4e4e4; } -/*body .ui-resizable-disabled .ui-resizable-handle { display: none; } -body .ui-resizable-autohide .ui-resizable-handle { display: none; }*/ -.ui-resizable-s { cursor: s-resize; height: 10px; width: 100% !important; bottom: -11px; left: 0; -border-bottom: solid 1px #ededed; - background: #f7f7f7 url("../images/resizable-s2.png") no-repeat scroll center center; } -/* -.ui-resizable-e { -cursor: e-resize; width: 10px; right: 0; top: 0; height: 100%; border-right: solid -1px #ededed;background: #f7f7f7 url("../images/resizable-e2.png") no-repeat scroll center center; } -*/ - -/* -------------------------------------------------------------------------- -Lightbox -*/ -.lightbox { - width: 769px; - padding: 1.5em; - margin: 0 auto; - border: solid 1px #dcdcdc; - background: #fff; - -moz-box-shadow: 1px 1px 5px rgba(0,0,0,0.1); - -webkit-box-shadow: 1px 1px 5px rgba(0,0,0,0.1); - box-shadow: 1px 1px 5px rgba(0,0,0,0.1) -} -.lightbox .header { - float: left; - width: 720px; - margin: -10px 20px 10px 0; -} -.lightbox .close { - float: right; - width: 10px; - height: 10px; - margin: -10px -10px 10px 0; - text-indent: -1000em; - background: url(../images/close.png) no-repeat 0 0; -} -.lightbox .close:hover, .lightbox .close:focus { - background-position: -10px 0; -} - -/* -------------------------------------------------------------------------- -Styles for samples browser -*/ - -#codesample-wrapper { - width:100000px; /* super wide to contain floats, but doesn't cause scroll */ - overflow:visible; -} -pre#codesample-block { - float:left; - overflow:visible; - background:transparent; - border:none; -} -pre#codesample-block a.number { - display:none; -} -pre#codesample-block .code-line:hover { - background:#e7e7e7; -} -pre#codesample-line-numbers { - float:left; - width:2em; - background:transparent; - border:none; - border-right:1px solid #ccc; - padding-left:0; - font-family:monospace; - text-align:right; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: -moz-none; - -ms-user-select: none; - user-select: none; -} -pre#codesample-line-numbers a { - color:#999; -} -pre#codesample-line-numbers.hidden { - display:none; -} -pre#codesample-block span.code-line { - width:100%; - display:inline-block; -} - -/* -Styles for displaying image or video resources in samples browser. -Resources are marked as no-display if they exceed the size limit. -*/ -div#codesample-resource img, div#codesample-resource video { - border: 1px solid #ececec; -} - -div#codesample-resource.noDisplay div { - border: 1px solid #ececec; - width:120px; - margin-bottom:4px; - padding:20px; -} - -div#codesample-resource .noDisplay-message:after { - font-style:italic; - font-size:12px; - content: 'This resource is not available for browsing. To view it, please download the project.'; -} - -/* -Styles for project structure (treeview) page -*/ -.structure-dir { -background-image:url(../../assets/images/folder.png); -background-repeat:no-repeat; -background-position:16px 2px; - margin:.25em 0 0 0; - padding:0 0 0 0; -} - -.structure-toggleme { - margin:0 0 0 3em; - padding:0 0 0 0; - text-decoration:none; -} - -.structure-java{ -background-image:url(../../assets/images/file-java.png); -background-repeat:no-repeat; -background-position:0px 2px; - margin:.3em 0 0 0; - padding:.3em 0 .3em 22px; -} - -.structure-file { -background-image:url(../../assets/images/file-generic.png); -background-repeat:no-repeat; -background-position:0px 2px; - margin:.3em 0 0 0; - padding:.3em 0 .3em 22px; -} - -.structure-xml { -background-image:url(../../assets/images/file-xml.png); -background-repeat:no-repeat; -background-position:0px 2px; - margin:.3em 0 0 0; - padding:.3em 0 .25em 22px; -} - -.structure-img { -background-image:url(../../assets/images/file-image.png); -background-repeat:no-repeat; -background-position:0px 2px; - margin:.3em 0 0 0; - padding:.3em 0 .25em 22px; -} - -.structure-manifest { -background-image:url(../../assets/images/file-manifest.png); -background-repeat:no-repeat; - margin:.0 0 0 1.25em; - padding:0 0 0 22px; - text-decoration:none; -} - -#jd-content .structure-toggle-img { - margin:.5em 0 0 0; -padding-right:2.1em; -} - -.dirInfo { - margin-left:2em; -} - -.structure-dir a { - text-decoration:none; -} - -.structure-manifest a { - text-decoration: none; -} -.structure-file a { - text-decoration: none; -} - -.sampleEmbed { - background-color:rgb(249, 249, 249); -} - -.sampleEmbed ol.lineNumbers { - list-style-type: decimal; - padding-left:1em; -} - -.sampleEmbed ol.lineNumbers li { -border-left:1px solid #ddd; -border-right:1px solid #ddd; -color:gray; -background-color:#f7f7f7; -margin:0 0 0 24px; -padding: 2px 2px 2px 6px; -} - -.sampleEmbed ol.lineNumbers li:hover { -background: #efefef; -} - -.samples-nav li a { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -/* -------------------------------------------------------------------------- -Styles for raw formatted line numbers (not used with listformatted version) -div.sampleLine div.lineNumber { - display: inline; -} -div.sampleLine div.lineCode { - display: inline; - padding-left:6px; -} -div.sampleLine { - padding:0; - margin:0; -}*/ - -/* -------------------------------------------------------------------------- -Butterbar -*/ -#butterbar-wrapper { - position:absolute; - top:0; - left:0; - width:100%; -} -#butterbar { - width:100%; - margin:0 auto; -} -#butterbar-message { - background-color:rgba(255, 187, 51, .4); - font-size:13px; - padding: 5px 0; - text-align:center; -} -a#butterbar-message { - cursor:pointer; - display:block; -} -a#butterbar-message:hover { - text-decoration:underline; -} - -/* -------------------------------------------------------------------------- -Misc -*/ - - -.clearfix:before, .clearfix:after { - content: ""; - display: table -} -.clearfix:after { - clear: both -} -.clearfix { - *zoom: 1 -} -table.blank th, table.blank td { - border: 0; - background: none -} -.caption { - margin: 0.5em 0 2em 0; - color: #000; - font-size: 11.5px; -} - -.nolist, .nolist ul, .nolist ol { - list-style:none; - margin-left:0; -} -#tb .nolist { - margin-left:15px; -} - -dl.xml>dt { - text-transform:uppercase; -} -dl.xml dl.attr { - margin-top:0; -} - -pre.classic { - background-color:transparent; - border:none; - padding:0; -} - -p.img-caption { - margin: -10px 0 20px; - font-size:13px; - color:#666; -} - -div.figure, -div.figure-right { - float:right; - clear:right; - margin:10px 0 0 0; - padding:0 0 0 20px; - /* width must be defined w/ an inline style matching the image width */ -} - -div.figure-left { - float:left; - clear:left; - margin:10px 0 0 0; - padding:0 20px 0 0; - /* width must be defined w/ an inline style matching the image width */ -} - -img.frame { - border:1px solid #DDD; - padding:4px; -} - -p.table-caption { - margin: 0 0 4px 0; - font-size:13px; - color:#666; -} - -p.code-caption { - margin-bottom: 4px; - font: 12px/1.5 monospace; - color:#666; -} - -div.note, -div.caution, -div.warning { - margin: 0 0 15px; -} - -p.note, div.note, -p.caution, div.caution, -p.warning, div.warning { - padding: 0 0 0 10px; - border-left: 4px solid; -} - -p.note, div.note { - border-color: #258AAF; -} - -p.caution, div.caution { - border-color: #FF8800; -} - -p.warning, div.warning { - border-color: #ff4443; -} - -div.note.design { - border-left: 4px solid #33B5E5; -} - -div.note.develop { - border-left: 4px solid #F80; -} - -div.note.distribute { - border-left: 4px solid #9C0; -} - -.note p, .caution p, .warning p { - margin:0 0 5px; -} - -.note p:last-child, .caution p:last-child, .warning p:last-child { - margin-bottom:0; -} - -body.about blockquote { - display:block; - float:right; - width:280px; - font-size:20px; - font-style:italic; - line-height:24px; - color:#33B5E5; - margin:0 0 20px 30px; -} - -div.design-announce p { - margin:0 0 10px; -} - -.expandable { - height:34px; - padding-left:20px; - position:relative; -} -.expandable:before { - content: ''; - background-image: url(../images/styles/disclosure_down.png); - background-repeat:no-repeat; - background-position: -12px -9px; - width: 20px; - height: 20px; - display: inline-block; - position: absolute; - top: 0; - left: 0; } -} -.expandable.expanded:before { - background-image: url(../images/styles/disclosure_up.png); -} - -/* notice box for cross links between Design/Develop docs */ -a.notice-developers-video, -a.notice-developers, -a.notice-designers-video, -a.notice-designers { - float:right; - clear:right; - width:238px; - min-height:50px; - margin:0 0 20px 20px; - border:1px solid #ddd; -} -a.notice-developers-video.wide, -a.notice-developers.wide, -a.notice-designers-video.wide, -a.notice-designers.wide { - width:278px; -} -a.notice-developers-video div, -a.notice-developers div, -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-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-size:40px 40px; -} -a.notice-designers-video div { - 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-size:40px 40px; -} -a.notice-developers-video:hover, -a.notice-developers:hover, -a.notice-designers-video:hover, -a.notice-designers:hover { - background:#eee; -} -a.notice-developers-video h3, -a.notice-developers h3, -a.notice-designers-video h3, -a.notice-designers h3 { - font-size:13px; - line-height:18px; - font-weight:bold; - text-transform:uppercase; - color:#000 !important; - margin:0 0 1px; -} -a.notice-developers-video p, -a.notice-developers p, -a.notice-designers-video p, -a.notice-designers p { - margin:0; - line-height:14px; -} -a.notice-developers-video.left, -a.notice-developers.left, -a.notice-designers-video.left, -a.notice-designers.left { - margin-left:0; - float:left; -} - - -/* hide nested list items; companion to hideNestedLists() */ -.hide-nested li ol, -.hide-nested li ul { - display:none; -} - -a.header-toggle { - display:block; - float:right; - text-transform:uppercase; - font-size:.8em !important; - font-weight:normal; - margin-top:2px; -} - - -/* for IDE instruction toggle (Studio/Eclipse/Other) */ -select.ide { - background: transparent; - border: 1px solid #bbb; - border-left: 0; - border-right: 0; - margin: 10px 0; - padding: 10px 0; - color:#666; -} -select.ide, -select.ide option { - font-family: inherit; - font-size:16px; - font-weight:500; -} -/* hide all except studio by default */ -.select-ide.eclipse, -.select-ide.other { - display:none; -} -/* ... unless studio also includes one of the others */ -.select-ide.studio.eclipse, -.select-ide.studio.other { - display:none; -} - - -/* ----------------------------------------------- -good/bad example containers -*/ - -div.example-block { - background-repeat: no-repeat; - background-position:10px 8px; - background-color:#ccc; - padding:4px; - margin:.8em auto 1.5em 2em; - width:260px; - float:right; -} -/* red container */ -.example-block.bad { - background-image: url(/images/example-bad.png); - background-color:#f4cccc; -} -/* green container */ -.example-block.good { - background-image: url(/images/example-good.png); - background-color:#d9ead3; -} -/* container heading div */ -#jd-content .example-block .heading { - font-weight:bold; - margin:6px 0 9px 36px; - padding:6px auto; -} -/* container image (if any) */ -#jd-content .example-block img { - margin:0; - padding:0px; -} - -.example-block table { - margin:0; -} - -/* ----------------------------------------------- -Dialog box for popup messages -*/ - -div.dialog { - height:0; - margin:0 auto; -} - -div.dialog>div { - z-index:99; - position:fixed; - margin:70px 0; - width: 391px; - height: 200px; - background: #F7F7F7; --moz-box-shadow: 0 0 15px rgba(0,0,0,0.5); --webkit-box-shadow: 0 0 15px rgba(0,0,0,0.5); -box-shadow: 0 0 15px rgba(0,0,0,0.5); -} -/* IE6 can't position fixed */ -* html div.dialog div { position:absolute; } - - -div#deprecatedSticker { - display:none; - z-index:99; - position:fixed; - right:15px; - top:114px; - margin:0; - padding:1em; - background:#FFF; - border:1px solid #dddd00; - box-shadow:-5px 5px 10px #ccc; - -moz-box-shadow:-5px 5px 10px #ccc; - -webkit-box-shadow:-5px 5px 10px #ccc; -} - -div#langMessage, -div#naMessage { - display:none; - width:555px; - height:0; - margin:0 auto; -} - - -div#langMessage>div, -div#naMessage div { - z-index:99; - width:450px; - position:fixed; - margin:50px 0; - padding:4em 4em 3em; - background:#FFF; - border:1px solid #999; - box-shadow:-10px 10px 40px #888; - -moz-box-shadow:-10px 10px 40px #888; - -webkit-box-shadow:-10px 10px 40px #888; -} -/* IE6 can't position fixed */ -* html div#langMessage>div, -* html div#naMessage div { position:absolute; } - -div#naMessage strong { - font-size:1.1em; -} - -div#langMessage .lang { - display:none; -} - -/* -------------------------------------------------------------------------- -Slideshow Controls & Next/Prev -*/ -.slideshow-next, .slideshow-prev { - width: 20px; - height: 36px; - text-indent: -1000em; -} -.slideshow-container { - margin: 2em 0; -} -.slideshow-container:before, .slideshow-container:after { - content: ""; - display: table; - clear: both; -} -a.slideshow-next, a.slideshow-next:visited { - - float: right; - - background: url(../images/arrow-right.png) no-repeat 0 0 - -} - -a.slideshow-prev, a.slideshow-prev:visited { - - float: left; - - background: url(../images/arrow-left.png) no-repeat 0 0 - -} - -.slideshow-next:hover, .slideshow-prev:hover, .slideshow-next:focus, .slideshow-prev:focus { - - background-position: 0 -36px - -} - -.slideshow-next:active, .slideshow-prev:active { - - background-position: 0 -72px - -} -.slideshow-nav { - width: 74px; - margin: 0 auto; -} -.slideshow-nav a, .slideshow-nav a:visited { - display: inline-block; - width: 12px; - height: 12px; - margin: 0 2px 20px 2px; - background: #ccc; - -webkit-border-radius: 50%; - -moz-border-radius: 50%; - border-radius: 50%; -} -.slideshow-nav a:hover, .slideshow-nav a:focus { - - background: #33B5E5 -} - -.slideshow-nav a:active { - - background: #1e799a; - background: #ebebeb; - -webkit-box-shadow: inset 0px 0px 5px 2px rgba(0, 0, 0, .05); - -moz-box-shadow: inset 0px 0px 5px 2px rgba(0, 0, 0, .05); - box-shadow: inset 0px 0px 5px 2px rgba(0, 0, 0, .05); -} -.slideshow-nav a.active, .slideshow-nav a.active:active, .slideshow-nav a.active:visited { - background: #33B5E5 -} -/* -------------------------------------------------------------------------- -Tabs -*/ -ul.tabs { - padding: 0; - margin: 2em 0 0 0; -} -ul.tabs:before, ul.tabs:after { - content: ""; - display: table; - clear: both; -} -ul.tabs li { - list-style-type: none; - float: left; -} -ul.tabs li a, ul.tabs li a:active, ul.tabs li a:visited { - display: block; - height: 36px; - line-height: 36px; - padding: 0 15px; - margin-right: 2px; - color: #222; - -moz-border-radius-topleft: 2px; - -moz-border-radius-topright: 2px; - -moz-border-radius-bottomright: px; - -moz-border-radius-bottomleft: px; - -webkit-border-radius: 2px 2px px px; - border-radius: 2px 2px px px; - border-top: solid 1px #ebebeb; - border-left: solid 1px #ebebeb; - border-right: solid 1px #ebebeb; - background-color: #fff; - background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#fafafa)); - background-image: -webkit-linear-gradient(top, #ffffff, #fafafa); - background-image: -moz-linear-gradient(top, #ffffff, #fafafa); - background-image: -ms-linear-gradient(top, #ffffff, #fafafa); - background-image: -o-linear-gradient(top, #ffffff, #fafafa); - background-image: linear-gradient(top, #ffffff, #fafafa); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', -EndColorStr='#fafafa'); -} -ul.tabs li a:hover { - color: #33B5E5; -} -ul.tabs li a.selected { - height: 37px; - color: #33B5E5; - background-color: #f7f7f7; - background-image: none; - border-color: #ddd; -} -.tab-content { - padding: 1.2em; - margin: -1px 0 2em 0; - -webkit-border-radius: 2px; - -moz-border-radius: 2px; - border-radius: 2px; - border: solid 1px #ddd; - background: #f7f7f7; -} -/* -------------------------------------------------------------------------- -Feature Boxes -*/ -.feature-box { - width: 291px; - height: 200px; - position: relative; - background: #F7F7F7; -} -.box-border .top, .box-border .bottom, .box-border .left, .box-border .right { - z-index: 100; - position: absolute; - background-color: #aaa; -} -.box-border .top, .box-border .bottom { - width: 291px; - height: 1px; -} -.dialog .box-border .top, -.dialog .box-border .bottom { width:391px; } - -.box-border .left, .box-border .right { - width: 1px; - height: 8px; -} -.box-border .top { top: 0; left: 0 } -.box-border .top .left { top: 1px; left: 0 } -.box-border .top .right { top: 1px; right: 0 } -.box-border .bottom .left { top: -8px; left: 0 } -.box-border .bottom { top: 200px; left: 0 } -.box-border .bottom .right { top: -8px; right: 0 } - -.feature-box h4, -.dialog h4 { - margin: 15px 18px 10px; - padding:0; -} - -.feature-box p, -.dialog p { - margin: 10px 18px; - padding:0; -} -.feature-box .link, -.dialog .link { - border-top: 1px solid #dedede; - bottom: 0; - position: absolute; - width: inherit; -} -.feature-box a, .feature-box h4, -.dialog a, .dialog h4 { - -webkit-transition: color .4s ease; - -moz-transition: color .4s ease; - -o-transition: color .4s ease; - transition: color .4s ease; -} -.feature-box:hover { - cursor: pointer; -} -.feature-box:hover .box-border .top, .feature-box:hover .box-border .bottom, .feature-box:hover -.left, .feature-box:hover .right { - background-color: #33B5E5; -} -.feature-box:hover h4, .feature-box:hover a { - color: #33B5E5; -} -/* -------------------------------------------------------------------------- -Page-Specific Styles -*/ -.colors { - position: relative; - float: left; - width: 92px; - margin: 40px 0 20px; -} -.colors div { - color: #fff; - font-size: 11.5px; - width: 82px; - height: 82px; - margin-top:-30px; - line-height: 82px; - text-align: center; - border: solid 5px #fff; - -webkit-border-radius: 50%; - -moz-border-radius: 50%; - border-radius: 50%; -} - - - - - - - - - - - - - - -/* ########### REFERENCE DOCS ################## */ - -#packages-nav h2, -#classes-nav h2 { - font-size:18px; - margin:0; - padding:0 0 0 4px; -} - -#jd-header { - padding: 0 0 12px; - margin: 20px 0 12px; - font-size:12px; - padding-bottom:12px; - border-bottom:solid 1px #ccc; -} - -#jd-header h1 { - margin:0; - padding:0 0 6px 0; -} - -/* not sure if this is needed in the ref docs, disabling for now -.jd-descr h2 { - margin:16px 0; -} -*/ - -/* page-top-right container for reference pages (holds -links to summary tables) */ -#api-info-block { - font-size:12px; - margin:20px 0 0; - padding:0 10px 6px; - font-weight:normal; - float:right; - text-align:right; - color:#999; - max-width:80%; - font-size: 12px; - line-height:14px; -} - -#api-info-block div.api-level { - font-weight:bold; - font-size:inherit; - float:none; - color:#222; - padding:0; - margin:0; -} - -/* inheritance table */ -.jd-inheritance-table { - border-spacing:0; - margin:0; - padding:0; - font-size:12px; - line-height:14px; - background-color:transparent; -} -.jd-inheritance-table tr td { - border: none; - margin: 0; - padding: 0; - background-color:transparent; -} -.jd-inheritance-table .jd-inheritance-space { - font-weight:bold; - width:1em; -} -.jd-inheritance-table .jd-inheritance-interface-cell { - padding-left: 17px; -} - - - -.jd-sumtable a { - text-decoration:none; -} - -.jd-sumtable a:hover { - text-decoration:underline; -} - -/* the link inside a sumtable for "Show All/Hide All" */ -.toggle-all { - display:block; - float:right; - font-weight:normal; - font-size:0.9em; -} - -/* adjustments for in/direct subclasses tables */ -.jd-sumtable.jd-sumtable-subclasses { - margin: 1em 0 0 0; - max-width:968px; - background-color:transparent; - font-size:13px; -} - -/* extra space between end of method name and open-paren */ -.sympad { - margin-right: 2px; -} - -/* right alignment for the return type in sumtable */ -.jd-sumtable .jd-typecol { - text-align:right; -} - -/* adjustments for the expando table-in-table */ -.jd-sumtable-expando { - margin:.5em 0; - padding:0; -} - -/* a div that holds a short description */ -.jd-descrdiv { - padding:3px 1em 0 1em; - margin:0; - border:0; -} - -#jd-content img.jd-expando-trigger-img { - padding:0 4px 4px 0; - margin:0; -} - -.jd-sumtable-subclasses div#subclasses-direct, -.jd-sumtable-subclasses div#subclasses-indirect { - margin:0 0 0 13px; -} - - - -/********* MEMBER REF *************/ - - -.jd-details { -/* border:1px solid #669999; - padding:4px; */ - margin:0 0 1em; -} - -/* API reference: a container for the -.tagdata blocks that make up the detailed -description */ -.jd-details-descr { - padding:0; - margin:.5em .25em; -} - -/* API reference: a block containing -a detailed description, a params table, -seealso list, etc */ -.jd-tagdata { - margin:.5em 1em; -} - -.jd-tagdata p { - margin:0 0 1em 1em; -} - -/* API reference: adjustments to -the detailed description block */ -.jd-tagdescr { - margin:.25em 0 .75em 0; -} - -.jd-tagdescr ol, -.jd-tagdescr ul { - margin:0 2.5em; - padding:0; -} - -.jd-tagdescr table, -.jd-tagdescr img { - margin:.25em 1em; -} - -.jd-tagdescr li { -margin:0 0 .25em 0; -padding:0; -} - -/* API reference: heading marking -the details section for constants, -attrs, methods, etc. */ -h4.jd-details-title { - font-size:1.15em; - background-color: #E2E2E2; - margin:1.5em 0 .6em; - padding:3px 95px 3px 3px; /* room for api-level */ -} -body.google h4.jd-details-title { - background-color: #FFF; - padding-top:5px; - border-top: 1px solid #ccc; -} -body.google table.jd-sumtable th { - background-color: #FFF; - color:#000; -} - -h4.jd-tagtitle { - margin:0; -} - -h4 .normal { - font-weight:normal; -} - -/* API reference: heading for "Parameters", "See Also", etc., -in details sections */ -h5.jd-tagtitle { - margin:0 0 .25em 0; - font-size:1em; -} - -.jd-tagtable { - margin:0; - background-color:transparent; - width:auto; -} - -.jd-tagtable td, -.jd-tagtable th { - border:none; - background-color:#fff; - vertical-align:top; - font-weight:normal; - padding:2px 10px; -} - -.jd-tagtable th { - font-style:italic; -} - -/* Inline api level indicator for methods */ -div.api-level { - font-size:.8em; - font-weight:normal; - color:#999; - float:right; - padding:0 8px 0; - margin-top:-30px; -} - -table.jd-tagtable td, -table.jd-tagtable th { - background-color:transparent; -} - -table.jd-tagtable th { - color:inherit; -} - - - - - - - - - - - - - - - - - - - - - - - -/* SEARCH FILTER */ - -.menu-container { - position:relative; -} -#search_autocomplete { - font-weight:normal; -} - -.search_filtered_wrapper.reference { - width: 193px; - float: right; -} -.search_filtered_wrapper.docs { - width:875px; - float: left; - position:absolute; - top:26px; - right:66px; -} -.suggest-card { - position:relative; - width:170px; - min-height:90px; - padding:5px; - border: solid 1px #C5C5C5; - background: white; - top: 15px; - margin-right:-5px; - -moz-box-shadow: 0 0 10px rgba(0,0,0,0.2); - -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); -} -.suggest-card.reference { - position:absolute; - z-index:999; - min-width:171px; /* +padding and border makes this match input width */ - min-height:93px; /* add 3px because this has 1 not 4px top border */ - width:auto; - top:41px; - margin:0; -} -.suggest-card.develop { - z-index:997; - border-top: solid 4px #F80; - float:right; -} -.suggest-card.design { - z-index:996; - border-top: solid 4px #33b5e5; - float:right; -} -.suggest-card.distribute { - z-index:995; - border-top: solid 4px #9C0; - float:right; -} -.child-card { - width:100%; -} -.suggest-card.dummy { - width:172px; - float:right; - border:0; - background:transparent; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -ul.search_filtered { - min-width:100%; - list-style: none; - margin: 0 0 5px; - padding: 0; -} -.search_filtered .jd-selected { - background:#efefef; - cursor:pointer; -} -.search_filtered .jd-selected, -.search_filtered .jd-selected a { - color:#09C !important; -} - -.no-display { - display: none; -} - -.search_filtered li.jd-autocomplete { - font-size: 0.81em; - border: none; - margin: 0 0 2px; - padding: 0; - line-height:1.5em; -} - -.search_filtered li a { - padding:0 5px; - color:#222 !important; - display:inline-block; - line-height:12px; -} - -.search_filtered li.header { - font-weight:bold; - color:#444; - border: none; - margin: 8px 0 2px; - padding:1px 5px; - line-height:1.5em; -} -.search_filtered li.header.small { - font-size:0.85em; -} - -.suggest-card.reference -.search_filtered li.header { - color:#aaa; - font-size: 0.81em; -} - -.search_filtered li.header:first-child { - margin: 0 0 2px; -} - -.show-item { - display: table-row; -} -.hide-item { - display: hidden; -} - - - - - -/* SEARCH RESULTS */ - - -#leftSearchControl .gsc-twiddle { - background-image : none; -} - -#leftSearchControl td, #searchForm td { - border: 0px solid #000; - padding:0; -} - -#leftSearchControl .gsc-resultsHeader .gsc-title { - padding-left : 0px; - font-weight : bold; - font-size : 13px; - color:#006699; - display : none; -} - -#leftSearchControl .gsc-resultsHeader div.gsc-results-selector { - display : none; -} - -#leftSearchControl .gsc-resultsRoot { - padding-top : 6px; -} - -#leftSearchControl div.gs-visibleUrl-long { - display : block; - color:#006699; -} - -#leftSearchControl .gsc-webResult { - padding:0 0 20px 0; -} - -.gsc-webResult div.gs-visibleUrl-short, -table.gsc-branding, -.gsc-clear-button { - display : none; -} - -.gsc-cursor-box .gsc-cursor div.gsc-cursor-page, -.gsc-cursor-box .gsc-trailing-more-results a.gsc-trailing-more-results, -#leftSearchControl a, -#leftSearchControl a b { - color:#006699; -} - -.gsc-resultsHeader { - display: none; -} - -/* Disable built in search forms */ -.gsc-control form.gsc-search-box { - display : none; -} -table.gsc-search-box { - margin:6px 0 0 0; - border-collapse:collapse; -} - -td.gsc-input { - padding:0 2px; - width:100%; - vertical-align:middle; -} - -input.gsc-input { - border:1px solid #BCCDF0; - width:99%; - padding-left:2px; - font-size:.95em; -} - -td.gsc-search-button { - text-align: right; - padding:0; - vertical-align:top; -} - - -#searchResults { - overflow:hidden; /* because the repositioned page links makes the section think it needs to scroll -(it doesn't) */ - height:auto; -} - -#searchResults .gsc-control { - position:relative; - width:auto; - padding:0 0 10px; -} - -#searchResults .gsc-tabsArea { - position:relative; - white-space:nowrap; - float:left; - width:200px; -} - -#searchResults .gsc-above-wrapper-area { - display:none; -} - -#searchResults .gsc-resultsbox-visible { - float:left; - width:720px; - margin-left:20px; -} - -#searchResults .gsc-tabHeader { - padding: 3px 6px; - position:relative; - width:auto; - display:block; -} - -#searchResults h2#searchTitle { - padding:0; - margin:5px 0; - border:none; -} - -#searchResults h2#searchTitle em { - font-style:normal; - color:#33B5E5; -} - -#searchResults .gsc-table-result { - margin:5px 0 10px 0; - background-color:transparent; -} -#searchResults .gs-web-image-box, .gs-promotion-image-box { - width:120px; -} -#searchResults .gs-web-image-box img.gs-image, .gs-promotion-image-box img.gs-promotion-image { - max-width:120px; -} - -#searchResults .gsc-table-result .gsc-thumbnail { - padding:0 20px 0 0; -} - -#searchResults td { - background-color:transparent; -} - -#searchResults .gsc-expansionArea { - position:relative; -} -#searchResults .gsc-tabsArea .gsc-cursor-box { - width:200px; - padding:20px 0 0 1px; -} -#searchResults .gsc-cursor-page { - display:inline-block; - float:left; - margin:-1px 0 0 -1px; - padding:0; - height:27px; - width:27px; - text-align:center; - line-height:2; -} - -#searchResults .gsc-tabHeader.gsc-tabhInactive, -#searchResults .gsc-cursor-page { - text-decoration:none; - color:#258AAF; - border: solid 1px #DADADA; -} - -#searchResults .gsc-tabHeader.gsc-tabhInactive:hover, -#searchResults .gsc-cursor-page:hover { - border-color: #DBDBDB; - background-color: #F3F3F3; - background-image: -webkit-gradient(linear, left top, left bottom, from(#F9F9F9), to(#ECECEC)); - background-image: -webkit-linear-gradient(top, #F9F9F9, #ECECEC); - background-image: -moz-linear-gradient(top, #F9F9F9, #ECECEC); - background-image: -ms-linear-gradient(top, #F9F9F9, #ECECEC); - background-image: -o-linear-gradient(top, #F9F9F9, #ECECEC); - background-image: linear-gradient(top, #F9F9F9, #ECECEC); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f9f9f9', -EndColorStr='#ececec'); - color: #33B5E5; -} - -#searchResults .gsc-tabHeader.gsc-tabhActive, -#searchResults .gsc-tabHeader.gsc-tabhActive:hover, -#searchResults .gsc-cursor-page.gsc-cursor-current-page, -#searchResults .gsc-cursor-page.gsc-cursor-current-page:hover { - color:#fff; - background-color: #09C; - background-image: -webkit-gradient(linear, left top, left bottom, from(#2FADDB), to(#09C)); - background-image: -webkit-linear-gradient(top, #2FADDB, #09C); - background-image: -moz-linear-gradient(top, #2FADDB, #09C); - background-image: -ms-linear-gradient(top, #2FADDB, #09C); - background-image: -o-linear-gradient(top, #2FADDB, #09C); - background-image: linear-gradient(top, #2FADDB, #09C); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#2faddb', EndColorStr='#09c'); - border: 1px solid #3990AB; - z-index:100; -} - - - - - -/************ STICKY NAV BAR ******************/ - -#header-wrapper { - background: #f9f9f9; - margin: 0 -10px 0 -10px; - padding: 31px 10px 0px 10px; - position: relative; -} -#header-wrapper #nav-x div.wrap { - max-width: 940px; - height: 38px; -} -#header-wrapper #nav-x ul.nav-x li { - margin-right: 31px !important; - margin-top: 5px; - margin-bottom: 0px; - height: 30px; -} -#header-wrapper #nav-x > div.wrap ul.nav-x li.active { - color: #669900; - border-bottom: 3px solid #669900; -} -#header-wrapper #nav-x > div.wrap ul.nav-x li.active a { - color: #669900; -} -#header-wrapper #nav-x > div.wrap ul.nav-x a { - font-size: 14.5px; -} -#header-wrapper .developer-console-btn { - float: right; - background: #fefefe; - border-radius: 4px; - padding: 8px 14px; - box-shadow: 1px 1px 0px #7a7a7a; - font-size: 14px; - margin-top: -6px; - cursor: pointer; - color: #464646; - margin-right: 20px; -} -/* not currently used */ -#header-wrapper .shadow { - width: 1034px; - height: 4px; - position: absolute; - left: 50%; - margin-left: -517px; - bottom: -4px; - background-image: url(../images/header-shadow.png); -} - -#context { - clear: both; - padding-top: 14px; -} -#context .breadcrumb { - float: left; - margin-bottom: 10px; -} -#context .util { - float: right; - margin-right: 20px; -} - -.breadcrumb { - list-style: none; - margin: 0; - padding: 0; - position: relative; -} -.breadcrumb li { - float: left; - padding: 0 20px 0 0; - color: #000; - white-space: nowrap; -} -.breadcrumb li a { - color: #000; -} -.breadcrumb li:after { - content: url(../images/breadcrumb.png); - position: relative; - top: 1px; - left: 10px; - width: 5px; - height: 10px; -} -.breadcrumb li.current { - font-weight: 700; -} -.breadcrumb li.current:after { - display: none; -} - -/* Sticky Nav overrides */ -.sticky-menu { - position: fixed; - width: 940px; - height: 0px; - z-index: 51; - top: 12px; -} -#sticky-header { - display: none; - padding: 0 10px; - position: fixed; - background: #f9f9f9; - top: 0px; - left: 0px; - right: 0px; - height: 45px; - box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.1); - border-bottom: 1px solid #a5c43a; - z-index: 50; -} -#sticky-header.design { - border-bottom: 1px solid #33b5e5; -} -#sticky-header.develop { - border-bottom: 1px solid #F80; -} -#sticky-header.distribute { - border-bottom: 1px solid #9C0; -} -#sticky-header.about { - border-bottom: 1px solid #9933CC; -} -#sticky-header > div { - overflow: hidden; - *zoom: 1; - width: 940px; - margin: 0 auto; - clear: both; - padding-top: 9px; -} -#sticky-header > div .logo { - float: left; - width: 26px; - height: 25px; - background: url(../images/dac_logo.png); - background-image: -webkit-image-set(url(../images/dac_logo.png) 1x, url(../images/dac_logo@2x.png) 2x); - z-index: 52; - position: relative; -} -#sticky-header > div .top { - float: left; - width: 38px; - height: 38px; - position: relative; - background: url(../images/styles/gototop.png); - z-index: 52; -} -#sticky-header > div .breadcrumb { - float: left; - padding: 0 0 0 10px; - border-left: 1px solid #d2d2d2; - line-height: 24px; - font-size: 14px; - position: relative; - top: 0px; - z-index: 52; -} - -/* offset the <a name=""> tags to account for sticky nav */ -body.reference a[name]:empty { - visibility: hidden; - display: block; - position: relative; - top: -56px; -} - - -} - - - - - - - -/*********** PREVIOUSLY dac-styles.css ***************/ - - -#header { - border-bottom:0; -} - -#header .wrap { - max-width:940px; - height:41px; - border-bottom:1px solid; - border-color: #ccc; - position:relative; -} - -.about #header .wrap { - border-color: #9933CC; -} - -.design #header .wrap { - border-color: #33b5e5; -} - -.develop #header .wrap { - border-color: #F80; -} - -.distribute #header .wrap { - border-color: #9C0; -} - -.logo a { - float:left; -} - -#header .logo { - margin-top: -6px; - margin-left: 0px; - margin-bottom:0px; - width: 160px; - padding-right:10px; -} - - -#header-wrap .logo.landing-logo { - width:220px; - margin:0; - padding:0; - margin-bottom:22px; -} -#header-wrap .logo.landing-logo img { - padding:0 0 0 10px; -} - -.search { - height:25px; - margin-top: -3px; - margin-bottom: 0px; -} - - - -/* Quicknav */ -.btn-quicknav { - width:20px; - height:28px; - float:left; - margin-left:6px; - padding-right:10px; - position:relative; - cursor:pointer; - border-right:1px solid #CCC; -} - -.btn-quicknav a { - zoom:1; - position:absolute; - top:13px; - left:5px; - display:block; - text-indent:-9999em; - width:10px; - height:5px; - background:url(../images/quicknav_arrow.png) no-repeat; -} - -.btn-quicknav a.arrow-active { - background-position: 0 -5px; - display:none; -} - -#header-wrap.quicknav a.arrow-inactive { - display:none; -} - -.btn-quicknav.active a.arrow-active { - display:block; -} - -.nav-x li { - display:block; - float:left; - margin-right:45px; - -webkit-transition: all 0.25s linear; - -moz-transition: all 0.25s linear; - -ms-transition: all 0.25s linear; - -o-transition: all 0.25s linear; - transition: all 0.25s linear; -} - -#header-wrap.quicknav .nav-x li { - min-width:160px; - margin-right:20px; -} - -#header-wrap.quicknav li.last { - margin-right:0px; -} - -#quicknav { - float:none; - clear:both; - margin-left:0; - margin-top:-30px; - display:none; - overflow:hidden; -} - -#header-wrap.quicknav #quicknav { - -} - -#quicknav ul { - margin:10px 0; - padding:0; -} - -#quicknav ul li.about { - border-top:1px solid #9933CC; -} - -#quicknav ul li.design { - border-top:1px solid #33b5e5; -} - -#quicknav ul li.develop { - border-top:1px solid #FF8800; -} - -#quicknav ul li.distribute { - border-top:1px solid #99cc00; -} - -#quicknav ul li { - display:block; - float:left; - margin:0 20px 0 0; - min-width:140px; -} - -#quicknav ul li.last { - margin-right:0px; -} - -#quicknav ul li ul li { - float:none; -} - -#quicknav ul li ul li a { - color:#222; -} - -#quicknav ul li li ul, -#quicknav ul li li ul li { - margin:0; -} - -#quicknav ul li li ul li:before { - content:"\21B3"; -} - -#header-wrap { - -webkit-transition: all 0.25s ease-out; - -moz-transition: all 0.25s ease-out; - -ms-transition: all 0.25s ease-out; - -o-transition: all 0.25s ease-out; - transition: all 0.25s ease-out; - -} - -#header-wrap.quicknav { - height:216px; - -} - -/* SEARCH AND MORE */ -.search { - position: absolute; - width: 50px; - height:28px; - display: block; - margin-top:-3px; - margin-bottom:7px; - overflow:hidden; - z-index:100; - right:54px; - -webkit-transition: width 0.4s ease; - -moz-transition: width 0.4s ease; - -o-transition: width 0.4s ease; - transition: width 0.4s ease; -} - -.search #search-btn { - width:50px; - height:28px; - background:url(../images/icon_search.png) no-repeat; - float:left; -} - -.search-inner { - width:245px; -} - -.search:hover, .search.active { - width:245px; -} - -.search .bottom, .search .left, .search .right { - position: absolute; - background-color: #a2a2a2 -} - -.search .bottom { - width: 214px; - height: 1px; - top: 24px; - left: 0 -} - -.search .left, .search .right { - height: 5px; - width: 1px -} - -.search .left { - top: 22px; - left: 56px; - background-color:#CCC; -} - -.search .right { - top: 22px; - left: 238px; - background-color:#CCC; -} - -.search form { - margin-top: 2px; - width: 162px; - float:left; -} - -.search form input { - color: #2f2f2f; - font-size: 0.95em; - width: 178px; - border: none; - margin-left: 6px; - z-index: 1500; - position: relative; - background-color: transparent; - border-bottom:1px solid #CCC; - padding:0 0 0 4px; - outline:none; - height:24px; -} - -.search:hover form input { - border-bottom:1px solid #33B5E5; -} - -.search:hover .bottom, .search:hover .left, .search:hover .right { - background-color: #33b5e5; -} - -.search:hover #search-btn { - background-position: 0 -28px -} - -.search form input:focus { - color: #222; - font-weight: bold -} - -.moremenu { - float: right; - position: relative; - width: 50px; - height:28px; - display: block; - margin-top:-3px; - margin-bottom:7px; - overflow:hidden; - -webkit-transition: width 0.25s ease; - -moz-transition: width 0.25s ease; - -o-transition: width 0.25s ease; - transition: width 0.25s ease; -} - -.moremenu #more-btn { - width:40px; - height:28px; - background:url(../images/icon_more.png) no-repeat; - border-left:1px solid #CCC; - float:left; - cursor:pointer; -} - -.moremenu:hover #more-btn { - background-position:0 -28px; -} - -.morehover { - position:absolute; - right:6px; - top:-9px; - width:40px; - height:35px; - z-index:99; - overflow:hidden; - - -webkit-opacity:0; - -moz-opacity:0; - -o-opacity:0; - opacity:0; - - -webkit-transform-origin:100% 0%; - -moz-transform-origin:100% 0%; - -o-transform-origin:100% 0%; - transform-origin:100% 0%; - - -webkit-transition-property: -webkit-opacity; - -webkit-transition-duration: .25s; - -webkit-transition-timing-function:ease; - - -moz-transition-property: -moz-opacity; - -moz-transition-duration: .25s; - -moz-transition-timing-function:ease; - - -o-transition-property: -o-opacity; - -o-transition-duration: .25s; - -o-transition-timing-function:ease; - - transition-property: opacity; - transition-duration: .25s; - transition-timing-function:ease; -} - -.morehover:hover, -.morehover.hover { - opacity:1; - height:385px; - width:268px; - -webkit-transition-property:height, -webkit-opacity; -} - -.morehover .top { - width:268px; - height:39px; - background:url(../images/more_top.png) no-repeat; -} - -.morehover .mid { - width:228px; - background:url(../images/more_mid.png) repeat-y; - padding:10px 20px 0 20px; -} - -.morehover .mid .header { - border-bottom:1px solid #ccc; - font-weight:bold; -} - -.morehover .bottom { - width:268px; - height:6px; - background:url(../images/more_bottom.png) no-repeat; -} - -.morehover ul { - margin:10px 10px 20px 0; -} - -.morehover ul li { - list-style:none; -} - -.morehover ul li.active a, -.morehover ul li.active a:hover { - color:#222 !important; -} - -.morehover ul li.active img { - margin-right:4px; -} - - - - -/* MARQUEE */ -.slideshow-container { - width:100%; - overflow:hidden; - position:relative; -} -.slideshow-container .slideshow-prev { - position:absolute; - top:50%; - left:0px; - margin-top:-36px; - z-index:99; -} -.slideshow-container .slideshow-next { - position:absolute; - top:50%; - margin-top:-36px; - z-index:99; - right:0px; -} - -.slideshow-container .pagination { - position:absolute; - bottom:20px; - width:100%; - text-align:center; - z-index:99; -} -.slideshow-container .pagination ul { - margin:0; -} -.slideshow-container .pagination ul li{ - display: inline-block; - width:12px; - height:12px; - text-indent:-8000px; - list-style:none; - margin: 0 2px; - border-radius:6px; - background-color:#ccc; - cursor:pointer; - -webkit-transition:color .5s ease-in; - -moz-transition:color .5s ease-in; - -o-transition:color .5s ease-in; - transition:color .5s ease-in; -} -.slideshow-container .pagination ul li:hover { - background-color:#999; -} -.slideshow-container .pagination ul li.active { - background-color:#33b5e5; -} -.slideshow-container .pagination ul li.active:hover { - background-color:#33b5e5; -} -.slideshow-container ul li { - display:inline; - list-style:none; -} - - -#landing h1 { - margin:17px 0 20px 0 !important; -} - -a.download-sdk { - float:right; - margin:-10px 0; - height:30px; - padding-top:4px; - padding-bottom:0px; -} - -#nav-x { - padding-top: 13px; -} - -#nav-x .wrap { - min-height:32px; -} - -#nav-x .wrap, -#searchResults.wrap { - max-width:940px; - border-bottom:1px solid #CCC; -} - -#searchResults.wrap #leftSearchControl { - min-height:700px -} -.nav-x { - margin-left:0; - margin-bottom:0; -} - - - - - - - - - - -/* - * CSS Styles that are needed by jScrollPane for it to operate correctly. - */ - -.jspContainer { - overflow: hidden; - position: relative; -} - -.jspPane { - position: absolute; - width:100% !important; /* to avoid cut-off api names in reference in horiz scroll */ -} - -.jspVerticalBar { - position: absolute; - top: 0; - right: 0; - width: 4px; - height: 100%; - background: #f5f5f5; -} - -.jspHorizontalBar { - position: absolute; - bottom: 0; - left: 0; - width: 100%; - height: 4px; - background: #f5f5f5; -} - -.jspVerticalBar *, -.jspHorizontalBar * { - margin: 0; - padding: 0; -} -.jspCap { - display: block; -} - -.jspVerticalBar .jspCap { - height: 4px; -} - -.jspHorizontalBar .jspCap { - width: 0; - height: 100%; -} - -.jspHorizontalBar .jspCap { - float: left; -} - -.jspTrack { - position: relative; -} - -.jspDrag { - background: #bbb; - position: relative; - top: 0; - left: 0; - cursor: pointer; -} - -.jspDrag:hover, -.jspDrag:active { - border-color: #09c; - background-color: #4cadcb; - background-image: -webkit-gradient(linear, left top, right top, from(#5dbcd9), to(#4cadcb)); - background-image: -webkit-linear-gradient(left, #5dbcd9, #4cadcb); - background-image: -moz-linear-gradient(left, #5dbcd9, #4cadcb); - background-image: -ms-linear-gradient(left, #5dbcd9, #4cadcb); - background-image: -o-linear-gradient(left, #5dbcd9, #4cadcb); - background-image: linear-gradient(left, #5dbcd9, #4cadcb); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#5dbcd9', EndColorStr='#4cadcb'); -} - -.jspHorizontalBar .jspTrack, -.jspHorizontalBar .jspDrag { - float: left; - height: 100%; -} - -.jspArrow { - background: #999; - text-indent: -20000px; - display: block; - cursor: pointer; -} - -.jspArrow.jspDisabled { - cursor: default; - background: #ccc; -} - -.jspVerticalBar .jspArrow { - height: 16px; -} - -.jspHorizontalBar .jspArrow { - width: 16px; - float: left; - height: 100%; -} - -.jspVerticalBar .jspArrow:focus { - outline: none; -} - -.jspCorner { - float: left; - height: 100%; -} - -/* Yuk! CSS Hack for IE6 3 pixel bug :( */ -* html .jspCorner { - margin: 0 -3px 0 0; -} -/******* end of jscrollpane *********/ - - - - - -/************ DEVELOP HOMEPAGE ******************/ - -/* Slideshow */ -.slideshow-develop { - height: 316px; - width: 940px; - position: relative; - overflow:hidden; -} -.slideshow-develop .frame { - width: 940px; - height: 316px; -} -.slideshow-develop img.play { - max-width:350px; - max-height:240px; - margin:20px 0 0 90px; - -webkit-transform: perspective(800px ) rotateY( 35deg ); - box-shadow: -16px 20px 40px rgba(0, 0, 0, 0.3); - -moz-box-shadow: -16px 20px 40px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: -16px 20px 40px rgba(0, 0, 0, 0.3); -} -.slideshow-develop img.play.no-shadow { - box-shadow: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; -} -.slideshow-develop img.play.no-transform { - -webkit-transform: none; -} -.slideshow-develop a.slideshow-next { - background: url(../images/arrow-right-develop.png); -} -.slideshow-develop a.slideshow-prev { - background: url(../images/arrow-left-develop.png); -} -.slideshow-develop .content-right { - float: left; -} -.slideshow-develop .content-right h2 { - padding:0; - margin-bottom:10px; - border:none; - font-size:24px; -} -.slideshow-develop .item { - height: 300px; - width: 940px; -} -.slideshow-develop .pagination ul li.active { - background-color: #F80; -} -.slideshow-develop .pagination ul li.active:hover { - background-color: #F80; -} -.slideshow-develop .item hr { - margin:5px 0 10px; -} -.slideshow-develop .item p { - margin:10px 0; -} -.slideshow-develop .item p.title-intro { - position:absolute; - margin:0; -} - -/* Feeds */ -.feed ul { - margin: 0; -} -.feed .feed-nav { - height: 25px; - border-bottom: 1px solid #CCC; -} -.feed .feed-nav li { - list-style: none; - float: left; - height: 21px; /* +4px bottom border = 25px; same as .feed-nav */ - margin-right: 25px; - cursor: pointer; -} -.feed .feed-nav li.active { - color: #000; - border-bottom: 4px solid #F80; -} -.feed .feed-container { - overflow: hidden; - width: 460px; -} -.feed .feed-container .feed-frame { - width: 1000px; -} -.feed .feed-container .feed-frame ul { - float: left; - width:460px; -} -.feed .feed-container .feed-frame ul ul { - float: none; - margin:10px 0 0 30px; -} -.feed .feed-container .feed-frame li { - list-style: none; - margin: 20px 0 20px 0; - width: 460px; - height:93px; -} -.feed .feed-container .feed-frame li.playlist { - height:auto; -} -.feed .feed-container .feed-frame li.playlist a { - height:93px; - display:block; -} -.feed .feed-container .feed-frame li.more { - height:20px; - margin:10px 0 5px 5px; -} -.feed .feed-container .feed-frame li.more a { - height:inherit; -} -.feed .feed-container .feed-frame li.playlist-video { - list-style: none; - margin: 0; - width: 460px; - height:55px; - font-size:12px; -} -.feed .feed-container .feed-frame li.playlist-video a { - height:45px; - padding:5px; -} -.feed .feed-container .feed-frame li.playlist-video h5 { - font-size:12px; - line-height:13px; - margin:0; -} -.feed .feed-container .feed-frame li.playlist-video p { - margin:5px 0 0; - line-height:15px; -} -.feed-container .feed-frame div.feed-image { - float: left; - border: 1px solid #999; - margin:0 20px 0 0; - width:122px; - height:92px; - background:url('../images/blog-default.png') no-repeat 0 0; - background-size:180px; -} -#jd-content .feed .feed-container .feed-frame li img { - float: left; - border: 1px solid #999; - margin:0 20px 0 0; - width:122px; - height:92px; -} -#jd-content .feed .feed-container .feed-frame li.playlist-video img { - width:inherit; - height:inherit; -} - -.feed .feed-container .feed-frame li a, -.feed .feed-container .feed-frame li a:active { - color:#555 !important; -} - -.feed .feed-container .feed-frame li a:hover, -.feed .feed-container .feed-frame li a:hover * { - color:#7AA1B0 !important; -} - -/* Video player */ -#player-wrapper { - display:none; - margin: -1px auto 0; - position: relative; - width: 940px; - height: 0px; -} -#player-frame { - background: #EFEFEF; - border: 1px solid #CCC; - padding: 0px 207px; - z-index: 10; /* stay above marque, but below search suggestions */ - width: 525px; - height: 330px; - position: relative; -} - - - -/************ DEVELOP TOPIC CONTAINERS ************/ - -.landing-banner, -.landing-docs { - margin:20px 0; -} -.landing-banner > div:first-child, -.landing-docs > div:first-child, -.landing-docs > .col-12 { - margin-left:0; - min-height:280px; -} -.landing-banner.short > div { - min-height:50px; -} -.landing-banner > div:last-child, -.landing-docs > div:last-child, -.landing-docs > .col-12 { - margin-right:0; -} - -.landing-banner > div > *:last-child { - margin-bottom:0; -} -.landing-banner h1 { - margin-top:16px; - padding-bottom:24px; -} -.landing-docs, -.landing-banner { - clear:both; - overflow:hidden; -} -.landing-docs h3 { - font-size:14px; - line-height:21px; - color:#555; - text-transform:uppercase; - border-bottom:1px solid #CCC; - margin:0 0 20px; -} -.landing-docs a { - color:#333 !important; -} - -.landing-docs a:hover, -.landing-docs a:hover * { - color:#7AA1B0 !important -} - -.landing-docs .normal-links a { - color:#258aaf !important; -} - -.plusone { - float:right; -} - - - -.next-docs { - border-top:1px solid #ccc; - margin:40px 0 0; - padding:5px 0 0; - clear:left; - overflow:hidden; -} -.next-docs div:first-child { - margin-left:0; -} -.next-docs div:last-child { - margin-right:0; -} - -.next-docs h2 { - font-size:14px; - line-height:21px; - color:#555; - text-transform:uppercase; - border-bottom:none; - margin:0 0 1em; - padding:5px 0 0; -} - - - -/************* HOME/LANDING PAGE *****************/ - -.slideshow-home { - height: 500px; - width: 940px; - border-bottom: 1px solid #CCC; - position: relative; - margin: 0; -} -.slideshow-home .frame { - width: 940px; - height: 500px; -} -.slideshow-home .content-left { - float: left; - text-align: center; - vertical-align: center; - margin: 0 0 0 35px; -} -.slideshow-home .content-right { - margin: 80px 0 0 0; -} -.slideshow-home .content-right p { - margin-bottom: 10px; -} -.slideshow-home .content-right p:last-child { - margin-top: 15px; -} -.slideshow-home .content-right h1 { - padding:0; -} -.slideshow-home .item { - height: 500px; - width: 940px; -} -.home-sections { - padding: 30px 20px 20px; - margin: 20px 0; - background: -webkit-linear-gradient(top, #F6F6F6,#F9F9F9); -} -.home-sections ul { - margin: 0; -} -.home-sections ul li { - float: left; - display: block; - list-style: none; - width: 170px; - height: 35px; - border: 1px solid #ccc; - background: white; - margin-right: 10px; - border-radius: 1px; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - box-shadow: 1px 1px 5px #EEE; - -webkit-box-shadow: 1px 1px 5px #EEE; - -moz-box-shadow: 1px 1px 5px #EEE; - background: white; -} -.home-sections ul li:hover { - background: #F9F9F9; - border: 1px solid #CCC; -} -.home-sections ul li a, -.home-sections ul li a:hover { - font-weight: bold; - margin-top: 8px; - line-height: 18px; - float: left; - width: 100%; - text-align: center; - color: #09c !important; -} -.home-sections ul li a { - font-weight: bold; - margin-top: 8px; - line-height: 18px; - float: left; - width:100%; - text-align:center; -} -.home-sections ul li img { - float: left; - margin: -8px 0 0 10px; -} -.home-sections ul li.last { - margin-right: 0px; -} -.fullpage #footer { - margin-top: -40px; -} - -/************ DISTRIBUTE PAGES ******************/ - -.article-detail #body-content { - padding-top: 10px; -} - -/* A container for grid sets with uppercase h3 and rule */ -.dynamic-grid h3 { - font-size:14px; - line-height:21px; - color:#555; - text-transform:uppercase; - border-bottom:1px solid #CCC; - padding:8px 0 0 1px; - margin-bottom:14px; - clear:both; -} - -.top-right-float { - float: right; -} - -.clearfloat { - float: none; - clear: both; -} - -.border-img { - border: 1px solid #CCC; -} - -.center-img { - margin: auto; - text-align: center; -} -.center-img img { - margin-bottom: 15px; -} - -.figure img, .border-img { - margin-bottom: 15px; -} - -/************ RESOURCE CARDS ******************/ - -/* Resource cards, 12, 13, 16-col */ - -/* Basic card-styling with shadow */ -.resource-card { - border-radius: 1px; - box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.12); - background: #fefefe; -} - -/* Styling for background image including tinting and section icons in stacks */ -.card-bg { - display: block; - position: absolute; - vertical-align: top; - width: 100%; - left: 0; - top: 0; - background-size: cover; - background-repeat: no-repeat; - background-position: center; - background-image: url(../images/resource-card-default-android.jpg); -} -.card-bg:after { - content: ""; - display: block; - height: 100%; - width: 100%; - opacity: 1; - background: rgba(0, 0, 0, 0.2); - -webkit-transition: opacity 0.5s; - -moz-transition: opacity 0.5s; - -o-transition: opacity 0.5s; - transition: opacity 0.5s; -} -.static .card-bg:after { - display:none; -} -.card-bg .card-section-icon { - position: absolute; - top: 50%; - width: 100%; - margin-top: -35px; - text-align: center; - padding-top: 65px; - z-index: 100; -} -.card-bg .card-section-icon .icon { - position: absolute; - left: 50%; - margin-left: -28px; - top: 0px; - width: 56px; - height: 56px; - background-repeat: no-repeat; - background-position: 50% 50%; - background-image: url(../images/stack-icon.png); -} -.card-bg .card-section-icon .section { - text-transform: uppercase; - color: white; - font-size: 14px; -} - -.card-info { - position: absolute; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - top: 0; - right: 0; - bottom: 0; - left: 0; - overflow: hidden; - background: #fefefe; - padding: 4px 12px 6px 12px; -} -.card-info .section { - text-transform: uppercase; - color: #898989; - font-size: 12px; - margin-bottom: 1px; -} -.card-info .title { - color: #363636; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - padding-bottom: 5px; - margin-bottom: -2px; - font-size: 16px; -} -.card-info .description { - overflow: hidden; -} -.card-info .description .text { - color: #464646; - font: 13px/15px Roboto Condensed; - overflow: hidden; - width:100%; -} -.card-info .description .util { - position: absolute; - right: 5px; - bottom: 70px; /*-2px;*/ - opacity: 0; - -webkit-transition: opacity 0.5s; - -moz-transition: opacity 0.5s; - -o-transition: opacity 0.5s; - transition: opacity 0.5s; -} -.card-info.empty-desc .title { - white-space: normal; - overflow: visible; -} -.card-info.empty-desc .description { - display: none; -} -/* Truncate card summaries at bounding box and - * and apply ellipsis at lower right */ -.ellipsis { - overflow: hidden; - float:right; - line-height: 15px; - width:100%; -} -.resource-card-6x6 .card-info .description .teddddddxt { - float:left; - position:relative; - margin-left:0; -} -.ellipsis:before { - content:""; - float: left; - width: 5px; - height:100%; -} -.ellipsis > *:first-child.text { - float: right; - width: 100% !important; - margin-left: -5px; -} -.ellipsis:after { - content: "\02026"; - height:17px; - padding-bottom:4px; - - box-sizing: content-box; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - - float: right; position: relative; - top: -16px; left: 100%; - width: 4em; margin-left: -4em; - padding-right: 5px; - - background: -webkit-gradient(linear, left top, right top, - from(rgba(255, 255, 255, 0)), to(white), color-stop(65%, white)); - background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); - background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); - background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); - background: linear-gradient(to right, rgba(255, 255, 255, 0), white 65%, white); -} -.ellipsis:after { - font-style: normal; color: #aaa; - font-size:13px; - text-align: right; -} - -/* Flow Layout */ -.resource-flow-layout { - display: inline-block; -} -.resource-flow-layout .resource-card, .resource-flow-layout .resource-card-stack { - float: left; - position: relative; -} -.resource-flow-layout .resource-card-stack > .resource-card { - margin-right: 0px !important; -} -.resource-flow-layout:after { - content: "."; - display: block; - height: 0; - position:relative; - clear: both; - visibility: hidden; -} -.resource-card:hover { - cursor: pointer; -} -.static .resource-card:hover { - cursor: auto; -} -.resource-card:hover .card-bg:after { - opacity: 0; -} -/* disabled to make way for fade/ellipsis truncation, - and the plusone moves up. -.resource-card:hover .card-info .description .text { - padding-right: 70px; -} */ -.resource-card:hover .card-info .description .util { - opacity: 1; -} - -/* Carousel Layout */ -/* Carousel styles for landing page */ -.resource-carousel-layout { - margin: 20px 0 20px 0; - position: relative; - overflow: hidden; -} -.resource-carousel-layout .slideshow-prev, .resource-carousel-layout .slideshow-next { - display: none; -} -.resource-carousel-layout .pagination { - bottom: 0px; -} -.resource-carousel-layout .frame li { - position: relative; -} -.resource-carousel-layout .frame li .card-bg { - height: 300px; -} -.resource-carousel-layout .frame li .card-info { - padding: 7px 15px 0px 15px; - top: 300px; -} -.resource-carousel-layout .frame li .card-info .section { - font-size: 13px; - margin-bottom: 7px; -} -.resource-carousel-layout .frame li .card-info .title { - font-size: 25px; - margin-bottom: 2px; -} -.resource-carousel-layout .frame li .card-info .description { - font-family: 15px/16px Roboto Condensed, sans-serif; -} -.resource-carousel-layout .frame li .card-info .description .text { - height: 40px; -} -.resource-carousel-layout .frame li .card-info .description .util { - bottom:97px; - right:4px; -} - -/* Stack Layout */ -.resource-stack-layout { - display: inline-block; -} -.resource-stack-layout .resource-card-stack { - float: left; - position: relative; -} -.resource-stack-layout .resource-card { - margin-bottom: 20px; - display: block; - position: relative; -} -.resource-stack-layout .section-card-menu > .card-info .section, .resource-stack-layout .section-card > .card-info .title { - /*text-transform: uppercase;*/ - color: #898989; - font-size: 17px; - line-height: 24px; - margin-bottom: 6px; -} -.resource-stack-layout .section-card { - height: 284px; -} -.resource-stack-layout .section-card > .card-bg { - height: 192px; -} -.resource-stack-layout .section-card > .card-info { - padding: 4px 12px 6px 12px; - top: 192px; -} -.resource-stack-layout .section-card > .card-info .section { - display: none; -} -.resource-stack-layout .section-card > .card-info .title { - font-size: 17px; - border-bottom: 1px solid #959595; - padding-bottom: 0px; -} -.resource-stack-layout .section-card > .card-info .description { - font-size: 13px; - line-height: 15px; -} -.resource-stack-layout .section-card > .card-info .description .text { - height: 30px; -} -.resource-stack-layout .related-card { - height: 90px; -} -.resource-stack-layout .related-card > .card-bg { - left: 0; - top: 0; - width: 90px; - height: 100%; - position: absolute; - display: block; -} -.resource-stack-layout .related-card > .card-info { - left: 90px; - padding: 4px 12px 4px 12px; -} -.resource-stack-layout .related-card > .card-info .section { - font-size: 12px; - margin-bottom: 1px; - display: none; -} -.resource-stack-layout .related-card > .card-info .title { - font-size: 16px; - margin-bottom: -2px; - white-space: normal; - overflow: visible; - text-overflow: ellipsis; -} -.resource-stack-layout .related-card > .card-info .title:after { - content: url(../images/link-out.png); - display: block; -} -.resource-stack-layout .related-card > .card-info .description { - display: none; -} -.resource-stack-layout .section-card-menu { - /* Flexible height */ - display: block; - height: auto; - width: auto; -} -.resource-stack-layout .section-card-menu .card-bg { - height: 155px; - /* Flexible height */ - position: relative; - display: inline-block; - vertical-align: top; -} -.resource-stack-layout .section-card-menu .card-info { - padding: 4px 12px 0px 12px; - /* Flexible height */ - position: relative; - left: auto; - top: auto; - right: auto; - bottom: auto; -} -.resource-stack-layout .section-card-menu .card-info ul { - list-style: none; - margin: 0; -} -.resource-stack-layout .section-card-menu .card-info ul li { - list-style: none; - margin: 0; - padding: 15px 0; - border-top-width: 1px; - border-top-style: solid; - border-top-color: #959595; -} -.resource-stack-layout .section-card-menu .card-info ul li a, .resource-stack-layout .section-card-menu .card-info ul li a:focus, .resource-stack-layout .section-card-menu .card-info ul li a:link, .resource-stack-layout .section-card-menu .card-info ul li a:visited, .resource-stack-layout .section-card-menu .card-info ul li a:active, .resource-stack-layout .section-card-menu .card-info ul li a:hover { - color: #363636 !important; -} -.resource-stack-layout .section-card-menu .card-info ul li:first-child { - border-top: none; -} -.resource-stack-layout .section-card-menu .card-info ul li:hover .title:after { - opacity: 1; - -webkit-transition: opacity 0.5s; - -moz-transition: opacity 0.5s; - -o-transition: opacity 0.5s; - transition: opacity 0.5s; -} -.resource-stack-layout .section-card-menu .card-info ul li:hover .description { - max-height: 30px; - opacity: 1; - -webkit-transition: max-height 0.5s, opacity 1s; - -moz-transition: max-height 0.5s, opacity 1s; - -o-transition: max-height 0.5s, opacity 1s; - transition: max-height 0.5s, opacity 1s; -} -.resource-stack-layout .section-card-menu .card-info .title { - font-size: 16px; - margin-bottom: -2px; - position: relative; -} -.resource-stack-layout .section-card-menu .card-info .title:after { - background: url(../images/stack-arrow-right.png); - content: ''; - opacity: 0; - -webkit-transition: opacity 0.25s; - -moz-transition: opacity 0.25s; - -o-transition: opacity 0.25s; - transition: opacity 0.25s; - position: absolute; - right: 0px; - top: 3px; - width: 10px; - height: 15px; -} -.resource-stack-layout .section-card-menu .card-info .title.more { - text-transform: uppercase; - color: #898989; - display: inline-block; -} -.resource-stack-layout .section-card-menu .card-info .title.more:after { - background: url(../images/stack-arrow-right.png); - content: ''; - display: block; - position: absolute; - right: -20px; - top: 3px; - width: 10px; - height: 15px; -} -.resource-stack-layout .section-card-menu .card-info .description { - max-height: 0px; - opacity: 0; - overflow: hidden; - font-size: 13px; - line-height: 15px; - /* Hover off */ - -webkit-transition: max-height 0.5s, opacity 0.5s; - -moz-transition: max-height 0.5s, opacity 0.5s; - -o-transition: max-height 0.5s, opacity 0.5s; - transition: max-height 0.5s, opacity 0.5s; -} -.resource-stack-layout .section-card-menu .card-info .description .text { - height: 30px; -} -.resource-stack-layout:after { - content: "."; - display: block; - height: 0; - clear: both; - visibility: hidden; -} - -/* Generate the flow layout styles for a 3-column 16-col span */ -.resource-flow-layout.col-16 { - margin: 0 -14px 0 0; - width: 954px; -} -.resource-flow-layout.col-16 .resource-card, .resource-flow-layout.col-16 .resource-card-stack { - margin: 0 14px 20px 0; -} -.resource-flow-layout.col-16 .resource-card-row-stack-last { - margin-bottom: 0px !important; -} -.resource-flow-layout.col-16 .resource-card-col-stack-last { - margin-bottom: 0px !important; -} -.resource-flow-layout.col-16 .resource-card-3x6 { - width: 145px; - height: 284px; -} -.resource-flow-layout.col-16 .resource-card-3x12 { - width: 145px; - height: 588px; -} -.resource-flow-layout.col-16 .resource-card-3x18 { - width: 145px; - height: 892px; -} -.resource-flow-layout.col-16 .resource-card-6x6 { - width: 304px; - height: 284px; -} -.resource-flow-layout.col-16 .resource-card-6x12 { - width: 304px; - height: 588px; -} -.resource-flow-layout.col-16 .resource-card-6x18 { - width: 304px; - height: 892px; -} -.resource-flow-layout.col-16 .resource-card-9x6 { - width: 463px; - height: 284px; -} -.resource-flow-layout.col-16 .resource-card-9x12 { - width: 463px; - height: 588px; -} -.resource-flow-layout.col-16 .resource-card-9x18 { - width: 463px; - height: 892px; -} -.resource-flow-layout.col-16 .resource-card-12x6 { - width: 622px; - height: 284px; -} -.resource-flow-layout.col-16 .resource-card-12x12 { - width: 622px; - height: 588px; -} -.resource-flow-layout.col-16 .resource-card-12x18 { - width: 622px; - height: 892px; -} -.resource-flow-layout.col-16 .resource-card-15x6 { - width: 781px; - height: 284px; -} -.resource-flow-layout.col-16 .resource-card-15x12 { - width: 781px; - height: 588px; -} -.resource-flow-layout.col-16 .resource-card-15x18 { - width: 781px; - height: 892px; -} -.resource-flow-layout.col-16 .resource-card-18x6 { - width: 940px; - height: 284px; -} -.resource-flow-layout.col-16 .resource-card-18x12 { - width: 940px; - height: 420px; -} -.resource-flow-layout.col-16 .resource-card-18x18 { - width: 940px; - height: 892px; -} -.resource-flow-layout.col-16 .resource-card-3x2 { - width: 145px; - height: 95px; -} -.resource-flow-layout.col-16 .resource-card-3x2x3 { - width: 145px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-16 .resource-card-3x3 { - width: 145px; - height: 142px; -} -.resource-flow-layout.col-16 .resource-card-3x3x2 { - width: 145px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-16 .resource-card-6x2 { - width: 304px; - height: 95px; -} -.resource-flow-layout.col-16 .resource-card-6x2x3 { - width: 304px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-16 .resource-card-6x3 { - width: 304px; - height: 142px; -} -.resource-flow-layout.col-16 .resource-card-6x3x2 { - width: 304px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-16 .resource-card-9x2 { - width: 463px; - height: 95px; -} -.resource-flow-layout.col-16 .resource-card-9x2x3 { - width: 463px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-16 .resource-card-9x3 { - width: 463px; - height: 142px; -} -.resource-flow-layout.col-16 .resource-card-9x3x2 { - width: 463px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-16 .resource-card-12x2 { - width: 622px; - height: 95px; -} -.resource-flow-layout.col-16 .resource-card-12x2x3 { - width: 622px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-16 .resource-card-12x3 { - width: 622px; - height: 142px; -} -.resource-flow-layout.col-16 .resource-card-12x3x2 { - width: 622px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-16 .resource-card-15x2 { - width: 781px; - height: 95px; -} -.resource-flow-layout.col-16 .resource-card-15x2x3 { - width: 781px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-16 .resource-card-15x3 { - width: 781px; - height: 142px; -} -.resource-flow-layout.col-16 .resource-card-15x3x2 { - width: 781px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-16 .resource-card-18x2 { - width: 940px; - height: 95px; -} -.resource-flow-layout.col-16 .resource-card-18x2x3 { - width: 940px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-16 .resource-card-18x3 { - width: 940px; - height: 142px; -} -.resource-flow-layout.col-16 .resource-card-18x3x2 { - width: 940px; - height: 138px; - margin-bottom: 8px; -} - -/* Generate the flow layout styles for a 3-column 16-col span */ -.resource-flow-layout.col-12 { - margin: 0 -14px 0 0; - width: 714px; -} - -.resource-flow-layout.col-12 .resource-card, .resource-flow-layout.col-12 .resource-card-stack { - margin: 0 14px 20px 0; -} -.resource-flow-layout.col-12 .resource-card-row-stack-last { - margin-bottom: 0px !important; -} -.resource-flow-layout.col-12 .resource-card-col-stack-last { - margin-bottom: 0px !important; -} -.resource-flow-layout.col-12 .resource-card-3x6 { - width: 105px; - height: 284px; -} -.resource-flow-layout.col-12 .resource-card-3x12 { - width: 105px; - height: 588px; -} -.resource-flow-layout.col-12 .resource-card-3x18 { - width: 105px; - height: 892px; -} -.resource-flow-layout.col-12 .resource-card-6x6 { - width: 224px; - height: 284px; -} -.resource-flow-layout.col-12 .resource-card-6x12 { - width: 224px; - height: 588px; -} -.resource-flow-layout.col-12 .resource-card-6x18 { - width: 224px; - height: 892px; -} -.resource-flow-layout.col-12 .resource-card-9x6 { - width: 343px; - height: 284px; -} -.resource-flow-layout.col-12 .resource-card-9x12 { - width: 343px; - height: 588px; -} -.resource-flow-layout.col-12 .resource-card-9x18 { - width: 343px; - height: 892px; -} -.resource-flow-layout.col-12 .resource-card-12x6 { - width: 462px; - height: 284px; -} -.resource-flow-layout.col-12 .resource-card-12x12 { - width: 462px; - height: 588px; -} -.resource-flow-layout.col-12 .resource-card-12x18 { - width: 462px; - height: 892px; -} -.resource-flow-layout.col-12 .resource-card-15x6 { - width: 581px; - height: 284px; -} -.resource-flow-layout.col-12 .resource-card-15x12 { - width: 581px; - height: 588px; -} -.resource-flow-layout.col-12 .resource-card-15x18 { - width: 581px; - height: 892px; -} -.resource-flow-layout.col-12 .resource-card-18x6 { - width: 700px; - height: 284px; -} -.resource-flow-layout.col-12 .resource-card-18x12 { - width: 700px; - height: 420px; -} -.resource-flow-layout.col-12 .resource-card-18x18 { - width: 700px; - height: 892px; -} -.resource-flow-layout.col-12 .resource-card-3x2 { - width: 105px; - height: 95px; -} -.resource-flow-layout.col-12 .resource-card-3x2x3 { - width: 105px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-12 .resource-card-3x3 { - width: 105px; - height: 142px; -} -.resource-flow-layout.col-12 .resource-card-3x3x2 { - width: 105px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-12 .resource-card-6x2 { - width: 224px; - height: 95px; -} -.resource-flow-layout.col-12 .resource-card-6x2x3 { - width: 224px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-12 .resource-card-6x3 { - width: 224px; - height: 142px; -} -.resource-flow-layout.col-12 .resource-card-6x3x2 { - width: 224px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-12 .resource-card-9x2 { - width: 343px; - height: 95px; -} -.resource-flow-layout.col-12 .resource-card-9x2x3 { - width: 343px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-12 .resource-card-9x3 { - width: 343px; - height: 142px; -} -.resource-flow-layout.col-12 .resource-card-9x3x2 { - width: 343px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-12 .resource-card-12x2 { - width: 462px; - height: 95px; -} -.resource-flow-layout.col-12 .resource-card-12x2x3 { - width: 462px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-12 .resource-card-12x3 { - width: 462px; - height: 142px; -} -.resource-flow-layout.col-12 .resource-card-12x3x2 { - width: 462px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-12 .resource-card-15x2 { - width: 581px; - height: 95px; -} -.resource-flow-layout.col-12 .resource-card-15x2x3 { - width: 581px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-12 .resource-card-15x3 { - width: 581px; - height: 142px; -} -.resource-flow-layout.col-12 .resource-card-15x3x2 { - width: 581px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-12 .resource-card-18x2 { - width: 700px; - height: 95px; -} -.resource-flow-layout.col-12 .resource-card-18x2x3 { - width: 700px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-12 .resource-card-18x3 { - width: 700px; - height: 142px; -} -.resource-flow-layout.col-12 .resource-card-18x3x2 { - width: 700px; - height: 138px; - margin-bottom: 8px; -} - -/* Generate the flow layout styles for a 3-column 13-col span */ - -.resource-flow-layout.col-13 { - margin: 0 -14px 0 0; - width: 774px; -} -.resource-flow-layout.col-13 .resource-card, .resource-flow-layout.col-13 .resource-card-stack { - margin: 0 14px 20px 0; -} -.resource-flow-layout.col-13 .resource-card-row-stack-last { - margin-bottom: 0px !important; -} -.resource-flow-layout.col-13 .resource-card-col-stack-last { - margin-bottom: 0px !important; -} -.resource-flow-layout.col-13 .resource-card-3x6 { - width: 115px; - height: 284px; -} -.resource-flow-layout.col-13 .resource-card-3x12 { - width: 115px; - height: 588px; -} -.resource-flow-layout.col-13 .resource-card-3x18 { - width: 115px; - height: 892px; -} -.resource-flow-layout.col-13 .resource-card-6x6 { - width: 244px; - height: 284px; -} -.resource-flow-layout.col-13 .resource-card-6x12 { - width: 244px; - height: 588px; -} -.resource-flow-layout.col-13 .resource-card-6x18 { - width: 244px; - height: 892px; -} -.resource-flow-layout.col-13 .resource-card-9x6 { - width: 373px; - height: 284px; -} -.resource-flow-layout.col-13 .resource-card-9x12 { - width: 373px; - height: 588px; -} -.resource-flow-layout.col-13 .resource-card-9x18 { - width: 373px; - height: 892px; -} -.resource-flow-layout.col-13 .resource-card-12x6 { - width: 502px; - height: 284px; -} -.resource-flow-layout.col-13 .resource-card-12x12 { - width: 502px; - height: 588px; -} -.resource-flow-layout.col-13 .resource-card-12x18 { - width: 502px; - height: 892px; -} -.resource-flow-layout.col-13 .resource-card-15x6 { - width: 631px; - height: 284px; -} -.resource-flow-layout.col-13 .resource-card-15x12 { - width: 631px; - height: 588px; -} -.resource-flow-layout.col-13 .resource-card-15x18 { - width: 631px; - height: 892px; -} -.resource-flow-layout.col-13 .resource-card-18x6 { - width: 760px; - height: 284px; -} -.resource-flow-layout.col-13 .resource-card-18x12 { - width: 760px; - height: 420px; -} -.resource-flow-layout.col-13 .resource-card-18x18 { - width: 760px; - height: 892px; -} -.resource-flow-layout.col-13 .resource-card-3x2 { - width: 115px; - height: 95px; -} -.resource-flow-layout.col-13 .resource-card-3x2x3 { - width: 115px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-13 .resource-card-3x3 { - width: 115px; - height: 142px; -} -.resource-flow-layout.col-13 .resource-card-3x3x2 { - width: 115px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-13 .resource-card-6x2 { - width: 244px; - height: 95px; -} -.resource-flow-layout.col-13 .resource-card-6x2x3 { - width: 244px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-13 .resource-card-6x3 { - width: 244px; - height: 142px; -} -.resource-flow-layout.col-13 .resource-card-6x3x2 { - width: 244px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-13 .resource-card-9x2 { - width: 373px; - height: 95px; -} -.resource-flow-layout.col-13 .resource-card-9x2x3 { - width: 373px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-13 .resource-card-9x3 { - width: 373px; - height: 142px; -} -.resource-flow-layout.col-13 .resource-card-9x3x2 { - width: 373px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-13 .resource-card-12x2 { - width: 502px; - height: 95px; -} -.resource-flow-layout.col-13 .resource-card-12x2x3 { - width: 502px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-13 .resource-card-12x3 { - width: 502px; - height: 142px; -} -.resource-flow-layout.col-13 .resource-card-12x3x2 { - width: 502px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-13 .resource-card-15x2 { - width: 631px; - height: 95px; -} -.resource-flow-layout.col-13 .resource-card-15x2x3 { - width: 631px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-13 .resource-card-15x3 { - width: 631px; - height: 142px; -} -.resource-flow-layout.col-13 .resource-card-15x3x2 { - width: 631px; - height: 138px; - margin-bottom: 8px; -} -.resource-flow-layout.col-13 .resource-card-18x2 { - width: 760px; - height: 95px; -} -.resource-flow-layout.col-13 .resource-card-18x2x3 { - width: 760px; - height: 90px; - margin-bottom: 7px; -} -.resource-flow-layout.col-13 .resource-card-18x3 { - width: 760px; - height: 142px; -} -.resource-flow-layout.col-13 .resource-card-18x3x2 { - width: 760px; - height: 138px; - margin-bottom: 8px; -} - -/* - The following are styles for cards in the flowlayout above, styled by the number of rows they span -*/ -/* Single row items, might be simpler to just apply a class */ -.resource-card-3x6 > .card-bg, .resource-card-6x6 > .card-bg, .resource-card-9x6 > .card-bg, .resource-card-12x6 > .card-bg, .resource-card-15x6 > .card-bg, .resource-card-18x6 > .card-bg { - height: 192px; -} -.resource-card-3x6 > .card-info, .resource-card-6x6 > .card-info, .resource-card-9x6 > .card-info, .resource-card-12x6 > .card-info, .resource-card-15x6 > .card-info, .resource-card-18x6 > .card-info { - padding: 4px 12px 6px 12px; - top: 192px; -} -.resource-card-3x6 > .card-info .section, .resource-card-6x6 > .card-info .section, .resource-card-9x6 > .card-info .section, .resource-card-12x6 > .card-info .section, .resource-card-15x6 > .card-info .section, .resource-card-18x6 > .card-info .section { - font-size: 12px; - margin-bottom: 1px; -} -.resource-card-3x6 > .card-info .title, .resource-card-6x6 > .card-info .title, .resource-card-9x6 > .card-info .title, .resource-card-12x6 > .card-info .title, .resource-card-15x6 > .card-info .title, .resource-card-18x6 > .card-info .title { - font-size: 16px; - margin-bottom: -2px; -} -.resource-card-3x6 > .card-info .description, .resource-card-6x6 > .card-info .description, .resource-card-9x6 > .card-info .description, .resource-card-12x6 > .card-info .description, .resource-card-15x6 > .card-info .description, .resource-card-18x6 > .card-info .description { - font-size: 13px; - line-height: 15px; -} -.resource-card-3x6 > .card-info .description .text, .resource-card-6x6 > .card-info .description .text, .resource-card-9x6 > .card-info .description .text, .resource-card-12x6 > .card-info .description .text, .resource-card-15x6 > .card-info .description .text, .resource-card-18x6 > .card-info .description .text { - height: 30px; -} - -/* Double row items */ -.resource-card-3x12 > .card-bg, .resource-card-6x12 > .card-bg, .resource-card-9x12 > .card-bg, .resource-card-12x12 > .card-bg, .resource-card-15x12 > .card-bg, .resource-card-18x12 > .card-bg { - height: 320px; -} -.resource-card-3x12 > .card-info, .resource-card-6x12 > .card-info, .resource-card-9x12 > .card-info, .resource-card-12x12 > .card-info, .resource-card-15x12 > .card-info, .resource-card-18x12 > .card-info { - padding: 4px 12px 6px 12px; - top: 320px; -} -.resource-card-3x12 > .card-info .section, .resource-card-6x12 > .card-info .section, .resource-card-9x12 > .card-info .section, .resource-card-12x12 > .card-info .section, .resource-card-15x12 > .card-info .section, .resource-card-18x12 > .card-info .section { - font-size: 12px; - margin-bottom: 1px; -} -.resource-card-3x12 > .card-info .title, .resource-card-6x12 > .card-info .title, .resource-card-9x12 > .card-info .title, .resource-card-12x12 > .card-info .title, .resource-card-15x12 > .card-info .title, .resource-card-18x12 > .card-info .title { - font-size: 16px; - margin-bottom: -2px; - white-space: normal; -} -.resource-card-3x12 > .card-info .description, .resource-card-6x12 > .card-info .description, .resource-card-9x12 > .card-info .description, .resource-card-12x12 > .card-info .description, .resource-card-15x12 > .card-info .description, .resource-card-18x12 > .card-info .description { - font-size: 13px; - line-height: 15px; -} - -/* 1/3 row items */ -.resource-card-3x2 > .card-bg, .resource-card-6x2 > .card-bg, .resource-card-9x2 > .card-bg, .resource-card-12x2 > .card-bg, .resource-card-15x2 > .card-bg, .resource-card-18x2 > .card-bg { - left: 0; - top: 0; - width: 90px; - height: 100%; - position: absolute; - display: block; -} -.resource-card-3x2 > .card-info, .resource-card-6x2 > .card-info, .resource-card-9x2 > .card-info, .resource-card-12x2 > .card-info, .resource-card-15x2 > .card-info, .resource-card-18x2 > .card-info { - left: 90px; - padding: 4px 12px 4px 12px; - height: 80px; - overflow: hidden; -} -.resource-card-3x2 > .card-info .section, .resource-card-6x2 > .card-info .section, .resource-card-6x3 > .card-info .section, .resource-card-9x2 > .card-info .section, .resource-card-12x2 > .card-info .section, .resource-card-15x2 > .card-info .section, .resource-card-18x2 > .card-info .section { - font-size: 12px; - margin-bottom: 1px; - /* display: none; */ -} -.resource-card-3x2 > .card-info .title, .resource-card-6x2 > .card-info .title, .resource-card-9x2 > .card-info .title, .resource-card-12x2 > .card-info .title, .resource-card-15x2 > .card-info .title, .resource-card-18x2 > .card-info .title { - font-size: 16px; - margin-bottom: -2px; - white-space: normal; - overflow: visible; - text-overflow: ellipsis; -} -.resource-card-3x2 > .card-info .title:after, .resource-card-6x2 > .card-info .title:after, .resource-card-9x2 > .card-info .title:after, .resource-card-12x2 > .card-info .title:after, .resource-card-15x2 > .card-info .title:after, .resource-card-18x2 > .card-info .title:after { - /* content: url(../images/link-out.png); */ - display: block; -} -.resource-card-3x2 > .card-info .description, .resource-card-6x2 > .card-info .description, .resource-card-9x2 > .card-info .description, .resource-card-12x2 > .card-info .description, .resource-card-15x2 > .card-info .description, .resource-card-18x2 > .card-info .description { - display: none; -} - - -/* Override to show the description instead of the content section */ -.no-section .resource-card-3x2 > .card-info .section, -.no-section .resource-card-6x2 > .card-info .section { - display: none; -} -.no-section .resource-card-3x2 > .card-info .description, -.no-section .resource-card-6x2 > .card-info .description { - display: block; -} - -/* 1/2 row items */ -.resource-card-3x3 > .card-bg, .resource-card-6x3 > .card-bg, .resource-card-9x3 > .card-bg, .resource-card-12x3 > .card-bg, .resource-card-15x3 > .card-bg, .resource-card-18x3 > .card-bg { - left: 0; - top: 0; - width: 90px; - height: 100%; - position: absolute; - display: block; -} -.resource-card-3x3 > .card-info, .resource-card-6x3 > .card-info, .resource-card-9x3 > .card-info, .resource-card-12x3 > .card-info, .resource-card-15x3 > .card-info, .resource-card-18x3 > .card-info { - left: 90px; - padding: 4px 12px 0px 12px; -} -.resource-card-3x3 > .card-info .section, .resource-card-6x3 > .card-info .section, .resource-card-9x3 > .card-info .section, .resource-card-12x3 > .card-info .section, .resource-card-15x3 > .card-info .section, .resource-card-18x3 > .card-info .section { - font-size: 12px; - margin-bottom: 1px; - display: none; -} -.resource-card-3x3 > .card-info .title, .resource-card-6x3 > .card-info .title, .resource-card-9x3 > .card-info .title, .resource-card-12x3 > .card-info .title, .resource-card-15x3 > .card-info .title, .resource-card-18x3 > .card-info .title { - font-size: 16px; - margin-bottom: -2px; - white-space: normal; - overflow: visible; -} -.resource-card-3x3 > .card-info .description .text, .resource-card-6x3 > .card-info .description .text, .resource-card-9x3 > .card-info .description .text, .resource-card-12x3 > .card-info .description .text, .resource-card-15x3 > .card-info .description .text, .resource-card-18x3 > .card-info .description .text { - font-size: 12px; - line-height: 15px; - padding-right: 0px !important; - height: 80px; -} -.resource-card-3x3 > .card-info .description .util, .resource-card-6x3 > .card-info .description .util, .resource-card-9x3 > .card-info .description .util, .resource-card-12x3 > .card-info .description .util, .resource-card-15x3 > .card-info .description .util, .resource-card-18x3 > .card-info .description .util { - display: none; -} -/* placement of plusone */ -.resource-card-6x12 > .card-info .description .util, .resource-card-9x12 > .card-info .description .util, .resource-card-12x12 > .card-info .description .util, .resource-card-15x12 > .card-info .description .util { - bottom:2px; -} -.resource-card-18x12 > .card-info .description .util { - bottom:2px; -} -/* Overrides for col-16 6x6 cards linking to local content on landing pages. - Suppresses "section" and puts the title above a hairline rule. */ -.landing .card-info .section, .resource-flow-layout.col-16.landing .resource-card-9x6 .card-info .section { - display:none; -} -.landing .card-info .title { - color: #898989; - font-size: 17px; - line-height: 24px; - margin-bottom: 6px; - border-bottom: 1px solid #959595; - padding-bottom: 0px; -} -.landing .card-info .description { - font-size: 13px; - line-height: 15px; -} -.landing .card-info .description .text { -height:30px; -} -.landing .resource-card-6x6 > .card-info .description .util, .landing .resource-card-9x6 > .card-info .description .util { - bottom:2px; -} -/* - Generate a resource stack layout for a 3 column widget spanning 16 grid cols -*/ -.resource-stack-layout.col-16 { - margin: 0 -14px 0 0; - width: 954px; -} -.resource-stack-layout.col-16 .resource-card-stack { - margin: 0 14px 0 0; - width: 304px; -} - -/* Example of card menu tinting */ -.resource-widget[data-section=distribute\/tools] .section-card-menu -.card-bg:after { - background: rgba(126, 55, 148, 0.4) !important; -} -.resource-widget[data-section=distribute\/tools] .section-card-menu -.card-section-icon .icon { - background-color: #7e3794 !important; -} -.resource-widget[data-section=distribute\/tools] .section-card-menu -.card-info ul li { - border-top-color: #7e3794 !important; -} - -/* tinting for stacks */ - -div.jd-descr > .resource-widget[data-section=distribute\/tools] -.section-card-menu .card-info ul li { - border-top-color: #7e3794 !important; -} - - - -/** - * UTILITIES - */ - - -.border-box { - box-sizing: border-box; -} - -.vertical-center-outer { - display: table; - height: 100%; - width: 100%; -} - -.vertical-center-inner { - display: table-cell; - vertical-align: middle; -} - -/** - * TYPE STYLES - */ - -.landing-h1 { - font-weight: 100; - font-size: 60px; - line-height: 78px; - text-align: center; - letter-spacing: -1px; -} - -.landing-pre-h1 { - font-weight: 400; - font-size: 28px; - color: #93B73F; - line-height: 36px; - text-align: center; - letter-spacing: -1px; - text-transform: uppercase; - -} - -.landing-h1.hero { - text-align: left; -} - -.landing-h2 { - font-weight: 300; - font-size: 42px; - line-height: 64px; - text-align: center; -} - -.landing-subhead { - color: #999999; - font-size: 20px; - line-height: 28px; - font-weight:300; - text-align: center; -} -.landing-subhead.hero { - text-align: left; - color: white; -} - -.landing-hero-description { - text-align: left; - margin: 1em 0; -} - -.landing-hero-description p { - font-weight: 300; - margin: 0; - font-size: 18px; - line-height: 24px; -} - -.landing-body .landing-small { - font-size: 14px; - line-height: 19px; -} - -.landing-body.landing-align-center { - text-align: center; -} - -.landing-align-left { - text-align: left; -} - -/** - * LAYOUT - */ - -#body-content, -.fullpage, -#jd-content, -.jd-descr, -.landing-body-content { - height: 100%; -} - -.landing-section { - padding: 80px 10px 80px; - width: 100%; - margin-left: -10px; - text-rendering: optimizeLegibility; -} - -#extending-android-to-wearables { - padding-top: 30px; -} - -.landing-short-section { - padding: 40px 10px 28px; -} - -.landing-gray-background { - background-color: #e9e9e9; -} - -.landing-white-background { - background-color: white; -} - -.landing-red-background { - color: white; - background-color: hsl(8, 70%, 54%); -} - -.landing-subhead-red { - color: hsl(8, 71%, 84%); - text-align: left; -} - -.landing-subhead-red p { - margin-top: 20px; -} - -.landing-hero-container { - height: 100%; -} - - -.preview-hero { - height: calc(100% - 110px); - min-height: 504px; - margin-top: -5px; - padding-top: 0; - padding-bottom: 0; - background-image: url(../../preview/images/hero.jpg); - background-size: cover; - background-position: right center; - color: white; - position: relative; - overflow: hidden; -} - -.wear-hero { - height: calc(100% - 110px); - min-height: 504px; - margin-top: -5px; - padding-top: 0; - padding-bottom: 0; - background-image: url(../../wear/images/hero.jpg); - background-size: cover; - background-position: top center; - color: white; - position: relative; - overflow: hidden; -} - -.tv-hero { - height: calc(100% - 110px); - min-height: 504px; - margin-top: -5px; - padding-top: 0; - padding-bottom: 0; - background-image: url(../../tv/images/hero.jpg); - background-size: cover; - background-position: right center; - color: white; - position: relative; - overflow: hidden; -} - -.auto-hero { - height: calc(100% - 110px); - min-height: 504px; - margin-top: -5px; - padding-top: 0; - padding-bottom: 0; - background-image: url(../../auto/images/hero.jpg); - background-size: cover; - background-position: right center; - color: white; - position: relative; - overflow: hidden; -} - -.landing-hero-scrim { - background: black; - opacity: .2; - position: absolute; - width: 100%; - height: 100%; - margin-left: -10px; -} - -.landing-hero-wrap { - margin: 0 auto; - width: 940px; - clear: both; - height: 100%; - position: relative; -} - -.landing-section-header { - margin-bottom: 40px; -} - -.landing-hero-wrap .landing-section-header { - margin-bottom: 16px; -} - -.landing-body { - font-size: 18px; - line-height: 24px; -} - -.landing-button { - white-space: nowrap; - display: inline-block; - padding: 16px 32px; - font-size: 18px; - font-weight: 500; - line-height: 24px; - cursor: pointer; - color: white; - -webkit-user-select: none; - -moz-user-select: none; - -o-user-select: none; - user-select: none; - -webkit-transition: .2s background-color ease-in-out; - -moz-transition: .2s background-color ease-in-out; - -o-transition: .2s background-color ease-in-out; - transition: .2s background-color ease-in-out; -} - -.landing-primary { - background-color: hsl(8, 70%, 44%); - color: #f8f8f8; -} - -.landing-button.landing-primary:hover { - background-color: hsl(8, 70%, 36%); -} - -.landing-button.landing-primary:active { - background-color: hsl(8, 70%, 30%); -} - -.landing-button.landing-secondary { - background-color: #2faddb; -} - -.landing-button.landing-secondary:hover { - background-color: #09c; -} - -.landing-button.landing-secondary:active { - background-color: #3990ab; -} - -a.landing-button, -a.landing-button:hover, -a.landing-button:visited { - color: white !important; -} - -.landing-video-link { - white-space: nowrap; - display: inline-block; - padding: 16px 32px 16px 82px; - font-size: 18px; - font-weight: 400; - line-height: 24px; - cursor: pointer; - color: hsla(0, 0%, 100%, .8); - -webkit-user-select: none; - -moz-user-select: none; - -o-user-select: none; - user-select: none; - -webkit-transition: .2s color ease-in-out; - -moz-transition: .2s color ease-in-out; - -o-transition: .2s color ease-in-out; - transition: .2s color ease-in-out; -} - -.landing-video-link:before { - height: 64px; - width: 64px; - display: inline-block; - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAFuklEQVR42u2dXWgcVRSAV9LWtBBTTZVWUhNqEQtq1QeroDRKFRFsROqTYPuo+JCiIoJKFC0USqlUfCiowRcfrBgVUUElefAPkW5T8aeaGn9aRbFsjP0x2cx8PuRMvFxmdjeb2Z17Z8+B85DsZPbO+eaec3/OPSkABdXsVI2gABSAqgJQAKoKQAGoKgAFoKoAFICqAlAAqgpAAai6DqDRAiwDeoFtwB7gPaAInABKwKToCWAMeB/YDdwJrAWWNLh9+QMAXABsBQ4A3wFTwAxQBmaBAAhjNJDPy3L938BXwAvArUCHAkh+kCXAVcA+YBw4bRg7MngtkgTlDPA98CywHmhTAP8/xCbgVeAvMZZpwDQllN7xB/AysKGlAQAXAvuBkzW85UVgCBgENlfQQbmuWAXELPAnsAvoaikAQBtwh/j3coLhS2LIfqCzzu/plL8fkvvFgZiR4L2lHrfkHQBgpQTFUwmGnwC212v0KjC2y/3jQPwDPA+05xYAcBHwubx1YZzhC02QBBBRbxgBzssdAOBy4JgRZE0ZTPuNr7FHDCbEhqNAd24AAN0yUbID7QSwsZChABut3hANXY8Bq70HIMb/Ocb4w81+66v0hmGrN0QQ1ngLQJYRvpWHMWWo4KDIaMnuCcVKgdlZAGL8t2J8vpPGrwChDLyWBMFlAA8D0z4ZvwKEs8D93gCQEc9Jy/jFgkdizaRDGUSs8wXAu1bQLQE9ngHosWbPAXDQeQAypT9rBd3+gociyxi2K9riLABZUj5iuZ6RgsciM2OzFxw2A7JrAO6VwGtKTwpG+Anoy9AVmb3gDHCPcwCAFcChRox6jPu9CazMeFQUAKNRL3AJwE2yopjq228BQPZ/d2bcCyaBTa4BeNGa8Q6naIA4GQWubiKEYWvBbp8zAGQt5VfL/fQ3GEAkTzXDLVkjokA2k5a7AuA2GaLNj/tTfvhq0pQgbcwLQtlQusYVALtlzSR191MjADNI9zbJDZWBR10BMGr5/4GMADQ0SAMDlht62xUAxy0AmzMEEMnhtIO0ZF2YAH5wITd0hQw/5wE04M1bjDyXZpC2hqMlYGnWAHqBf40APOEYgChI35VSWyasWfGqrAH0WVkOIw4CSC1IG2tDoSy7XJE1gPs8ArDoIG0BmJGk30wBDHgGYFFBOgbAtqwB7GxxAHerC8rOBU0Dt2gQzjYIb8gawDor+6HVhqFdrkzEwhabiAVOTMSkUb+06FLEUVfWgj5q0cW4g64AeNo66ZLlcnTDNmesBN4y8KArAG6QU42ttCEzBVzpCoAO4EfLDeV5SzIEvgHaXdqUP2BlQud1Ux55zj2uZUX02cPRnKalRLmu17qYmPWF5YbymJgVAh8Ay5wCII3ZEZOYm6fURGT2u9X43Mnk3CDHybmfmRVYXExPv9nKEcpLejqSC3SjdY2TBzTesHqB7wc0onTEV2KucxLApXKkJy9HlAI5anuJFwCkYQ/EuCJfD+mdBnYkXOssgHY53un7MdVZ4CVgqVcADAhjMafkfTioHc14P04yvvMApIEXy5F/+7S8y6UKolPyR4BVVf7Wi2IdawwIPhTrmAW+rmZ8bwBIQ7vloXwoVzNWS6UUrwAYy9YfOlqwKZDkgneA5Qu4l3cly84F9sqGhislywLmaozuYoGFXr0DII1ukxP1hxJ6QzR7HqLxRfumZaRzXZ3f4XXZyi7gCeB3kqsnzs+kSb9s5XHgMeD8RTxDLgq3rmeuYuFvNYCoR8wqujNi+L3UWBcu9wAMt3QZ8LiMlk5RuU50teq6kcEDgTolveIRYHUQBOek1O5cFu/ukLz7/ZJgNSm+OirebWpgaPS7slxfAr4EngGuX8jopqUBxGzyrAVuB54EXgc+lV4yLhO8cfn5E+ZqUD8kBu9sQvv0Hzj4rmoEBaAAVBWAAlBVAApAVQEoAFUFoABUFYACUFUACkC1CfofXVRJocowZVYAAAAASUVORK5CYII=); - background-size: contain; - position: absolute; - content: ""; - opacity: .7; - margin-top: -19px; - margin-left: -64px; - -webkit-transition: .2s opacity ease-in-out; - -moz-transition: .2s opacity ease-in-out; - -o-transition: .2s opacity ease-in-out; - transition: .2s opacity ease-in-out; -} - -.landing-video-link:hover { - color: hsla(0, 0%, 100%, 1); -} - -.landing-video-link:hover:before { - opacity: 1; -} - -.landing-social-image { - float: left; - margin-right: 14px; - height: 64px; - width: 64px; -} - -.landing-social-copy { - padding-left: 78px; -} - -.landing-scroll-down-affordance { - position: absolute; - bottom: 0; - width: 100%; - text-align: center; - z-index: 10; -} - -.landing-down-arrow { - padding: 24px; - display: inline-block; - opacity: .5; - -webkit-transition: .2s opacity ease-in-out; - -moz-transition: .2s opacity ease-in-out; - -o-transition: .2s opacity ease-in-out; - transition: .2s opacity ease-in-out; - - -webkit-animation-name: pulse-opacity; - -webkit-animation-duration: 4s; -} - -.landing-down-arrow:hover { - opacity: 1; -} - -.landing-down-arrow img { - height: 28px; - width: 28px; - margin: 0 auto; - display: block; -} - -.landing-divider { - display: inline-block; - height: 2px; - background-color: white; - position: relative; - margin: 10px 0; -} - -/* 3 CLOLUMN LAYOUT */ - -.landing-breakout { - margin-top: 40px; - margin-bottom: 40px; -} - -.landing-breakout img { - margin-bottom: 20px; -} - -.landing-partners img { - margin-bottom: 20px; -} - -.landing-breakout p { - padding: 0 23px; -} - -.landing-breakout.landing-partners img { - margin-bottom: 20px; -} - -.col-3-wide { - display: inline; - float: left; - margin-left: 10px; - margin-right: 10px; -} - -.col-3-wide { - width: 302px; -} - -/** - * ANIMATION - */ - -@-webkit-keyframes pulse-opacity { - 0% { - opacity: .5; - } - 20% { - opacity: .5; - } - 40% { - opacity: 1; - } - 60% { - opacity: .5; - } - 80% { - opacity: 1; - } - 100% { - opacity: .5; - } -} - - - -/** - * VIDEO - */ - -#video-container { - display:none; - position:fixed; - top:0; - left:0; - width:100%; - height:100%; - background-color:rgba(0,0,0,0.8); - z-index:9999; -} - -#video-frame { - width:940px; - height:100%; - margin:72px auto; - display:none; - position:relative; -} - -.video-close { - cursor: pointer; - position: absolute; - right: -49px; - top: -49px; - pointer-events: all; -} - -#icon-video-close { - background-image: url("../images/close-white.png"); - background-image: -webkit-image-set(url(../images/close-white.png) 1x, url(../images/close-white_2x.png) 2x); - background-repeat: no-repeat; - background-position: 0 0; - background-size: 36px 36px; - height: 36px; - width: 36px; - display:block; -} - -#icon-video-close:hover { - background-image: url("../images/close-grey.png"); - background-image: -webkit-image-set(url(../images/close-grey.png) 1x, url(../images/close-grey_2x.png) 2x); -} - -/* Preload the hover images */ -a.video-shadowbox-button.white:after { - display:none; - content:url("../images/close-grey.png") url("../images/close-grey_2x.png"); -} - -a.video-shadowbox-button.white { - background-image: url("../images/play-circle-white.png"); - background-image: -webkit-image-set(url(../images/play-circle-white.png) 1x, url(../images/play-circle-white_2x.png) 2x); - background-size: 36px 36px; - background-repeat: no-repeat; - background-position: right; - padding: 16px 42px 16px 8px; - font-size: 18px; - font-weight: 500; - line-height: 24px; - color: #fff; - text-decoration:none; -} - -a.video-shadowbox-button.white:hover { - color:#bababa !important; - background-image: url("../images/play-circle-grey.png"); - background-image: -webkit-image-set(url(../images/play-circle-grey.png) 1x, url(../images/play-circle-grey_2x.png) 2x); -} - -/* Preload the hover images */ -a.video-shadowbox-button.white:after { - display:none; - content:url("../images/play-circle-grey.png") url("../images/play-circle-grey_2x.png"); -} - -/****************** -Styles for d.a.c/index: -*******************/ - - - -/* Generic full screen carousel styling to be used across pages. */ -.fullscreen-carousel { - margin: 0 -10px; - width: 100%; - overflow: hidden; - position: relative; -} - -.fullscreen-carousel-content { - width: 100%; - height: 100%; - position: relative; - display: table; /* For vertical centering */ -} - -.fullscreen-carousel .vcenter { - display: table-cell; - vertical-align: middle; - position: relative; -} - -.fullscreen-carousel .vcenter > div { - margin: 10px auto; -} - -/* Styles for the full-bleed hero image type. */ -.fullscreen-carousel .hero, .fullscreen-carousel .hero h1 { - color: #fff; -} - -.fullscreen-carousel .hero h1 { - font-weight: 300; - font-size: 60px; - line-height: 68px; - letter-spacing: -1px; - margin-top: 0; -} - -.fullscreen-carousel .hero p { - font-weight: 300; - font-size: 18px; - line-height: 24px; - -webkit-font-smoothing: antialiased; -} - -.fullscreen-carousel .hero .hero-bg { - background-size: cover; - width: 100%; - height: 100%; - position: absolute; - left: 0px; - top: 0px; -} - - -/* Full screen carousel styling for the resource flow layout type of content */ -.fullscreen-carousel .resource-flow-layout:after { - height: 0; /* Dont know why this is set at 10 in default.css */ -} - -.fullscreen-carousel .resource-flow-layout { - margin-bottom: 20px; -} - - - -/* Generic Tab carousel styling to be used across multiple pages. */ - -.tab-carousel .tab-nav { - list-style: none; - position: relative; - text-align: center; -} - -.tab-carousel .tab-nav li { - display: inline-block; - font-size: 22px; - font-weight: 400; - line-height: 50px; - list-style: none; - margin: 0; - padding: 0 25px; - position: relative; -} - -.tab-carousel .tab-nav li a, -.tab-carousel .tab-nav li a:hover { - color: #333 !important; - padding: 10px 10px 13px 10px; - position: relative; - z-index: 1000; -} - -.tab-carousel .tab-nav li:after { - background: #ddd; - bottom: 0; - content: ''; - height: 4px; - left: 0; - position: absolute; - width: 100%; - z-index: 0; -} - -.tab-carousel .tab-nav .highlight { - position: absolute; - height: 4px; - width: 100px; - bottom: 0; - background: #33b5e5; -} - -.tab-carousel .tab-carousel-content { - position: relative; - overflow: hidden; - white-space: nowrap; -} - -.tab-carousel .tab-carousel-content [data-tab] { - display: inline-block; - white-space: normal; -} - - - -/* - Resource styling for the tab carousel. The tab carousel contains either - a 3 column layout of resources or a single full-width resource. The - latter has the 18x12 class applied to it and can be styled differently - that way. -*/ - -.tab-carousel .resource .image { - width: 100%; - height: 250px; - background-repeat: no-repeat; - background-size: contain; - background-position: 50% 50%; -} - -.tab-carousel .resource .info .title { - font-size: 18px; - line-height: 24px; -} - -.tab-carousel .resource .info .summary, -.tab-carousel .resource .info .cta { - line-height: 24px; - font-size: 16px; -} - -.tab-carousel .resource-card-18x12 { - position: relative; - padding-left: 450px; - box-sizing: border-box; - display: table-cell; - vertical-align: middle; -} - -.tab-carousel .resource-card-18x12 .image { - position: absolute; - width: 420px; - height: 100%; - left: 0; - top: 0; -} - -.tab-carousel .resource-card-18x12 .info { - display: inline-block; -} - -.tab-carousel .resource-card-18x12 .info .title { - margin-bottom: 26px; -} - - - - - -/* - Styles for the entity link used in the actions bar and in the cta of - the resources that appear in the tab carousel. -*/ -.actions-bar a:after, -.resource .cta:after { - content: '›'; - font-weight: 400; - font-size: 22px; - left: 5px; - line-height: 1; - position: relative; - top: 1px; - transition: left 190ms ease-out; -} - -.actions-bar a:hover:after, -.resource .cta:hover:after { - left: 10px; -} - - - - -/* - Styles for the actions bar. -*/ -.actions-bar { - background: #9acd00; - margin: 0 -10px; - text-align: center; -} - -.actions-bar .actions { - padding: 30px 0 30px; - text-align: justify; - font-size: 0.1px; - line-height: 0.1px; - margin: 0 10px 0 0; -} - -.actions-bar .actions:after { - content: ''; - width: 100%; - display: inline-block; -} - -.actions-bar .actions > div { - display: inline-block; -} - -.actions-bar a { - font-size: 21px; - line-height: 27px; - color: #fff; - font-weight: 300; - -webkit-font-smoothing: antialiased; -} - -.actions-bar a:after { - top: 0px; - font-size: 22px; -} - -.actions-bar a:hover { - color: #fff !important; -} - - - - - -/* - Specific styles for new home page layout of the carousels. -*/ - -/* Big blue button */ -a.home-new-cta-btn, -.home-new-carousel-1 .resource-card-18x6 .cta { - white-space: nowrap; - display: inline-block; - padding: 14px 32px; - font-size: 18px; - font-weight: 500; - line-height: 24px; - cursor: pointer; - background: #33b5e6; - border-radius: 4px; - margin-top: 20px; - color: #fff; - transition: 0.2s background-color ease-in-out; -} - -.home-new-carousel-1 .resource-card-18x6 .cta:after { - display: none; /* Hide the entity for this button */ -} - -a.home-new-cta-btn:hover, -.home-new-carousel-1 .resource-card-18x6 .cta:hover { - color: #fff !important; - background: #2d9fca; -} - -.home-new-carousel-1 .resource-card-18x6 .cta { - position: absolute; - bottom: 20px; - left: 16px; -} - -/* Fullscreen carousel. */ -.home-new-carousel-1 { - max-height: 700px; /* Set max height so doesn't get too long */ -} - -.home-new-carousel-1 .fullscreen-carousel-content { - min-height: 450px; /* Set min height for all content */ -} - -.home-new-carousel-1 .hero { - background: #000; -} - -.home-new-carousel-1 .hero-bg { - background-image: url(/home-new/images/hero.jpg); - background-position: right center; - opacity: 0.85; -} - -/* - Styling for special top card of full screen layout resource layout. - We need to specifically style the 18x6 card to adjust its size and layout, - since it's not a standard card, not sure if this is unique to the home page - layout or should be namespaced within the fullscreen-carousel container. -*/ -.home-new-carousel-1 .resource-flow-layout.col-16 .resource-card-18x6 { - height: 320px; - background-color:#F9F9F9; - border-radius: 0px; - box-shadow: 0px 0px 0px rgba(0, 0, 0, 0); - -} - -.home-new-carousel-1 .resource-card-18x6 .card-bg { - width: 636px; - height: 100%; -} - -.home-new-carousel-1 .resource-card-18x6 .card-info { - right: 0px; - left: 636px; - height: 100%; - top: 0px; - padding: 15px 22px; -} - -.home-new-carousel-1 .resource-card-18x6 .card-info .util { - display: none; -} - -.home-new-carousel-1 .resource-card-18x6 .card-info .title { - font-size: 20px; - font-weight: 500; - margin-top: 15px; - margin-bottom: 15px; -} - -.home-new-carousel-1 .resource-card-18x6 .card-info .text { - font-size: 15px; - line-height: 21px; -} - - -/* Tabbed carousel. */ -.home-new-carousel-2 { - margin: 35px auto 100px auto; -} - -.home-new-carousel-2 h1 { - font-size: 47px; - font-weight: 100; - line-height: 54px; - text-align: center; -} - -.annotation-message { - display: block; - font-style: italic; - color: #F80; -} - - - -/* Helpouts widget */ -.resource-card-6x2.helpouts-card { - width: 255px; - height: 40px; - position:absolute; - z-index:999; - top:-8px; - right:1px; -} - -.resource-card-6x2.helpouts-card > .card-info { - left:35px; - height:35px; - padding:4px 8px 4px 0; -} - -.resource-card-6x2.helpouts-card > .card-info .helpouts-description { - display:block; - overflow:visible; - font-size:12px; - line-height:12px; - text-align:right; - color:#666; -} - -.helpouts-description .link-color { - text-transform: uppercase; -} - -.resource-card-6x2 > .card-bg.helpouts-card-bg { - width:35px; - height:35px; - margin:2px 0 0 0; - background-image: url(../images/styles/helpouts-logo-35_2x.png); - background-image: -webkit-image-set(url(../images/styles/helpouts-logo-35.png) 1x, url(../images/styles/helpouts-logo-35_2x.png) 2x); -} - -.resource-card-6x2 > .card-bg.helpouts-card-bg:after { - display:none; -} diff --git a/tools/droiddoc/templates-ndk/assets/css/fullscreen.css b/tools/droiddoc/templates-ndk/assets/css/fullscreen.css deleted file mode 100644 index 7912e3490a..0000000000 --- a/tools/droiddoc/templates-ndk/assets/css/fullscreen.css +++ /dev/null @@ -1,208 +0,0 @@ - -/* ============================================================================= - Columns - ========================================================================== */ -/* Applied to body to debug layout alignments -.grid { - width:100%; - height:100%; - background:url(../images/grid.png) center repeat-y; - top:0px; - margin:auto; - position:absolute; -} -*/ - -@media screen, projection, print { -.full { - padding: 2.5em 0; - border-top: solid 1px #ddd; - border-bottom: solid 1px #ddd; - background: #f7f7f7; -} -.wrap { - margin: 0 auto; - width: 100%; - min-width:600px; - clear: both; -} -.cols { - height: 1%; - margin: 0 -1.533742331288343558282%; - width: 103.06748466257669%} -*+html .cols { - margin-bottom: 20px; -} -.cols:after { - clear: both; - content: ' '; - display: block; - height: 0; - visibility: hidden; -} -.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, -.col-13, .col-14, .col-15, .col-16 { - float: left; - margin: 0 1.063829787234% 20px 1.063829787234%; -} -* html .col-1, * html .col-2, * html .col-3, * html .col-4, * html .col-5, * html .col-6, * html -.col-7, * html .col-8, * html .col-9, * html .col-10, * html .col-11, * html .col-12, * html -.col-13, * html .col-14, * html .col-15, * html .col-16 { - margin: 0; - margin: 0 1.063829787234% 20px 1.063829787234%; -} -[dir='rtl'] .col-1, [dir='rtl'] .col-2, [dir='rtl'] .col-3, [dir='rtl'] .col-4, [dir='rtl'] .col-5, -[dir='rtl'] .col-6, [dir='rtl'] .col-7, [dir='rtl'] .col-8, [dir='rtl'] .col-9, [dir='rtl'] .col-10, -[dir='rtl'] .col-11, [dir='rtl'] .col-12 { - float: right; -} -.col-1 { - width: 4.16666666666667%; -} -.col-2 { - width: 10.4166666666667%; -} -.col-3 { - width: 16.6666666666667%; -} -.col-4 { - width: 22.9166666666667%; -} -.col-5 { - width: 29.1666666666667%; -} -.col-6 { - width: 35.4166666666667%; -} -.col-7 { - width: 41.6666666666667%; -} -.col-8 { - width: 47.9166666666667%; -} -.col-9 { - width: 55.3333333333333%; -} -.col-10 { - width: 60.4166666666667%; -} -.col-11 { - width: 66.6666666666667%; -} -.col-12 { - width: 72.9166666666667%; -} -.col-13 { - width: 79.1666666666667%; -} -.col-14 { - width: 85.4166666666667%; -} -.col-15 { - width: 91.6666666666667%; -} -.col-16 { - width: 97.9166666666667%; -} - - - - - - - -#header .col-1, -#nav-x .col-1 { width: 40px } -#header .col-2, -#nav-x .col-2 { width: 100px } -#header .col-3, -#nav-x .col-3 { width: 160px } -#header .col-4, -#nav-x .col-4 { width: 220px } -#header .col-5, -#nav-x .col-5 { width: 280px } -#header .col-6, -#nav-x .col-6 { width: 340px } -#header .col-7, -#nav-x .col-7 { width: 400px } -#header .col-8, -#nav-x .col-8 { width: 460px } -#header .col-9, -#nav-x .col-9 { width: 520px } -#header .col-10, -#nav-x .col-10 { width: 580px } -#header .col-11, -#nav-x .col-11 { width: 640px } -#header .col-12, -#nav-x .col-12 { width: 700px } -#header .col-13, -#nav-x .col-13 { width: 760px } -#header .col-14, -#nav-x .col-14 { width: 820px } -#header .col-15, -#nav-x .col-15 { width: 880px } -#header .col-16, -#nav-x .col-16 { width: 940px } - - - -body { - padding:0 20px; -} -#header, -#searchResults, -#nav-x { - margin:0; -} -#body-content { - margin:0; -} -#body-content > .col-12 { - width:77.9804965%; - margin:0 0 0 0.97%; /* this percentage chosen to make IE9 happy */ -} -#side-nav { - width: 19.9804965%; - margin:0 1.063829787234% 0 0; -} - -#header .wrap { - max-width: 100%; -} - -#header-wrapper #nav-x div.wrap, -#searchResults.wrap { - max-width:100%; -} - -.nav-x { - margin:-2px 0 0 0; -} - -#devdoc-nav.fixed, -#devdoc-nav.fixed a.totop { - left:20px; /* !important ... for IE i think */ -} - -#sticky-header { - padding: 0 20px; -} - -#sticky-header > div { - width: 100%; -} - -.sticky-menu { - width:100%; - left:-20px; -} - -.col-right { - margin-right:0px; -} - -@media screen and (max-width:772px) { -.col-5, .col-6, .col-7 { - clear: both; - width: 97.0238096%} -}
\ No newline at end of file diff --git a/tools/droiddoc/templates-ndk/assets/design/default.js b/tools/droiddoc/templates-ndk/assets/design/default.js deleted file mode 100644 index 3ba8486860..0000000000 --- a/tools/droiddoc/templates-ndk/assets/design/default.js +++ /dev/null @@ -1,188 +0,0 @@ -$(document).ready(function() { - // prep nav expandos - var pagePath = document.location.pathname; - if (pagePath.indexOf(SITE_ROOT) == 0) { - pagePath = pagePath.substr(SITE_ROOT.length); - if (pagePath == '' || pagePath.charAt(pagePath.length - 1) == '/') { - pagePath += 'index.html'; - } - } - - if (SITE_ROOT.match(/\.\.\//) || SITE_ROOT == '') { - // If running locally, SITE_ROOT will be a relative path, so account for that by - // finding the relative URL to this page. This will allow us to find links on the page - // leading back to this page. - var pathParts = pagePath.split('/'); - var relativePagePathParts = []; - var upDirs = (SITE_ROOT.match(/(\.\.\/)+/) || [''])[0].length / 3; - for (var i = 0; i < upDirs; i++) { - relativePagePathParts.push('..'); - } - for (var i = 0; i < upDirs; i++) { - relativePagePathParts.push(pathParts[pathParts.length - (upDirs - i) - 1]); - } - relativePagePathParts.push(pathParts[pathParts.length - 1]); - pagePath = relativePagePathParts.join('/'); - } else { - // Otherwise the page path should be an absolute URL. - pagePath = SITE_ROOT + pagePath; - } - - // select current page in sidenav and set up prev/next links if they exist - var $selNavLink = $('.nav-y').find('a[href="' + pagePath + '"]'); - if ($selNavLink.length) { - $selListItem = $selNavLink.closest('li'); - - $selListItem.addClass('selected'); - $selListItem.closest('li>ul').addClass('expanded'); - - // set up prev links - var $prevLink = []; - var $prevListItem = $selListItem.prev('li'); - if ($prevListItem.length) { - if ($prevListItem.hasClass('nav-section')) { - // jump to last topic of previous section - $prevLink = $prevListItem.find('a:last'); - } else { - // jump to previous topic in this section - $prevLink = $prevListItem.find('a:eq(0)'); - } - } else { - // jump to this section's index page (if it exists) - $prevLink = $selListItem.parents('li').find('a'); - } - - if ($prevLink.length) { - var prevHref = $prevLink.attr('href'); - if (prevHref == SITE_ROOT + 'index.html') { - // Don't show Previous when it leads to the homepage - $('.prev-page-link').hide(); - } else { - $('.prev-page-link').attr('href', prevHref).show(); - } - } else { - $('.prev-page-link').hide(); - } - - // set up next links - var $nextLink = []; - if ($selListItem.hasClass('nav-section')) { - // we're on an index page, jump to the first topic - $nextLink = $selListItem.find('ul').find('a:eq(0)') - } else { - // jump to the next topic in this section (if it exists) - $nextLink = $selListItem.next('li').find('a:eq(0)'); - if (!$nextLink.length) { - // no more topics in this section, jump to the first topic in the next section - $nextLink = $selListItem.parents('li').next('li.nav-section').find('a:eq(0)'); - } - } - if ($nextLink.length) { - $('.next-page-link').attr('href', $nextLink.attr('href')).show(); - } else { - $('.next-page-link').hide(); - } - } - - // Set up expand/collapse behavior - $('.nav-y li').has('ul').click(function() { - if ($(this).hasClass('expanded')) { - return; - } - - // hide other - var $old = $('.nav-y li.expanded'); - if ($old.length) { - var $oldUl = $old.children('ul'); - $oldUl.css('height', $oldUl.height() + 'px'); - window.setTimeout(function() { - $oldUl - .addClass('animate-height') - .css('height', ''); - }, 0); - $old.removeClass('expanded'); - } - - // show me - $(this).addClass('expanded'); - var $ul = $(this).children('ul'); - var expandedHeight = $ul.height(); - $ul - .removeClass('animate-height') - .css('height', 0); - window.setTimeout(function() { - $ul - .addClass('animate-height') - .css('height', expandedHeight + 'px'); - }, 0); - }); - - // Stop expand/collapse behavior when clicking on nav section links (since we're navigating away - // from the page) - $('.nav-y li').has('ul').find('a:eq(0)').click(function(evt) { - window.location.href = $(this).attr('href'); - return false; - }); - - // Set up play-on-hover <video> tags. - $('video.play-on-hover').bind('click', function(){ - $(this).get(0).load(); // in case the video isn't seekable - $(this).get(0).play(); - }); - - // Set up tooltips - var TOOLTIP_MARGIN = 10; - $('acronym').each(function() { - var $target = $(this); - var $tooltip = $('<div>') - .addClass('tooltip-box') - .text($target.attr('title')) - .hide() - .appendTo('body'); - $target.removeAttr('title'); - - $target.hover(function() { - // in - var targetRect = $target.offset(); - targetRect.width = $target.width(); - targetRect.height = $target.height(); - - $tooltip.css({ - left: targetRect.left, - top: targetRect.top + targetRect.height + TOOLTIP_MARGIN - }); - $tooltip.addClass('below'); - $tooltip.show(); - }, function() { - // out - $tooltip.hide(); - }); - }); - - // Set up <h2> deeplinks - $('h2').click(function() { - var id = $(this).attr('id'); - if (id) { - document.location.hash = id; - } - }); - - // Set up fixed navbar - var navBarIsFixed = false; - $(window).scroll(function() { - var scrollTop = $(window).scrollTop(); - var navBarShouldBeFixed = (scrollTop > (100 - 40)); - if (navBarIsFixed != navBarShouldBeFixed) { - if (navBarShouldBeFixed) { - $('#nav') - .addClass('fixed') - .prependTo('#page-container'); - } else { - $('#nav') - .removeClass('fixed') - .prependTo('#nav-container'); - } - navBarIsFixed = navBarShouldBeFixed; - } - }); -});
\ No newline at end of file diff --git a/tools/droiddoc/templates-ndk/assets/images/icon_more.png b/tools/droiddoc/templates-ndk/assets/images/icon_more.png Binary files differdeleted file mode 100644 index 6cd03a39a2..0000000000 --- a/tools/droiddoc/templates-ndk/assets/images/icon_more.png +++ /dev/null diff --git a/tools/droiddoc/templates-ndk/assets/images/icon_search.png b/tools/droiddoc/templates-ndk/assets/images/icon_search.png Binary files differdeleted file mode 100644 index ee90a12acb..0000000000 --- a/tools/droiddoc/templates-ndk/assets/images/icon_search.png +++ /dev/null diff --git a/tools/droiddoc/templates-ndk/assets/images/more_bottom.png b/tools/droiddoc/templates-ndk/assets/images/more_bottom.png Binary files differdeleted file mode 100644 index 632546aacf..0000000000 --- a/tools/droiddoc/templates-ndk/assets/images/more_bottom.png +++ /dev/null diff --git a/tools/droiddoc/templates-ndk/assets/images/more_mid.png b/tools/droiddoc/templates-ndk/assets/images/more_mid.png Binary files differdeleted file mode 100644 index 99bc99927a..0000000000 --- a/tools/droiddoc/templates-ndk/assets/images/more_mid.png +++ /dev/null diff --git a/tools/droiddoc/templates-ndk/assets/images/more_top.png b/tools/droiddoc/templates-ndk/assets/images/more_top.png Binary files differdeleted file mode 100644 index 8ead1d3939..0000000000 --- a/tools/droiddoc/templates-ndk/assets/images/more_top.png +++ /dev/null diff --git a/tools/droiddoc/templates-ndk/assets/js/android_3p-bundle.js b/tools/droiddoc/templates-ndk/assets/js/android_3p-bundle.js deleted file mode 100644 index a67b5b0d8c..0000000000 --- a/tools/droiddoc/templates-ndk/assets/js/android_3p-bundle.js +++ /dev/null @@ -1,2766 +0,0 @@ -//third_party/javascript/google_code_prettify/src/prettify.js -/** - * @license Copyright (C) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * some functions for browser-side pretty printing of code contained in html. - * <p> - * - * For a fairly comprehensive set of languages see the - * <a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs">README</a> - * file that came with this source. At a minimum, the lexer should work on a - * number of languages including C and friends, Java, Python, Bash, SQL, HTML, - * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk - * and a subset of Perl, but, because of commenting conventions, doesn't work on - * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class. - * <p> - * Usage: <ol> - * <li> include this source file in an html page via - * {@code <script type="text/javascript" src="/path/to/prettify.js"></script>} - * <li> define style rules. See the example page for examples. - * <li> mark the {@code <pre>} and {@code <code>} tags in your source with - * {@code class=prettyprint.} - * You can also use the (html deprecated) {@code <xmp>} tag, but the pretty - * printer needs to do more substantial DOM manipulations to support that, so - * some css styles may not be preserved. - * </ol> - * That's it. I wanted to keep the API as simple as possible, so there's no - * need to specify which language the code is in, but if you wish, you can add - * another class to the {@code <pre>} or {@code <code>} element to specify the - * language, as in {@code <pre class="prettyprint lang-java">}. Any class that - * starts with "lang-" followed by a file extension, specifies the file type. - * See the "lang-*.js" files in this directory for code that implements - * per-language file handlers. - * <p> - * Change log:<br> - * cbeust, 2006/08/22 - * <blockquote> - * Java annotations (start with "@") are now captured as literals ("lit") - * </blockquote> - * @requires console - */ - -// JSLint declarations -/*global console, document, navigator, setTimeout, window */ - -/** - * Split {@code prettyPrint} into multiple timeouts so as not to interfere with - * UI events. - * If set to {@code false}, {@code prettyPrint()} is synchronous. - */ -window['PR_SHOULD_USE_CONTINUATION'] = true; - -/** the number of characters between tab columns */ -window['PR_TAB_WIDTH'] = 8; - -/** Walks the DOM returning a properly escaped version of innerHTML. - * @param {Node} node - * @param {Array.<string>} out output buffer that receives chunks of HTML. - */ -window['PR_normalizedHtml'] - -/** Contains functions for creating and registering new language handlers. - * @type {Object} - */ - = window['PR'] - -/** Pretty print a chunk of code. - * - * @param {string} sourceCodeHtml code as html - * @return {string} code as html, but prettier - */ - = window['prettyPrintOne'] -/** Find all the {@code <pre>} and {@code <code>} tags in the DOM with - * {@code class=prettyprint} and prettify them. - * @param {Function?} opt_whenDone if specified, called when the last entry - * has been finished. - */ - = window['prettyPrint'] = void 0; - -/** browser detection. @extern @returns false if not IE, otherwise the major version. */ -window['_pr_isIE6'] = function () { - var ieVersion = navigator && navigator.userAgent && - navigator.userAgent.match(/\bMSIE ([678])\./); - ieVersion = ieVersion ? +ieVersion[1] : false; - window['_pr_isIE6'] = function () { return ieVersion; }; - return ieVersion; -}; - - -(function () { - // Keyword lists for various languages. - var FLOW_CONTROL_KEYWORDS = - "break continue do else for if return while "; - var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " + - "double enum extern float goto int long register short signed sizeof " + - "static struct switch typedef union unsigned void volatile "; - var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " + - "new operator private protected public this throw true try typeof "; - var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " + - "concept concept_map const_cast constexpr decltype " + - "dynamic_cast explicit export friend inline late_check " + - "mutable namespace nullptr reinterpret_cast static_assert static_cast " + - "template typeid typename using virtual wchar_t where "; - var JAVA_KEYWORDS = COMMON_KEYWORDS + - "abstract boolean byte extends final finally implements import " + - "instanceof null native package strictfp super synchronized throws " + - "transient "; - var CSHARP_KEYWORDS = JAVA_KEYWORDS + - "as base by checked decimal delegate descending dynamic event " + - "fixed foreach from group implicit in interface internal into is lock " + - "object out override orderby params partial readonly ref sbyte sealed " + - "stackalloc string select uint ulong unchecked unsafe ushort var "; - var COFFEE_KEYWORDS = "all and by catch class else extends false finally " + - "for if in is isnt loop new no not null of off on or return super then " + - "true try unless until when while yes "; - var JSCRIPT_KEYWORDS = COMMON_KEYWORDS + - "debugger eval export function get null set undefined var with " + - "Infinity NaN "; - var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " + - "goto if import last local my next no our print package redo require " + - "sub undef unless until use wantarray while BEGIN END "; - var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " + - "elif except exec finally from global import in is lambda " + - "nonlocal not or pass print raise try with yield " + - "False True None "; - var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" + - " defined elsif end ensure false in module next nil not or redo rescue " + - "retry self super then true undef unless until when yield BEGIN END "; - var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " + - "function in local set then until "; - var ALL_KEYWORDS = ( - CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS + - PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS); - - // token style names. correspond to css classes - /** token style for a string literal */ - var PR_STRING = 'str'; - /** token style for a keyword */ - var PR_KEYWORD = 'kwd'; - /** token style for a comment */ - var PR_COMMENT = 'com'; - /** token style for a type */ - var PR_TYPE = 'typ'; - /** token style for a literal value. e.g. 1, null, true. */ - var PR_LITERAL = 'lit'; - /** token style for a punctuation string. */ - var PR_PUNCTUATION = 'pun'; - /** token style for a punctuation string. */ - var PR_PLAIN = 'pln'; - - /** token style for an sgml tag. */ - var PR_TAG = 'tag'; - /** token style for a markup declaration such as a DOCTYPE. */ - var PR_DECLARATION = 'dec'; - /** token style for embedded source. */ - var PR_SOURCE = 'src'; - /** token style for an sgml attribute name. */ - var PR_ATTRIB_NAME = 'atn'; - /** token style for an sgml attribute value. */ - var PR_ATTRIB_VALUE = 'atv'; - - /** - * A class that indicates a section of markup that is not code, e.g. to allow - * embedding of line numbers within code listings. - */ - var PR_NOCODE = 'nocode'; - - /** A set of tokens that can precede a regular expression literal in - * javascript. - * http://www.mozilla.org/js/language/js20/rationale/syntax.html has the full - * list, but I've removed ones that might be problematic when seen in - * languages that don't support regular expression literals. - * - * <p>Specifically, I've removed any keywords that can't precede a regexp - * literal in a syntactically legal javascript program, and I've removed the - * "in" keyword since it's not a keyword in many languages, and might be used - * as a count of inches. - * - * <p>The link a above does not accurately describe EcmaScript rules since - * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works - * very well in practice. - * - * @private - */ - var REGEXP_PRECEDER_PATTERN = function () { - var preceders = [ - "!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=", - "&=", "(", "*", "*=", /* "+", */ "+=", ",", /* "-", */ "-=", - "->", /*".", "..", "...", handled below */ "/", "/=", ":", "::", ";", - "<", "<<", "<<=", "<=", "=", "==", "===", ">", - ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", - "^", "^=", "^^", "^^=", "{", "|", "|=", "||", - "||=", "~" /* handles =~ and !~ */, - "break", "case", "continue", "delete", - "do", "else", "finally", "instanceof", - "return", "throw", "try", "typeof" - ]; - var pattern = '(?:^^|[+-]'; - for (var i = 0; i < preceders.length; ++i) { - pattern += '|' + preceders[i].replace(/([^=<>:&a-z])/g, '\\$1'); - } - pattern += ')\\s*'; // matches at end, and matches empty string - return pattern; - // CAVEAT: this does not properly handle the case where a regular - // expression immediately follows another since a regular expression may - // have flags for case-sensitivity and the like. Having regexp tokens - // adjacent is not valid in any language I'm aware of, so I'm punting. - // TODO: maybe style special characters inside a regexp as punctuation. - }(); - - // Define regexps here so that the interpreter doesn't have to create an - // object each time the function containing them is called. - // The language spec requires a new object created even if you don't access - // the $1 members. - var pr_amp = /&/g; - var pr_lt = /</g; - var pr_gt = />/g; - var pr_quot = /\"/g; - /** like textToHtml but escapes double quotes to be attribute safe. */ - function attribToHtml(str) { - return str.replace(pr_amp, '&') - .replace(pr_lt, '<') - .replace(pr_gt, '>') - .replace(pr_quot, '"'); - } - - /** escapest html special characters to html. */ - function textToHtml(str) { - return str.replace(pr_amp, '&') - .replace(pr_lt, '<') - .replace(pr_gt, '>'); - } - - - var pr_ltEnt = /</g; - var pr_gtEnt = />/g; - var pr_aposEnt = /'/g; - var pr_quotEnt = /"/g; - var pr_ampEnt = /&/g; - var pr_nbspEnt = / /g; - /** unescapes html to plain text. */ - function htmlToText(html) { - var pos = html.indexOf('&'); - if (pos < 0) { return html; } - // Handle numeric entities specially. We can't use functional substitution - // since that doesn't work in older versions of Safari. - // These should be rare since most browsers convert them to normal chars. - for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0;) { - var end = html.indexOf(';', pos); - if (end >= 0) { - var num = html.substring(pos + 3, end); - var radix = 10; - if (num && num.charAt(0) === 'x') { - num = num.substring(1); - radix = 16; - } - var codePoint = parseInt(num, radix); - if (!isNaN(codePoint)) { - html = (html.substring(0, pos) + String.fromCharCode(codePoint) + - html.substring(end + 1)); - } - } - } - - return html.replace(pr_ltEnt, '<') - .replace(pr_gtEnt, '>') - .replace(pr_aposEnt, "'") - .replace(pr_quotEnt, '"') - .replace(pr_nbspEnt, ' ') - .replace(pr_ampEnt, '&'); - } - - /** is the given node's innerHTML normally unescaped? */ - function isRawContent(node) { - return 'XMP' === node.tagName; - } - - var newlineRe = /[\r\n]/g; - /** - * Are newlines and adjacent spaces significant in the given node's innerHTML? - */ - function isPreformatted(node, content) { - // PRE means preformatted, and is a very common case, so don't create - // unnecessary computed style objects. - if ('PRE' === node.tagName) { return true; } - if (!newlineRe.test(content)) { return true; } // Don't care - var whitespace = ''; - // For disconnected nodes, IE has no currentStyle. - if (node.currentStyle) { - whitespace = node.currentStyle.whiteSpace; - } else if (window.getComputedStyle) { - // Firefox makes a best guess if node is disconnected whereas Safari - // returns the empty string. - whitespace = window.getComputedStyle(node, null).whiteSpace; - } - return !whitespace || whitespace === 'pre'; - } - - function normalizedHtml(node, out, opt_sortAttrs) { - switch (node.nodeType) { - case 1: // an element - var name = node.tagName.toLowerCase(); - - out.push('<', name); - var attrs = node.attributes; - var n = attrs.length; - if (n) { - if (opt_sortAttrs) { - var sortedAttrs = []; - for (var i = n; --i >= 0;) { sortedAttrs[i] = attrs[i]; } - sortedAttrs.sort(function (a, b) { - return (a.name < b.name) ? -1 : a.name === b.name ? 0 : 1; - }); - attrs = sortedAttrs; - } - for (var i = 0; i < n; ++i) { - var attr = attrs[i]; - if (!attr.specified) { continue; } - out.push(' ', attr.name.toLowerCase(), - '="', attribToHtml(attr.value), '"'); - } - } - out.push('>'); - for (var child = node.firstChild; child; child = child.nextSibling) { - normalizedHtml(child, out, opt_sortAttrs); - } - if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { - out.push('<\/', name, '>'); - } - break; - case 3: case 4: // text - out.push(textToHtml(node.nodeValue)); - break; - } - } - - /** - * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally - * matches the union o the sets o strings matched d by the input RegExp. - * Since it matches globally, if the input strings have a start-of-input - * anchor (/^.../), it is ignored for the purposes of unioning. - * @param {Array.<RegExp>} regexs non multiline, non-global regexs. - * @return {RegExp} a global regex. - */ - function combinePrefixPatterns(regexs) { - var capturedGroupIndex = 0; - - var needToFoldCase = false; - var ignoreCase = false; - for (var i = 0, n = regexs.length; i < n; ++i) { - var regex = regexs[i]; - if (regex.ignoreCase) { - ignoreCase = true; - } else if (/[a-z]/i.test(regex.source.replace( - /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) { - needToFoldCase = true; - ignoreCase = false; - break; - } - } - - function decodeEscape(charsetPart) { - if (charsetPart.charAt(0) !== '\\') { return charsetPart.charCodeAt(0); } - switch (charsetPart.charAt(1)) { - case 'b': return 8; - case 't': return 9; - case 'n': return 0xa; - case 'v': return 0xb; - case 'f': return 0xc; - case 'r': return 0xd; - case 'u': case 'x': - return parseInt(charsetPart.substring(2), 16) - || charsetPart.charCodeAt(1); - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': - return parseInt(charsetPart.substring(1), 8); - default: return charsetPart.charCodeAt(1); - } - } - - function encodeEscape(charCode) { - if (charCode < 0x20) { - return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16); - } - var ch = String.fromCharCode(charCode); - if (ch === '\\' || ch === '-' || ch === '[' || ch === ']') { - ch = '\\' + ch; - } - return ch; - } - - function caseFoldCharset(charSet) { - var charsetParts = charSet.substring(1, charSet.length - 1).match( - new RegExp( - '\\\\u[0-9A-Fa-f]{4}' - + '|\\\\x[0-9A-Fa-f]{2}' - + '|\\\\[0-3][0-7]{0,2}' - + '|\\\\[0-7]{1,2}' - + '|\\\\[\\s\\S]' - + '|-' - + '|[^-\\\\]', - 'g')); - var groups = []; - var ranges = []; - var inverse = charsetParts[0] === '^'; - for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) { - var p = charsetParts[i]; - switch (p) { - case '\\B': case '\\b': - case '\\D': case '\\d': - case '\\S': case '\\s': - case '\\W': case '\\w': - groups.push(p); - continue; - } - var start = decodeEscape(p); - var end; - if (i + 2 < n && '-' === charsetParts[i + 1]) { - end = decodeEscape(charsetParts[i + 2]); - i += 2; - } else { - end = start; - } - ranges.push([start, end]); - // If the range might intersect letters, then expand it. - if (!(end < 65 || start > 122)) { - if (!(end < 65 || start > 90)) { - ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]); - } - if (!(end < 97 || start > 122)) { - ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]); - } - } - } - - // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]] - // -> [[1, 12], [14, 14], [16, 17]] - ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1] - a[1]); }); - var consolidatedRanges = []; - var lastRange = [NaN, NaN]; - for (var i = 0; i < ranges.length; ++i) { - var range = ranges[i]; - if (range[0] <= lastRange[1] + 1) { - lastRange[1] = Math.max(lastRange[1], range[1]); - } else { - consolidatedRanges.push(lastRange = range); - } - } - - var out = ['[']; - if (inverse) { out.push('^'); } - out.push.apply(out, groups); - for (var i = 0; i < consolidatedRanges.length; ++i) { - var range = consolidatedRanges[i]; - out.push(encodeEscape(range[0])); - if (range[1] > range[0]) { - if (range[1] + 1 > range[0]) { out.push('-'); } - out.push(encodeEscape(range[1])); - } - } - out.push(']'); - return out.join(''); - } - - function allowAnywhereFoldCaseAndRenumberGroups(regex) { - // Split into character sets, escape sequences, punctuation strings - // like ('(', '(?:', ')', '^'), and runs of characters that do not - // include any of the above. - var parts = regex.source.match( - new RegExp( - '(?:' - + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]' // a character set - + '|\\\\u[A-Fa-f0-9]{4}' // a unicode escape - + '|\\\\x[A-Fa-f0-9]{2}' // a hex escape - + '|\\\\[0-9]+' // a back-reference or octal escape - + '|\\\\[^ux0-9]' // other escape sequence - + '|\\(\\?[:!=]' // start of a non-capturing group - + '|[\\(\\)\\^]' // start/emd of a group, or line start - + '|[^\\x5B\\x5C\\(\\)\\^]+' // run of other characters - + ')', - 'g')); - var n = parts.length; - - // Maps captured group numbers to the number they will occupy in - // the output or to -1 if that has not been determined, or to - // undefined if they need not be capturing in the output. - var capturedGroups = []; - - // Walk over and identify back references to build the capturedGroups - // mapping. - for (var i = 0, groupIndex = 0; i < n; ++i) { - var p = parts[i]; - if (p === '(') { - // groups are 1-indexed, so max group index is count of '(' - ++groupIndex; - } else if ('\\' === p.charAt(0)) { - var decimalValue = +p.substring(1); - if (decimalValue && decimalValue <= groupIndex) { - capturedGroups[decimalValue] = -1; - } - } - } - - // Renumber groups and reduce capturing groups to non-capturing groups - // where possible. - for (var i = 1; i < capturedGroups.length; ++i) { - if (-1 === capturedGroups[i]) { - capturedGroups[i] = ++capturedGroupIndex; - } - } - for (var i = 0, groupIndex = 0; i < n; ++i) { - var p = parts[i]; - if (p === '(') { - ++groupIndex; - if (capturedGroups[groupIndex] === undefined) { - parts[i] = '(?:'; - } - } else if ('\\' === p.charAt(0)) { - var decimalValue = +p.substring(1); - if (decimalValue && decimalValue <= groupIndex) { - parts[i] = '\\' + capturedGroups[groupIndex]; - } - } - } - - // Remove any prefix anchors so that the output will match anywhere. - // ^^ really does mean an anchored match though. - for (var i = 0, groupIndex = 0; i < n; ++i) { - if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; } - } - - // Expand letters to groupts to handle mixing of case-sensitive and - // case-insensitive patterns if necessary. - if (regex.ignoreCase && needToFoldCase) { - for (var i = 0; i < n; ++i) { - var p = parts[i]; - var ch0 = p.charAt(0); - if (p.length >= 2 && ch0 === '[') { - parts[i] = caseFoldCharset(p); - } else if (ch0 !== '\\') { - // TODO: handle letters in numeric escapes. - parts[i] = p.replace( - /[a-zA-Z]/g, - function (ch) { - var cc = ch.charCodeAt(0); - return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']'; - }); - } - } - } - - return parts.join(''); - } - - var rewritten = []; - for (var i = 0, n = regexs.length; i < n; ++i) { - var regex = regexs[i]; - if (regex.global || regex.multiline) { throw new Error('' + regex); } - rewritten.push( - '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')'); - } - - return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g'); - } - - var PR_innerHtmlWorks = null; - function getInnerHtml(node) { - // inner html is hopelessly broken in Safari 2.0.4 when the content is - // an html description of well formed XML and the containing tag is a PRE - // tag, so we detect that case and emulate innerHTML. - if (null === PR_innerHtmlWorks) { - var testNode = document.createElement('PRE'); - testNode.appendChild( - document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); - PR_innerHtmlWorks = !/</.test(testNode.innerHTML); - } - - if (PR_innerHtmlWorks) { - var content = node.innerHTML; - // XMP tags contain unescaped entities so require special handling. - if (isRawContent(node)) { - content = textToHtml(content); - } else if (!isPreformatted(node, content)) { - content = content.replace(/(<br\s*\/?>)[\r\n]+/g, '$1') - .replace(/(?:[\r\n]+[ \t]*)+/g, ' '); - } - return content; - } - - var out = []; - for (var child = node.firstChild; child; child = child.nextSibling) { - normalizedHtml(child, out); - } - return out.join(''); - } - - /** returns a function that expand tabs to spaces. This function can be fed - * successive chunks of text, and will maintain its own internal state to - * keep track of how tabs are expanded. - * @return {function (string) : string} a function that takes - * plain text and return the text with tabs expanded. - * @private - */ - function makeTabExpander(tabWidth) { - var SPACES = ' '; - var charInLine = 0; - - return function (plainText) { - // walk over each character looking for tabs and newlines. - // On tabs, expand them. On newlines, reset charInLine. - // Otherwise increment charInLine - var out = null; - var pos = 0; - for (var i = 0, n = plainText.length; i < n; ++i) { - var ch = plainText.charAt(i); - - switch (ch) { - case '\t': - if (!out) { out = []; } - out.push(plainText.substring(pos, i)); - // calculate how much space we need in front of this part - // nSpaces is the amount of padding -- the number of spaces needed - // to move us to the next column, where columns occur at factors of - // tabWidth. - var nSpaces = tabWidth - (charInLine % tabWidth); - charInLine += nSpaces; - for (; nSpaces >= 0; nSpaces -= SPACES.length) { - out.push(SPACES.substring(0, nSpaces)); - } - pos = i + 1; - break; - case '\n': - charInLine = 0; - break; - default: - ++charInLine; - } - } - if (!out) { return plainText; } - out.push(plainText.substring(pos)); - return out.join(''); - }; - } - - var pr_chunkPattern = new RegExp( - '[^<]+' // A run of characters other than '<' - + '|<\!--[\\s\\S]*?--\>' // an HTML comment - + '|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>' // a CDATA section - // a probable tag that should not be highlighted - + '|<\/?[a-zA-Z](?:[^>\"\']|\'[^\']*\'|\"[^\"]*\")*>' - + '|<', // A '<' that does not begin a larger chunk - 'g'); - var pr_commentPrefix = /^<\!--/; - var pr_cdataPrefix = /^<!\[CDATA\[/; - var pr_brPrefix = /^<br\b/i; - var pr_tagNameRe = /^<(\/?)([a-zA-Z][a-zA-Z0-9]*)/; - - /** split markup into chunks of html tags (style null) and - * plain text (style {@link #PR_PLAIN}), converting tags which are - * significant for tokenization (<br>) into their textual equivalent. - * - * @param {string} s html where whitespace is considered significant. - * @return {Object} source code and extracted tags. - * @private - */ - function extractTags(s) { - // since the pattern has the 'g' modifier and defines no capturing groups, - // this will return a list of all chunks which we then classify and wrap as - // PR_Tokens - var matches = s.match(pr_chunkPattern); - var sourceBuf = []; - var sourceBufLen = 0; - var extractedTags = []; - if (matches) { - for (var i = 0, n = matches.length; i < n; ++i) { - var match = matches[i]; - if (match.length > 1 && match.charAt(0) === '<') { - if (pr_commentPrefix.test(match)) { continue; } - if (pr_cdataPrefix.test(match)) { - // strip CDATA prefix and suffix. Don't unescape since it's CDATA - sourceBuf.push(match.substring(9, match.length - 3)); - sourceBufLen += match.length - 12; - } else if (pr_brPrefix.test(match)) { - // <br> tags are lexically significant so convert them to text. - // This is undone later. - sourceBuf.push('\n'); - ++sourceBufLen; - } else { - if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) { - // A <span class="nocode"> will start a section that should be - // ignored. Continue walking the list until we see a matching end - // tag. - var name = match.match(pr_tagNameRe)[2]; - var depth = 1; - var j; - end_tag_loop: - for (j = i + 1; j < n; ++j) { - var name2 = matches[j].match(pr_tagNameRe); - if (name2 && name2[2] === name) { - if (name2[1] === '/') { - if (--depth === 0) { break end_tag_loop; } - } else { - ++depth; - } - } - } - if (j < n) { - extractedTags.push( - sourceBufLen, matches.slice(i, j + 1).join('')); - i = j; - } else { // Ignore unclosed sections. - extractedTags.push(sourceBufLen, match); - } - } else { - extractedTags.push(sourceBufLen, match); - } - } - } else { - var literalText = htmlToText(match); - sourceBuf.push(literalText); - sourceBufLen += literalText.length; - } - } - } - return { source: sourceBuf.join(''), tags: extractedTags }; - } - - /** True if the given tag contains a class attribute with the nocode class. */ - function isNoCodeTag(tag) { - return !!tag - // First canonicalize the representation of attributes - .replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g, - ' $1="$2$3$4"') - // Then look for the attribute we want. - .match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/); - } - - /** - * Apply the given language handler to sourceCode and add the resulting - * decorations to out. - * @param {number} basePos the index of sourceCode within the chunk of source - * whose decorations are already present on out. - */ - function appendDecorations(basePos, sourceCode, langHandler, out) { - if (!sourceCode) { return; } - var job = { - source: sourceCode, - basePos: basePos - }; - langHandler(job); - out.push.apply(out, job.decorations); - } - - /** Given triples of [style, pattern, context] returns a lexing function, - * The lexing function interprets the patterns to find token boundaries and - * returns a decoration list of the form - * [index_0, style_0, index_1, style_1, ..., index_n, style_n] - * where index_n is an index into the sourceCode, and style_n is a style - * constant like PR_PLAIN. index_n-1 <= index_n, and style_n-1 applies to - * all characters in sourceCode[index_n-1:index_n]. - * - * The stylePatterns is a list whose elements have the form - * [style : string, pattern : RegExp, DEPRECATED, shortcut : string]. - * - * Style is a style constant like PR_PLAIN, or can be a string of the - * form 'lang-FOO', where FOO is a language extension describing the - * language of the portion of the token in $1 after pattern executes. - * E.g., if style is 'lang-lisp', and group 1 contains the text - * '(hello (world))', then that portion of the token will be passed to the - * registered lisp handler for formatting. - * The text before and after group 1 will be restyled using this decorator - * so decorators should take care that this doesn't result in infinite - * recursion. For example, the HTML lexer rule for SCRIPT elements looks - * something like ['lang-js', /<[s]cript>(.+?)<\/script>/]. This may match - * '<script>foo()<\/script>', which would cause the current decorator to - * be called with '<script>' which would not match the same rule since - * group 1 must not be empty, so it would be instead styled as PR_TAG by - * the generic tag rule. The handler registered for the 'js' extension would - * then be called with 'foo()', and finally, the current decorator would - * be called with '<\/script>' which would not match the original rule and - * so the generic tag rule would identify it as a tag. - * - * Pattern must only match prefixes, and if it matches a prefix, then that - * match is considered a token with the same style. - * - * Context is applied to the last non-whitespace, non-comment token - * recognized. - * - * Shortcut is an optional string of characters, any of which, if the first - * character, gurantee that this pattern and only this pattern matches. - * - * @param {Array} shortcutStylePatterns patterns that always start with - * a known character. Must have a shortcut string. - * @param {Array} fallthroughStylePatterns patterns that will be tried in - * order if the shortcut ones fail. May have shortcuts. - * - * @return {function (Object)} a - * function that takes source code and returns a list of decorations. - */ - function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { - var shortcuts = {}; - var tokenizer; - (function () { - var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); - var allRegexs = []; - var regexKeys = {}; - for (var i = 0, n = allPatterns.length; i < n; ++i) { - var patternParts = allPatterns[i]; - var shortcutChars = patternParts[3]; - if (shortcutChars) { - for (var c = shortcutChars.length; --c >= 0;) { - shortcuts[shortcutChars.charAt(c)] = patternParts; - } - } - var regex = patternParts[1]; - var k = '' + regex; - if (!regexKeys.hasOwnProperty(k)) { - allRegexs.push(regex); - regexKeys[k] = null; - } - } - allRegexs.push(/[\0-\uffff]/); - tokenizer = combinePrefixPatterns(allRegexs); - })(); - - var nPatterns = fallthroughStylePatterns.length; - var notWs = /\S/; - - /** - * Lexes job.source and produces an output array job.decorations of style - * classes preceded by the position at which they start in job.source in - * order. - * - * @param {Object} job an object like {@code - * source: {string} sourceText plain text, - * basePos: {int} position of job.source in the larger chunk of - * sourceCode. - * } - */ - var decorate = function (job) { - var sourceCode = job.source, basePos = job.basePos; - /** Even entries are positions in source in ascending order. Odd enties - * are style markers (e.g., PR_COMMENT) that run from that position until - * the end. - * @type {Array.<number|string>} - */ - var decorations = [basePos, PR_PLAIN]; - var pos = 0; // index into sourceCode - var tokens = sourceCode.match(tokenizer) || []; - var styleCache = {}; - - for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) { - var token = tokens[ti]; - var style = styleCache[token]; - var match = void 0; - - var isEmbedded; - if (typeof style === 'string') { - isEmbedded = false; - } else { - var patternParts = shortcuts[token.charAt(0)]; - if (patternParts) { - match = token.match(patternParts[1]); - style = patternParts[0]; - } else { - for (var i = 0; i < nPatterns; ++i) { - patternParts = fallthroughStylePatterns[i]; - match = token.match(patternParts[1]); - if (match) { - style = patternParts[0]; - break; - } - } - - if (!match) { // make sure that we make progress - style = PR_PLAIN; - } - } - - isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5); - if (isEmbedded && !(match && typeof match[1] === 'string')) { - isEmbedded = false; - style = PR_SOURCE; - } - - if (!isEmbedded) { styleCache[token] = style; } - } - - var tokenStart = pos; - pos += token.length; - - if (!isEmbedded) { - decorations.push(basePos + tokenStart, style); - } else { // Treat group 1 as an embedded block of source code. - var embeddedSource = match[1]; - var embeddedSourceStart = token.indexOf(embeddedSource); - var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length; - if (match[2]) { - // If embeddedSource can be blank, then it would match at the - // beginning which would cause us to infinitely recurse on the - // entire token, so we catch the right context in match[2]. - embeddedSourceEnd = token.length - match[2].length; - embeddedSourceStart = embeddedSourceEnd - embeddedSource.length; - } - var lang = style.substring(5); - // Decorate the left of the embedded source - appendDecorations( - basePos + tokenStart, - token.substring(0, embeddedSourceStart), - decorate, decorations); - // Decorate the embedded source - appendDecorations( - basePos + tokenStart + embeddedSourceStart, - embeddedSource, - langHandlerForExtension(lang, embeddedSource), - decorations); - // Decorate the right of the embedded section - appendDecorations( - basePos + tokenStart + embeddedSourceEnd, - token.substring(embeddedSourceEnd), - decorate, decorations); - } - } - job.decorations = decorations; - }; - return decorate; - } - - /** returns a function that produces a list of decorations from source text. - * - * This code treats ", ', and ` as string delimiters, and \ as a string - * escape. It does not recognize perl's qq() style strings. - * It has no special handling for double delimiter escapes as in basic, or - * the tripled delimiters used in python, but should work on those regardless - * although in those cases a single string literal may be broken up into - * multiple adjacent string literals. - * - * It recognizes C, C++, and shell style comments. - * - * @param {Object} options a set of optional parameters. - * @return {function (Object)} a function that examines the source code - * in the input job and builds the decoration list. - */ - function sourceDecorator(options) { - var shortcutStylePatterns = [], fallthroughStylePatterns = []; - if (options['tripleQuotedStrings']) { - // '''multi-line-string''', 'single-line-string', and double-quoted - shortcutStylePatterns.push( - [PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, - null, '\'"']); - } else if (options['multiLineStrings']) { - // 'multi-line-string', "multi-line-string" - shortcutStylePatterns.push( - [PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, - null, '\'"`']); - } else { - // 'single-line-string', "single-line-string" - shortcutStylePatterns.push( - [PR_STRING, - /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, - null, '"\'']); - } - if (options['verbatimStrings']) { - // verbatim-string-literal production from the C# grammar. See issue 93. - fallthroughStylePatterns.push( - [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]); - } - var hc = options['hashComments']; - if (hc) { - if (options['cStyleComments']) { - if (hc > 1) { // multiline hash comments - shortcutStylePatterns.push( - [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']); - } else { - // Stop C preprocessor declarations at an unclosed open comment - shortcutStylePatterns.push( - [PR_COMMENT, /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/, - null, '#']); - } - fallthroughStylePatterns.push( - [PR_STRING, - /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/, - null]); - } else { - shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); - } - } - if (options['cStyleComments']) { - fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); - fallthroughStylePatterns.push( - [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); - } - if (options['regexLiterals']) { - var REGEX_LITERAL = ( - // A regular expression literal starts with a slash that is - // not followed by * or / so that it is not confused with - // comments. - '/(?=[^/*])' - // and then contains any number of raw characters, - + '(?:[^/\\x5B\\x5C]' - // escape sequences (\x5C), - + '|\\x5C[\\s\\S]' - // or non-nesting character sets (\x5B\x5D); - + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+' - // finally closed by a /. - + '/'); - fallthroughStylePatterns.push( - ['lang-regex', - new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')') - ]); - } - - var keywords = options['keywords'].replace(/^\s+|\s+$/g, ''); - if (keywords.length) { - fallthroughStylePatterns.push( - [PR_KEYWORD, - new RegExp('^(?:' + keywords.replace(/\s+/g, '|') + ')\\b'), null]); - } - - shortcutStylePatterns.push([PR_PLAIN, /^\s+/, null, ' \r\n\t\xA0']); - fallthroughStylePatterns.push( - // TODO(mikesamuel): recognize non-latin letters and numerals in idents - [PR_LITERAL, /^@[a-z_$][a-z_$@0-9]*/i, null], - [PR_TYPE, /^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/, null], - [PR_PLAIN, /^[a-z_$][a-z_$@0-9]*/i, null], - [PR_LITERAL, - new RegExp( - '^(?:' - // A hex number - + '0x[a-f0-9]+' - // or an octal or decimal number, - + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)' - // possibly in scientific notation - + '(?:e[+\\-]?\\d+)?' - + ')' - // with an optional modifier like UL for unsigned long - + '[a-z]*', 'i'), - null, '0123456789'], - [PR_PUNCTUATION, /^.[^\s\w\.$@\'\"\`\/\#]*/, null]); - - return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns); - } - - var decorateSource = sourceDecorator({ - 'keywords': ALL_KEYWORDS, - 'hashComments': true, - 'cStyleComments': true, - 'multiLineStrings': true, - 'regexLiterals': true - }); - - /** Breaks {@code job.source} around style boundaries in - * {@code job.decorations} while re-interleaving {@code job.extractedTags}, - * and leaves the result in {@code job.prettyPrintedHtml}. - * @param {Object} job like { - * source: {string} source as plain text, - * extractedTags: {Array.<number|string>} extractedTags chunks of raw - * html preceded by their position in {@code job.source} - * in order - * decorations: {Array.<number|string} an array of style classes preceded - * by the position at which they start in job.source in order - * } - * @private - */ - function recombineTagsAndDecorations(job) { - var sourceText = job.source; - var extractedTags = job.extractedTags; - var decorations = job.decorations; - var numberLines = job.numberLines; - var sourceNode = job.sourceNode; - - var html = []; - // index past the last char in sourceText written to html - var outputIdx = 0; - - var openDecoration = null; - var currentDecoration = null; - var tagPos = 0; // index into extractedTags - var decPos = 0; // index into decorations - var tabExpander = makeTabExpander(window['PR_TAB_WIDTH']); - - var adjacentSpaceRe = /([\r\n ]) /g; - var startOrSpaceRe = /(^| ) /gm; - var newlineRe = /\r\n?|\n/g; - var trailingSpaceRe = /[ \r\n]$/; - var lastWasSpace = true; // the last text chunk emitted ended with a space. - - // See bug 71 and http://stackoverflow.com/questions/136443/why-doesnt-ie7- - var isIE678 = window['_pr_isIE6'](); - var lineBreakHtml = ( - isIE678 - ? (sourceNode && sourceNode.tagName === 'PRE' - // Use line feeds instead of <br>s so that copying and pasting works - // on IE. - // See Issue 104 for the derivation of this mess. - ? (isIE678 === 6 ? ' \r\n' : - isIE678 === 7 ? ' <br />\r' : - isIE678 === 8 ? ' <br />' : ' \r') - // IE collapses multiple adjacent <br>s into 1 line break. - // Prefix every newline with ' ' to prevent such behavior. - // is the same as   but works in XML as well as HTML. - : ' <br />') - : '<br />'); - - var lineBreaker; - if (numberLines) { - var lineBreaks = []; - for (var i = 0; i < 10; ++i) { - lineBreaks[i] = lineBreakHtml + '</li><li class="L' + i + '">'; - } - var lineNum = typeof numberLines === 'number' - ? numberLines - 1 /* number lines are 1 indexed */ : 0; - html.push('<ol class="linenums"><li class="L', (lineNum) % 10, '"'); - if (lineNum) { - html.push(' value="', lineNum + 1, '"'); - } - html.push('>'); - lineBreaker = function () { - var lb = lineBreaks[++lineNum % 10]; - // If a decoration is open, we need to close it before closing a list-item - // and reopen it on the other side of the list item. - return openDecoration - ? ('</span>' + lb + '<span class="' + openDecoration + '">') : lb; - }; - } else { - lineBreaker = lineBreakHtml; - } - - // A helper function that is responsible for opening sections of decoration - // and outputing properly escaped chunks of source - function emitTextUpTo(sourceIdx) { - if (sourceIdx > outputIdx) { - if (openDecoration && openDecoration !== currentDecoration) { - // Close the current decoration - html.push('</span>'); - openDecoration = null; - } - if (!openDecoration && currentDecoration) { - openDecoration = currentDecoration; - html.push('<span class="', openDecoration, '">'); - } - // This interacts badly with some wikis which introduces paragraph tags - // into pre blocks for some strange reason. - // It's necessary for IE though which seems to lose the preformattedness - // of <pre> tags when their innerHTML is assigned. - // http://stud3.tuwien.ac.at/~e0226430/innerHtmlQuirk.html - // and it serves to undo the conversion of <br>s to newlines done in - // chunkify. - var htmlChunk = textToHtml( - tabExpander(sourceText.substring(outputIdx, sourceIdx))) - .replace(lastWasSpace - ? startOrSpaceRe - : adjacentSpaceRe, '$1 '); - // Keep track of whether we need to escape space at the beginning of the - // next chunk. - lastWasSpace = trailingSpaceRe.test(htmlChunk); - html.push(htmlChunk.replace(newlineRe, lineBreaker)); - outputIdx = sourceIdx; - } - } - - while (true) { - // Determine if we're going to consume a tag this time around. Otherwise - // we consume a decoration or exit. - var outputTag; - if (tagPos < extractedTags.length) { - if (decPos < decorations.length) { - // Pick one giving preference to extractedTags since we shouldn't open - // a new style that we're going to have to immediately close in order - // to output a tag. - outputTag = extractedTags[tagPos] <= decorations[decPos]; - } else { - outputTag = true; - } - } else { - outputTag = false; - } - // Consume either a decoration or a tag or exit. - if (outputTag) { - emitTextUpTo(extractedTags[tagPos]); - if (openDecoration) { - // Close the current decoration - html.push('</span>'); - openDecoration = null; - } - html.push(extractedTags[tagPos + 1]); - tagPos += 2; - } else if (decPos < decorations.length) { - emitTextUpTo(decorations[decPos]); - currentDecoration = decorations[decPos + 1]; - decPos += 2; - } else { - break; - } - } - emitTextUpTo(sourceText.length); - if (openDecoration) { - html.push('</span>'); - } - if (numberLines) { html.push('</li></ol>'); } - job.prettyPrintedHtml = html.join(''); - } - - /** Maps language-specific file extensions to handlers. */ - var langHandlerRegistry = {}; - /** Register a language handler for the given file extensions. - * @param {function (Object)} handler a function from source code to a list - * of decorations. Takes a single argument job which describes the - * state of the computation. The single parameter has the form - * {@code { - * source: {string} as plain text. - * decorations: {Array.<number|string>} an array of style classes - * preceded by the position at which they start in - * job.source in order. - * The language handler should assigned this field. - * basePos: {int} the position of source in the larger source chunk. - * All positions in the output decorations array are relative - * to the larger source chunk. - * } } - * @param {Array.<string>} fileExtensions - */ - function registerLangHandler(handler, fileExtensions) { - for (var i = fileExtensions.length; --i >= 0;) { - var ext = fileExtensions[i]; - if (!langHandlerRegistry.hasOwnProperty(ext)) { - langHandlerRegistry[ext] = handler; - } else if ('console' in window) { - console['warn']('cannot override language handler %s', ext); - } - } - } - function langHandlerForExtension(extension, source) { - if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) { - // Treat it as markup if the first non whitespace character is a < and - // the last non-whitespace character is a >. - extension = /^\s*</.test(source) - ? 'default-markup' - : 'default-code'; - } - return langHandlerRegistry[extension]; - } - registerLangHandler(decorateSource, ['default-code']); - registerLangHandler( - createSimpleLexer( - [], - [ - [PR_PLAIN, /^[^<?]+/], - [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/], - [PR_COMMENT, /^<\!--[\s\S]*?(?:-\->|$)/], - // Unescaped content in an unknown language - ['lang-', /^<\?([\s\S]+?)(?:\?>|$)/], - ['lang-', /^<%([\s\S]+?)(?:%>|$)/], - [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/], - ['lang-', /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i], - // Unescaped content in javascript. (Or possibly vbscript). - ['lang-js', /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i], - // Contains unescaped stylesheet content - ['lang-css', /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i], - ['lang-in.tag', /^(<\/?[a-z][^<>]*>)/i] - ]), - ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']); - registerLangHandler( - createSimpleLexer( - [ - [PR_PLAIN, /^[\s]+/, null, ' \t\r\n'], - [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\''] - ], - [ - [PR_TAG, /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i], - [PR_ATTRIB_NAME, /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i], - ['lang-uq.val', /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/], - [PR_PUNCTUATION, /^[=<>\/]+/], - ['lang-js', /^on\w+\s*=\s*\"([^\"]+)\"/i], - ['lang-js', /^on\w+\s*=\s*\'([^\']+)\'/i], - ['lang-js', /^on\w+\s*=\s*([^\"\'>\s]+)/i], - ['lang-css', /^style\s*=\s*\"([^\"]+)\"/i], - ['lang-css', /^style\s*=\s*\'([^\']+)\'/i], - ['lang-css', /^style\s*=\s*([^\"\'>\s]+)/i] - ]), - ['in.tag']); - registerLangHandler( - createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']); - registerLangHandler(sourceDecorator({ - 'keywords': CPP_KEYWORDS, - 'hashComments': true, - 'cStyleComments': true - }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']); - registerLangHandler(sourceDecorator({ - 'keywords': 'null true false' - }), ['json']); - registerLangHandler(sourceDecorator({ - 'keywords': CSHARP_KEYWORDS, - 'hashComments': true, - 'cStyleComments': true, - 'verbatimStrings': true - }), ['cs']); - registerLangHandler(sourceDecorator({ - 'keywords': JAVA_KEYWORDS, - 'cStyleComments': true - }), ['java']); - registerLangHandler(sourceDecorator({ - 'keywords': SH_KEYWORDS, - 'hashComments': true, - 'multiLineStrings': true - }), ['bsh', 'csh', 'sh']); - registerLangHandler(sourceDecorator({ - 'keywords': PYTHON_KEYWORDS, - 'hashComments': true, - 'multiLineStrings': true, - 'tripleQuotedStrings': true - }), ['cv', 'py']); - registerLangHandler(sourceDecorator({ - 'keywords': PERL_KEYWORDS, - 'hashComments': true, - 'multiLineStrings': true, - 'regexLiterals': true - }), ['perl', 'pl', 'pm']); - registerLangHandler(sourceDecorator({ - 'keywords': RUBY_KEYWORDS, - 'hashComments': true, - 'multiLineStrings': true, - 'regexLiterals': true - }), ['rb']); - registerLangHandler(sourceDecorator({ - 'keywords': JSCRIPT_KEYWORDS, - 'cStyleComments': true, - 'regexLiterals': true - }), ['js']); - registerLangHandler(sourceDecorator({ - 'keywords': COFFEE_KEYWORDS, - 'hashComments': 3, // ### style block comments - 'cStyleComments': true, - 'multilineStrings': true, - 'tripleQuotedStrings': true, - 'regexLiterals': true - }), ['coffee']); - registerLangHandler(createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']); - - function applyDecorator(job) { - var sourceCodeHtml = job.sourceCodeHtml; - var opt_langExtension = job.langExtension; - - // Prepopulate output in case processing fails with an exception. - job.prettyPrintedHtml = sourceCodeHtml; - - try { - // Extract tags, and convert the source code to plain text. - var sourceAndExtractedTags = extractTags(sourceCodeHtml); - /** Plain text. @type {string} */ - var source = sourceAndExtractedTags.source; - job.source = source; - job.basePos = 0; - - /** Even entries are positions in source in ascending order. Odd entries - * are tags that were extracted at that position. - * @type {Array.<number|string>} - */ - job.extractedTags = sourceAndExtractedTags.tags; - - // Apply the appropriate language handler - langHandlerForExtension(opt_langExtension, source)(job); - // Integrate the decorations and tags back into the source code to produce - // a decorated html string which is left in job.prettyPrintedHtml. - recombineTagsAndDecorations(job); - } catch (e) { - if ('console' in window) { - console['log'](e && e['stack'] ? e['stack'] : e); - } - } - } - - /** - * @param sourceCodeHtml {string} The HTML to pretty print. - * @param opt_langExtension {string} The language name to use. - * Typically, a filename extension like 'cpp' or 'java'. - * @param opt_numberLines {number|boolean} True to number lines, - * or the 1-indexed number of the first line in sourceCodeHtml. - */ - function prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) { - var job = { - sourceCodeHtml: sourceCodeHtml, - langExtension: opt_langExtension, - numberLines: opt_numberLines - }; - applyDecorator(job); - return job.prettyPrintedHtml; - } - - function prettyPrint(opt_whenDone) { - function byTagName(tn) { return document.getElementsByTagName(tn); } - // fetch a list of nodes to rewrite - var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')]; - var elements = []; - for (var i = 0; i < codeSegments.length; ++i) { - for (var j = 0, n = codeSegments[i].length; j < n; ++j) { - elements.push(codeSegments[i][j]); - } - } - codeSegments = null; - - var clock = Date; - if (!clock['now']) { - clock = { 'now': function () { return (new Date).getTime(); } }; - } - - // The loop is broken into a series of continuations to make sure that we - // don't make the browser unresponsive when rewriting a large page. - var k = 0; - var prettyPrintingJob; - - function doWork() { - var endTime = (window['PR_SHOULD_USE_CONTINUATION'] ? - clock.now() + 250 /* ms */ : - Infinity); - for (; k < elements.length && clock.now() < endTime; k++) { - var cs = elements[k]; - if (cs.className && cs.className.indexOf('prettyprint') >= 0) { - // If the classes includes a language extensions, use it. - // Language extensions can be specified like - // <pre class="prettyprint lang-cpp"> - // the language extension "cpp" is used to find a language handler as - // passed to PR.registerLangHandler. - var langExtension = cs.className.match(/\blang-(\w+)\b/); - if (langExtension) { langExtension = langExtension[1]; } - - // make sure this is not nested in an already prettified element - var nested = false; - for (var p = cs.parentNode; p; p = p.parentNode) { - if ((p.tagName === 'pre' || p.tagName === 'code' || - p.tagName === 'xmp') && - p.className && p.className.indexOf('prettyprint') >= 0) { - nested = true; - break; - } - } - if (!nested) { - // fetch the content as a snippet of properly escaped HTML. - // Firefox adds newlines at the end. - var content = getInnerHtml(cs); - content = content.replace(/(?:\r\n?|\n)$/, ''); - - // Look for a class like linenums or linenums:<n> where <n> is the - // 1-indexed number of the first line. - var numberLines = cs.className.match(/\blinenums\b(?::(\d+))?/); - - // do the pretty printing - prettyPrintingJob = { - sourceCodeHtml: content, - langExtension: langExtension, - sourceNode: cs, - numberLines: numberLines - ? numberLines[1] && numberLines[1].length ? +numberLines[1] : true - : false - }; - applyDecorator(prettyPrintingJob); - replaceWithPrettyPrintedHtml(); - } - } - } - if (k < elements.length) { - // finish up in a continuation - setTimeout(doWork, 250); - } else if (opt_whenDone) { - opt_whenDone(); - } - } - - function replaceWithPrettyPrintedHtml() { - var newContent = prettyPrintingJob.prettyPrintedHtml; - if (!newContent) { return; } - var cs = prettyPrintingJob.sourceNode; - - // push the prettified html back into the tag. - if (!isRawContent(cs)) { - // just replace the old html with the new - cs.innerHTML = newContent; - } else { - // we need to change the tag to a <pre> since <xmp>s do not allow - // embedded tags such as the span tags used to attach styles to - // sections of source code. - var pre = document.createElement('PRE'); - for (var i = 0; i < cs.attributes.length; ++i) { - var a = cs.attributes[i]; - if (a.specified) { - var aname = a.name.toLowerCase(); - if (aname === 'class') { - pre.className = a.value; // For IE 6 - } else { - pre.setAttribute(a.name, a.value); - } - } - } - pre.innerHTML = newContent; - - // remove the old - cs.parentNode.replaceChild(pre, cs); - cs = pre; - } - } - - doWork(); - } - - window['PR_normalizedHtml'] = normalizedHtml; - window['prettyPrintOne'] = prettyPrintOne; - window['prettyPrint'] = prettyPrint; - window['PR'] = { - 'combinePrefixPatterns': combinePrefixPatterns, - 'createSimpleLexer': createSimpleLexer, - 'registerLangHandler': registerLangHandler, - 'sourceDecorator': sourceDecorator, - 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, - 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, - 'PR_COMMENT': PR_COMMENT, - 'PR_DECLARATION': PR_DECLARATION, - 'PR_KEYWORD': PR_KEYWORD, - 'PR_LITERAL': PR_LITERAL, - 'PR_NOCODE': PR_NOCODE, - 'PR_PLAIN': PR_PLAIN, - 'PR_PUNCTUATION': PR_PUNCTUATION, - 'PR_SOURCE': PR_SOURCE, - 'PR_STRING': PR_STRING, - 'PR_TAG': PR_TAG, - 'PR_TYPE': PR_TYPE - }; -})(); - -//third_party/javascript/google_code_prettify/src/lang-apollo.js -/** - * @license Copyright (C) 2009 Onno Hommes. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for the AGC/AEA Assembly Language as described - * at http://virtualagc.googlecode.com - * <p> - * This file could be used by goodle code to allow syntax highlight for - * Virtual AGC SVN repository or if you don't want to commonize - * the header for the agc/aea html assembly listing. - * - * @author ohommes@alumni.cmu.edu - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // A line comment that starts with ; - [PR['PR_COMMENT'], /^#[^\r\n]*/, null, '#'], - // Whitespace - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], - // A double quoted, possibly multi-line, string. - [PR['PR_STRING'], /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'] - ], - [ - [PR['PR_KEYWORD'], /^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,null], - [PR['PR_TYPE'], /^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null], - // A single quote possibly followed by a word that optionally ends with - // = ! or ?. - [PR['PR_LITERAL'], - /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/], - // Any word including labels that optionally ends with = ! or ?. - [PR['PR_PLAIN'], - /^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i], - // A printable non-space non-special character - [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0()\"\\\';]+/] - ]), - ['apollo', 'agc', 'aea']); - -//third_party/javascript/google_code_prettify/src/lang-clj.js -/** - * @license Copyright (C) 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for Clojure. - * - * - * To use, include prettify.js and this file in your HTML page. - * Then put your code in an HTML tag like - * <pre class="prettyprint lang-lisp">(my lisp code)</pre> - * The lang-cl class identifies the language as common lisp. - * This file supports the following language extensions: - * lang-clj - Clojure - * - * - * I used lang-lisp.js as the basis for this adding the clojure specific - * keywords and syntax. - * - * "Name" = 'Clojure' - * "Author" = 'Rich Hickey' - * "Version" = '1.2' - * "About" = 'Clojure is a lisp for the jvm with concurrency primitives and a richer set of types.' - * - * - * I used <a href="http://clojure.org/Reference">Clojure.org Reference</a> as - * the basis for the reserved word list. - * - * - * @author jwall@google.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // clojure has more paren types than minimal lisp. - ['opn', /^[\(\{\[]+/, null, '([{'], - ['clo', /^[\)\}\]]+/, null, ')]}'], - // A line comment that starts with ; - [PR['PR_COMMENT'], /^;[^\r\n]*/, null, ';'], - // Whitespace - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], - // A double quoted, possibly multi-line, string. - [PR['PR_STRING'], /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'] - ], - [ - // clojure has a much larger set of keywords - [PR['PR_KEYWORD'], /^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/, null], - [PR['PR_TYPE'], /^:[0-9a-zA-Z\-]+/] - ]), - ['clj']); - -//third_party/javascript/google_code_prettify/src/lang-css.js -/** - * @license Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for CSS. - * - * - * To use, include prettify.js and this file in your HTML page. - * Then put your code in an HTML tag like - * <pre class="prettyprint lang-css"></pre> - * - * - * http://www.w3.org/TR/CSS21/grammar.html Section G2 defines the lexical - * grammar. This scheme does not recognize keywords containing escapes. - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // The space production <s> - [PR['PR_PLAIN'], /^[ \t\r\n\f]+/, null, ' \t\r\n\f'] - ], - [ - // Quoted strings. <string1> and <string2> - [PR['PR_STRING'], - /^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/, null], - [PR['PR_STRING'], - /^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/, null], - ['lang-css-str', /^url\(([^\)\"\']*)\)/i], - [PR['PR_KEYWORD'], - /^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i, - null], - // A property name -- an identifier followed by a colon. - ['lang-css-kw', /^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i], - // A C style block comment. The <comment> production. - [PR['PR_COMMENT'], /^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//], - // Escaping text spans - [PR['PR_COMMENT'], /^(?:<!--|-->)/], - // A number possibly containing a suffix. - [PR['PR_LITERAL'], /^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i], - // A hex color - [PR['PR_LITERAL'], /^#(?:[0-9a-f]{3}){1,2}/i], - // An identifier - [PR['PR_PLAIN'], - /^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i], - // A run of punctuation - [PR['PR_PUNCTUATION'], /^[^\s\w\'\"]+/] - ]), - ['css']); -PR['registerLangHandler']( - PR['createSimpleLexer']([], - [ - [PR['PR_KEYWORD'], - /^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i] - ]), - ['css-kw']); -PR['registerLangHandler']( - PR['createSimpleLexer']([], - [ - [PR['PR_STRING'], /^[^\)\"\']+/] - ]), - ['css-str']); - -//third_party/javascript/google_code_prettify/src/lang-go.js -/** - * @license Copyright (C) 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for the Go language.. - * <p> - * Based on the lexical grammar at - * http://golang.org/doc/go_spec.html#Lexical_elements - * <p> - * Go uses a minimal style for highlighting so the below does not distinguish - * strings, keywords, literals, etc. by design. - * From a discussion with the Go designers: - * <pre> - * On Thursday, July 22, 2010, Mike Samuel <...> wrote: - * > On Thu, Jul 22, 2010, Rob 'Commander' Pike <...> wrote: - * >> Personally, I would vote for the subdued style godoc presents at http://golang.org - * >> - * >> Not as fancy as some like, but a case can be made it's the official style. - * >> If people want more colors, I wouldn't fight too hard, in the interest of - * >> encouragement through familiarity, but even then I would ask to shy away - * >> from technicolor starbursts. - * > - * > Like http://golang.org/pkg/go/scanner/ where comments are blue and all - * > other content is black? I can do that. - * </pre> - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace is made up of spaces, tabs and newline characters. - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], - // Not escaped as a string. See note on minimalism above. - [PR['PR_PLAIN'], /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])+(?:\'|$))/, null, '"\''] - ], - [ - // Block comments are delimited by /* and */. - // Single-line comments begin with // and extend to the end of a line. - [PR['PR_COMMENT'], /^(?:\/\/[^\r\n]*|\/\*[\s\S]*?\*\/)/], - [PR['PR_PLAIN'], /^(?:[^\/\"\']|\/(?![\/\*]))+/i] - ]), - ['go']); - -//third_party/javascript/google_code_prettify/src/lang-hs.js -/** - * @license Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for Haskell. - * - * - * To use, include prettify.js and this file in your HTML page. - * Then put your code in an HTML tag like - * <pre class="prettyprint lang-hs">(my lisp code)</pre> - * The lang-cl class identifies the language as common lisp. - * This file supports the following language extensions: - * lang-cl - Common Lisp - * lang-el - Emacs Lisp - * lang-lisp - Lisp - * lang-scm - Scheme - * - * - * I used http://www.informatik.uni-freiburg.de/~thiemann/haskell/haskell98-report-html/syntax-iso.html - * as the basis, but ignore the way the ncomment production nests since this - * makes the lexical grammar irregular. It might be possible to support - * ncomments using the lookbehind filter. - * - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace - // whitechar -> newline | vertab | space | tab | uniWhite - // newline -> return linefeed | return | linefeed | formfeed - [PR['PR_PLAIN'], /^[\t\n\x0B\x0C\r ]+/, null, '\t\n\x0B\x0C\r '], - // Single line double and single-quoted strings. - // char -> ' (graphic<' | \> | space | escape<\&>) ' - // string -> " {graphic<" | \> | space | escape | gap}" - // escape -> \ ( charesc | ascii | decimal | o octal - // | x hexadecimal ) - // charesc -> a | b | f | n | r | t | v | \ | " | ' | & - [PR['PR_STRING'], /^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/, - null, '"'], - [PR['PR_STRING'], /^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/, - null, "'"], - // decimal -> digit{digit} - // octal -> octit{octit} - // hexadecimal -> hexit{hexit} - // integer -> decimal - // | 0o octal | 0O octal - // | 0x hexadecimal | 0X hexadecimal - // float -> decimal . decimal [exponent] - // | decimal exponent - // exponent -> (e | E) [+ | -] decimal - [PR['PR_LITERAL'], - /^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i, - null, '0123456789'] - ], - [ - // Haskell does not have a regular lexical grammar due to the nested - // ncomment. - // comment -> dashes [ any<symbol> {any}] newline - // ncomment -> opencom ANYseq {ncomment ANYseq}closecom - // dashes -> '--' {'-'} - // opencom -> '{-' - // closecom -> '-}' - [PR['PR_COMMENT'], /^(?:(?:--+(?:[^\r\n\x0C]*)?)|(?:\{-(?:[^-]|-+[^-\}])*-\}))/], - // reservedid -> case | class | data | default | deriving | do - // | else | if | import | in | infix | infixl | infixr - // | instance | let | module | newtype | of | then - // | type | where | _ - [PR['PR_KEYWORD'], /^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^a-zA-Z0-9\']|$)/, null], - // qvarid -> [ modid . ] varid - // qconid -> [ modid . ] conid - // varid -> (small {small | large | digit | ' })<reservedid> - // conid -> large {small | large | digit | ' } - // modid -> conid - // small -> ascSmall | uniSmall | _ - // ascSmall -> a | b | ... | z - // uniSmall -> any Unicode lowercase letter - // large -> ascLarge | uniLarge - // ascLarge -> A | B | ... | Z - // uniLarge -> any uppercase or titlecase Unicode letter - [PR['PR_PLAIN'], /^(?:[A-Z][\w\']*\.)*[a-zA-Z][\w\']*/], - // matches the symbol production - [PR['PR_PUNCTUATION'], /^[^\t\n\x0B\x0C\r a-zA-Z0-9\'\"]+/] - ]), - ['hs']); - -//third_party/javascript/google_code_prettify/src/lang-lisp.js -/** - * @license Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for Common Lisp and related languages. - * - * - * To use, include prettify.js and this file in your HTML page. - * Then put your code in an HTML tag like - * <pre class="prettyprint lang-lisp">(my lisp code)</pre> - * The lang-cl class identifies the language as common lisp. - * This file supports the following language extensions: - * lang-cl - Common Lisp - * lang-el - Emacs Lisp - * lang-lisp - Lisp - * lang-scm - Scheme - * - * - * I used http://www.devincook.com/goldparser/doc/meta-language/grammar-LISP.htm - * as the basis, but added line comments that start with ; and changed the atom - * production to disallow unquoted semicolons. - * - * "Name" = 'LISP' - * "Author" = 'John McCarthy' - * "Version" = 'Minimal' - * "About" = 'LISP is an abstract language that organizes ALL' - * | 'data around "lists".' - * - * "Start Symbol" = [s-Expression] - * - * {Atom Char} = {Printable} - {Whitespace} - [()"\''] - * - * Atom = ( {Atom Char} | '\'{Printable} )+ - * - * [s-Expression] ::= [Quote] Atom - * | [Quote] '(' [Series] ')' - * | [Quote] '(' [s-Expression] '.' [s-Expression] ')' - * - * [Series] ::= [s-Expression] [Series] - * | - * - * [Quote] ::= '' !Quote = do not evaluate - * | - * - * - * I used <a href="http://gigamonkeys.com/book/">Practical Common Lisp</a> as - * the basis for the reserved word list. - * - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - ['opn', /^\(+/, null, '('], - ['clo', /^\)+/, null, ')'], - // A line comment that starts with ; - [PR['PR_COMMENT'], /^;[^\r\n]*/, null, ';'], - // Whitespace - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], - // A double quoted, possibly multi-line, string. - [PR['PR_STRING'], /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'] - ], - [ - [PR['PR_KEYWORD'], /^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/, null], - [PR['PR_LITERAL'], - /^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i], - // A single quote possibly followed by a word that optionally ends with - // = ! or ?. - [PR['PR_LITERAL'], - /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/], - // A word that optionally ends with = ! or ?. - [PR['PR_PLAIN'], - /^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i], - // A printable non-space non-special character - [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0()\"\\\';]+/] - ]), - ['cl', 'el', 'lisp', 'scm']); - -//third_party/javascript/google_code_prettify/src/lang-lua.js -/** - * @license Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for Lua. - * - * - * To use, include prettify.js and this file in your HTML page. - * Then put your code in an HTML tag like - * <pre class="prettyprint lang-lua">(my Lua code)</pre> - * - * - * I used http://www.lua.org/manual/5.1/manual.html#2.1 - * Because of the long-bracket concept used in strings and comments, Lua does - * not have a regular lexical grammar, but luckily it fits within the space - * of irregular grammars supported by javascript regular expressions. - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], - // A double or single quoted, possibly multi-line, string. - [PR['PR_STRING'], /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/, null, '"\''] - ], - [ - // A comment is either a line comment that starts with two dashes, or - // two dashes preceding a long bracketed block. - [PR['PR_COMMENT'], /^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/], - // A long bracketed block not preceded by -- is a string. - [PR['PR_STRING'], /^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/], - [PR['PR_KEYWORD'], /^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/, null], - // A number is a hex integer literal, a decimal real literal, or in - // scientific notation. - [PR['PR_LITERAL'], - /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], - // An identifier - [PR['PR_PLAIN'], /^[a-z_]\w*/i], - // A run of punctuation - [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0][^\w\t\n\r \xA0\"\'\-\+=]*/] - ]), - ['lua']); - -//third_party/javascript/google_code_prettify/src/lang-ml.js -/** - * @license Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for OCaml, SML, F# and similar languages. - * - * Based on the lexical grammar at - * http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc270597388 - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace is made up of spaces, tabs and newline characters. - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], - // #if ident/#else/#endif directives delimit conditional compilation - // sections - [PR['PR_COMMENT'], - /^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i, - null, '#'], - // A double or single quoted, possibly multi-line, string. - // F# allows escaped newlines in strings. - [PR['PR_STRING'], /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])(?:\'|$))/, null, '"\''] - ], - [ - // Block comments are delimited by (* and *) and may be - // nested. Single-line comments begin with // and extend to - // the end of a line. - // TODO: (*...*) comments can be nested. This does not handle that. - [PR['PR_COMMENT'], /^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/], - [PR['PR_KEYWORD'], /^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/], - // A number is a hex integer literal, a decimal real literal, or in - // scientific notation. - [PR['PR_LITERAL'], - /^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], - [PR['PR_PLAIN'], /^(?:[a-z_][\w']*[!?#]?|``[^\r\n\t`]*(?:``|$))/i], - // A printable non-space non-special character - [PR['PR_PUNCTUATION'], /^[^\t\n\r \xA0\"\'\w]+/] - ]), - ['fs', 'ml']); - -//third_party/javascript/google_code_prettify/src/lang-proto.js -/** - * @license Copyright (C) 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for Protocol Buffers as described at - * http://code.google.com/p/protobuf/. - * - * Based on the lexical grammar at - * http://research.microsoft.com/fsharp/manual/spec2.aspx#_Toc202383715 - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler'](PR['sourceDecorator']({ - keywords: ( - 'bool bytes default double enum extend extensions false fixed32 ' - + 'fixed64 float group import int32 int64 max message option ' - + 'optional package repeated required returns rpc service ' - + 'sfixed32 sfixed64 sint32 sint64 string syntax to true uint32 ' - + 'uint64'), - cStyleComments: true - }), ['proto']); - -//third_party/javascript/google_code_prettify/src/lang-scala.js -/** - * @license Copyright (C) 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for Scala. - * - * Derived from http://lampsvn.epfl.ch/svn-repos/scala/scala-documentation/trunk/src/reference/SyntaxSummary.tex - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], - // A double or single quoted string - // or a triple double-quoted multi-line string. - [PR['PR_STRING'], - /^(?:"(?:(?:""(?:""?(?!")|[^\\"]|\\.)*"{0,3})|(?:[^"\r\n\\]|\\.)*"?))/, - null, '"'], - [PR['PR_LITERAL'], /^`(?:[^\r\n\\`]|\\.)*`?/, null, '`'], - [PR['PR_PUNCTUATION'], /^[!#%&()*+,\-:;<=>?@\[\\\]^{|}~]+/, null, - '!#%&()*+,-:;<=>?@[\\]^{|}~'] - ], - [ - // A symbol literal is a single quote followed by an identifier with no - // single quote following - // A character literal has single quotes on either side - [PR['PR_STRING'], /^'(?:[^\r\n\\']|\\(?:'|[^\r\n']+))'/], - [PR['PR_LITERAL'], /^'[a-zA-Z_$][\w$]*(?!['$\w])/], - [PR['PR_KEYWORD'], /^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/], - [PR['PR_LITERAL'], /^(?:true|false|null|this)\b/], - [PR['PR_LITERAL'], /^(?:(?:0(?:[0-7]+|X[0-9A-F]+))L?|(?:(?:0|[1-9][0-9]*)(?:(?:\.[0-9]+)?(?:E[+\-]?[0-9]+)?F?|L?))|\\.[0-9]+(?:E[+\-]?[0-9]+)?F?)/i], - // Treat upper camel case identifiers as types. - [PR['PR_TYPE'], /^[$_]*[A-Z][_$A-Z0-9]*[a-z][\w$]*/], - [PR['PR_PLAIN'], /^[$a-zA-Z_][\w$]*/], - [PR['PR_COMMENT'], /^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/], - [PR['PR_PUNCTUATION'], /^(?:\.+|\/)/] - ]), - ['scala']); - -//third_party/javascript/google_code_prettify/src/lang-sql.js -/** - * @license Copyright (C) 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -/** - * @fileoverview - * Registers a language handler for SQL. - * - * - * To use, include prettify.js and this file in your HTML page. - * Then put your code in an HTML tag like - * <pre class="prettyprint lang-sql">(my SQL code)</pre> - * - * - * http://savage.net.au/SQL/sql-99.bnf.html is the basis for the grammar, and - * http://msdn.microsoft.com/en-us/library/aa238507(SQL.80).aspx as the basis - * for the keyword list. - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], - // A double or single quoted, possibly multi-line, string. - [PR['PR_STRING'], /^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/, null, - '"\''] - ], - [ - // A comment is either a line comment that starts with two dashes, or - // two dashes preceding a long bracketed block. - [PR['PR_COMMENT'], /^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/], - [PR['PR_KEYWORD'], /^(?:ADD|ALL|ALTER|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PERCENT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNION|UNIQUE|UPDATE|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WRITETEXT)(?=[^\w-]|$)/i, null], - // A number is a hex integer literal, a decimal real literal, or in - // scientific notation. - [PR['PR_LITERAL'], - /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], - // An identifier - [PR['PR_PLAIN'], /^[a-z_][\w-]*/i], - // A run of punctuation - [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/] - ]), - ['sql']); - -//third_party/javascript/google_code_prettify/src/lang-vb.js -/** - * @license Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - - -/** - * @fileoverview - * Registers a language handler for various flavors of basic. - * - * - * To use, include prettify.js and this file in your HTML page. - * Then put your code in an HTML tag like - * <pre class="prettyprint lang-vb"></pre> - * - * - * http://msdn.microsoft.com/en-us/library/aa711638(VS.71).aspx defines the - * visual basic grammar lexical grammar. - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace - [PR['PR_PLAIN'], /^[\t\n\r \xA0\u2028\u2029]+/, null, '\t\n\r \xA0\u2028\u2029'], - // A double quoted string with quotes escaped by doubling them. - // A single character can be suffixed with C. - [PR['PR_STRING'], /^(?:[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})(?:[\"\u201C\u201D]c|$)|[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})*(?:[\"\u201C\u201D]|$))/i, null, - '"\u201C\u201D'], - // A comment starts with a single quote and runs until the end of the - // line. - [PR['PR_COMMENT'], /^[\'\u2018\u2019][^\r\n\u2028\u2029]*/, null, '\'\u2018\u2019'] - ], - [ - [PR['PR_KEYWORD'], /^(?:AddHandler|AddressOf|Alias|And|AndAlso|Ansi|As|Assembly|Auto|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|New|Next|Not|NotInheritable|NotOverridable|Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Preserve|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TypeOf|Unicode|Until|Variant|Wend|When|While|With|WithEvents|WriteOnly|Xor|EndIf|GoSub|Let|Variant|Wend)\b/i, null], - // A second comment form - [PR['PR_COMMENT'], /^REM[^\r\n\u2028\u2029]*/i], - // A boolean, numeric, or date literal. - [PR['PR_LITERAL'], - /^(?:True\b|False\b|Nothing\b|\d+(?:E[+\-]?\d+[FRD]?|[FRDSIL])?|(?:&H[0-9A-F]+|&O[0-7]+)[SIL]?|\d*\.\d+(?:E[+\-]?\d+)?[FRD]?|#\s+(?:\d+[\-\/]\d+[\-\/]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)?|\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)\s+#)/i], - // An identifier? - [PR['PR_PLAIN'], /^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*\])/i], - // A run of punctuation - [PR['PR_PUNCTUATION'], - /^[^\w\t\n\r \"\'\[\]\xA0\u2018\u2019\u201C\u201D\u2028\u2029]+/], - // Square brackets - [PR['PR_PUNCTUATION'], /^(?:\[|\])/] - ]), - ['vb', 'vbs']); - -//third_party/javascript/google_code_prettify/src/lang-vhdl.js -/** - * @fileoverview - * Registers a language handler for VHDL '93. - * - * Based on the lexical grammar and keywords at - * http://www.iis.ee.ethz.ch/~zimmi/download/vhdl93_syntax.html - * - * @author benoit@ryder.fr - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace - [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'] - ], - [ - // String, character or bit string - [PR['PR_STRING'], /^(?:[BOX]?"(?:[^\"]|"")*"|'.')/i], - // Comment, from two dashes until end of line. - [PR['PR_COMMENT'], /^--[^\r\n]*/], - [PR['PR_KEYWORD'], /^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i, null], - // Type, predefined or standard - [PR['PR_TYPE'], /^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i, null], - // Predefined attributes - [PR['PR_TYPE'], /^\'(?:ACTIVE|ASCENDING|BASE|DELAYED|DRIVING|DRIVING_VALUE|EVENT|HIGH|IMAGE|INSTANCE_NAME|LAST_ACTIVE|LAST_EVENT|LAST_VALUE|LEFT|LEFTOF|LENGTH|LOW|PATH_NAME|POS|PRED|QUIET|RANGE|REVERSE_RANGE|RIGHT|RIGHTOF|SIMPLE_NAME|STABLE|SUCC|TRANSACTION|VAL|VALUE)(?=[^\w-]|$)/i, null], - // Number, decimal or based literal - [PR['PR_LITERAL'], /^\d+(?:_\d+)*(?:#[\w\\.]+#(?:[+\-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:E[+\-]?\d+(?:_\d+)*)?)/i], - // Identifier, basic or extended - [PR['PR_PLAIN'], /^(?:[a-z]\w*|\\[^\\]*\\)/i], - // Punctuation - [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0\-\"\']*/] - ]), - ['vhdl', 'vhd']); - -//third_party/javascript/google_code_prettify/src/lang-wiki.js -/** - * @license Copyright (C) 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview - * Registers a language handler for Wiki pages. - * - * Based on WikiSyntax at http://code.google.com/p/support/wiki/WikiSyntax - * - * @author mikesamuel@gmail.com - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - // Whitespace - [PR['PR_PLAIN'], /^[\t \xA0a-gi-z0-9]+/, null, - '\t \xA0abcdefgijklmnopqrstuvwxyz0123456789'], - // Wiki formatting - [PR['PR_PUNCTUATION'], /^[=*~\^\[\]]+/, null, '=*~^[]'] - ], - [ - // Meta-info like #summary, #labels, etc. - ['lang-wiki.meta', /(?:^^|\r\n?|\n)(#[a-z]+)\b/], - // A WikiWord - [PR['PR_LITERAL'], /^(?:[A-Z][a-z][a-z0-9]+[A-Z][a-z][a-zA-Z0-9]+)\b/ - ], - // A preformatted block in an unknown language - ['lang-', /^\{\{\{([\s\S]+?)\}\}\}/], - // A block of source code in an unknown language - ['lang-', /^`([^\r\n`]+)`/], - // An inline URL. - [PR['PR_STRING'], - /^https?:\/\/[^\/?#\s]*(?:\/[^?#\s]*)?(?:\?[^#\s]*)?(?:#\S*)?/i], - [PR['PR_PLAIN'], /^(?:\r\n|[\s\S])[^#=*~^A-Zh\{`\[\r\n]*/] - ]), - ['wiki']); - -PR['registerLangHandler']( - PR['createSimpleLexer']([[PR['PR_KEYWORD'], /^#[a-z]+/i, null, '#']], []), - ['wiki.meta']); - -//third_party/javascript/google_code_prettify/src/lang-yaml.js -/** Contributed by ribrdb @ code.google.com - */ - -/** - * @fileoverview - * Registers a language handler for YAML. - * - * @author ribrdb - */ - -PR['registerLangHandler']( - PR['createSimpleLexer']( - [ - [PR['PR_PUNCTUATION'], /^[:|>?]+/, null, ':|>?'], - [PR['PR_DECLARATION'], /^%(?:YAML|TAG)[^#\r\n]+/, null, '%'], - [PR['PR_TYPE'], /^[&]\S+/, null, '&'], - [PR['PR_TYPE'], /^!\S*/, null, '!'], - [PR['PR_STRING'], /^"(?:[^\\"]|\\.)*(?:"|$)/, null, '"'], - [PR['PR_STRING'], /^'(?:[^']|'')*(?:'|$)/, null, "'"], - [PR['PR_COMMENT'], /^#[^\r\n]*/, null, '#'], - [PR['PR_PLAIN'], /^\s+/, null, ' \t\r\n'] - ], - [ - [PR['PR_DECLARATION'], /^(?:---|\.\.\.)(?:[\r\n]|$)/], - [PR['PR_PUNCTUATION'], /^-/], - [PR['PR_KEYWORD'], /^\w+:[ \r\n]/], - [PR['PR_PLAIN'], /^\w+/] - ]), ['yaml', 'yml']); - -//third_party/javascript/jquery/v1_7_2/jquery-1.7.2.min.js -/** - * @license jQuery JavaScript Library v1.7.2 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Mar 21 12:46:34 2012 -0700 - */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test("Â ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( -a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f -.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); - -//third_party/javascript/jquery_hashchange/jquery.hashchange.js -/** - * @license - * jQuery hashchange 1.0.0 - * - * (based on jquery.history) - * - * Copyright (c) 2008 Chris Leishman (chrisleishman.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - */ -(function($) { - -$.fn.extend({ - hashchange: function(callback) { this.bind('hashchange', callback) }, - openOnClick: function(href) { - if (href === undefined || href.length == 0) - href = '#'; - return this.click(function(ev) { - if (href && href.charAt(0) == '#') { - // execute load in separate call stack - window.setTimeout(function() { $.locationHash(href) }, 0); - } else { - window.location(href); - } - ev.stopPropagation(); - return false; - }); - } -}); - -// IE 8 introduces the hashchange event natively - so nothing more to do -if ($.browser.msie && document.documentMode && document.documentMode >= 8) { - $.extend({ - locationHash: function(hash) { - if (!hash) hash = '#'; - else if (hash.charAt(0) != '#') hash = '#' + hash; - location.hash = hash; - } - }); - return; -} - -var curHash; -// hidden iframe for IE (earlier than 8) -var iframe; - -$.extend({ - locationHash: function(hash) { - if (curHash === undefined) return; - - if (!hash) hash = '#'; - else if (hash.charAt(0) != '#') hash = '#' + hash; - - location.hash = hash; - - if (curHash == hash) return; - curHash = hash; - - if ($.browser.msie) updateIEFrame(hash); - $.event.trigger('hashchange'); - } -}); - -$(document).ready(function() { - curHash = location.hash; - if ($.browser.msie) { - // stop the callback firing twice during init if no hash present - if (curHash == '') curHash = '#'; - // add hidden iframe for IE - iframe = $('<iframe />').hide().get(0); - $('body').prepend(iframe); - updateIEFrame(location.hash); - setInterval(checkHashIE, 100); - } else { - setInterval(checkHash, 100); - } -}); -$(window).unload(function() { iframe = null }); - -function checkHash() { - var hash = location.hash; - if (hash != curHash) { - curHash = hash; - $.event.trigger('hashchange'); - } -} - -if ($.browser.msie) { - // Attach a live handler for any anchor links - $('a[href^=#]').live('click', function() { - var hash = $(this).attr('href'); - // Don't intercept the click if there is an existing anchor on the page - // that matches this hash - if ($(hash).length == 0 && $('a[name='+hash.slice(1)+']').length == 0) { - $.locationHash(hash); - return false; - } - }); -} - -function checkHashIE() { - // On IE, check for location.hash of iframe - var idoc = iframe.contentDocument || iframe.contentWindow.document; - var hash = idoc.location.hash; - if (hash == '') hash = '#'; - - if (hash != curHash) { - if (location.hash != hash) location.hash = hash; - curHash = hash; - $.event.trigger('hashchange'); - } -} - -function updateIEFrame(hash) { - if (hash == '#') hash = ''; - var idoc = iframe.contentWindow.document; - idoc.open(); - idoc.close(); - if (idoc.location.hash != hash) idoc.location.hash = hash; -} - -})(jQuery); - -//third_party/javascript/jquery_jscrollpane/jquery.jscrollpane.min.js -/* - * @license - * jScrollPane - v2.0.0beta12 - 2012-09-27 - * http://jscrollpane.kelvinluck.com/ - * - * Copyright (c) 2010 Kelvin Luck - * Dual licensed under the MIT or GPL licenses. - */ -(function(b,a,c){b.fn.jScrollPane=function(e){function d(D,O){var ay,Q=this,Y,aj,v,al,T,Z,y,q,az,aE,au,i,I,h,j,aa,U,ap,X,t,A,aq,af,am,G,l,at,ax,x,av,aH,f,L,ai=true,P=true,aG=false,k=false,ao=D.clone(false,false).empty(),ac=b.fn.mwheelIntent?"mwheelIntent.jsp":"mousewheel.jsp";aH=D.css("paddingTop")+" "+D.css("paddingRight")+" "+D.css("paddingBottom")+" "+D.css("paddingLeft");f=(parseInt(D.css("paddingLeft"),10)||0)+(parseInt(D.css("paddingRight"),10)||0);function ar(aQ){var aL,aN,aM,aJ,aI,aP,aO=false,aK=false;ay=aQ;if(Y===c){aI=D.scrollTop();aP=D.scrollLeft();D.css({overflow:"hidden",padding:0});aj=D.innerWidth()+f;v=D.innerHeight();D.width(aj);Y=b('<div class="jspPane" />').css("padding",aH).append(D.children());al=b('<div class="jspContainer" />').css({width:aj+"px",height:v+"px"}).append(Y).appendTo(D)}else{D.css("width","");aO=ay.stickToBottom&&K();aK=ay.stickToRight&&B();aJ=D.innerWidth()+f!=aj||D.outerHeight()!=v;if(aJ){aj=D.innerWidth()+f;v=D.innerHeight();al.css({width:aj+"px",height:v+"px"})}if(!aJ&&L==T&&Y.outerHeight()==Z){D.width(aj);return}L=T;Y.css("width","");D.width(aj);al.find(">.jspVerticalBar,>.jspHorizontalBar").remove().end()}Y.css("overflow","auto");if(aQ.contentWidth){T=aQ.contentWidth}else{T=Y[0].scrollWidth}Z=Y[0].scrollHeight;Y.css("overflow","");y=T/aj;q=Z/v;az=q>1;aE=y>1;if(!(aE||az)){D.removeClass("jspScrollable");Y.css({top:0,width:al.width()-f});n();E();R();w()}else{D.addClass("jspScrollable");aL=ay.maintainPosition&&(I||aa);if(aL){aN=aC();aM=aA()}aF();z();F();if(aL){N(aK?(T-aj):aN,false);M(aO?(Z-v):aM,false)}J();ag();an();if(ay.enableKeyboardNavigation){S()}if(ay.clickOnTrack){p()}C();if(ay.hijackInternalLinks){m()}}if(ay.autoReinitialise&&!av){av=setInterval(function(){ar(ay)},ay.autoReinitialiseDelay)}else{if(!ay.autoReinitialise&&av){clearInterval(av)}}aI&&D.scrollTop(0)&&M(aI,false);aP&&D.scrollLeft(0)&&N(aP,false);D.trigger("jsp-initialised",[aE||az])}function aF(){if(az){al.append(b('<div class="jspVerticalBar" />').append(b('<div class="jspCap jspCapTop" />'),b('<div class="jspTrack" />').append(b('<div class="jspDrag" />').append(b('<div class="jspDragTop" />'),b('<div class="jspDragBottom" />'))),b('<div class="jspCap jspCapBottom" />')));U=al.find(">.jspVerticalBar");ap=U.find(">.jspTrack");au=ap.find(">.jspDrag");if(ay.showArrows){aq=b('<a class="jspArrow jspArrowUp" />').bind("mousedown.jsp",aD(0,-1)).bind("click.jsp",aB);af=b('<a class="jspArrow jspArrowDown" />').bind("mousedown.jsp",aD(0,1)).bind("click.jsp",aB);if(ay.arrowScrollOnHover){aq.bind("mouseover.jsp",aD(0,-1,aq));af.bind("mouseover.jsp",aD(0,1,af))}ak(ap,ay.verticalArrowPositions,aq,af)}t=v;al.find(">.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow").each(function(){t-=b(this).outerHeight()});au.hover(function(){au.addClass("jspHover")},function(){au.removeClass("jspHover")}).bind("mousedown.jsp",function(aI){b("html").bind("dragstart.jsp selectstart.jsp",aB);au.addClass("jspActive");var s=aI.pageY-au.position().top;b("html").bind("mousemove.jsp",function(aJ){V(aJ.pageY-s,false)}).bind("mouseup.jsp mouseleave.jsp",aw);return false});o()}}function o(){ap.height(t+"px");I=0;X=ay.verticalGutter+ap.outerWidth();Y.width(aj-X-f);try{if(U.position().left===0){Y.css("margin-left",X+"px")}}catch(s){}}function z(){if(aE){al.append(b('<div class="jspHorizontalBar" />').append(b('<div class="jspCap jspCapLeft" />'),b('<div class="jspTrack" />').append(b('<div class="jspDrag" />').append(b('<div class="jspDragLeft" />'),b('<div class="jspDragRight" />'))),b('<div class="jspCap jspCapRight" />')));am=al.find(">.jspHorizontalBar");G=am.find(">.jspTrack");h=G.find(">.jspDrag");if(ay.showArrows){ax=b('<a class="jspArrow jspArrowLeft" />').bind("mousedown.jsp",aD(-1,0)).bind("click.jsp",aB);x=b('<a class="jspArrow jspArrowRight" />').bind("mousedown.jsp",aD(1,0)).bind("click.jsp",aB); -if(ay.arrowScrollOnHover){ax.bind("mouseover.jsp",aD(-1,0,ax));x.bind("mouseover.jsp",aD(1,0,x))}ak(G,ay.horizontalArrowPositions,ax,x)}h.hover(function(){h.addClass("jspHover")},function(){h.removeClass("jspHover")}).bind("mousedown.jsp",function(aI){b("html").bind("dragstart.jsp selectstart.jsp",aB);h.addClass("jspActive");var s=aI.pageX-h.position().left;b("html").bind("mousemove.jsp",function(aJ){W(aJ.pageX-s,false)}).bind("mouseup.jsp mouseleave.jsp",aw);return false});l=al.innerWidth();ah()}}function ah(){al.find(">.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow").each(function(){l-=b(this).outerWidth()});G.width(l+"px");aa=0}function F(){if(aE&&az){var aI=G.outerHeight(),s=ap.outerWidth();t-=aI;b(am).find(">.jspCap:visible,>.jspArrow").each(function(){l+=b(this).outerWidth()});l-=s;v-=s;aj-=aI;G.parent().append(b('<div class="jspCorner" />').css("width",aI+"px"));o();ah()}if(aE){Y.width((al.outerWidth()-f)+"px")}Z=Y.outerHeight();q=Z/v;if(aE){at=Math.ceil(1/y*l);if(at>ay.horizontalDragMaxWidth){at=ay.horizontalDragMaxWidth}else{if(at<ay.horizontalDragMinWidth){at=ay.horizontalDragMinWidth}}h.width(at+"px");j=l-at;ae(aa)}if(az){A=Math.ceil(1/q*t);if(A>ay.verticalDragMaxHeight){A=ay.verticalDragMaxHeight}else{if(A<ay.verticalDragMinHeight){A=ay.verticalDragMinHeight}}au.height(A+"px");i=t-A;ad(I)}}function ak(aJ,aL,aI,s){var aN="before",aK="after",aM;if(aL=="os"){aL=/Mac/.test(navigator.platform)?"after":"split"}if(aL==aN){aK=aL}else{if(aL==aK){aN=aL;aM=aI;aI=s;s=aM}}aJ[aN](aI)[aK](s)}function aD(aI,s,aJ){return function(){H(aI,s,this,aJ);this.blur();return false}}function H(aL,aK,aO,aN){aO=b(aO).addClass("jspActive");var aM,aJ,aI=true,s=function(){if(aL!==0){Q.scrollByX(aL*ay.arrowButtonSpeed)}if(aK!==0){Q.scrollByY(aK*ay.arrowButtonSpeed)}aJ=setTimeout(s,aI?ay.initialDelay:ay.arrowRepeatFreq);aI=false};s();aM=aN?"mouseout.jsp":"mouseup.jsp";aN=aN||b("html");aN.bind(aM,function(){aO.removeClass("jspActive");aJ&&clearTimeout(aJ);aJ=null;aN.unbind(aM)})}function p(){w();if(az){ap.bind("mousedown.jsp",function(aN){if(aN.originalTarget===c||aN.originalTarget==aN.currentTarget){var aL=b(this),aO=aL.offset(),aM=aN.pageY-aO.top-I,aJ,aI=true,s=function(){var aR=aL.offset(),aS=aN.pageY-aR.top-A/2,aP=v*ay.scrollPagePercent,aQ=i*aP/(Z-v);if(aM<0){if(I-aQ>aS){Q.scrollByY(-aP)}else{V(aS)}}else{if(aM>0){if(I+aQ<aS){Q.scrollByY(aP)}else{V(aS)}}else{aK();return}}aJ=setTimeout(s,aI?ay.initialDelay:ay.trackClickRepeatFreq);aI=false},aK=function(){aJ&&clearTimeout(aJ);aJ=null;b(document).unbind("mouseup.jsp",aK)};s();b(document).bind("mouseup.jsp",aK);return false}})}if(aE){G.bind("mousedown.jsp",function(aN){if(aN.originalTarget===c||aN.originalTarget==aN.currentTarget){var aL=b(this),aO=aL.offset(),aM=aN.pageX-aO.left-aa,aJ,aI=true,s=function(){var aR=aL.offset(),aS=aN.pageX-aR.left-at/2,aP=aj*ay.scrollPagePercent,aQ=j*aP/(T-aj);if(aM<0){if(aa-aQ>aS){Q.scrollByX(-aP)}else{W(aS)}}else{if(aM>0){if(aa+aQ<aS){Q.scrollByX(aP)}else{W(aS)}}else{aK();return}}aJ=setTimeout(s,aI?ay.initialDelay:ay.trackClickRepeatFreq);aI=false},aK=function(){aJ&&clearTimeout(aJ);aJ=null;b(document).unbind("mouseup.jsp",aK)};s();b(document).bind("mouseup.jsp",aK);return false}})}}function w(){if(G){G.unbind("mousedown.jsp")}if(ap){ap.unbind("mousedown.jsp")}}function aw(){b("html").unbind("dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp");if(au){au.removeClass("jspActive")}if(h){h.removeClass("jspActive")}}function V(s,aI){if(!az){return}if(s<0){s=0}else{if(s>i){s=i}}if(aI===c){aI=ay.animateScroll}if(aI){Q.animate(au,"top",s,ad)}else{au.css("top",s);ad(s)}}function ad(aI){if(aI===c){aI=au.position().top}al.scrollTop(0);I=aI;var aL=I===0,aJ=I==i,aK=aI/i,s=-aK*(Z-v);if(ai!=aL||aG!=aJ){ai=aL;aG=aJ;D.trigger("jsp-arrow-change",[ai,aG,P,k])}u(aL,aJ);Y.css("top",s);D.trigger("jsp-scroll-y",[-s,aL,aJ]).trigger("scroll")}function W(aI,s){if(!aE){return}if(aI<0){aI=0}else{if(aI>j){aI=j}}if(s===c){s=ay.animateScroll}if(s){Q.animate(h,"left",aI,ae) -}else{h.css("left",aI);ae(aI)}}function ae(aI){if(aI===c){aI=h.position().left}al.scrollTop(0);aa=aI;var aL=aa===0,aK=aa==j,aJ=aI/j,s=-aJ*(T-aj);if(P!=aL||k!=aK){P=aL;k=aK;D.trigger("jsp-arrow-change",[ai,aG,P,k])}r(aL,aK);Y.css("left",s);D.trigger("jsp-scroll-x",[-s,aL,aK]).trigger("scroll")}function u(aI,s){if(ay.showArrows){aq[aI?"addClass":"removeClass"]("jspDisabled");af[s?"addClass":"removeClass"]("jspDisabled")}}function r(aI,s){if(ay.showArrows){ax[aI?"addClass":"removeClass"]("jspDisabled");x[s?"addClass":"removeClass"]("jspDisabled")}}function M(s,aI){var aJ=s/(Z-v);V(aJ*i,aI)}function N(aI,s){var aJ=aI/(T-aj);W(aJ*j,s)}function ab(aV,aQ,aJ){var aN,aK,aL,s=0,aU=0,aI,aP,aO,aS,aR,aT;try{aN=b(aV)}catch(aM){return}aK=aN.outerHeight();aL=aN.outerWidth();al.scrollTop(0);al.scrollLeft(0);while(!aN.is(".jspPane")){s+=aN.position().top;aU+=aN.position().left;aN=aN.offsetParent();if(/^body|html$/i.test(aN[0].nodeName)){return}}aI=aA();aO=aI+v;if(s<aI||aQ){aR=s-ay.verticalGutter}else{if(s+aK>aO){aR=s-v+aK+ay.verticalGutter}}if(aR){M(aR,aJ)}aP=aC();aS=aP+aj;if(aU<aP||aQ){aT=aU-ay.horizontalGutter}else{if(aU+aL>aS){aT=aU-aj+aL+ay.horizontalGutter}}if(aT){N(aT,aJ)}}function aC(){return -Y.position().left}function aA(){return -Y.position().top}function K(){var s=Z-v;return(s>20)&&(s-aA()<10)}function B(){var s=T-aj;return(s>20)&&(s-aC()<10)}function ag(){al.unbind(ac).bind(ac,function(aL,aM,aK,aI){var aJ=aa,s=I;Q.scrollBy(aK*ay.mouseWheelSpeed,-aI*ay.mouseWheelSpeed,false);return aJ==aa&&s==I})}function n(){al.unbind(ac)}function aB(){return false}function J(){Y.find(":input,a").unbind("focus.jsp").bind("focus.jsp",function(s){ab(s.target,false)})}function E(){Y.find(":input,a").unbind("focus.jsp")}function S(){var s,aI,aK=[];aE&&aK.push(am[0]);az&&aK.push(U[0]);Y.focus(function(){D.focus()});D.attr("tabindex",0).unbind("keydown.jsp keypress.jsp").bind("keydown.jsp",function(aN){if(aN.target!==this&&!(aK.length&&b(aN.target).closest(aK).length)){return}var aM=aa,aL=I;switch(aN.keyCode){case 40:case 38:case 34:case 32:case 33:case 39:case 37:s=aN.keyCode;aJ();break;case 35:M(Z-v);s=null;break;case 36:M(0);s=null;break}aI=aN.keyCode==s&&aM!=aa||aL!=I;return !aI}).bind("keypress.jsp",function(aL){if(aL.keyCode==s){aJ()}return !aI});if(ay.hideFocus){D.css("outline","none");if("hideFocus" in al[0]){D.attr("hideFocus",true)}}else{D.css("outline","");if("hideFocus" in al[0]){D.attr("hideFocus",false)}}function aJ(){var aM=aa,aL=I;switch(s){case 40:Q.scrollByY(ay.keyboardSpeed,false);break;case 38:Q.scrollByY(-ay.keyboardSpeed,false);break;case 34:case 32:Q.scrollByY(v*ay.scrollPagePercent,false);break;case 33:Q.scrollByY(-v*ay.scrollPagePercent,false);break;case 39:Q.scrollByX(ay.keyboardSpeed,false);break;case 37:Q.scrollByX(-ay.keyboardSpeed,false);break}aI=aM!=aa||aL!=I;return aI}}function R(){D.attr("tabindex","-1").removeAttr("tabindex").unbind("keydown.jsp keypress.jsp")}function C(){if(location.hash&&location.hash.length>1){var aK,aI,aJ=escape(location.hash.substr(1));try{aK=b("#"+aJ+', a[name="'+aJ+'"]')}catch(s){return}if(aK.length&&Y.find(aJ)){if(al.scrollTop()===0){aI=setInterval(function(){if(al.scrollTop()>0){ab(aK,true);b(document).scrollTop(al.position().top);clearInterval(aI)}},50)}else{ab(aK,true);b(document).scrollTop(al.position().top)}}}}function m(){if(b(document.body).data("jspHijack")){return}b(document.body).data("jspHijack",true);b(document.body).delegate("a[href*=#]","click",function(s){var aI=this.href.substr(0,this.href.indexOf("#")),aK=location.href,aO,aP,aJ,aM,aL,aN;if(location.href.indexOf("#")!==-1){aK=location.href.substr(0,location.href.indexOf("#"))}if(aI!==aK){return}aO=escape(this.href.substr(this.href.indexOf("#")+1));aP;try{aP=b("#"+aO+', a[name="'+aO+'"]')}catch(aQ){return}if(!aP.length){return}aJ=aP.closest(".jspScrollable");aM=aJ.data("jsp");aM.scrollToElement(aP,true);if(aJ[0].scrollIntoView){aL=b(a).scrollTop();aN=aP.offset().top;if(aN<aL||aN>aL+b(a).height()){aJ[0].scrollIntoView()}}s.preventDefault() -})}function an(){var aJ,aI,aL,aK,aM,s=false;al.unbind("touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick").bind("touchstart.jsp",function(aN){var aO=aN.originalEvent.touches[0];aJ=aC();aI=aA();aL=aO.pageX;aK=aO.pageY;aM=false;s=true}).bind("touchmove.jsp",function(aQ){if(!s){return}var aP=aQ.originalEvent.touches[0],aO=aa,aN=I;Q.scrollTo(aJ+aL-aP.pageX,aI+aK-aP.pageY);aM=aM||Math.abs(aL-aP.pageX)>5||Math.abs(aK-aP.pageY)>5;return aO==aa&&aN==I}).bind("touchend.jsp",function(aN){s=false}).bind("click.jsp-touchclick",function(aN){if(aM){aM=false;return false}})}function g(){var s=aA(),aI=aC();D.removeClass("jspScrollable").unbind(".jsp");D.replaceWith(ao.append(Y.children()));ao.scrollTop(s);ao.scrollLeft(aI);if(av){clearInterval(av)}}b.extend(Q,{reinitialise:function(aI){aI=b.extend({},ay,aI);ar(aI)},scrollToElement:function(aJ,aI,s){ab(aJ,aI,s)},scrollTo:function(aJ,s,aI){N(aJ,aI);M(s,aI)},scrollToX:function(aI,s){N(aI,s)},scrollToY:function(s,aI){M(s,aI)},scrollToPercentX:function(aI,s){N(aI*(T-aj),s)},scrollToPercentY:function(aI,s){M(aI*(Z-v),s)},scrollBy:function(aI,s,aJ){Q.scrollByX(aI,aJ);Q.scrollByY(s,aJ)},scrollByX:function(s,aJ){var aI=aC()+Math[s<0?"floor":"ceil"](s),aK=aI/(T-aj);W(aK*j,aJ)},scrollByY:function(s,aJ){var aI=aA()+Math[s<0?"floor":"ceil"](s),aK=aI/(Z-v);V(aK*i,aJ)},positionDragX:function(s,aI){W(s,aI)},positionDragY:function(aI,s){V(aI,s)},animate:function(aI,aL,s,aK){var aJ={};aJ[aL]=s;aI.animate(aJ,{duration:ay.animateDuration,easing:ay.animateEase,queue:false,step:aK})},getContentPositionX:function(){return aC()},getContentPositionY:function(){return aA()},getContentWidth:function(){return T},getContentHeight:function(){return Z},getPercentScrolledX:function(){return aC()/(T-aj)},getPercentScrolledY:function(){return aA()/(Z-v)},getIsScrollableH:function(){return aE},getIsScrollableV:function(){return az},getContentPane:function(){return Y},scrollToBottom:function(s){V(i,s)},hijackInternalLinks:b.noop,destroy:function(){g()}});ar(O)}e=b.extend({},b.fn.jScrollPane.defaults,e);b.each(["mouseWheelSpeed","arrowButtonSpeed","trackClickSpeed","keyboardSpeed"],function(){e[this]=e[this]||e.speed});return this.each(function(){var f=b(this),g=f.data("jsp");if(g){g.reinitialise(e)}else{b("script",f).filter('[type="text/javascript"],:not([type])').remove();g=new d(f,e);f.data("jsp",g)}})};b.fn.jScrollPane.defaults={showArrows:false,maintainPosition:true,stickToBottom:false,stickToRight:false,clickOnTrack:true,autoReinitialise:false,autoReinitialiseDelay:500,verticalDragMinHeight:0,verticalDragMaxHeight:99999,horizontalDragMinWidth:0,horizontalDragMaxWidth:99999,contentWidth:c,animateScroll:false,animateDuration:300,animateEase:"linear",hijackInternalLinks:false,verticalGutter:4,horizontalGutter:4,mouseWheelSpeed:0,arrowButtonSpeed:0,arrowRepeatFreq:50,arrowScrollOnHover:false,trackClickSpeed:0,trackClickRepeatFreq:70,verticalArrowPositions:"split",horizontalArrowPositions:"split",enableKeyboardNavigation:true,hideFocus:false,keyboardSpeed:0,initialDelay:300,speed:30,scrollPagePercent:0.8}})(jQuery,this); - -//third_party/javascript/jquery_mousewheel/jquery.mousewheel.min.js -/** - * @license - * Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) - * Licensed under the MIT License (LICENSE.txt). - * - * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. - * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. - * Thanks to: Seamus Leahy for adding deltaX and deltaY - * - * Version: 3.0.6 - * - * Requires: 1.2.2+ - */ -(function(a){function d(b){var c=b||window.event,d=[].slice.call(arguments,1),e=0,f=!0,g=0,h=0;return b=a.event.fix(c),b.type="mousewheel",c.wheelDelta&&(e=c.wheelDelta/120),c.detail&&(e=-c.detail/3),h=e,c.axis!==undefined&&c.axis===c.HORIZONTAL_AXIS&&(h=0,g=-1*e),c.wheelDeltaY!==undefined&&(h=c.wheelDeltaY/120),c.wheelDeltaX!==undefined&&(g=-1*c.wheelDeltaX/120),d.unshift(b,e,g,h),(a.event.dispatch||a.event.handle).apply(this,d)}var b=["DOMMouseScroll","mousewheel"];if(a.event.fixHooks)for(var c=b.length;c;)a.event.fixHooks[b[--c]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=b.length;a;)this.addEventListener(b[--a],d,!1);else this.onmousewheel=d},teardown:function(){if(this.removeEventListener)for(var a=b.length;a;)this.removeEventListener(b[--a],d,!1);else this.onmousewheel=null}},a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery); - -//third_party/javascript/jquery_ui/v1_8_23/js/jquery-ui-1.8.23.custom.min.js -/** - * jQuery UI - * @version 1.8.23 - * @date 2012-08-15 - * @link https://github.com/jquery/jquery-ui - * Includes: jquery.ui.core.js - * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) - * @license MIT (Dual licensed with GPL Version 2 license). - * http://jquery.org/license - */ -(function(a,b){function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;return!b.href||!g||f.nodeName.toLowerCase()!=="map"?!1:(h=a("img[usemap=#"+g+"]")[0],!!h&&d(h))}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(a.ui.version)return;a.extend(a.ui,{version:"1.8.23",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;return a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a("<a>").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function h(b,c,d,f){return a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)}),c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?g["inner"+d].call(this):this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return typeof b!="number"?g["outer"+d].call(this,b):this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.createPseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.curCSS||(a.curCSS=a.css),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!d||!a.element[0].parentNode)return;for(var e=0;e<d.length;e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(b,c){if(a(b).css("overflow")==="hidden")return!1;var d=c&&c==="left"?"scrollLeft":"scrollTop",e=!1;return b[d]>0?!0:(b[d]=1,e=b[d]>0,b[d]=0,e)},isOverAxis:function(a,b,c){return a>b&&a<b+c},isOver:function(b,c,d,e,f,g){return a.ui.isOverAxis(b,d,f)&&a.ui.isOverAxis(c,e,g)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.widget.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){if(a.cleanData){var c=a.cleanData;a.cleanData=function(b){for(var d=0,e;(e=b[d])!=null;d++)try{a(e).triggerHandler("remove")}catch(f){}c(b)}}else{var d=a.fn.remove;a.fn.remove=function(b,c){return this.each(function(){return c||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){try{a(this).triggerHandler("remove")}catch(b){}}),d.call(a(this),b,c)})}}a.widget=function(b,c,d){var e=b.split(".")[0],f;b=b.split(".")[1],f=e+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][f]=function(c){return!!a.data(c,b)},a[e]=a[e]||{},a[e][b]=function(a,b){arguments.length&&this._createWidget(a,b)};var g=new c;g.options=a.extend(!0,{},g.options),a[e][b].prototype=a.extend(!0,g,{namespace:e,widgetName:b,widgetEventPrefix:a[e][b].prototype.widgetEventPrefix||b,widgetBaseClass:f},d),a.widget.bridge(b,a[e][b])},a.widget.bridge=function(c,d){a.fn[c]=function(e){var f=typeof e=="string",g=Array.prototype.slice.call(arguments,1),h=this;return e=!f&&g.length?a.extend.apply(null,[!0,e].concat(g)):e,f&&e.charAt(0)==="_"?h:(f?this.each(function(){var d=a.data(this,c),f=d&&a.isFunction(d[e])?d[e].apply(d,g):d;if(f!==d&&f!==b)return h=f,!1}):this.each(function(){var b=a.data(this,c);b?b.option(e||{})._init():a.data(this,c,new d(e,this))}),h)}},a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)},a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:!1},_createWidget:function(b,c){a.data(c,this.widgetName,this),this.element=a(c),this.options=a.extend(!0,{},this.options,this._getCreateOptions(),b);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName),this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled "+"ui-state-disabled")},widget:function(){return this.element},option:function(c,d){var e=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c=="string"){if(d===b)return this.options[c];e={},e[c]=d}return this._setOptions(e),this},_setOptions:function(b){var c=this;return a.each(b,function(a,b){c._setOption(a,b)}),this},_setOption:function(a,b){return this.options[a]=b,a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled"+" "+"ui-state-disabled").attr("aria-disabled",b),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_trigger:function(b,c,d){var e,f,g=this.options[b];d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent;if(f)for(e in f)e in c||(c[e]=f[e]);return this.element.trigger(c,d),!(a.isFunction(g)&&g.call(this.element[0],c,d)===!1||c.isDefaultPrevented())}}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.mouse.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){var c=!1;a(document).mouseup(function(a){c=!1}),a.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var b=this;this.element.bind("mousedown."+this.widgetName,function(a){return b._mouseDown(a)}).bind("click."+this.widgetName,function(c){if(!0===a.data(c.target,b.widgetName+".preventClickEvent"))return a.removeData(c.target,b.widgetName+".preventClickEvent"),c.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(b){if(c)return;this._mouseStarted&&this._mouseUp(b),this._mouseDownEvent=b;var d=this,e=b.which==1,f=typeof this.options.cancel=="string"&&b.target.nodeName?a(b.target).closest(this.options.cancel).length:!1;if(!e||f||!this._mouseCapture(b))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){this._mouseStarted=this._mouseStart(b)!==!1;if(!this._mouseStarted)return b.preventDefault(),!0}return!0===a.data(b.target,this.widgetName+".preventClickEvent")&&a.removeData(b.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(a){return d._mouseMove(a)},this._mouseUpDelegate=function(a){return d._mouseUp(a)},a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),b.preventDefault(),c=!0,!0},_mouseMove:function(b){return!a.browser.msie||document.documentMode>=9||!!b.button?this._mouseStarted?(this._mouseDrag(b),b.preventDefault()):(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b)),!this._mouseStarted):this._mouseUp(b)},_mouseUp:function(b){return a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b)),!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.position.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;return i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1],this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]===e)return;var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0},top:function(b,c){if(c.at[1]===e)return;var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return!c||!c.ownerDocument?null:b?a.isFunction(b)?this.each(function(c){a(this).offset(b.call(this,c,a(this).offset()))}):this.each(function(){a.offset.setOffset(this,b)}):h.call(this)}),a.curCSS||(a.curCSS=a.css),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.draggable.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},destroy:function(){if(!this.element.data("draggable"))return;return this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy(),this},_mouseCapture:function(b){var c=this.options;return this.helper||c.disabled||a(b.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(b),this.handle?(c.iframeFix&&a(c.iframeFix===!0?"iframe":c.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(a(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(b){var c=this.options;return this.helper=this._createHelper(b),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),a.ui.ddmanager&&(a.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt),c.containment&&this._setContainment(),this._trigger("start",b)===!1?(this._clear(),!1):(this._cacheHelperProportions(),a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this._mouseDrag(b,!0),a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,b),!0)},_mouseDrag:function(b,c){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute");if(!c){var d=this._uiHash();if(this._trigger("drag",b,d)===!1)return this._mouseUp({}),!1;this.position=d.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),!1},_mouseStop:function(b){var c=!1;a.ui.ddmanager&&!this.options.dropBehaviour&&(c=a.ui.ddmanager.drop(this,b)),this.dropped&&(c=this.dropped,this.dropped=!1);var d=this.element[0],e=!1;while(d&&(d=d.parentNode))d==document&&(e=!0);if(!e&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===!0||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var f=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){f._trigger("stop",b)!==!1&&f._clear()})}else this._trigger("stop",b)!==!1&&this._clear();return!1},_mouseUp:function(b){return this.options.iframeFix===!0&&a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b),a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?!0:!1;return a(this.options.handle,this.element).find("*").andSelf().each(function(){this==b.target&&(c=!0)}),c},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo),d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute"),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[b.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,b.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(b.containment=="document"?0:a(window).scrollLeft())+a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b.containment=="document"?0:a(window).scrollTop())+(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)&&b.containment.constructor!=Array){var c=a(b.containment),d=c[0];if(!d)return;var e=c.offset(),f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=c}else b.containment.constructor==Array&&(this.containment=b.containment)},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName),f=b.pageX,g=b.pageY;if(this.originalPosition){var h;if(this.containment){if(this.relative_container){var i=this.relative_container.offset();h=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]}else h=this.containment;b.pageX-this.offset.click.left<h[0]&&(f=h[0]+this.offset.click.left),b.pageY-this.offset.click.top<h[1]&&(g=h[1]+this.offset.click.top),b.pageX-this.offset.click.left>h[2]&&(f=h[2]+this.offset.click.left),b.pageY-this.offset.click.top>h[3]&&(g=h[3]+this.offset.click.top)}if(c.grid){var j=c.grid[1]?this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;g=h?j-this.offset.click.top<h[1]||j-this.offset.click.top>h[3]?j-this.offset.click.top<h[1]?j+c.grid[1]:j-c.grid[1]:j:j;var k=c.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0]:this.originalPageX;f=h?k-this.offset.click.left<h[0]||k-this.offset.click.left>h[2]?k-this.offset.click.left<h[0]?k+c.grid[0]:k-c.grid[0]:k:k}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(b,c,d){return d=d||this._uiHash(),a.ui.plugin.call(this,b,[c,d]),b=="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),a.Widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(a){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),a.extend(a.ui.draggable,{version:"1.8.23"}),a.ui.plugin.add("draggable","connectToSortable",{start:function(b,c){var d=a(this).data("draggable"),e=d.options,f=a.extend({},c,{item:d.element});d.sortables=[],a(e.connectToSortable).each(function(){var c=a.data(this,"sortable");c&&!c.options.disabled&&(d.sortables.push({instance:c,shouldRevert:c.options.revert}),c.refreshPositions(),c._trigger("activate",b,f))})},stop:function(b,c){var d=a(this).data("draggable"),e=a.extend({},c,{item:d.element});a.each(d.sortables,function(){this.instance.isOver?(this.instance.isOver=0,d.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(b),this.instance.options.helper=this.instance.options._helper,d.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",b,e))})},drag:function(b,c){var d=a(this).data("draggable"),e=this,f=function(b){var c=this.offset.click.top,d=this.offset.click.left,e=this.positionAbs.top,f=this.positionAbs.left,g=b.height,h=b.width,i=b.top,j=b.left;return a.ui.isOver(e+c,f+d,i,j,g,h)};a.each(d.sortables,function(f){this.instance.positionAbs=d.positionAbs,this.instance.helperProportions=d.helperProportions,this.instance.offset.click=d.offset.click,this.instance._intersectsWith(this.instance.containerCache)?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=a(e).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return c.helper[0]},b.target=this.instance.currentItem[0],this.instance._mouseCapture(b,!0),this.instance._mouseStart(b,!0,!0),this.instance.offset.click.top=d.offset.click.top,this.instance.offset.click.left=d.offset.click.left,this.instance.offset.parent.left-=d.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=d.offset.parent.top-this.instance.offset.parent.top,d._trigger("toSortable",b),d.dropped=this.instance.element,d.currentItem=d.element,this.instance.fromOutside=d),this.instance.currentItem&&this.instance._mouseDrag(b)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",b,this.instance._uiHash(this.instance)),this.instance._mouseStop(b,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),d._trigger("fromSortable",b),d.dropped=!1)})}}),a.ui.plugin.add("draggable","cursor",{start:function(b,c){var d=a("body"),e=a(this).data("draggable").options;d.css("cursor")&&(e._cursor=d.css("cursor")),d.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;d._cursor&&a("body").css("cursor",d._cursor)}}),a.ui.plugin.add("draggable","opacity",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("opacity")&&(e._opacity=d.css("opacity")),d.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;d._opacity&&a(c.helper).css("opacity",d._opacity)}}),a.ui.plugin.add("draggable","scroll",{start:function(b,c){var d=a(this).data("draggable");d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"&&(d.overflowOffset=d.scrollParent.offset())},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=!1;if(d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"){if(!e.axis||e.axis!="x")d.overflowOffset.top+d.scrollParent[0].offsetHeight-b.pageY<e.scrollSensitivity?d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop+e.scrollSpeed:b.pageY-d.overflowOffset.top<e.scrollSensitivity&&(d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop-e.scrollSpeed);if(!e.axis||e.axis!="y")d.overflowOffset.left+d.scrollParent[0].offsetWidth-b.pageX<e.scrollSensitivity?d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft+e.scrollSpeed:b.pageX-d.overflowOffset.left<e.scrollSensitivity&&(d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft-e.scrollSpeed)}else{if(!e.axis||e.axis!="x")b.pageY-a(document).scrollTop()<e.scrollSensitivity?f=a(document).scrollTop(a(document).scrollTop()-e.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<e.scrollSensitivity&&(f=a(document).scrollTop(a(document).scrollTop()+e.scrollSpeed));if(!e.axis||e.axis!="y")b.pageX-a(document).scrollLeft()<e.scrollSensitivity?f=a(document).scrollLeft(a(document).scrollLeft()-e.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<e.scrollSensitivity&&(f=a(document).scrollLeft(a(document).scrollLeft()+e.scrollSpeed))}f!==!1&&a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(d,b)}}),a.ui.plugin.add("draggable","snap",{start:function(b,c){var d=a(this).data("draggable"),e=d.options;d.snapElements=[],a(e.snap.constructor!=String?e.snap.items||":data(draggable)":e.snap).each(function(){var b=a(this),c=b.offset();this!=d.element[0]&&d.snapElements.push({item:this,width:b.outerWidth(),height:b.outerHeight(),top:c.top,left:c.left})})},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=e.snapTolerance,g=c.offset.left,h=g+d.helperProportions.width,i=c.offset.top,j=i+d.helperProportions.height;for(var k=d.snapElements.length-1;k>=0;k--){var l=d.snapElements[k].left,m=l+d.snapElements[k].width,n=d.snapElements[k].top,o=n+d.snapElements[k].height;if(!(l-f<g&&g<m+f&&n-f<i&&i<o+f||l-f<g&&g<m+f&&n-f<j&&j<o+f||l-f<h&&h<m+f&&n-f<i&&i<o+f||l-f<h&&h<m+f&&n-f<j&&j<o+f)){d.snapElements[k].snapping&&d.options.snap.release&&d.options.snap.release.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=!1;continue}if(e.snapMode!="inner"){var p=Math.abs(n-j)<=f,q=Math.abs(o-i)<=f,r=Math.abs(l-h)<=f,s=Math.abs(m-g)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n-d.helperProportions.height,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l-d.helperProportions.width}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m}).left-d.margins.left)}var t=p||q||r||s;if(e.snapMode!="outer"){var p=Math.abs(n-i)<=f,q=Math.abs(o-j)<=f,r=Math.abs(l-g)<=f,s=Math.abs(m-h)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o-d.helperProportions.height,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m-d.helperProportions.width}).left-d.margins.left)}!d.snapElements[k].snapping&&(p||q||r||s||t)&&d.options.snap.snap&&d.options.snap.snap.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=p||q||r||s||t}}}),a.ui.plugin.add("draggable","stack",{start:function(b,c){var d=a(this).data("draggable").options,e=a.makeArray(a(d.stack)).sort(function(b,c){return(parseInt(a(b).css("zIndex"),10)||0)-(parseInt(a(c).css("zIndex"),10)||0)});if(!e.length)return;var f=parseInt(e[0].style.zIndex)||0;a(e).each(function(a){this.style.zIndex=f+a}),this[0].style.zIndex=f+e.length}}),a.ui.plugin.add("draggable","zIndex",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("zIndex")&&(e._zIndex=d.css("zIndex")),d.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;d._zIndex&&a(c.helper).css("zIndex",d._zIndex)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.droppable.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var b=this.options,c=b.accept;this.isover=0,this.isout=1,this.accept=a.isFunction(c)?c:function(a){return a.is(c)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},a.ui.ddmanager.droppables[b.scope]=a.ui.ddmanager.droppables[b.scope]||[],a.ui.ddmanager.droppables[b.scope].push(this),b.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++)b[c]==this&&b.splice(c,1);return this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable"),this},_setOption:function(b,c){b=="accept"&&(this.accept=a.isFunction(c)?c:function(a){return a.is(c)}),a.Widget.prototype._setOption.apply(this,arguments)},_activate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),c&&this._trigger("activate",b,this.ui(c))},_deactivate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),c&&this._trigger("deactivate",b,this.ui(c))},_over:function(b){var c=a.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return;this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",b,this.ui(c)))},_out:function(b){var c=a.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return;this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",b,this.ui(c)))},_drop:function(b,c){var d=c||a.ui.ddmanager.current;if(!d||(d.currentItem||d.element)[0]==this.element[0])return!1;var e=!1;return this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var b=a.data(this,"droppable");if(b.options.greedy&&!b.options.disabled&&b.options.scope==d.options.scope&&b.accept.call(b.element[0],d.currentItem||d.element)&&a.ui.intersect(d,a.extend(b,{offset:b.element.offset()}),b.options.tolerance))return e=!0,!1}),e?!1:this.accept.call(this.element[0],d.currentItem||d.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",b,this.ui(d)),this.element):!1},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}}),a.extend(a.ui.droppable,{version:"1.8.23"}),a.ui.intersect=function(b,c,d){if(!c.offset)return!1;var e=(b.positionAbs||b.position.absolute).left,f=e+b.helperProportions.width,g=(b.positionAbs||b.position.absolute).top,h=g+b.helperProportions.height,i=c.offset.left,j=i+c.proportions.width,k=c.offset.top,l=k+c.proportions.height;switch(d){case"fit":return i<=e&&f<=j&&k<=g&&h<=l;case"intersect":return i<e+b.helperProportions.width/2&&f-b.helperProportions.width/2<j&&k<g+b.helperProportions.height/2&&h-b.helperProportions.height/2<l;case"pointer":var m=(b.positionAbs||b.position.absolute).left+(b.clickOffset||b.offset.click).left,n=(b.positionAbs||b.position.absolute).top+(b.clickOffset||b.offset.click).top,o=a.ui.isOver(n,m,k,i,c.proportions.height,c.proportions.width);return o;case"touch":return(g>=k&&g<=l||h>=k&&h<=l||g<k&&h>l)&&(e>=i&&e<=j||f>=i&&f<=j||e<i&&f>j);default:return!1}},a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(b,c){var d=a.ui.ddmanager.droppables[b.options.scope]||[],e=c?c.type:null,f=(b.currentItem||b.element).find(":data(droppable)").andSelf();g:for(var h=0;h<d.length;h++){if(d[h].options.disabled||b&&!d[h].accept.call(d[h].element[0],b.currentItem||b.element))continue;for(var i=0;i<f.length;i++)if(f[i]==d[h].element[0]){d[h].proportions.height=0;continue g}d[h].visible=d[h].element.css("display")!="none";if(!d[h].visible)continue;e=="mousedown"&&d[h]._activate.call(d[h],c),d[h].offset=d[h].element.offset(),d[h].proportions={width:d[h].element[0].offsetWidth,height:d[h].element[0].offsetHeight}}},drop:function(b,c){var d=!1;return a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)&&(d=this._drop.call(this,c)||d),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],b.currentItem||b.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,c))}),d},dragStart:function(b,c){b.element.parents(":not(body,html)").bind("scroll.droppable",function(){b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)})},drag:function(b,c){b.options.refreshPositions&&a.ui.ddmanager.prepareOffsets(b,c),a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var d=a.ui.intersect(b,this,this.options.tolerance),e=!d&&this.isover==1?"isout":d&&this.isover==0?"isover":null;if(!e)return;var f;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");g.length&&(f=a.data(g[0],"droppable"),f.greedyChild=e=="isover"?1:0)}f&&e=="isover"&&(f.isover=0,f.isout=1,f._out.call(f,c)),this[e]=1,this[e=="isout"?"isover":"isout"]=0,this[e=="isover"?"_over":"_out"].call(this,c),f&&e=="isout"&&(f.isout=0,f.isover=1,f._over.call(f,c))})},dragStop:function(b,c){b.element.parents(":not(body,html)").unbind("scroll.droppable"),b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)}}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.resizable.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.widget("ui.resizable",a.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var b=this,c=this.options;this.element.addClass("ui-resizable"),a.extend(this,{_aspectRatio:!!c.aspectRatio,aspectRatio:c.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:c.helper||c.ghost||c.animate?c.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(a('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e<d.length;e++){var f=a.trim(d[e]),g="ui-resizable-"+f,h=a('<div class="ui-resizable-handle '+g+'"></div>');h.css({zIndex:c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){if(c.disabled)return;a(this).removeClass("ui-resizable-autohide"),b._handles.show()},function(){if(c.disabled)return;b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}return this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement),this},_mouseCapture:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalMousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");return a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b),!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);return l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",b,this.ui()),!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}return a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.minHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),e<h.maxWidth&&(h.maxWidth=e),g<h.maxHeight&&(h.maxHeight=g);this._vBoundaries=h},_updateCache:function(a){var b=this.options;this.offset=this.helper.offset(),d(a.left)&&(this.position.left=a.left),d(a.top)&&(this.position.top=a.top),d(a.height)&&(this.size.height=a.height),d(a.width)&&(this.size.width=a.width)},_updateRatio:function(a,b){var c=this.options,e=this.position,f=this.size,g=this.axis;return d(a.height)?a.width=a.height*this.aspectRatio:d(a.width)&&(a.height=a.width/this.aspectRatio),g=="sw"&&(a.left=e.left+(f.width-a.width),a.top=null),g=="nw"&&(a.top=e.top+(f.height-a.height),a.left=e.left+(f.width-a.width)),a},_respectSize:function(a,b){var c=this.helper,e=this._vBoundaries,f=this._aspectRatio||b.shiftKey,g=this.axis,h=d(a.width)&&e.maxWidth&&e.maxWidth<a.width,i=d(a.height)&&e.maxHeight&&e.maxHeight<a.height,j=d(a.width)&&e.minWidth&&e.minWidth>a.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;return p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null),a},_proportionallyResize:function(){var b=this.options;if(!this._proportionallyResizeElements.length)return;var c=this.helper||this.element;for(var d=0;d<this._proportionallyResizeElements.length;d++){var e=this._proportionallyResizeElements[d];if(!this.borderDif){var f=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],g=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];this.borderDif=a.map(f,function(a,b){var c=parseInt(a,10)||0,d=parseInt(g[b],10)||0;return c+d})}if(!a.browser.msie||!a(c).is(":hidden")&&!a(c).parents(":hidden").length)e.css({height:c.height()-this.borderDif[0]-this.borderDif[2]||0,width:c.width()-this.borderDif[1]-this.borderDif[3]||0});else continue}},_renderProxy:function(){var b=this.element,c=this.options;this.elementOffset=b.offset();if(this._helper){this.helper=this.helper||a('<div style="overflow:hidden;"></div>');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSize.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.23"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?["width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),10),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!i)return;e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/d.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*d.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.selectable.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var b=this;this.element.addClass("ui-selectable"),this.dragged=!1;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]),c.addClass("ui-selectee"),c.each(function(){var b=a(this),c=b.offset();a.data(this,"selectable-item",{element:this,$element:b,left:c.left,top:c.top,right:c.left+b.outerWidth(),bottom:c.top+b.outerHeight(),startselected:!1,selected:b.hasClass("ui-selected"),selecting:b.hasClass("ui-selecting"),unselecting:b.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=c.addClass("ui-selectee"),this._mouseInit(),this.helper=a("<div class='ui-selectable-helper'></div>")},destroy:function(){return this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable"),this._mouseDestroy(),this},_mouseStart:function(b){var c=this;this.opos=[b.pageX,b.pageY];if(this.options.disabled)return;var d=this.options;this.selectees=a(d.filter,this.element[0]),this._trigger("start",b),a(d.appendTo).append(this.helper),this.helper.css({left:b.clientX,top:b.clientY,width:0,height:0}),d.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var d=a.data(this,"selectable-item");d.startselected=!0,!b.metaKey&&!b.ctrlKey&&(d.$element.removeClass("ui-selected"),d.selected=!1,d.$element.addClass("ui-unselecting"),d.unselecting=!0,c._trigger("unselecting",b,{unselecting:d.element}))}),a(b.target).parents().andSelf().each(function(){var d=a.data(this,"selectable-item");if(d){var e=!b.metaKey&&!b.ctrlKey||!d.$element.hasClass("ui-selected");return d.$element.removeClass(e?"ui-unselecting":"ui-selected").addClass(e?"ui-selecting":"ui-unselecting"),d.unselecting=!e,d.selecting=e,d.selected=e,e?c._trigger("selecting",b,{selecting:d.element}):c._trigger("unselecting",b,{unselecting:d.element}),!1}})},_mouseDrag:function(b){var c=this;this.dragged=!0;if(this.options.disabled)return;var d=this.options,e=this.opos[0],f=this.opos[1],g=b.pageX,h=b.pageY;if(e>g){var i=g;g=e,e=i}if(f>h){var i=h;h=f,f=i}return this.helper.css({left:e,top:f,width:g-e,height:h-f}),this.selectees.each(function(){var i=a.data(this,"selectable-item");if(!i||i.element==c.element[0])return;var j=!1;d.tolerance=="touch"?j=!(i.left>g||i.right<e||i.top>h||i.bottom<f):d.tolerance=="fit"&&(j=i.left>e&&i.right<g&&i.top>f&&i.bottom<h),j?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,c._trigger("selecting",b,{selecting:i.element}))):(i.selecting&&((b.metaKey||b.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),c._trigger("unselecting",b,{unselecting:i.element}))),i.selected&&!b.metaKey&&!b.ctrlKey&&!i.startselected&&(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,c._trigger("unselecting",b,{unselecting:i.element})))}),!1},_mouseStop:function(b){var c=this;this.dragged=!1;var d=this.options;return a(".ui-unselecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-unselecting"),d.unselecting=!1,d.startselected=!1,c._trigger("unselected",b,{unselected:d.element})}),a(".ui-selecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected"),d.selecting=!1,d.selected=!0,d.startselected=!0,c._trigger("selected",b,{selected:d.element})}),this._trigger("stop",b),this.helper.remove(),!1}}),a.extend(a.ui.selectable,{version:"1.8.23"})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.sortable.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.widget("ui.sortable",a.ui.mouse,{widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var a=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},destroy:function(){a.Widget.prototype.destroy.call(this),this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--)this.items[b].item.removeData(this.widgetName+"-item");return this},_setOption:function(b,c){b==="disabled"?(this.options[b]=c,this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(b,c){var d=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(b);var e=null,f=this,g=a(b.target).parents().each(function(){if(a.data(this,d.widgetName+"-item")==f)return e=a(this),!1});a.data(b.target,d.widgetName+"-item")==f&&(e=a(b.target));if(!e)return!1;if(this.options.handle&&!c){var h=!1;a(this.options.handle,e).find("*").andSelf().each(function(){this==b.target&&(h=!0)});if(!h)return!1}return this.currentItem=e,this._removeCurrentsFromItems(),!0},_mouseStart:function(b,c,d){var e=this.options,f=this;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(b),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),e.containment&&this._setContainment(),e.cursor&&(a("body").css("cursor")&&(this._storedCursor=a("body").css("cursor")),a("body").css("cursor",e.cursor)),e.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",e.opacity)),e.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",e.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",b,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(var g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",b,f._uiHash(this));return a.ui.ddmanager&&(a.ui.ddmanager.current=this),a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(b),!0},_mouseDrag:function(b){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var c=this.options,d=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-b.pageY<c.scrollSensitivity?this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop+c.scrollSpeed:b.pageY-this.overflowOffset.top<c.scrollSensitivity&&(this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop-c.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-b.pageX<c.scrollSensitivity?this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft+c.scrollSpeed:b.pageX-this.overflowOffset.left<c.scrollSensitivity&&(this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft-c.scrollSpeed)):(b.pageY-a(document).scrollTop()<c.scrollSensitivity?d=a(document).scrollTop(a(document).scrollTop()-c.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<c.scrollSensitivity&&(d=a(document).scrollTop(a(document).scrollTop()+c.scrollSpeed)),b.pageX-a(document).scrollLeft()<c.scrollSensitivity?d=a(document).scrollLeft(a(document).scrollLeft()-c.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<c.scrollSensitivity&&(d=a(document).scrollLeft(a(document).scrollLeft()+c.scrollSpeed))),d!==!1&&a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var e=this.items.length-1;e>=0;e--){var f=this.items[e],g=f.item[0],h=this._intersectsWithPointer(f);if(!h)continue;if(g!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=g&&!a.ui.contains(this.placeholder[0],g)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],g):!0)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(f))this._rearrange(b,f);else break;this._trigger("change",b,this._uiHash());break}}return this._contactContainers(b),a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),this._trigger("sort",b,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(b,c){if(!b)return;a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,b);if(this.options.revert){var d=this,e=d.placeholder.offset();d.reverting=!0,a(this.helper).animate({left:e.left-this.offset.parent.left-d.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-d.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){d._clear(b)})}else this._clear(b,c);return!1},cancel:function(){var b=this;if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("deactivate",null,b._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,b._uiHash(this)),this.containers[c].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},a(c).each(function(){var c=(a(b.item||this).attr(b.attribute||"id")||"").match(b.expression||/(.+)[-=_](.+)/);c&&d.push((b.key||c[1]+"[]")+"="+(b.key&&b.expression?c[1]:c[2]))}),!d.length&&b.key&&d.push(b.key+"="),d.join("&")},toArray:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},c.each(function(){d.push(a(b.item||this).attr(b.attribute||"id")||"")}),d},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,d=this.positionAbs.top,e=d+this.helperProportions.height,f=a.left,g=f+a.width,h=a.top,i=h+a.height,j=this.offset.click.top,k=this.offset.click.left,l=d+j>h&&d+j<i&&b+k>f&&b+k<g;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?l:f<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<g&&h<d+this.helperProportions.height/2&&e-this.helperProportions.height/2<i},_intersectsWithPointer:function(b){var c=this.options.axis==="x"||a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top,b.height),d=this.options.axis==="y"||a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left,b.width),e=c&&d,f=this._getDragVerticalDirection(),g=this._getDragHorizontalDirection();return e?this.floating?g&&g=="right"||f=="down"?2:1:f&&(f=="down"?2:1):!1},_intersectsWithSides:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top+b.height/2,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left+b.width/2,b.width),e=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();return this.floating&&f?f=="right"&&d||f=="left"&&!d:e&&(e=="down"&&c||e=="up"&&!c)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){return this._refreshItems(a),this.refreshPositions(),this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(b){var c=this,d=[],e=[],f=this._connectWith();if(f&&b)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&e.push([a.isFunction(j.options.items)?j.options.items.call(j.element):a(j.options.items,j.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),j])}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var g=e.length-1;g>=0;g--)e[g][0].each(function(){d.push(this)});return a(d)},_removeCurrentsFromItems:function(){var a=this.currentItem.find(":data("+this.widgetName+"-item)");for(var b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(b){this.items=[],this.containers=[this];var c=this.items,d=this,e=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]],f=this._connectWith();if(f&&this.ready)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&(e.push([a.isFunction(j.options.items)?j.options.items.call(j.element[0],b,{item:this.currentItem}):a(j.options.items,j.element),j]),this.containers.push(j))}}for(var g=e.length-1;g>=0;g--){var k=e[g][1],l=e[g][0];for(var i=0,m=l.length;i<m;i++){var n=a(l[i]);n.data(this.widgetName+"-item",k),c.push({item:n,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var c=this.items.length-1;c>=0;c--){var d=this.items[c];if(d.instance!=this.currentContainer&&this.currentContainer&&d.item[0]!=this.currentItem[0])continue;var e=this.options.toleranceElement?a(this.options.toleranceElement,d.item):d.item;b||(d.width=e.outerWidth(),d.height=e.outerHeight());var f=e.offset();d.left=f.left,d.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var c=this.containers.length-1;c>=0;c--){var f=this.containers[c].element.offset();this.containers[c].containerCache.left=f.left,this.containers[c].containerCache.top=f.top,this.containers[c].containerCache.width=this.containers[c].element.outerWidth(),this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(b){var c=b||this,d=c.options;if(!d.placeholder||d.placeholder.constructor==String){var e=d.placeholder;d.placeholder={element:function(){var b=a(document.createElement(c.currentItem[0].nodeName)).addClass(e||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return e||(b.style.visibility="hidden"),b},update:function(a,b){if(e&&!d.forcePlaceholderSize)return;b.height()||b.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10)),b.width()||b.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft")||0,10)-parseInt(c.currentItem.css("paddingRight")||0,10))}}}c.placeholder=a(d.placeholder.element.call(c.element,c.currentItem)),c.currentItem.after(c.placeholder),d.placeholder.update(c,c.placeholder)},_contactContainers:function(b){var c=null,d=null;for(var e=this.containers.length-1;e>=0;e--){if(a.ui.contains(this.currentItem[0],this.containers[e].element[0]))continue;if(this._intersectsWith(this.containers[e].containerCache)){if(c&&a.ui.contains(this.containers[e].element[0],c.element[0]))continue;c=this.containers[e],d=e}else this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",b,this._uiHash(this)),this.containers[e].containerCache.over=0)}if(!c)return;if(this.containers.length===1)this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1;else if(this.currentContainer!=this.containers[d]){var f=1e4,g=null,h=this.positionAbs[this.containers[d].floating?"left":"top"];for(var i=this.items.length-1;i>=0;i--){if(!a.ui.contains(this.containers[d].element[0],this.items[i].item[0]))continue;var j=this.containers[d].floating?this.items[i].item.offset().left:this.items[i].item.offset().top;Math.abs(j-h)<f&&(f=Math.abs(j-h),g=this.items[i],this.direction=j-h>0?"down":"up")}if(!g&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[d],g?this._rearrange(b,g,null,!0):this._rearrange(b,null,this.containers[d].element,!0),this._trigger("change",b,this._uiHash()),this.containers[d]._trigger("change",b,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1}},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b,this.currentItem])):c.helper=="clone"?this.currentItem.clone():this.currentItem;return d.parents("body").length||a(c.appendTo!="parent"?c.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]),d[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(d[0].style.width==""||c.forceHelperSize)&&d.width(this.currentItem.width()),(d[0].style.height==""||c.forceHelperSize)&&d.height(this.currentItem.height()),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)){var c=a(b.containment)[0],d=a(b.containment).offset(),e=a(c).css("overflow")!="hidden";this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var f=b.pageX,g=b.pageY;if(this.originalPosition){this.containment&&(b.pageX-this.offset.click.left<this.containment[0]&&(f=this.containment[0]+this.offset.click.left),b.pageY-this.offset.click.top<this.containment[1]&&(g=this.containment[1]+this.offset.click.top),b.pageX-this.offset.click.left>this.containment[2]&&(f=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(g=this.containment[3]+this.offset.click.top));if(c.grid){var h=this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1];g=this.containment?h-this.offset.click.top<this.containment[1]||h-this.offset.click.top>this.containment[3]?h-this.offset.click.top<this.containment[1]?h+c.grid[1]:h-c.grid[1]:h:h;var i=this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0];f=this.containment?i-this.offset.click.left<this.containment[0]||i-this.offset.click.left>this.containment[2]?i-this.offset.click.left<this.containment[0]?i+c.grid[0]:i-c.grid[0]:i:i}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_rearrange:function(a,b,c,d){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var e=this,f=this.counter;window.setTimeout(function(){f==e.counter&&e.refreshPositions(!d)},0)},_clear:function(b,c){this.reverting=!1;var d=[],e=this;!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var f in this._storedCSS)if(this._storedCSS[f]=="auto"||this._storedCSS[f]=="static")this._storedCSS[f]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!c&&d.push(function(a){this._trigger("receive",a,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!c&&d.push(function(a){this._trigger("update",a,this._uiHash())});if(!a.ui.contains(this.element[0],this.currentItem[0])){c||d.push(function(a){this._trigger("remove",a,this._uiHash())});for(var f=this.containers.length-1;f>=0;f--)a.ui.contains(this.containers[f].element[0],this.currentItem[0])&&!c&&(d.push(function(a){return function(b){a._trigger("receive",b,this._uiHash(this))}}.call(this,this.containers[f])),d.push(function(a){return function(b){a._trigger("update",b,this._uiHash(this))}}.call(this,this.containers[f])))}for(var f=this.containers.length-1;f>=0;f--)c||d.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over&&(d.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over=0);this._storedCursor&&a("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!c){this._trigger("beforeStop",b,this._uiHash());for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return this.fromOutside=!1,!1}c||this._trigger("beforeStop",b,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!c){for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){a.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(b){var c=b||this;return{helper:c.helper,placeholder:c.placeholder||a([]),position:c.position,originalPosition:c.originalPosition,offset:c.positionAbs,item:c.currentItem,sender:b?b.element:null}}}),a.extend(a.ui.sortable,{version:"1.8.23"})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.accordion.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:!0,clearStyle:!1,collapsible:!1,event:"click",fillSpace:!1,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var b=this,c=b.options;b.running=0,b.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"),b.headers=b.element.find(c.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){if(c.disabled)return;a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){if(c.disabled)return;a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){if(c.disabled)return;a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){if(c.disabled)return;a(this).removeClass("ui-state-focus")}),b.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");if(c.navigation){var d=b.element.find("a").filter(c.navigationFilter).eq(0);if(d.length){var e=d.closest(".ui-accordion-header");e.length?b.active=e:b.active=d.closest(".ui-accordion-content").prev()}}b.active=b._findActive(b.active||c.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top"),b.active.next().addClass("ui-accordion-content-active"),b._createIcons(),b.resize(),b.element.attr("role","tablist"),b.headers.attr("role","tab").bind("keydown.accordion",function(a){return b._keydown(a)}).next().attr("role","tabpanel"),b.headers.not(b.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide(),b.active.length?b.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):b.headers.eq(0).attr("tabIndex",0),a.browser.safari||b.headers.find("a").attr("tabIndex",-1),c.event&&b.headers.bind(c.event.split(" ").join(".accordion ")+".accordion",function(a){b._clickHandler.call(b,a,this),a.preventDefault()})},_createIcons:function(){var b=this.options;b.icons&&(a("<span></span>").addClass("ui-icon "+b.icons.header).prependTo(this.headers),this.active.children(".ui-icon").toggleClass(b.icons.header).toggleClass(b.icons.headerSelected),this.element.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.children(".ui-icon").remove(),this.element.removeClass("ui-accordion-icons")},destroy:function(){var b=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"),this.headers.find("a").removeAttr("tabIndex"),this._destroyIcons();var c=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");return(b.autoHeight||b.fillHeight)&&c.css("height",""),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b=="active"&&this.activate(c),b=="icons"&&(this._destroyIcons(),c&&this._createIcons()),b=="disabled"&&this.headers.add(this.headers.next())[c?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(b){if(this.options.disabled||b.altKey||b.ctrlKey)return;var c=a.ui.keyCode,d=this.headers.length,e=this.headers.index(b.target),f=!1;switch(b.keyCode){case c.RIGHT:case c.DOWN:f=this.headers[(e+1)%d];break;case c.LEFT:case c.UP:f=this.headers[(e-1+d)%d];break;case c.SPACE:case c.ENTER:this._clickHandler({target:b.target},b.target),b.preventDefault()}return f?(a(b.target).attr("tabIndex",-1),a(f).attr("tabIndex",0),f.focus(),!1):!0},resize:function(){var b=this.options,c;if(b.fillSpace){if(a.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}c=this.element.parent().height(),a.browser.msie&&this.element.parent().css("overflow",d),this.headers.each(function(){c-=a(this).outerHeight(!0)}),this.headers.next().each(function(){a(this).height(Math.max(0,c-a(this).innerHeight()+a(this).height()))}).css("overflow","auto")}else b.autoHeight&&(c=0,this.headers.next().each(function(){c=Math.max(c,a(this).height("").height())}).height(c));return this},activate:function(a){this.options.active=a;var b=this._findActive(a)[0];return this._clickHandler({target:b},b),this},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===!1?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,c){var d=this.options;if(d.disabled)return;if(!b.target){if(!d.collapsible)return;this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),this.active.next().addClass("ui-accordion-content-active");var e=this.active.next(),f={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:e},g=this.active=a([]);this._toggle(g,e,f);return}var h=a(b.currentTarget||c),i=h[0]===this.active[0];d.active=d.collapsible&&i?!1:this.headers.index(h);if(this.running||!d.collapsible&&i)return;var j=this.active,g=h.next(),e=this.active.next(),f={options:d,newHeader:i&&d.collapsible?a([]):h,oldHeader:this.active,newContent:i&&d.collapsible?a([]):g,oldContent:e},k=this.headers.index(this.active[0])>this.headers.index(h[0]);this.active=i?a([]):h,this._toggle(g,e,f,i,k),j.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),i||(h.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected),h.next().addClass("ui-accordion-content-active"));return},_toggle:function(b,c,d,e,f){var g=this,h=g.options;g.toShow=b,g.toHide=c,g.data=d;var i=function(){if(!g)return;return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data),g.running=c.size()===0?b.size():c.size();if(h.animated){var j={};h.collapsible&&e?j={toShow:a([]),toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace}:j={toShow:b,toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace},h.proxied||(h.proxied=h.animated),h.proxiedDuration||(h.proxiedDuration=h.duration),h.animated=a.isFunction(h.proxied)?h.proxied(j):h.proxied,h.duration=a.isFunction(h.proxiedDuration)?h.proxiedDuration(j):h.proxiedDuration;var k=a.ui.accordion.animations,l=h.duration,m=h.animated;m&&!k[m]&&!a.easing[m]&&(m="slide"),k[m]||(k[m]=function(a){this.slide(a,{easing:m,duration:l||700})}),k[m](j)}else h.collapsible&&e?b.toggle():(c.hide(),b.show()),i(!0);c.prev().attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).blur(),b.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(this.running)return;this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""}),this.toHide.removeClass("ui-accordion-content-active"),this.toHide.length&&(this.toHide.parent()[0].className=this.toHide.parent()[0].className),this._trigger("change",null,this.data)}}),a.extend(a.ui.accordion,{version:"1.8.23",animations:{slide:function(b,c){b=a.extend({easing:"swing",duration:300},b,c);if(!b.toHide.size()){b.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},b);return}if(!b.toShow.size()){b.toHide.animate({height:"hide",paddingTop:"hide",paddingBottom:"hide"},b);return}var d=b.toShow.css("overflow"),e=0,f={},g={},h=["height","paddingTop","paddingBottom"],i,j=b.toShow;i=j[0].style.width,j.width(j.parent().width()-parseFloat(j.css("paddingLeft"))-parseFloat(j.css("paddingRight"))-(parseFloat(j.css("borderLeftWidth"))||0)-(parseFloat(j.css("borderRightWidth"))||0)),a.each(h,function(c,d){g[d]="hide";var e=(""+a.css(b.toShow[0],d)).match(/^([\d+-.]+)(.*)$/);f[d]={value:e[1],unit:e[2]||"px"}}),b.toShow.css({height:0,overflow:"hidden"}).show(),b.toHide.filter(":hidden").each(b.complete).end().filter(":visible").animate(g,{step:function(a,c){c.prop=="height"&&(e=c.end-c.start===0?0:(c.now-c.start)/(c.end-c.start)),b.toShow[0].style[c.prop]=e*f[c.prop].value+f[c.prop].unit},duration:b.duration,easing:b.easing,complete:function(){b.autoHeight||b.toShow.css("height",""),b.toShow.css({width:i,overflow:d}),b.complete()}})},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1e3:200})}}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.autocomplete.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){var c=0;a.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var b=this,c=this.element[0].ownerDocument,d;this.isMultiLine=this.element.is("textarea"),this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(b.options.disabled||b.element.propAttr("readOnly"))return;d=!1;var e=a.ui.keyCode;switch(c.keyCode){case e.PAGE_UP:b._move("previousPage",c);break;case e.PAGE_DOWN:b._move("nextPage",c);break;case e.UP:b._keyEvent("previous",c);break;case e.DOWN:b._keyEvent("next",c);break;case e.ENTER:case e.NUMPAD_ENTER:b.menu.active&&(d=!0,c.preventDefault());case e.TAB:if(!b.menu.active)return;b.menu.select(c);break;case e.ESCAPE:b.element.val(b.term),b.close(c);break;default:clearTimeout(b.searching),b.searching=setTimeout(function(){b.term!=b.element.val()&&(b.selectedItem=null,b.search(null,c))},b.options.delay)}}).bind("keypress.autocomplete",function(a){d&&(d=!1,a.preventDefault())}).bind("focus.autocomplete",function(){if(b.options.disabled)return;b.selectedItem=null,b.previous=b.element.val()}).bind("blur.autocomplete",function(a){if(b.options.disabled)return;clearTimeout(b.searching),b.closing=setTimeout(function(){b.close(a),b._change(a)},150)}),this._initSource(),this.menu=a("<ul></ul>").addClass("ui-autocomplete").appendTo(a(this.options.appendTo||"body",c)[0]).mousedown(function(c){var d=b.menu.element[0];a(c.target).closest(".ui-menu-item").length||setTimeout(function(){a(document).one("mousedown",function(c){c.target!==b.element[0]&&c.target!==d&&!a.ui.contains(d,c.target)&&b.close()})},1),setTimeout(function(){clearTimeout(b.closing)},13)}).menu({focus:function(a,c){var d=c.item.data("item.autocomplete");!1!==b._trigger("focus",a,{item:d})&&/^key/.test(a.originalEvent.type)&&b.element.val(d.value)},selected:function(a,d){var e=d.item.data("item.autocomplete"),f=b.previous;b.element[0]!==c.activeElement&&(b.element.focus(),b.previous=f,setTimeout(function(){b.previous=f,b.selectedItem=e},1)),!1!==b._trigger("select",a,{item:e})&&b.element.val(e.value),b.term=b.element.val(),b.close(a),b.selectedItem=e},blur:function(a,c){b.menu.element.is(":visible")&&b.element.val()!==b.term&&b.element.val(b.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"),a.fn.bgiframe&&this.menu.element.bgiframe(),b.beforeunloadHandler=function(){b.element.removeAttr("autocomplete")},a(window).bind("beforeunload",b.beforeunloadHandler)},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup"),this.menu.element.remove(),a(window).unbind("beforeunload",this.beforeunloadHandler),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b==="source"&&this._initSource(),b==="appendTo"&&this.menu.element.appendTo(a(c||"body",this.element[0].ownerDocument)[0]),b==="disabled"&&c&&this.xhr&&this.xhr.abort()},_initSource:function(){var b=this,c,d;a.isArray(this.options.source)?(c=this.options.source,this.source=function(b,d){d(a.ui.autocomplete.filter(c,b.term))}):typeof this.options.source=="string"?(d=this.options.source,this.source=function(c,e){b.xhr&&b.xhr.abort(),b.xhr=a.ajax({url:d,data:c,dataType:"json",success:function(a,b){e(a)},error:function(){e([])}})}):this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val(),this.term=this.element.val();if(a.length<this.options.minLength)return this.close(b);clearTimeout(this.closing);if(this._trigger("search",b)===!1)return;return this._search(a)},_search:function(a){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.source({term:a},this._response())},_response:function(){var a=this,b=++c;return function(d){b===c&&a.__response(d),a.pending--,a.pending||a.element.removeClass("ui-autocomplete-loading")}},__response:function(a){!this.options.disabled&&a&&a.length?(a=this._normalize(a),this._suggest(a),this._trigger("open")):this.close()},close:function(a){clearTimeout(this.closing),this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.deactivate(),this._trigger("close",a))},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(b){return b.length&&b[0].label&&b[0].value?b:a.map(b,function(b){return typeof b=="string"?{label:b,value:b}:a.extend({label:b.label||b.value,value:b.value||b.label},b)})},_suggest:function(b){var c=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(c,b),this.menu.deactivate(),this.menu.refresh(),c.show(),this._resizeMenu(),c.position(a.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next(new a.Event("mouseover"))},_resizeMenu:function(){var a=this.menu.element;a.outerWidth(Math.max(a.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(b,c){var d=this;a.each(c,function(a,c){d._renderItem(b,c)})},_renderItem:function(b,c){return a("<li></li>").data("item.autocomplete",c).append(a("<a></a>").text(c.label)).appendTo(b)},_move:function(a,b){if(!this.menu.element.is(":visible")){this.search(null,b);return}if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term),this.menu.deactivate();return}this.menu[a](b)},widget:function(){return this.menu.element},_keyEvent:function(a,b){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(a,b),b.preventDefault()}}),a.extend(a.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},filter:function(b,c){var d=new RegExp(a.ui.autocomplete.escapeRegex(c),"i");return a.grep(b,function(a){return d.test(a.label||a.value||a)})}})})(jQuery),function(a){a.widget("ui.menu",{_create:function(){var b=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){if(!a(c.target).closest(".ui-menu-item a").length)return;c.preventDefault(),b.select(c)}),this.refresh()},refresh:function(){var b=this,c=this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem");c.children("a").addClass("ui-corner-all").attr("tabindex",-1).mouseenter(function(c){b.activate(c,a(this).parent())}).mouseleave(function(){b.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var c=b.offset().top-this.element.offset().top,d=this.element.scrollTop(),e=this.element.height();c<0?this.element.scrollTop(d+c):c>=e&&this.element.scrollTop(d+c-e+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end(),this._trigger("focus",a,{item:b})},deactivate:function(){if(!this.active)return;this.active.children("a").removeClass("ui-state-hover").removeAttr("id"),this._trigger("blur"),this.active=null},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,c){if(!this.active){this.activate(c,this.element.children(b));return}var d=this.active[a+"All"](".ui-menu-item").eq(0);d.length?this.activate(c,d):this.activate(c,this.element.children(b))},nextPage:function(b){if(this.hasScroll()){if(!this.active||this.last()){this.activate(b,this.element.children(".ui-menu-item:first"));return}var c=this.active.offset().top,d=this.element.height(),e=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c-d+a(this).height();return b<10&&b>-10});e.length||(e=this.element.children(".ui-menu-item:last")),this.activate(b,e)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.last()?":first":":last"))},previousPage:function(b){if(this.hasScroll()){if(!this.active||this.first()){this.activate(b,this.element.children(".ui-menu-item:last"));return}var c=this.active.offset().top,d=this.element.height(),e=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c+d-a(this).height();return b<10&&b>-10});e.length||(e=this.element.children(".ui-menu-item:first")),this.activate(b,e)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element[a.fn.prop?"prop":"attr"]("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})}(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.button.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){var c,d,e,f,g="ui-button ui-widget ui-state-default ui-corner-all",h="ui-state-hover ui-state-active ",i="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",j=function(){var b=a(this).find(":ui-button");setTimeout(function(){b.button("refresh")},1)},k=function(b){var c=b.name,d=b.form,e=a([]);return c&&(d?e=a(d).find("[name='"+c+"']"):e=a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form})),e};a.widget("ui.button",{options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",j),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.propAttr("disabled"):this.element.propAttr("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var b=this,h=this.options,i=this.type==="checkbox"||this.type==="radio",l="ui-state-hover"+(i?"":" ui-state-active"),m="ui-state-focus";h.label===null&&(h.label=this.buttonElement.html()),this.buttonElement.addClass(g).attr("role","button").bind("mouseenter.button",function(){if(h.disabled)return;a(this).addClass("ui-state-hover"),this===c&&a(this).addClass("ui-state-active")}).bind("mouseleave.button",function(){if(h.disabled)return;a(this).removeClass(l)}).bind("click.button",function(a){h.disabled&&(a.preventDefault(),a.stopImmediatePropagation())}),this.element.bind("focus.button",function(){b.buttonElement.addClass(m)}).bind("blur.button",function(){b.buttonElement.removeClass(m)}),i&&(this.element.bind("change.button",function(){if(f)return;b.refresh()}),this.buttonElement.bind("mousedown.button",function(a){if(h.disabled)return;f=!1,d=a.pageX,e=a.pageY}).bind("mouseup.button",function(a){if(h.disabled)return;if(d!==a.pageX||e!==a.pageY)f=!0})),this.type==="checkbox"?this.buttonElement.bind("click.button",function(){if(h.disabled||f)return!1;a(this).toggleClass("ui-state-active"),b.buttonElement.attr("aria-pressed",b.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click.button",function(){if(h.disabled||f)return!1;a(this).addClass("ui-state-active"),b.buttonElement.attr("aria-pressed","true");var c=b.element[0];k(c).not(c).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown.button",function(){if(h.disabled)return!1;a(this).addClass("ui-state-active"),c=this,a(document).one("mouseup",function(){c=null})}).bind("mouseup.button",function(){if(h.disabled)return!1;a(this).removeClass("ui-state-active")}).bind("keydown.button",function(b){if(h.disabled)return!1;(b.keyCode==a.ui.keyCode.SPACE||b.keyCode==a.ui.keyCode.ENTER)&&a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(b){b.keyCode===a.ui.keyCode.SPACE&&a(this).click()})),this._setOption("disabled",h.disabled),this._resetButton()},_determineButtonType:function(){this.element.is(":checkbox")?this.type="checkbox":this.element.is(":radio")?this.type="radio":this.element.is("input")?this.type="input":this.type="button";if(this.type==="checkbox"||this.type==="radio"){var a=this.element.parents().filter(":last"),b="label[for='"+this.element.attr("id")+"']";this.buttonElement=a.find(b),this.buttonElement.length||(a=a.length?a.siblings():this.element.siblings(),this.buttonElement=a.filter(b),this.buttonElement.length||(this.buttonElement=a.find(b))),this.element.addClass("ui-helper-hidden-accessible");var c=this.element.is(":checked");c&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.attr("aria-pressed",c)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(g+" "+h+" "+i).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title"),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);if(b==="disabled"){c?this.element.propAttr("disabled",!0):this.element.propAttr("disabled",!1);return}this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b),this.type==="radio"?k(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input"){this.options.label&&this.element.val(this.options.label);return}var b=this.buttonElement.removeClass(i),c=a("<span></span>",this.element[0].ownerDocument).addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary,f=[];d.primary||d.secondary?(this.options.text&&f.push("ui-button-text-icon"+(e?"s":d.primary?"-primary":"-secondary")),d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>"),d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>"),this.options.text||(f.push(e?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||b.attr("title",c))):f.push("ui-button-text-only"),b.addClass(f.join(" "))}}),a.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c),a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var b=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(b?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(b?"ui-corner-left":"ui-corner-right").end().end()},destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"),a.Widget.prototype.destroy.call(this)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.dialog.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){var c="ui-dialog ui-widget ui-widget-content ui-corner-all ",d={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},e={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};a.widget("ui.dialog",{options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",collision:"fit",using:function(b){var c=a(this).css(b).offset().top;c<0&&a(this).css("top",b.top-c)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.options.title=this.options.title||this.originalTitle;var b=this,d=b.options,e=d.title||" ",f=a.ui.dialog.getTitleId(b.element),g=(b.uiDialog=a("<div></div>")).appendTo(document.body).hide().addClass(c+d.dialogClass).css({zIndex:d.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(c){d.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}).attr({role:"dialog","aria-labelledby":f}).mousedown(function(a){b.moveToTop(!1,a)}),h=b.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g),i=(b.uiDialogTitlebar=a("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),j=a('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){j.addClass("ui-state-hover")},function(){j.removeClass("ui-state-hover")}).focus(function(){j.addClass("ui-state-focus")}).blur(function(){j.removeClass("ui-state-focus")}).click(function(a){return b.close(a),!1}).appendTo(i),k=(b.uiDialogTitlebarCloseText=a("<span></span>")).addClass("ui-icon ui-icon-closethick").text(d.closeText).appendTo(j),l=a("<span></span>").addClass("ui-dialog-title").attr("id",f).html(e).prependTo(i);a.isFunction(d.beforeclose)&&!a.isFunction(d.beforeClose)&&(d.beforeClose=d.beforeclose),i.find("*").add(i).disableSelection(),d.draggable&&a.fn.draggable&&b._makeDraggable(),d.resizable&&a.fn.resizable&&b._makeResizable(),b._createButtons(d.buttons),b._isOpen=!1,a.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;return a.overlay&&a.overlay.destroy(),a.uiDialog.hide(),a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),a.uiDialog.remove(),a.originalTitle&&a.element.attr("title",a.originalTitle),a},widget:function(){return this.uiDialog},close:function(b){var c=this,d,e;if(!1===c._trigger("beforeClose",b))return;return c.overlay&&c.overlay.destroy(),c.uiDialog.unbind("keypress.ui-dialog"),c._isOpen=!1,c.options.hide?c.uiDialog.hide(c.options.hide,function(){c._trigger("close",b)}):(c.uiDialog.hide(),c._trigger("close",b)),a.ui.dialog.overlay.resize(),c.options.modal&&(d=0,a(".ui-dialog").each(function(){this!==c.uiDialog[0]&&(e=a(this).css("z-index"),isNaN(e)||(d=Math.max(d,e)))}),a.ui.dialog.maxZ=d),c},isOpen:function(){return this._isOpen},moveToTop:function(b,c){var d=this,e=d.options,f;return e.modal&&!b||!e.stack&&!e.modal?d._trigger("focus",c):(e.zIndex>a.ui.dialog.maxZ&&(a.ui.dialog.maxZ=e.zIndex),d.overlay&&(a.ui.dialog.maxZ+=1,d.overlay.$el.css("z-index",a.ui.dialog.overlay.maxZ=a.ui.dialog.maxZ)),f={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()},a.ui.dialog.maxZ+=1,d.uiDialog.css("z-index",a.ui.dialog.maxZ),d.element.attr(f),d._trigger("focus",c),d)},open:function(){if(this._isOpen)return;var b=this,c=b.options,d=b.uiDialog;return b.overlay=c.modal?new a.ui.dialog.overlay(b):null,b._size(),b._position(c.position),d.show(c.show),b.moveToTop(!0),c.modal&&d.bind("keydown.ui-dialog",function(b){if(b.keyCode!==a.ui.keyCode.TAB)return;var c=a(":tabbable",this),d=c.filter(":first"),e=c.filter(":last");if(b.target===e[0]&&!b.shiftKey)return d.focus(1),!1;if(b.target===d[0]&&b.shiftKey)return e.focus(1),!1}),a(b.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(),b._isOpen=!0,b._trigger("open"),b},_createButtons:function(b){var c=this,d=!1,e=a("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),f=a("<div></div>").addClass("ui-dialog-buttonset").appendTo(e);c.uiDialog.find(".ui-dialog-buttonpane").remove(),typeof b=="object"&&b!==null&&a.each(b,function(){return!(d=!0)}),d&&(a.each(b,function(b,d){d=a.isFunction(d)?{click:d,text:b}:d;var e=a('<button type="button"></button>').click(function(){d.click.apply(c.element[0],arguments)}).appendTo(f);a.each(d,function(a,b){if(a==="click")return;a in e?e[a](b):e.attr(a,b)}),a.fn.button&&e.button()}),e.appendTo(c.uiDialog))},_makeDraggable:function(){function f(a){return{position:a.position,offset:a.offset}}var b=this,c=b.options,d=a(document),e;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(d,g){e=c.height==="auto"?"auto":a(this).height(),a(this).height(a(this).height()).addClass("ui-dialog-dragging"),b._trigger("dragStart",d,f(g))},drag:function(a,c){b._trigger("drag",a,f(c))},stop:function(g,h){c.position=[h.position.left-d.scrollLeft(),h.position.top-d.scrollTop()],a(this).removeClass("ui-dialog-dragging").height(e),b._trigger("dragStop",g,f(h)),a.ui.dialog.overlay.resize()}})},_makeResizable:function(c){function h(a){return{originalPosition:a.originalPosition,originalSize:a.originalSize,position:a.position,size:a.size}}c=c===b?this.options.resizable:c;var d=this,e=d.options,f=d.uiDialog.css("position"),g=typeof c=="string"?c:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:g,start:function(b,c){a(this).addClass("ui-dialog-resizing"),d._trigger("resizeStart",b,h(c))},resize:function(a,b){d._trigger("resize",a,h(b))},stop:function(b,c){a(this).removeClass("ui-dialog-resizing"),e.height=a(this).height(),e.width=a(this).width(),d._trigger("resizeStop",b,h(c)),a.ui.dialog.overlay.resize()}}).css("position",f).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(b){var c=[],d=[0,0],e;if(b){if(typeof b=="string"||typeof b=="object"&&"0"in b)c=b.split?b.split(" "):[b[0],b[1]],c.length===1&&(c[1]=c[0]),a.each(["left","top"],function(a,b){+c[a]===c[a]&&(d[a]=c[a],c[a]=b)}),b={my:c.join(" "),at:c.join(" "),offset:d.join(" ")};b=a.extend({},a.ui.dialog.prototype.options.position,b)}else b=a.ui.dialog.prototype.options.position;e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.css({top:0,left:0}).position(a.extend({of:window},b)),e||this.uiDialog.hide()},_setOptions:function(b){var c=this,f={},g=!1;a.each(b,function(a,b){c._setOption(a,b),a in d&&(g=!0),a in e&&(f[a]=b)}),g&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",f)},_setOption:function(b,d){var e=this,f=e.uiDialog;switch(b){case"beforeclose":b="beforeClose";break;case"buttons":e._createButtons(d);break;case"closeText":e.uiDialogTitlebarCloseText.text(""+d);break;case"dialogClass":f.removeClass(e.options.dialogClass).addClass(c+d);break;case"disabled":d?f.addClass("ui-dialog-disabled"):f.removeClass("ui-dialog-disabled");break;case"draggable":var g=f.is(":data(draggable)");g&&!d&&f.draggable("destroy"),!g&&d&&e._makeDraggable();break;case"position":e._position(d);break;case"resizable":var h=f.is(":data(resizable)");h&&!d&&f.resizable("destroy"),h&&typeof d=="string"&&f.resizable("option","handles",d),!h&&d!==!1&&e._makeResizable(d);break;case"title":a(".ui-dialog-title",e.uiDialogTitlebar).html(""+(d||" "))}a.Widget.prototype._setOption.apply(e,arguments)},_size:function(){var b=this.options,c,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),b.minWidth>b.width&&(b.width=b.minWidth),c=this.uiDialog.css({height:"auto",width:b.width}).height(),d=Math.max(0,b.minHeight-c);if(b.height==="auto")if(a.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();var f=this.element.css("height","auto").height();e||this.uiDialog.hide(),this.element.height(Math.max(f,d))}else this.element.height(Math.max(b.height-c,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),a.extend(a.ui.dialog,{version:"1.8.23",uuid:0,maxZ:0,getTitleId:function(a){var b=a.attr("id");return b||(this.uuid+=1,b=this.uuid),"ui-dialog-title-"+b},overlay:function(b){this.$el=a.ui.dialog.overlay.create(b)}}),a.extend(a.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:a.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(b){this.instances.length===0&&(setTimeout(function(){a.ui.dialog.overlay.instances.length&&a(document).bind(a.ui.dialog.overlay.events,function(b){if(a(b.target).zIndex()<a.ui.dialog.overlay.maxZ)return!1})},1),a(document).bind("keydown.dialog-overlay",function(c){b.options.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}),a(window).bind("resize.dialog-overlay",a.ui.dialog.overlay.resize));var c=(this.oldInstances.pop()||a("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});return a.fn.bgiframe&&c.bgiframe(),this.instances.push(c),c},destroy:function(b){var c=a.inArray(b,this.instances);c!=-1&&this.oldInstances.push(this.instances.splice(c,1)[0]),this.instances.length===0&&a([document,window]).unbind(".dialog-overlay"),b.remove();var d=0;a.each(this.instances,function(){d=Math.max(d,this.css("z-index"))}),this.maxZ=d},height:function(){var b,c;return a.browser.msie&&a.browser.version<7?(b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),b<c?a(window).height()+"px":b+"px"):a(document).height()+"px"},width:function(){var b,c;return a.browser.msie?(b=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),c=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth),b<c?a(window).width()+"px":b+"px"):a(document).width()+"px"},resize:function(){var b=a([]);a.each(a.ui.dialog.overlay.instances,function(){b=b.add(this)}),b.css({width:0,height:0}).css({width:a.ui.dialog.overlay.width(),height:a.ui.dialog.overlay.height()})}}),a.extend(a.ui.dialog.overlay.prototype,{destroy:function(){a.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.slider.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){var c=5;a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var b=this,d=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&d.values.length!==2&&(d.values=[d.values[0],d.values[0]])),this.range=a("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(d.range==="min"||d.range==="max"?" ui-slider-range-"+d.range:"")));for(var i=e.length;i<g;i+=1)h.push(f);this.handles=e.add(a(h.join("")).appendTo(b.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(a){a.preventDefault()}).hover(function(){d.disabled||a(this).addClass("ui-state-hover")},function(){a(this).removeClass("ui-state-hover")}).focus(function(){d.disabled?a(this).blur():(a(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),a(this).addClass("ui-state-focus"))}).blur(function(){a(this).removeClass("ui-state-focus")}),this.handles.each(function(b){a(this).data("index.ui-slider-handle",b)}),this.handles.keydown(function(d){var e=a(this).data("index.ui-slider-handle"),f,g,h,i;if(b.options.disabled)return;switch(d.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.PAGE_UP:case a.ui.keyCode.PAGE_DOWN:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:d.preventDefault();if(!b._keySliding){b._keySliding=!0,a(this).addClass("ui-state-active"),f=b._start(d,e);if(f===!1)return}}i=b.options.step,b.options.values&&b.options.values.length?g=h=b.values(e):g=h=b.value();switch(d.keyCode){case a.ui.keyCode.HOME:h=b._valueMin();break;case a.ui.keyCode.END:h=b._valueMax();break;case a.ui.keyCode.PAGE_UP:h=b._trimAlignValue(g+(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.PAGE_DOWN:h=b._trimAlignValue(g-(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g===b._valueMax())return;h=b._trimAlignValue(g+i);break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g===b._valueMin())return;h=b._trimAlignValue(g-i)}b._slide(d,e,h)}).keyup(function(c){var d=a(this).data("index.ui-slider-handle");b._keySliding&&(b._keySliding=!1,b._stop(c,d),b._change(c,d),a(this).removeClass("ui-state-active"))}),this._refreshValue(),this._animateOff=!1},destroy:function(){return this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"),this._mouseDestroy(),this},_mouseCapture:function(b){var c=this.options,d,e,f,g,h,i,j,k,l;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),d={x:b.pageX,y:b.pageY},e=this._normValueFromMouse(d),f=this._valueMax()-this._valueMin()+1,h=this,this.handles.each(function(b){var c=Math.abs(e-h.values(b));f>c&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i),j===!1?!1:(this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0,!0))},_mouseStart:function(a){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);return this._slide(a,this._handleIndex,c),!1},_mouseStop:function(a){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;return this.orientation==="horizontal"?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),d<0&&(d=0),this.orientation==="vertical"&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e,this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};return this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),this.options.values.length===2&&this.options.range===!0&&(b===0&&c>d||b===1&&c<d)&&(c=d),c!==this.values(b)&&(e=this.values(),e[b]=c,f=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e}),d=this.values(b?0:1),f!==!1&&this.values(b,c,!0))):c!==this.value()&&(f=this._trigger("slide",a,{handle:this.handles[b],value:c}),f!==!1&&this.value(c))},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value=this._trimAlignValue(a),this._refreshValue(),this._change(null,0);return}return this._value()},values:function(b,c){var d,e,f;if(arguments.length>1){this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);return}if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();d=this.options.values,e=arguments[0];for(f=0;f<d.length;f+=1)d[f]=this._trimAlignValue(e[f]),this._change(null,f);this._refreshValue()},_setOption:function(b,c){var d,e=0;a.isArray(this.options.values)&&(e=this.options.values.length),a.Widget.prototype._setOption.apply(this,arguments);switch(b){case"disabled":c?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.propAttr("disabled",!0),this.element.addClass("ui-disabled")):(this.handles.propAttr("disabled",!1),this.element.removeClass("ui-disabled"));break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(d=0;d<e;d+=1)this._change(null,d);this._animateOff=!1}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a),a},_values:function(a){var b,c,d;if(arguments.length)return b=this.options.values[a],b=this._trimAlignValue(b),b;c=this.options.values.slice();for(d=0;d<c.length;d+=1)c[d]=this._trimAlignValue(c[d]);return c},_trimAlignValue:function(a){if(a<=this._valueMin())return this._valueMin();if(a>=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;return Math.abs(c)*2>=b&&(d+=c>0?b:-b),parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,f,g={},h,i,j,k;this.options.values&&this.options.values.length?this.handles.each(function(b,i){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&(d.orientation==="horizontal"?(b===0&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(b===0&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),b==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),b==="max"&&this.orientation==="horizontal"&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),b==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),b==="max"&&this.orientation==="vertical"&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.23"})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.tabs.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){function e(){return++c}function f(){return++d}var c=0,d=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:!1,cookie:null,collapsible:!1,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading…</em>",tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},_create:function(){this._tabify(!0)},_setOption:function(a,b){if(a=="selected"){if(this.options.collapsible&&b==this.options.selected)return;this.select(b)}else this.options[a]=b,this._tabify()},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+f());return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(a,b){return{tab:a,panel:b,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function m(b,c){b.css("display",""),!a.support.opacity&&c.opacity&&b[0].style.removeAttribute("filter")}var d=this,e=this.options,f=/^#.+/;this.list=this.element.find("ol,ul").eq(0),this.lis=a(" > li:has(a[href])",this.list),this.anchors=this.lis.map(function(){return a("a",this)[0]}),this.panels=a([]),this.anchors.each(function(b,c){var g=a(c).attr("href"),h=g.split("#")[0],i;h&&(h===location.toString().split("#")[0]||(i=a("base")[0])&&h===i.href)&&(g=c.hash,c.href=g);if(f.test(g))d.panels=d.panels.add(d.element.find(d._sanitizeSelector(g)));else if(g&&g!=="#"){a.data(c,"href.tabs",g),a.data(c,"load.tabs",g.replace(/#.*$/,""));var j=d._tabId(c);c.href="#"+j;var k=d.element.find("#"+j);k.length||(k=a(e.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(d.panels[b-1]||d.list),k.data("destroy.tabs",!0)),d.panels=d.panels.add(k)}else e.disabled.push(b)}),c?(this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"),this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.lis.addClass("ui-state-default ui-corner-top"),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom"),e.selected===b?(location.hash&&this.anchors.each(function(a,b){if(b.hash==location.hash)return e.selected=a,!1}),typeof e.selected!="number"&&e.cookie&&(e.selected=parseInt(d._cookie(),10)),typeof e.selected!="number"&&this.lis.filter(".ui-tabs-selected").length&&(e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))),e.selected=e.selected||(this.lis.length?0:-1)):e.selected===null&&(e.selected=-1),e.selected=e.selected>=0&&this.anchors[e.selected]||e.selected<0?e.selected:0,e.disabled=a.unique(e.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(a,b){return d.lis.index(a)}))).sort(),a.inArray(e.selected,e.disabled)!=-1&&e.disabled.splice(a.inArray(e.selected,e.disabled),1),this.panels.addClass("ui-tabs-hide"),this.lis.removeClass("ui-tabs-selected ui-state-active"),e.selected>=0&&this.anchors.length&&(d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash)).removeClass("ui-tabs-hide"),this.lis.eq(e.selected).addClass("ui-tabs-selected ui-state-active"),d.element.queue("tabs",function(){d._trigger("show",null,d._ui(d.anchors[e.selected],d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash))[0]))}),this.load(e.selected)),a(window).bind("unload",function(){d.lis.add(d.anchors).unbind(".tabs"),d.lis=d.anchors=d.panels=null})):e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")),this.element[e.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible"),e.cookie&&this._cookie(e.selected,e.cookie);for(var g=0,h;h=this.lis[g];g++)a(h)[a.inArray(g,e.disabled)!=-1&&!a(h).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");e.cache===!1&&this.anchors.removeData("cache.tabs"),this.lis.add(this.anchors).unbind(".tabs");if(e.event!=="mouseover"){var i=function(a,b){b.is(":not(.ui-state-disabled)")&&b.addClass("ui-state-"+a)},j=function(a,b){b.removeClass("ui-state-"+a)};this.lis.bind("mouseover.tabs",function(){i("hover",a(this))}),this.lis.bind("mouseout.tabs",function(){j("hover",a(this))}),this.anchors.bind("focus.tabs",function(){i("focus",a(this).closest("li"))}),this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var k,l;e.fx&&(a.isArray(e.fx)?(k=e.fx[0],l=e.fx[1]):k=l=e.fx);var n=l?function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.hide().removeClass("ui-tabs-hide").animate(l,l.duration||"normal",function(){m(c,l),d._trigger("show",null,d._ui(b,c[0]))})}:function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.removeClass("ui-tabs-hide"),d._trigger("show",null,d._ui(b,c[0]))},o=k?function(a,b){b.animate(k,k.duration||"normal",function(){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),m(b,k),d.element.dequeue("tabs")})}:function(a,b,c){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),d.element.dequeue("tabs")};this.anchors.bind(e.event+".tabs",function(){var b=this,c=a(b).closest("li"),f=d.panels.filter(":not(.ui-tabs-hide)"),g=d.element.find(d._sanitizeSelector(b.hash));if(c.hasClass("ui-tabs-selected")&&!e.collapsible||c.hasClass("ui-state-disabled")||c.hasClass("ui-state-processing")||d.panels.filter(":animated").length||d._trigger("select",null,d._ui(this,g[0]))===!1)return this.blur(),!1;e.selected=d.anchors.index(this),d.abort();if(e.collapsible){if(c.hasClass("ui-tabs-selected"))return e.selected=-1,e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){o(b,f)}).dequeue("tabs"),this.blur(),!1;if(!f.length)return e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this)),this.blur(),!1}e.cookie&&d._cookie(e.selected,e.cookie);if(g.length)f.length&&d.element.queue("tabs",function(){o(b,f)}),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this));else throw"jQuery UI Tabs: Mismatching fragment identifier.";a.browser.msie&&this.blur()}),this.anchors.bind("click.tabs",function(){return!1})},_getIndex:function(a){return typeof a=="string"&&(a=this.anchors.index(this.anchors.filter("[href$='"+a+"']"))),a},destroy:function(){var b=this.options;return this.abort(),this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs"),this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.anchors.each(function(){var b=a.data(this,"href.tabs");b&&(this.href=b);var c=a(this).unbind(".tabs");a.each(["href","load","cache"],function(a,b){c.removeData(b+".tabs")})}),this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}),b.cookie&&this._cookie(null,b.cookie),this},add:function(c,d,e){e===b&&(e=this.anchors.length);var f=this,g=this.options,h=a(g.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,d)),i=c.indexOf("#")?this._tabId(a("a",h)[0]):c.replace("#","");h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",!0);var j=f.element.find("#"+i);return j.length||(j=a(g.panelTemplate).attr("id",i).data("destroy.tabs",!0)),j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"),e>=this.lis.length?(h.appendTo(this.list),j.appendTo(this.list[0].parentNode)):(h.insertBefore(this.lis[e]),j.insertBefore(this.panels[e])),g.disabled=a.map(g.disabled,function(a,b){return a>=e?++a:a}),this._tabify(),this.anchors.length==1&&(g.selected=0,h.addClass("ui-tabs-selected ui-state-active"),j.removeClass("ui-tabs-hide"),this.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[0],f.panels[0]))}),this.load(0)),this._trigger("add",null,this._ui(this.anchors[e],this.panels[e])),this},remove:function(b){b=this._getIndex(b);var c=this.options,d=this.lis.eq(b).remove(),e=this.panels.eq(b).remove();return d.hasClass("ui-tabs-selected")&&this.anchors.length>1&&this.select(b+(b+1<this.anchors.length?1:-1)),c.disabled=a.map(a.grep(c.disabled,function(a,c){return a!=b}),function(a,c){return a>=b?--a:a}),this._tabify(),this._trigger("remove",null,this._ui(d.find("a")[0],e[0])),this},enable:function(b){b=this._getIndex(b);var c=this.options;if(a.inArray(b,c.disabled)==-1)return;return this.lis.eq(b).removeClass("ui-state-disabled"),c.disabled=a.grep(c.disabled,function(a,c){return a!=b}),this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b])),this},disable:function(a){a=this._getIndex(a);var b=this,c=this.options;return a!=c.selected&&(this.lis.eq(a).addClass("ui-state-disabled"),c.disabled.push(a),c.disabled.sort(),this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a]))),this},select:function(a){a=this._getIndex(a);if(a==-1)if(this.options.collapsible&&this.options.selected!=-1)a=this.options.selected;else return this;return this.anchors.eq(a).trigger(this.options.event+".tabs"),this},load:function(b){b=this._getIndex(b);var c=this,d=this.options,e=this.anchors.eq(b)[0],f=a.data(e,"load.tabs");this.abort();if(!f||this.element.queue("tabs").length!==0&&a.data(e,"cache.tabs")){this.element.dequeue("tabs");return}this.lis.eq(b).addClass("ui-state-processing");if(d.spinner){var g=a("span",e);g.data("label.tabs",g.html()).html(d.spinner)}return this.xhr=a.ajax(a.extend({},d.ajaxOptions,{url:f,success:function(f,g){c.element.find(c._sanitizeSelector(e.hash)).html(f),c._cleanup(),d.cache&&a.data(e,"cache.tabs",!0),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.success(f,g)}catch(h){}},error:function(a,f,g){c._cleanup(),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.error(a,f,b,e)}catch(g){}}})),c.element.dequeue("tabs"),this},abort:function(){return this.element.queue([]),this.panels.stop(!1,!0),this.element.queue("tabs",this.element.queue("tabs").splice(-2,2)),this.xhr&&(this.xhr.abort(),delete this.xhr),this._cleanup(),this},url:function(a,b){return this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",b),this},length:function(){return this.anchors.length}}),a.extend(a.ui.tabs,{version:"1.8.23"}),a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(a,b){var c=this,d=this.options,e=c._rotate||(c._rotate=function(b){clearTimeout(c.rotation),c.rotation=setTimeout(function(){var a=d.selected;c.select(++a<c.anchors.length?a:0)},a),b&&b.stopPropagation()}),f=c._unrotate||(c._unrotate=b?function(a){e()}:function(a){a.clientX&&c.rotate(null)});return a?(this.element.bind("tabsshow",e),this.anchors.bind(d.event+".tabs",f),e()):(clearTimeout(c.rotation),this.element.unbind("tabsshow",e),this.anchors.unbind(d.event+".tabs",f),delete this._rotate,delete this._unrotate),this}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.datepicker.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function($,undefined){function Datepicker(){this.debug=!1,this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},$.extend(this._defaults,this.regional[""]),this.dpDiv=bindHover($('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}function bindHover(a){var b="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return a.bind("mouseout",function(a){var c=$(a.target).closest(b);if(!c.length)return;c.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(c){var d=$(c.target).closest(b);if($.datepicker._isDisabledDatepicker(instActive.inline?a.parent()[0]:instActive.input[0])||!d.length)return;d.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),d.addClass("ui-state-hover"),d.hasClass("ui-datepicker-prev")&&d.addClass("ui-datepicker-prev-hover"),d.hasClass("ui-datepicker-next")&&d.addClass("ui-datepicker-next-hover")})}function extendRemove(a,b){$.extend(a,b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}function isArray(a){return a&&($.browser.safari&&typeof a=="object"&&a.length||a.constructor&&a.constructor.toString().match(/\Array\(\)/))}$.extend($.ui,{datepicker:{version:"1.8.23"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){return extendRemove(this._defaults,a||{}),this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(a,b){var c=a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:c,input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:b?bindHover($('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')):this.dpDiv}},_connectDatepicker:function(a,b){var c=$(a);b.append=$([]),b.trigger=$([]);if(c.hasClass(this.markerClassName))return;this._attachments(c,b),c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),this._autoSize(b),$.data(a,PROP_NAME,b),b.settings.disabled&&this._disableDatepicker(a)},_attachments:function(a,b){var c=this._get(b,"appendText"),d=this._get(b,"isRTL");b.append&&b.append.remove(),c&&(b.append=$('<span class="'+this._appendClass+'">'+c+"</span>"),a[d?"before":"after"](b.append)),a.unbind("focus",this._showDatepicker),b.trigger&&b.trigger.remove();var e=this._get(b,"showOn");(e=="focus"||e=="both")&&a.focus(this._showDatepicker);if(e=="button"||e=="both"){var f=this._get(b,"buttonText"),g=this._get(b,"buttonImage");b.trigger=$(this._get(b,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:g,alt:f,title:f}):$('<button type="button"></button>').addClass(this._triggerClass).html(g==""?f:$("<img/>").attr({src:g,alt:f,title:f}))),a[d?"before":"after"](b.trigger),b.trigger.click(function(){return $.datepicker._datepickerShowing&&$.datepicker._lastInput==a[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=a[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(a[0])):$.datepicker._showDatepicker(a[0]),!1})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var d=function(a){var b=0,c=0;for(var d=0;d<a.length;d++)a[d].length>b&&(b=a[d].length,c=d);return c};b.setMonth(d(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort"))),b.setDate(d(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=$(a);if(c.hasClass(this.markerClassName))return;c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),$.data(a,PROP_NAME,b),this._setDate(b,this._getDefaultDate(b),!0),this._updateDatepicker(b),this._updateAlternate(b),b.settings.disabled&&this._disableDatepicker(a),b.dpDiv.css("display","block")},_dialogDatepicker:function(a,b,c,d,e){var f=this._dialogInst;if(!f){this.uuid+=1;var g="dp"+this.uuid;this._dialogInput=$('<input type="text" id="'+g+'" style="position: absolute; top: -100px; width: 0px;"/>'),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),f=this._dialogInst=this._newInst(this._dialogInput,!1),f.settings={},$.data(this._dialogInput[0],PROP_NAME,f)}extendRemove(f.settings,d||{}),b=b&&b.constructor==Date?this._formatDate(f,b):b,this._dialogInput.val(b),this._pos=e?e.length?e:[e.pageX,e.pageY]:null;if(!this._pos){var h=document.documentElement.clientWidth,i=document.documentElement.clientHeight,j=document.documentElement.scrollLeft||document.body.scrollLeft,k=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[h/2-100+j,i/2-150+k]}return this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),f.settings.onSelect=c,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,f),this},_destroyDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!b.hasClass(this.markerClassName))return;var d=a.nodeName.toLowerCase();$.removeData(a,PROP_NAME),d=="input"?(c.append.remove(),c.trigger.remove(),b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(d=="div"||d=="span")&&b.removeClass(this.markerClassName).empty()},_enableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!b.hasClass(this.markerClassName))return;var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!1,c.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().removeClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b})},_disableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!b.hasClass(this.markerClassName))return;var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!0,c.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().addClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b}),this._disabledInputs[this._disabledInputs.length]=a},_isDisabledDatepicker:function(a){if(!a)return!1;for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return!0;return!1},_getInst:function(a){try{return $.data(a,PROP_NAME)}catch(b){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(a,b,c){var d=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?$.extend({},$.datepicker._defaults):d?b=="all"?$.extend({},d.settings):this._get(d,b):null;var e=b||{};typeof b=="string"&&(e={},e[b]=c);if(d){this._curInst==d&&this._hideDatepicker();var f=this._getDateDatepicker(a,!0),g=this._getMinMaxDate(d,"min"),h=this._getMinMaxDate(d,"max");extendRemove(d.settings,e),g!==null&&e.dateFormat!==undefined&&e.minDate===undefined&&(d.settings.minDate=this._formatDate(d,g)),h!==null&&e.dateFormat!==undefined&&e.maxDate===undefined&&(d.settings.maxDate=this._formatDate(d,h)),this._attachments($(a),d),this._autoSize(d),this._setDate(d,f),this._updateAlternate(d),this._updateDatepicker(d)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){var b=this._getInst(a);b&&this._updateDatepicker(b)},_setDateDatepicker:function(a,b){var c=this._getInst(a);c&&(this._setDate(c,b),this._updateDatepicker(c),this._updateAlternate(c))},_getDateDatepicker:function(a,b){var c=this._getInst(a);return c&&!c.inline&&this._setDateFromField(c,b),c?this._getDate(c):null},_doKeyDown:function(a){var b=$.datepicker._getInst(a.target),c=!0,d=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=!0;if($.datepicker._datepickerShowing)switch(a.keyCode){case 9:$.datepicker._hideDatepicker(),c=!1;break;case 13:var e=$("td."+$.datepicker._dayOverClass+":not(."+$.datepicker._currentClass+")",b.dpDiv);e[0]&&$.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,e[0]);var f=$.datepicker._get(b,"onSelect");if(f){var g=$.datepicker._formatDate(b);f.apply(b.input?b.input[0]:null,[g,b])}else $.datepicker._hideDatepicker();return!1;case 27:$.datepicker._hideDatepicker();break;case 33:$.datepicker._adjustDate(a.target,a.ctrlKey?-$.datepicker._get(b,"stepBigMonths"):-$.datepicker._get(b,"stepMonths"),"M");break;case 34:$.datepicker._adjustDate(a.target,a.ctrlKey?+$.datepicker._get(b,"stepBigMonths"):+$.datepicker._get(b,"stepMonths"),"M");break;case 35:(a.ctrlKey||a.metaKey)&&$.datepicker._clearDate(a.target),c=a.ctrlKey||a.metaKey;break;case 36:(a.ctrlKey||a.metaKey)&&$.datepicker._gotoToday(a.target),c=a.ctrlKey||a.metaKey;break;case 37:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,d?1:-1,"D"),c=a.ctrlKey||a.metaKey,a.originalEvent.altKey&&$.datepicker._adjustDate(a.target,a.ctrlKey?-$.datepicker._get(b,"stepBigMonths"):-$.datepicker._get(b,"stepMonths"),"M");break;case 38:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,-7,"D"),c=a.ctrlKey||a.metaKey;break;case 39:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,d?-1:1,"D"),c=a.ctrlKey||a.metaKey,a.originalEvent.altKey&&$.datepicker._adjustDate(a.target,a.ctrlKey?+$.datepicker._get(b,"stepBigMonths"):+$.datepicker._get(b,"stepMonths"),"M");break;case 40:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,7,"D"),c=a.ctrlKey||a.metaKey;break;default:c=!1}else a.keyCode==36&&a.ctrlKey?$.datepicker._showDatepicker(this):c=!1;c&&(a.preventDefault(),a.stopPropagation())},_doKeyPress:function(a){var b=$.datepicker._getInst(a.target);if($.datepicker._get(b,"constrainInput")){var c=$.datepicker._possibleChars($.datepicker._get(b,"dateFormat")),d=String.fromCharCode(a.charCode==undefined?a.keyCode:a.charCode);return a.ctrlKey||a.metaKey||d<" "||!c||c.indexOf(d)>-1}},_doKeyUp:function(a){var b=$.datepicker._getInst(a.target);if(b.input.val()!=b.lastVal)try{var c=$.datepicker.parseDate($.datepicker._get(b,"dateFormat"),b.input?b.input.val():null,$.datepicker._getFormatConfig(b));c&&($.datepicker._setDateFromField(b),$.datepicker._updateAlternate(b),$.datepicker._updateDatepicker(b))}catch(d){$.datepicker.log(d)}return!0},_showDatepicker:function(a){a=a.target||a,a.nodeName.toLowerCase()!="input"&&(a=$("input",a.parentNode)[0]);if($.datepicker._isDisabledDatepicker(a)||$.datepicker._lastInput==a)return;var b=$.datepicker._getInst(a);$.datepicker._curInst&&$.datepicker._curInst!=b&&($.datepicker._curInst.dpDiv.stop(!0,!0),b&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var c=$.datepicker._get(b,"beforeShow"),d=c?c.apply(a,[a,b]):{};if(d===!1)return;extendRemove(b.settings,d),b.lastVal=null,$.datepicker._lastInput=a,$.datepicker._setDateFromField(b),$.datepicker._inDialog&&(a.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(a),$.datepicker._pos[1]+=a.offsetHeight);var e=!1;$(a).parents().each(function(){return e|=$(this).css("position")=="fixed",!e}),e&&$.browser.opera&&($.datepicker._pos[0]-=document.documentElement.scrollLeft,$.datepicker._pos[1]-=document.documentElement.scrollTop);var f={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,b.dpDiv.empty(),b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(b),f=$.datepicker._checkOffset(b,f,e),b.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":e?"fixed":"absolute",display:"none",left:f.left+"px",top:f.top+"px"});if(!b.inline){var g=$.datepicker._get(b,"showAnim"),h=$.datepicker._get(b,"duration"),i=function(){var a=b.dpDiv.find("iframe.ui-datepicker-cover");if(!!a.length){var c=$.datepicker._getBorders(b.dpDiv);a.css({left:-c[0],top:-c[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex($(a).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&$.effects[g]?b.dpDiv.show(g,$.datepicker._get(b,"showOptions"),h,i):b.dpDiv[g||"show"](g?h:null,i),(!g||!h)&&i(),b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus(),$.datepicker._curInst=b}},_updateDatepicker:function(a){var b=this;b.maxRows=4;var c=$.datepicker._getBorders(a.dpDiv);instActive=a,a.dpDiv.empty().append(this._generateHTML(a)),this._attachHandlers(a);var d=a.dpDiv.find("iframe.ui-datepicker-cover");!d.length||d.css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}),a.dpDiv.find("."+this._dayOverClass+" a").mouseover();var e=this._getNumberOfMonths(a),f=e[1],g=17;a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),f>1&&a.dpDiv.addClass("ui-datepicker-multi-"+f).css("width",g*f+"em"),a.dpDiv[(e[0]!=1||e[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),a==$.datepicker._curInst&&$.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var h=a.yearshtml;setTimeout(function(){h===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml),h=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(a){return{thin:1,medium:2,thick:3}[a]||a};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var d=a.dpDiv.outerWidth(),e=a.dpDiv.outerHeight(),f=a.input?a.input.outerWidth():0,g=a.input?a.input.outerHeight():0,h=document.documentElement.clientWidth+(c?0:$(document).scrollLeft()),i=document.documentElement.clientHeight+(c?0:$(document).scrollTop());return b.left-=this._get(a,"isRTL")?d-f:0,b.left-=c&&b.left==a.input.offset().left?$(document).scrollLeft():0,b.top-=c&&b.top==a.input.offset().top+g?$(document).scrollTop():0,b.left-=Math.min(b.left,b.left+d>h&&h>d?Math.abs(b.left+d-h):0),b.top-=Math.min(b.top,b.top+e>i&&i>e?Math.abs(e+g):0),b},_findPos:function(a){var b=this._getInst(a),c=this._get(b,"isRTL");while(a&&(a.type=="hidden"||a.nodeType!=1||$.expr.filters.hidden(a)))a=a[c?"previousSibling":"nextSibling"];var d=$(a).offset();return[d.left,d.top]},_hideDatepicker:function(a){var b=this._curInst;if(!b||a&&b!=$.data(a,PROP_NAME))return;if(this._datepickerShowing){var c=this._get(b,"showAnim"),d=this._get(b,"duration"),e=function(){$.datepicker._tidyDialog(b)};$.effects&&$.effects[c]?b.dpDiv.hide(c,$.datepicker._get(b,"showOptions"),d,e):b.dpDiv[c=="slideDown"?"slideUp":c=="fadeIn"?"fadeOut":"hide"](c?d:null,e),c||e(),this._datepickerShowing=!1;var f=this._get(b,"onClose");f&&f.apply(b.input?b.input[0]:null,[b.input?b.input.val():"",b]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(!$.datepicker._curInst)return;var b=$(a.target),c=$.datepicker._getInst(b[0]);(b[0].id!=$.datepicker._mainDivId&&b.parents("#"+$.datepicker._mainDivId).length==0&&!b.hasClass($.datepicker.markerClassName)&&!b.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||b.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=c)&&$.datepicker._hideDatepicker()},_adjustDate:function(a,b,c){var d=$(a),e=this._getInst(d[0]);if(this._isDisabledDatepicker(d[0]))return;this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c),this._updateDatepicker(e)},_gotoToday:function(a){var b=$(a),c=this._getInst(b[0]);if(this._get(c,"gotoCurrent")&&c.currentDay)c.selectedDay=c.currentDay,c.drawMonth=c.selectedMonth=c.currentMonth,c.drawYear=c.selectedYear=c.currentYear;else{var d=new Date;c.selectedDay=d.getDate(),c.drawMonth=c.selectedMonth=d.getMonth(),c.drawYear=c.selectedYear=d.getFullYear()}this._notifyChange(c),this._adjustDate(b)},_selectMonthYear:function(a,b,c){var d=$(a),e=this._getInst(d[0]);e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10),this._notifyChange(e),this._adjustDate(d)},_selectDay:function(a,b,c,d){var e=$(a);if($(d).hasClass(this._unselectableClass)||this._isDisabledDatepicker(e[0]))return;var f=this._getInst(e[0]);f.selectedDay=f.currentDay=$("a",d).html(),f.selectedMonth=f.currentMonth=b,f.selectedYear=f.currentYear=c,this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))},_clearDate:function(a){var b=$(a),c=this._getInst(b[0]);this._selectDate(b,"")},_selectDate:function(a,b){var c=$(a),d=this._getInst(c[0]);b=b!=null?b:this._formatDate(d),d.input&&d.input.val(b),this._updateAlternate(d);var e=this._get(d,"onSelect");e?e.apply(d.input?d.input[0]:null,[b,d]):d.input&&d.input.trigger("change"),d.inline?this._updateDatepicker(d):(this._hideDatepicker(),this._lastInput=d.input[0],typeof d.input[0]!="object"&&d.input.focus(),this._lastInput=null)},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),d=this._getDate(a),e=this.formatDate(c,d,this._getFormatConfig(a));$(b).each(function(){$(this).val(e)})}},noWeekends:function(a){var b=a.getDay();return[b>0&&b<6,""]},iso8601Week:function(a){var b=new Date(a.getTime());b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;var d=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;d=typeof d!="string"?d:(new Date).getFullYear()%100+parseInt(d,10);var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,g=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,h=(c?c.monthNames:null)||this._defaults.monthNames,i=-1,j=-1,k=-1,l=-1,m=!1,n=function(b){var c=s+1<a.length&&a.charAt(s+1)==b;return c&&s++,c},o=function(a){var c=n(a),d=a=="@"?14:a=="!"?20:a=="y"&&c?4:a=="o"?3:2,e=new RegExp("^\\d{1,"+d+"}"),f=b.substring(r).match(e);if(!f)throw"Missing number at position "+r;return r+=f[0].length,parseInt(f[0],10)},p=function(a,c,d){var e=$.map(n(a)?d:c,function(a,b){return[[b,a]]}).sort(function(a,b){return-(a[1].length-b[1].length)}),f=-1;$.each(e,function(a,c){var d=c[1];if(b.substr(r,d.length).toLowerCase()==d.toLowerCase())return f=c[0],r+=d.length,!1});if(f!=-1)return f+1;throw"Unknown name at position "+r},q=function(){if(b.charAt(r)!=a.charAt(s))throw"Unexpected literal at position "+r;r++},r=0;for(var s=0;s<a.length;s++)if(m)a.charAt(s)=="'"&&!n("'")?m=!1:q();else switch(a.charAt(s)){case"d":k=o("d");break;case"D":p("D",e,f);break;case"o":l=o("o");break;case"m":j=o("m");break;case"M":j=p("M",g,h);break;case"y":i=o("y");break;case"@":var t=new Date(o("@"));i=t.getFullYear(),j=t.getMonth()+1,k=t.getDate();break;case"!":var t=new Date((o("!")-this._ticksTo1970)/1e4);i=t.getFullYear(),j=t.getMonth()+1,k=t.getDate();break;case"'":n("'")?q():m=!0;break;default:q()}if(r<b.length)throw"Extra/unparsed characters found in date: "+b.substring(r);i==-1?i=(new Date).getFullYear():i<100&&(i+=(new Date).getFullYear()-(new Date).getFullYear()%100+(i<=d?0:-100));if(l>-1){j=1,k=l;do{var u=this._getDaysInMonth(i,j-1);if(k<=u)break;j++,k-=u}while(!0)}var t=this._daylightSavingAdjust(new Date(i,j-1,k));if(t.getFullYear()!=i||t.getMonth()+1!=j||t.getDate()!=k)throw"Invalid date";return t},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(a,b,c){if(!b)return"";var d=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,e=(c?c.dayNames:null)||this._defaults.dayNames,f=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,h=function(b){var c=m+1<a.length&&a.charAt(m+1)==b;return c&&m++,c},i=function(a,b,c){var d=""+b;if(h(a))while(d.length<c)d="0"+d;return d},j=function(a,b,c,d){return h(a)?d[b]:c[b]},k="",l=!1;if(b)for(var m=0;m<a.length;m++)if(l)a.charAt(m)=="'"&&!h("'")?l=!1:k+=a.charAt(m);else switch(a.charAt(m)){case"d":k+=i("d",b.getDate(),2);break;case"D":k+=j("D",b.getDay(),d,e);break;case"o":k+=i("o",Math.round(((new Date(b.getFullYear(),b.getMonth(),b.getDate())).getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":k+=i("m",b.getMonth()+1,2);break;case"M":k+=j("M",b.getMonth(),f,g);break;case"y":k+=h("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case"@":k+=b.getTime();break;case"!":k+=b.getTime()*1e4+this._ticksTo1970;break;case"'":h("'")?k+="'":l=!0;break;default:k+=a.charAt(m)}return k},_possibleChars:function(a){var b="",c=!1,d=function(b){var c=e+1<a.length&&a.charAt(e+1)==b;return c&&e++,c};for(var e=0;e<a.length;e++)if(c)a.charAt(e)=="'"&&!d("'")?c=!1:b+=a.charAt(e);else switch(a.charAt(e)){case"d":case"m":case"y":case"@":b+="0123456789";break;case"D":case"M":return null;case"'":d("'")?b+="'":c=!0;break;default:b+=a.charAt(e)}return b},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()==a.lastVal)return;var c=this._get(a,"dateFormat"),d=a.lastVal=a.input?a.input.val():null,e,f;e=f=this._getDefaultDate(a);var g=this._getFormatConfig(a);try{e=this.parseDate(c,d,g)||f}catch(h){this.log(h),d=b?"":d}a.selectedDay=e.getDate(),a.drawMonth=a.selectedMonth=e.getMonth(),a.drawYear=a.selectedYear=e.getFullYear(),a.currentDay=d?e.getDate():0,a.currentMonth=d?e.getMonth():0,a.currentYear=d?e.getFullYear():0,this._adjustInstDate(a)},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},_determineDate:function(a,b,c){var d=function(a){var b=new Date;return b.setDate(b.getDate()+a),b},e=function(b){try{return $.datepicker.parseDate($.datepicker._get(a,"dateFormat"),b,$.datepicker._getFormatConfig(a))}catch(c){}var d=(b.toLowerCase().match(/^c/)?$.datepicker._getDate(a):null)||new Date,e=d.getFullYear(),f=d.getMonth(),g=d.getDate(),h=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,i=h.exec(b);while(i){switch(i[2]||"d"){case"d":case"D":g+=parseInt(i[1],10);break;case"w":case"W":g+=parseInt(i[1],10)*7;break;case"m":case"M":f+=parseInt(i[1],10),g=Math.min(g,$.datepicker._getDaysInMonth(e,f));break;case"y":case"Y":e+=parseInt(i[1],10),g=Math.min(g,$.datepicker._getDaysInMonth(e,f))}i=h.exec(b)}return new Date(e,f,g)},f=b==null||b===""?c:typeof b=="string"?e(b):typeof b=="number"?isNaN(b)?c:d(b):new Date(b.getTime());return f=f&&f.toString()=="Invalid Date"?c:f,f&&(f.setHours(0),f.setMinutes(0),f.setSeconds(0),f.setMilliseconds(0)),this._daylightSavingAdjust(f)},_daylightSavingAdjust:function(a){return a?(a.setHours(a.getHours()>12?a.getHours()+2:0),a):null},_setDate:function(a,b,c){var d=!b,e=a.selectedMonth,f=a.selectedYear,g=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=g.getDate(),a.drawMonth=a.selectedMonth=a.currentMonth=g.getMonth(),a.drawYear=a.selectedYear=a.currentYear=g.getFullYear(),(e!=a.selectedMonth||f!=a.selectedYear)&&!c&&this._notifyChange(a),this._adjustInstDate(a),a.input&&a.input.val(d?"":this._formatDate(a))},_getDate:function(a){var b=!a.currentYear||a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return b},_attachHandlers:function(a){var b=this._get(a,"stepMonths"),c="#"+a.id.replace(/\\\\/g,"\\");a.dpDiv.find("[data-handler]").map(function(){var a={prev:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(c,-b,"M")},next:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(c,+b,"M")},hide:function(){window["DP_jQuery_"+dpuuid].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+dpuuid].datepicker._gotoToday(c)},selectDay:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectDay(c,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(c,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(c,this,"Y"),!1}};$(this).bind(this.getAttribute("data-event"),a[this.getAttribute("data-handler")])})},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),d=this._get(a,"showButtonPanel"),e=this._get(a,"hideIfNoPrevNext"),f=this._get(a,"navigationAsDateFormat"),g=this._getNumberOfMonths(a),h=this._get(a,"showCurrentAtPos"),i=this._get(a,"stepMonths"),j=g[0]!=1||g[1]!=1,k=this._daylightSavingAdjust(a.currentDay?new Date(a.currentYear,a.currentMonth,a.currentDay):new Date(9999,9,9)),l=this._getMinMaxDate(a,"min"),m=this._getMinMaxDate(a,"max"),n=a.drawMonth-h,o=a.drawYear;n<0&&(n+=12,o--);if(m){var p=this._daylightSavingAdjust(new Date(m.getFullYear(),m.getMonth()-g[0]*g[1]+1,m.getDate()));p=l&&p<l?l:p;while(this._daylightSavingAdjust(new Date(o,n,1))>p)n--,n<0&&(n=11,o--)}a.drawMonth=n,a.drawYear=o;var q=this._get(a,"prevText");q=f?this.formatDate(q,this._daylightSavingAdjust(new Date(o,n-i,1)),this._getFormatConfig(a)):q;var r=this._canAdjustMonth(a,-1,o,n)?'<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click" title="'+q+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+q+"</span></a>":e?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+q+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+q+"</span></a>",s=this._get(a,"nextText");s=f?this.formatDate(s,this._daylightSavingAdjust(new Date(o,n+i,1)),this._getFormatConfig(a)):s;var t=this._canAdjustMonth(a,1,o,n)?'<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click" title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>":e?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>",u=this._get(a,"currentText"),v=this._get(a,"gotoCurrent")&&a.currentDay?k:b;u=f?this.formatDate(u,v,this._getFormatConfig(a)):u;var w=a.inline?"":'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">'+this._get(a,"closeText")+"</button>",x=d?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?w:"")+(this._isInRange(a,v)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click">'+u+"</button>":"")+(c?"":w)+"</div>":"",y=parseInt(this._get(a,"firstDay"),10);y=isNaN(y)?0:y;var z=this._get(a,"showWeek"),A=this._get(a,"dayNames"),B=this._get(a,"dayNamesShort"),C=this._get(a,"dayNamesMin"),D=this._get(a,"monthNames"),E=this._get(a,"monthNamesShort"),F=this._get(a,"beforeShowDay"),G=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths"),I=this._get(a,"calculateWeek")||this.iso8601Week,J=this._getDefaultDate(a),K="";for(var L=0;L<g[0];L++){var M="";this.maxRows=4;for(var N=0;N<g[1];N++){var O=this._daylightSavingAdjust(new Date(o,n,a.selectedDay)),P=" ui-corner-all",Q="";if(j){Q+='<div class="ui-datepicker-group';if(g[1]>1)switch(N){case 0:Q+=" ui-datepicker-group-first",P=" ui-corner-"+(c?"right":"left");break;case g[1]-1:Q+=" ui-datepicker-group-last",P=" ui-corner-"+(c?"left":"right");break;default:Q+=" ui-datepicker-group-middle",P=""}Q+='">'}Q+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+P+'">'+(/all|left/.test(P)&&L==0?c?t:r:"")+(/all|right/.test(P)&&L==0?c?r:t:"")+this._generateMonthYearHeader(a,n,o,l,m,L>0||N>0,D,E)+'</div><table class="ui-datepicker-calendar"><thead>'+"<tr>";var R=z?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(var S=0;S<7;S++){var T=(S+y)%7;R+="<th"+((S+y+6)%7>=5?' class="ui-datepicker-week-end"':"")+">"+'<span title="'+A[T]+'">'+C[T]+"</span></th>"}Q+=R+"</tr></thead><tbody>";var U=this._getDaysInMonth(o,n);o==a.selectedYear&&n==a.selectedMonth&&(a.selectedDay=Math.min(a.selectedDay,U));var V=(this._getFirstDayOfMonth(o,n)-y+7)%7,W=Math.ceil((V+U)/7),X=j?this.maxRows>W?this.maxRows:W:W;this.maxRows=X;var Y=this._daylightSavingAdjust(new Date(o,n,1-V));for(var Z=0;Z<X;Z++){Q+="<tr>";var _=z?'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(Y)+"</td>":"";for(var S=0;S<7;S++){var ba=F?F.apply(a.input?a.input[0]:null,[Y]):[!0,""],bb=Y.getMonth()!=n,bc=bb&&!H||!ba[0]||l&&Y<l||m&&Y>m;_+='<td class="'+((S+y+6)%7>=5?" ui-datepicker-week-end":"")+(bb?" ui-datepicker-other-month":"")+(Y.getTime()==O.getTime()&&n==a.selectedMonth&&a._keyEvent||J.getTime()==Y.getTime()&&J.getTime()==O.getTime()?" "+this._dayOverClass:"")+(bc?" "+this._unselectableClass+" ui-state-disabled":"")+(bb&&!G?"":" "+ba[1]+(Y.getTime()==k.getTime()?" "+this._currentClass:"")+(Y.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!bb||G)&&ba[2]?' title="'+ba[2]+'"':"")+(bc?"":' data-handler="selectDay" data-event="click" data-month="'+Y.getMonth()+'" data-year="'+Y.getFullYear()+'"')+">"+(bb&&!G?" ":bc?'<span class="ui-state-default">'+Y.getDate()+"</span>":'<a class="ui-state-default'+(Y.getTime()==b.getTime()?" ui-state-highlight":"")+(Y.getTime()==k.getTime()?" ui-state-active":"")+(bb?" ui-priority-secondary":"")+'" href="#">'+Y.getDate()+"</a>")+"</td>",Y.setDate(Y.getDate()+1),Y=this._daylightSavingAdjust(Y)}Q+=_+"</tr>"}n++,n>11&&(n=0,o++),Q+="</tbody></table>"+(j?"</div>"+(g[0]>0&&N==g[1]-1?'<div class="ui-datepicker-row-break"></div>':""):""),M+=Q}K+=M}return K+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':""),a._keyEvent=!1,K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='<div class="ui-datepicker-title">',m="";if(f||!i)m+='<span class="ui-datepicker-month">'+g[b]+"</span>";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';for(var p=0;p<12;p++)(!n||p>=d.getMonth())&&(!o||p<=e.getMonth())&&(m+='<option value="'+p+'"'+(p==b?' selected="selected"':"")+">"+h[p]+"</option>");m+="</select>"}k||(l+=m+(f||!i||!j?" ":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+='<span class="ui-datepicker-year">'+c+"</span>";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';for(;t<=u;t++)a.yearshtml+='<option value="'+t+'"'+(t==c?' selected="selected"':"")+">"+t+"</option>";a.yearshtml+="</select>",l+=a.yearshtml,a.yearshtml=null}}return l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?" ":"")+m),l+="</div>",l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&b<c?c:b;return e=d&&e>d?d:e,e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));return b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth())),this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");return b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10),{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);return typeof a!="string"||a!="isDisabled"&&a!="getDate"&&a!="widget"?a=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b)):this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)}):$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.23",window["DP_jQuery_"+dpuuid]=$})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.ui.progressbar.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){return a===b?this._value():(this._setOption("value",a),this)},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;return typeof a!="number"&&(a=0),Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.23"})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.core.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -jQuery.effects||function(a,b){function c(b){var c;return b&&b.constructor==Array&&b.length==3?b:(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))?[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)]:(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))?[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))?[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)]:(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))?[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)]:(c=/rgba\(0, 0, 0, 0\)/.exec(b))?e.transparent:e[a.trim(b).toLowerCase()]}function d(b,d){var e;do{e=(a.curCSS||a.css)(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};return a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete,[b,c,d,e]}function l(b){return!b||typeof b=="number"||a.fx.speeds[b]?!0:typeof b=="string"&&!a.effects[b]?!0:!1}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){return a.isFunction(d)&&(e=d,d=null),this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class")||"";a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.23",save:function(a,b){for(var c=0;c<b.length;c++)b[c]!==null&&a.data("ec.storage."+b[c],a[0].style[b[c]])},restore:function(a,b){for(var c=0;c<b.length;c++)b[c]!==null&&a.css(b[c],a.data("ec.storage."+b[c]))},setMode:function(a,b){return b=="toggle"&&(b=a.is(":hidden")?"show":"hide"),b},getBaseline:function(a,b){var c,d;switch(a[0]){case"top":c=0;break;case"middle":c=.5;break;case"bottom":c=1;break;default:c=a[0]/b.height}switch(a[1]){case"left":d=0;break;case"center":d=.5;break;case"right":d=1;break;default:d=a[1]/b.width}return{x:d,y:c}},createWrapper:function(b){if(b.parent().is(".ui-effects-wrapper"))return b.parent();var c={width:b.outerWidth(!0),height:b.outerHeight(!0),"float":b.css("float")},d=a("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;try{e.id}catch(f){e=document.body}return b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;return b.parent().is(".ui-effects-wrapper")?(c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus(),c):b},setTransition:function(b,c,d,e){return e=e||{},a.each(c,function(a,c){var f=b.cssUnit(c);f[0]>0&&(e[c]=f[0]*d+f[1])}),e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];return a.fx.off||!i?h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)}):i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="show",this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="hide",this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);return c[1].mode="toggle",this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];return a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])}),d}});var m={};a.each(["Quad","Cubic","Quart","Quint","Expo"],function(a,b){m[b]=function(b){return Math.pow(b,a+2)}}),a.extend(m,{Sine:function(a){return 1-Math.cos(a*Math.PI/2)},Circ:function(a){return 1-Math.sqrt(1-a*a)},Elastic:function(a){return a===0||a===1?a:-Math.pow(2,8*(a-1))*Math.sin(((a-1)*80-7.5)*Math.PI/15)},Back:function(a){return a*a*(3*a-2)},Bounce:function(a){var b,c=4;while(a<((b=Math.pow(2,--c))-1)/11);return 1/Math.pow(4,3-c)-7.5625*Math.pow((b*3-2)/22-a,2)}}),a.each(m,function(b,c){a.easing["easeIn"+b]=c,a.easing["easeOut"+b]=function(a){return 1-c(1-a)},a.easing["easeInOut"+b]=function(a){return a<.5?c(a*2)/2:c(a*-2+2)/-2+1}})}(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.blind.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.blind=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=f=="vertical"?"height":"width",i=f=="vertical"?g.height():g.width();e=="show"&&g.css(h,0);var j={};j[h]=e=="show"?i:0,g.animate(j,b.duration,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.bounce.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.bounce=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"up",g=b.options.distance||20,h=b.options.times||5,i=b.duration||250;/show|hide/.test(e)&&d.push("opacity"),a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",g=b.options.distance||(j=="top"?c.outerHeight(!0)/3:c.outerWidth(!0)/3);e=="show"&&c.css("opacity",0).css(j,k=="pos"?-g:g),e=="hide"&&(g=g/(h*2)),e!="hide"&&h--;if(e=="show"){var l={opacity:1};l[j]=(k=="pos"?"+=":"-=")+g,c.animate(l,i/2,b.options.easing),g=g/2,h--}for(var m=0;m<h;m++){var n={},p={};n[j]=(k=="pos"?"-=":"+=")+g,p[j]=(k=="pos"?"+=":"-=")+g,c.animate(n,i/2,b.options.easing).animate(p,i/2,b.options.easing),g=e=="hide"?g*2:g/2}if(e=="hide"){var l={opacity:0};l[j]=(k=="pos"?"-=":"+=")+g,c.animate(l,i/2,b.options.easing,function(){c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)})}else{var n={},p={};n[j]=(k=="pos"?"-=":"+=")+g,p[j]=(k=="pos"?"+=":"-=")+g,c.animate(n,i/2,b.options.easing).animate(p,i/2,b.options.easing,function(){a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)})}c.queue("fx",function(){c.dequeue()}),c.dequeue()})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.clip.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.clip=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","height","width"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=c[0].tagName=="IMG"?g:c,i={size:f=="vertical"?"height":"width",position:f=="vertical"?"top":"left"},j=f=="vertical"?h.height():h.width();e=="show"&&(h.css(i.size,0),h.css(i.position,j/2));var k={};k[i.size]=e=="show"?j:0,k[i.position]=e=="show"?0:j/2,h.animate(k,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.drop.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.drop=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","opacity"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"left";a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var g=f=="up"||f=="down"?"top":"left",h=f=="up"||f=="left"?"pos":"neg",i=b.options.distance||(g=="top"?c.outerHeight(!0)/2:c.outerWidth(!0)/2);e=="show"&&c.css("opacity",0).css(g,h=="pos"?-i:i);var j={opacity:e=="show"?1:0};j[g]=(e=="show"?h=="pos"?"+=":"-=":h=="pos"?"-=":"+=")+i,c.animate(j,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.explode.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.explode=function(b){return this.queue(function(){var c=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3,d=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;b.options.mode=b.options.mode=="toggle"?a(this).is(":visible")?"hide":"show":b.options.mode;var e=a(this).show().css("visibility","hidden"),f=e.offset();f.top-=parseInt(e.css("marginTop"),10)||0,f.left-=parseInt(e.css("marginLeft"),10)||0;var g=e.outerWidth(!0),h=e.outerHeight(!0);for(var i=0;i<c;i++)for(var j=0;j<d;j++)e.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-j*(g/d),top:-i*(h/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/d,height:h/c,left:f.left+j*(g/d)+(b.options.mode=="show"?(j-Math.floor(d/2))*(g/d):0),top:f.top+i*(h/c)+(b.options.mode=="show"?(i-Math.floor(c/2))*(h/c):0),opacity:b.options.mode=="show"?0:1}).animate({left:f.left+j*(g/d)+(b.options.mode=="show"?0:(j-Math.floor(d/2))*(g/d)),top:f.top+i*(h/c)+(b.options.mode=="show"?0:(i-Math.floor(c/2))*(h/c)),opacity:b.options.mode=="show"?1:0},b.duration||500);setTimeout(function(){b.options.mode=="show"?e.css({visibility:"visible"}):e.css({visibility:"visible"}).hide(),b.callback&&b.callback.apply(e[0]),e.dequeue(),a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.fade.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.fade=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide");c.animate({opacity:d},{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.fold.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.fold=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.size||15,g=!!b.options.horizFirst,h=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(c,d),c.show();var i=a.effects.createWrapper(c).css({overflow:"hidden"}),j=e=="show"!=g,k=j?["width","height"]:["height","width"],l=j?[i.width(),i.height()]:[i.height(),i.width()],m=/([0-9]+)%/.exec(f);m&&(f=parseInt(m[1],10)/100*l[e=="hide"?0:1]),e=="show"&&i.css(g?{height:0,width:f}:{height:f,width:0});var n={},p={};n[k[0]]=e=="show"?l[0]:f,p[k[1]]=e=="show"?l[1]:0,i.animate(n,h,b.options.easing).animate(p,h,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.highlight.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.highlight=function(b){return this.queue(function(){var c=a(this),d=["backgroundImage","backgroundColor","opacity"],e=a.effects.setMode(c,b.options.mode||"show"),f={backgroundColor:c.css("backgroundColor")};e=="hide"&&(f.opacity=0),a.effects.save(c,d),c.show().css({backgroundImage:"none",backgroundColor:b.options.color||"#ffff99"}).animate(f,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),e=="show"&&!a.support.opacity&&this.style.removeAttribute("filter"),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.pulsate.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.pulsate=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"show"),e=(b.options.times||5)*2-1,f=b.duration?b.duration/2:a.fx.speeds._default/2,g=c.is(":visible"),h=0;g||(c.css("opacity",0).show(),h=1),(d=="hide"&&g||d=="show"&&!g)&&e--;for(var i=0;i<e;i++)c.animate({opacity:h},f,b.options.easing),h=(h+1)%2;c.animate({opacity:h},f,b.options.easing,function(){h==0&&c.hide(),b.callback&&b.callback.apply(this,arguments)}),c.queue("fx",function(){c.dequeue()}).dequeue()})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.scale.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.puff=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide"),e=parseInt(b.options.percent,10)||150,f=e/100,g={height:c.height(),width:c.width()};a.extend(b.options,{fade:!0,mode:d,percent:d=="hide"?e:100,from:d=="hide"?g:{height:g.height*f,width:g.width*f}}),c.effect("scale",b.options,b.duration,b.callback),c.dequeue()})},a.effects.scale=function(b){return this.queue(function(){var c=a(this),d=a.extend(!0,{},b.options),e=a.effects.setMode(c,b.options.mode||"effect"),f=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:e=="hide"?0:100),g=b.options.direction||"both",h=b.options.origin;e!="effect"&&(d.origin=h||["middle","center"],d.restore=!0);var i={height:c.height(),width:c.width()};c.from=b.options.from||(e=="show"?{height:0,width:0}:i);var j={y:g!="horizontal"?f/100:1,x:g!="vertical"?f/100:1};c.to={height:i.height*j.y,width:i.width*j.x},b.options.fade&&(e=="show"&&(c.from.opacity=0,c.to.opacity=1),e=="hide"&&(c.from.opacity=1,c.to.opacity=0)),d.from=c.from,d.to=c.to,d.mode=e,c.effect("size",d,b.duration,b.callback),c.dequeue()})},a.effects.size=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","width","height","overflow","opacity"],e=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],g=["fontSize"],h=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],i=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],j=a.effects.setMode(c,b.options.mode||"effect"),k=b.options.restore||!1,l=b.options.scale||"both",m=b.options.origin,n={height:c.height(),width:c.width()};c.from=b.options.from||n,c.to=b.options.to||n;if(m){var p=a.effects.getBaseline(m,n);c.from.top=(n.height-c.from.height)*p.y,c.from.left=(n.width-c.from.width)*p.x,c.to.top=(n.height-c.to.height)*p.y,c.to.left=(n.width-c.to.width)*p.x}var q={from:{y:c.from.height/n.height,x:c.from.width/n.width},to:{y:c.to.height/n.height,x:c.to.width/n.width}};if(l=="box"||l=="both")q.from.y!=q.to.y&&(d=d.concat(h),c.from=a.effects.setTransition(c,h,q.from.y,c.from),c.to=a.effects.setTransition(c,h,q.to.y,c.to)),q.from.x!=q.to.x&&(d=d.concat(i),c.from=a.effects.setTransition(c,i,q.from.x,c.from),c.to=a.effects.setTransition(c,i,q.to.x,c.to));(l=="content"||l=="both")&&q.from.y!=q.to.y&&(d=d.concat(g),c.from=a.effects.setTransition(c,g,q.from.y,c.from),c.to=a.effects.setTransition(c,g,q.to.y,c.to)),a.effects.save(c,k?d:e),c.show(),a.effects.createWrapper(c),c.css("overflow","hidden").css(c.from);if(l=="content"||l=="both")h=h.concat(["marginTop","marginBottom"]).concat(g),i=i.concat(["marginLeft","marginRight"]),f=d.concat(h).concat(i),c.find("*[width]").each(function(){var c=a(this);k&&a.effects.save(c,f);var d={height:c.height(),width:c.width()};c.from={height:d.height*q.from.y,width:d.width*q.from.x},c.to={height:d.height*q.to.y,width:d.width*q.to.x},q.from.y!=q.to.y&&(c.from=a.effects.setTransition(c,h,q.from.y,c.from),c.to=a.effects.setTransition(c,h,q.to.y,c.to)),q.from.x!=q.to.x&&(c.from=a.effects.setTransition(c,i,q.from.x,c.from),c.to=a.effects.setTransition(c,i,q.to.x,c.to)),c.css(c.from),c.animate(c.to,b.duration,b.options.easing,function(){k&&a.effects.restore(c,f)})});c.animate(c.to,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){c.to.opacity===0&&c.css("opacity",c.from.opacity),j=="hide"&&c.hide(),a.effects.restore(c,k?d:e),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.shake.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.shake=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"left",g=b.options.distance||20,h=b.options.times||3,i=b.duration||b.options.duration||140;a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",l={},m={},n={};l[j]=(k=="pos"?"-=":"+=")+g,m[j]=(k=="pos"?"+=":"-=")+g*2,n[j]=(k=="pos"?"-=":"+=")+g*2,c.animate(l,i,b.options.easing);for(var p=1;p<h;p++)c.animate(m,i,b.options.easing).animate(n,i,b.options.easing);c.animate(m,i,b.options.easing).animate(l,i/2,b.options.easing,function(){a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)}),c.queue("fx",function(){c.dequeue()}),c.dequeue()})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.slide.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.slide=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"show"),f=b.options.direction||"left";a.effects.save(c,d),c.show(),a.effects.createWrapper(c).css({overflow:"hidden"});var g=f=="up"||f=="down"?"top":"left",h=f=="up"||f=="left"?"pos":"neg",i=b.options.distance||(g=="top"?c.outerHeight(!0):c.outerWidth(!0));e=="show"&&c.css(g,h=="pos"?isNaN(i)?"-"+i:-i:i);var j={};j[g]=(e=="show"?h=="pos"?"+=":"-=":h=="pos"?"-=":"+=")+i,c.animate(j,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 -* https://github.com/jquery/jquery-ui -* Includes: jquery.effects.transfer.js -* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ -(function(a,b){a.effects.transfer=function(b){return this.queue(function(){var c=a(this),d=a(b.options.to),e=d.offset(),f={top:e.top,left:e.left,height:d.innerHeight(),width:d.innerWidth()},g=c.offset(),h=a('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(b.options.className).css({top:g.top,left:g.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(f,b.duration,b.options.easing,function(){h.remove(),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;
\ No newline at end of file diff --git a/tools/droiddoc/templates-ndk/assets/js/docs.js b/tools/droiddoc/templates-ndk/assets/js/docs.js deleted file mode 100644 index 192d2190af..0000000000 --- a/tools/droiddoc/templates-ndk/assets/js/docs.js +++ /dev/null @@ -1,4366 +0,0 @@ -var classesNav; -var devdocNav; -var sidenav; -var cookie_namespace = 'android_developer'; -var NAV_PREF_TREE = "tree"; -var NAV_PREF_PANELS = "panels"; -var nav_pref; -var isMobile = false; // true if mobile, so we can adjust some layout -var mPagePath; // initialized in ready() function - -var basePath = getBaseUri(location.pathname); -var SITE_ROOT = toRoot + basePath.substring(1,basePath.indexOf("/",1)); -var GOOGLE_DATA; // combined data for google service apis, used for search suggest - -// Ensure that all ajax getScript() requests allow caching -$.ajaxSetup({ - cache: true -}); - -/****** ON LOAD SET UP STUFF *********/ - -$(document).ready(function() { - - // show lang dialog if the URL includes /intl/ - //if (location.pathname.substring(0,6) == "/intl/") { - // var lang = location.pathname.split('/')[2]; - // if (lang != getLangPref()) { - // $("#langMessage a.yes").attr("onclick","changeLangPref('" + lang - // + "', true); $('#langMessage').hide(); return false;"); - // $("#langMessage .lang." + lang).show(); - // $("#langMessage").show(); - // } - //} - - // load json file for JD doc search suggestions - $.getScript(toRoot + 'jd_lists_unified.js'); - // load json file for Android API search suggestions - $.getScript(toRoot + 'reference/lists.js'); - // load json files for Google services API suggestions - $.getScript(toRoot + 'reference/gcm_lists.js', function(data, textStatus, jqxhr) { - // once the GCM json (GCM_DATA) is loaded, load the GMS json (GMS_DATA) and merge the data - if(jqxhr.status === 200) { - $.getScript(toRoot + 'reference/gms_lists.js', function(data, textStatus, jqxhr) { - if(jqxhr.status === 200) { - // combine GCM and GMS data - GOOGLE_DATA = GMS_DATA; - var start = GOOGLE_DATA.length; - for (var i=0; i<GCM_DATA.length; i++) { - GOOGLE_DATA.push({id:start+i, label:GCM_DATA[i].label, - link:GCM_DATA[i].link, type:GCM_DATA[i].type}); - } - } - }); - } - }); - - // setup keyboard listener for search shortcut - $('body').keyup(function(event) { - if (event.which == 191) { - $('#search_autocomplete').focus(); - } - }); - - // init the fullscreen toggle click event - $('#nav-swap .fullscreen').click(function(){ - if ($(this).hasClass('disabled')) { - toggleFullscreen(true); - } else { - toggleFullscreen(false); - } - }); - - // initialize the divs with custom scrollbars - $('.scroll-pane').jScrollPane( {verticalGutter:0} ); - - // add HRs below all H2s (except for a few other h2 variants) - $('h2').not('#qv h2') - .not('#tb h2') - .not('.sidebox h2') - .not('#devdoc-nav h2') - .not('h2.norule').css({marginBottom:0}) - .after('<hr/>'); - - // set up the search close button - $('.search .close').click(function() { - $searchInput = $('#search_autocomplete'); - $searchInput.attr('value', ''); - $(this).addClass("hide"); - $("#search-container").removeClass('active'); - $("#search_autocomplete").blur(); - search_focus_changed($searchInput.get(), false); - hideResults(); - }); - - // Set up quicknav - var quicknav_open = false; - $("#btn-quicknav").click(function() { - if (quicknav_open) { - $(this).removeClass('active'); - quicknav_open = false; - collapse(); - } else { - $(this).addClass('active'); - quicknav_open = true; - expand(); - } - }) - - var expand = function() { - $('#header-wrap').addClass('quicknav'); - $('#quicknav').stop().show().animate({opacity:'1'}); - } - - var collapse = function() { - $('#quicknav').stop().animate({opacity:'0'}, 100, function() { - $(this).hide(); - $('#header-wrap').removeClass('quicknav'); - }); - } - - - //Set up search - $("#search_autocomplete").focus(function() { - $("#search-container").addClass('active'); - }) - $("#search-container").mouseover(function() { - $("#search-container").addClass('active'); - $("#search_autocomplete").focus(); - }) - $("#search-container").mouseout(function() { - if ($("#search_autocomplete").is(":focus")) return; - if ($("#search_autocomplete").val() == '') { - setTimeout(function(){ - $("#search-container").removeClass('active'); - $("#search_autocomplete").blur(); - },250); - } - }) - $("#search_autocomplete").blur(function() { - if ($("#search_autocomplete").val() == '') { - $("#search-container").removeClass('active'); - } - }) - - - // prep nav expandos - var pagePath = document.location.pathname; - // 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 / - } - - if (pagePath.indexOf(SITE_ROOT) == 0) { - if (pagePath == '' || pagePath.charAt(pagePath.length - 1) == '/') { - pagePath += 'index.html'; - } - } - - // Need a copy of the pagePath before it gets changed in the next block; - // it's needed to perform proper tab highlighting in offline docs (see rootDir below) - var pagePathOriginal = pagePath; - if (SITE_ROOT.match(/\.\.\//) || SITE_ROOT == '') { - // If running locally, SITE_ROOT will be a relative path, so account for that by - // finding the relative URL to this page. This will allow us to find links on the page - // leading back to this page. - var pathParts = pagePath.split('/'); - var relativePagePathParts = []; - var upDirs = (SITE_ROOT.match(/(\.\.\/)+/) || [''])[0].length / 3; - for (var i = 0; i < upDirs; i++) { - relativePagePathParts.push('..'); - } - for (var i = 0; i < upDirs; i++) { - relativePagePathParts.push(pathParts[pathParts.length - (upDirs - i) - 1]); - } - relativePagePathParts.push(pathParts[pathParts.length - 1]); - pagePath = relativePagePathParts.join('/'); - } else { - // Otherwise the page path is already an absolute URL - } - - // Highlight the header tabs... - // highlight Design tab - if ($("body").hasClass("design")) { - $("#header li.design a").addClass("selected"); - $("#sticky-header").addClass("design"); - - // highlight About tabs - } else if ($("body").hasClass("about")) { - var rootDir = pagePathOriginal.substring(1,pagePathOriginal.indexOf('/', 1)); - if (rootDir == "about") { - $("#nav-x li.about a").addClass("selected"); - } else if (rootDir == "wear") { - $("#nav-x li.wear a").addClass("selected"); - } else if (rootDir == "tv") { - $("#nav-x li.tv a").addClass("selected"); - } else if (rootDir == "auto") { - $("#nav-x li.auto a").addClass("selected"); - } - // highlight Develop tab - } else if ($("body").hasClass("develop") || $("body").hasClass("google")) { - $("#header li.develop a").addClass("selected"); - $("#sticky-header").addClass("develop"); - // In Develop docs, also highlight appropriate sub-tab - var rootDir = pagePathOriginal.substring(1,pagePathOriginal.indexOf('/', 1)); - if (rootDir == "training") { - $("#nav-x li.training a").addClass("selected"); - } else if (rootDir == "guide") { - $("#nav-x li.guide a").addClass("selected"); - } else if (rootDir == "reference") { - // If the root is reference, but page is also part of Google Services, select Google - if ($("body").hasClass("google")) { - $("#nav-x li.google a").addClass("selected"); - } else { - $("#nav-x li.reference a").addClass("selected"); - } - } else if ((rootDir == "tools") || (rootDir == "sdk")) { - $("#nav-x li.tools a").addClass("selected"); - } else if ($("body").hasClass("google")) { - $("#nav-x li.google a").addClass("selected"); - } else if ($("body").hasClass("samples")) { - $("#nav-x li.samples a").addClass("selected"); - } else if (rootDir == "ndk") { - if ($("body").hasClass("guide")) { - $("#nav-x li.guide a").addClass("selected"); - } else if ($("body").hasClass("samples")) { - $("#nav-x li.samples a").addClass("selected"); - } else if ($("body").hasClass("downloads")) { - $("#nav-x li.downloads a").addClass("selected"); - } else if ($("body").hasClass("reference")) { - $("#nav-x li.reference a").addClass("selected"); - } - } - - // highlight Distribute tab - } else if ($("body").hasClass("distribute")) { - $("#header li.distribute a").addClass("selected"); - $("#sticky-header").addClass("distribute"); - - var baseFrag = pagePathOriginal.indexOf('/', 1) + 1; - var secondFrag = pagePathOriginal.substring(baseFrag, pagePathOriginal.indexOf('/', baseFrag)); - if (secondFrag == "users") { - $("#nav-x li.users a").addClass("selected"); - } else if (secondFrag == "engage") { - $("#nav-x li.engage a").addClass("selected"); - } else if (secondFrag == "monetize") { - $("#nav-x li.monetize a").addClass("selected"); - } else if (secondFrag == "analyze") { - $("#nav-x li.analyze a").addClass("selected"); - } else if (secondFrag == "tools") { - $("#nav-x li.disttools a").addClass("selected"); - } else if (secondFrag == "stories") { - $("#nav-x li.stories a").addClass("selected"); - } else if (secondFrag == "essentials") { - $("#nav-x li.essentials a").addClass("selected"); - } else if (secondFrag == "googleplay") { - $("#nav-x li.googleplay a").addClass("selected"); - } - } else if ($("body").hasClass("about")) { - $("#sticky-header").addClass("about"); - } - - // set global variable so we can highlight the sidenav a bit later (such as for google reference) - // and highlight the sidenav - mPagePath = pagePath; - highlightSidenav(); - buildBreadcrumbs(); - - // set up prev/next links if they exist - var $selNavLink = $('#nav').find('a[href="' + pagePath + '"]'); - var $selListItem; - if ($selNavLink.length) { - $selListItem = $selNavLink.closest('li'); - - // set up prev links - var $prevLink = []; - var $prevListItem = $selListItem.prev('li'); - - var crossBoundaries = ($("body.design").length > 0) || ($("body.guide").length > 0) ? true : -false; // navigate across topic boundaries only in design docs - if ($prevListItem.length) { - if ($prevListItem.hasClass('nav-section') || crossBoundaries) { - // jump to last topic of previous section - $prevLink = $prevListItem.find('a:last'); - } else if (!$selListItem.hasClass('nav-section')) { - // jump to previous topic in this section - $prevLink = $prevListItem.find('a:eq(0)'); - } - } else { - // jump to this section's index page (if it exists) - var $parentListItem = $selListItem.parents('li'); - $prevLink = $selListItem.parents('li').find('a'); - - // except if cross boundaries aren't allowed, and we're at the top of a section already - // (and there's another parent) - if (!crossBoundaries && $parentListItem.hasClass('nav-section') - && $selListItem.hasClass('nav-section')) { - $prevLink = []; - } - } - - // set up next links - var $nextLink = []; - var startClass = false; - var isCrossingBoundary = false; - - if ($selListItem.hasClass('nav-section') && $selListItem.children('div.empty').length == 0) { - // we're on an index page, jump to the first topic - $nextLink = $selListItem.find('ul:eq(0)').find('a:eq(0)'); - - // if there aren't any children, go to the next section (required for About pages) - if($nextLink.length == 0) { - $nextLink = $selListItem.next('li').find('a'); - } else if ($('.topic-start-link').length) { - // as long as there's a child link and there is a "topic start link" (we're on a landing) - // then set the landing page "start link" text to be the first doc title - $('.topic-start-link').text($nextLink.text().toUpperCase()); - } - - // If the selected page has a description, then it's a class or article homepage - if ($selListItem.find('a[description]').length) { - // this means we're on a class landing page - startClass = true; - } - } else { - // jump to the next topic in this section (if it exists) - $nextLink = $selListItem.next('li').find('a:eq(0)'); - if ($nextLink.length == 0) { - isCrossingBoundary = true; - // no more topics in this section, jump to the first topic in the next section - $nextLink = $selListItem.parents('li:eq(0)').next('li').find('a:eq(0)'); - if (!$nextLink.length) { // Go up another layer to look for next page (lesson > class > course) - $nextLink = $selListItem.parents('li:eq(1)').next('li.nav-section').find('a:eq(0)'); - if ($nextLink.length == 0) { - // if that doesn't work, we're at the end of the list, so disable NEXT link - $('.next-page-link').attr('href','').addClass("disabled") - .click(function() { return false; }); - // and completely hide the one in the footer - $('.content-footer .next-page-link').hide(); - } - } - } - } - - if (startClass) { - $('.start-class-link').attr('href', $nextLink.attr('href')).removeClass("hide"); - - // if there's no training bar (below the start button), - // then we need to add a bottom border to button - if (!$("#tb").length) { - $('.start-class-link').css({'border-bottom':'1px solid #DADADA'}); - } - } else if (isCrossingBoundary && !$('body.design').length) { // Design always crosses boundaries - $('.content-footer.next-class').show(); - $('.next-page-link').attr('href','') - .removeClass("hide").addClass("disabled") - .click(function() { return false; }); - // and completely hide the one in the footer - $('.content-footer .next-page-link').hide(); - if ($nextLink.length) { - $('.next-class-link').attr('href',$nextLink.attr('href')) - .removeClass("hide") - .append(": " + $nextLink.html()); - $('.next-class-link').find('.new').empty(); - } - } else { - $('.next-page-link').attr('href', $nextLink.attr('href')) - .removeClass("hide"); - // for the footer link, also add the next page title - $('.content-footer .next-page-link').append(": " + $nextLink.html()); - } - - if (!startClass && $prevLink.length) { - var prevHref = $prevLink.attr('href'); - if (prevHref == SITE_ROOT + 'index.html') { - // Don't show Previous when it leads to the homepage - } else { - $('.prev-page-link').attr('href', $prevLink.attr('href')).removeClass("hide"); - } - } - - } - - - - // Set up the course landing pages for Training with class names and descriptions - if ($('body.trainingcourse').length) { - var $classLinks = $selListItem.find('ul li a').not('#nav .nav-section .nav-section ul a'); - - // create an array for all the class descriptions - var $classDescriptions = new Array($classLinks.length); - var lang = getLangPref(); - $classLinks.each(function(index) { - var langDescr = $(this).attr(lang + "-description"); - if (typeof langDescr !== 'undefined' && langDescr !== false) { - // if there's a class description in the selected language, use that - $classDescriptions[index] = langDescr; - } else { - // otherwise, use the default english description - $classDescriptions[index] = $(this).attr("description"); - } - }); - - var $olClasses = $('<ol class="class-list"></ol>'); - var $liClass; - var $imgIcon; - var $h2Title; - var $pSummary; - var $olLessons; - var $liLesson; - $classLinks.each(function(index) { - $liClass = $('<li></li>'); - $h2Title = $('<a class="title" href="'+$(this).attr('href')+'"><h2>' + $(this).html()+'</h2><span></span></a>'); - $pSummary = $('<p class="description">' + $classDescriptions[index] + '</p>'); - - $olLessons = $('<ol class="lesson-list"></ol>'); - - $lessons = $(this).closest('li').find('ul li a'); - - if ($lessons.length) { - $imgIcon = $('<img src="'+toRoot+'assets/images/resource-tutorial.png" ' - + ' width="64" height="64" alt=""/>'); - $lessons.each(function(index) { - $olLessons.append('<li><a href="'+$(this).attr('href')+'">' + $(this).html()+'</a></li>'); - }); - } else { - $imgIcon = $('<img src="'+toRoot+'assets/images/resource-article.png" ' - + ' width="64" height="64" alt=""/>'); - $pSummary.addClass('article'); - } - - $liClass.append($h2Title).append($imgIcon).append($pSummary).append($olLessons); - $olClasses.append($liClass); - }); - $('.jd-descr').append($olClasses); - } - - // Set up expand/collapse behavior - initExpandableNavItems("#nav"); - - - $(".scroll-pane").scroll(function(event) { - event.preventDefault(); - return false; - }); - - /* Resize nav height when window height changes */ - $(window).resize(function() { - if ($('#side-nav').length == 0) return; - var stylesheet = $('link[rel="stylesheet"][class="fullscreen"]'); - setNavBarLeftPos(); // do this even if sidenav isn't fixed because it could become fixed - // make sidenav behave when resizing the window and side-scolling is a concern - if (sticky) { - if ((stylesheet.attr("disabled") == "disabled") || stylesheet.length == 0) { - updateSideNavPosition(); - } else { - updateSidenavFullscreenWidth(); - } - } - resizeNav(); - }); - - - var navBarLeftPos; - if ($('#devdoc-nav').length) { - setNavBarLeftPos(); - } - - - // Set up play-on-hover <video> tags. - $('video.play-on-hover').bind('click', function(){ - $(this).get(0).load(); // in case the video isn't seekable - $(this).get(0).play(); - }); - - // Set up tooltips - var TOOLTIP_MARGIN = 10; - $('acronym,.tooltip-link').each(function() { - var $target = $(this); - var $tooltip = $('<div>') - .addClass('tooltip-box') - .append($target.attr('title')) - .hide() - .appendTo('body'); - $target.removeAttr('title'); - - $target.hover(function() { - // in - var targetRect = $target.offset(); - targetRect.width = $target.width(); - targetRect.height = $target.height(); - - $tooltip.css({ - left: targetRect.left, - top: targetRect.top + targetRect.height + TOOLTIP_MARGIN - }); - $tooltip.addClass('below'); - $tooltip.show(); - }, function() { - // out - $tooltip.hide(); - }); - }); - - // Set up <h2> deeplinks - $('h2').click(function() { - var id = $(this).attr('id'); - if (id) { - document.location.hash = id; - } - }); - - //Loads the +1 button - var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; - po.src = 'https://apis.google.com/js/plusone.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); - - - // Revise the sidenav widths to make room for the scrollbar - // which avoids the visible width from changing each time the bar appears - var $sidenav = $("#side-nav"); - var sidenav_width = parseInt($sidenav.innerWidth()); - - $("#devdoc-nav #nav").css("width", sidenav_width - 4 + "px"); // 4px is scrollbar width - - - $(".scroll-pane").removeAttr("tabindex"); // get rid of tabindex added by jscroller - - if ($(".scroll-pane").length > 1) { - // Check if there's a user preference for the panel heights - var cookieHeight = readCookie("reference_height"); - if (cookieHeight) { - restoreHeight(cookieHeight); - } - } - - // Resize once loading is finished - resizeNav(); - // Check if there's an anchor that we need to scroll into view. - // A delay is needed, because some browsers do not immediately scroll down to the anchor - window.setTimeout(offsetScrollForSticky, 100); - - /* init the language selector based on user cookie for lang */ - loadLangPref(); - changeNavLang(getLangPref()); - - /* setup event handlers to ensure the overflow menu is visible while picking lang */ - $("#language select") - .mousedown(function() { - $("div.morehover").addClass("hover"); }) - .blur(function() { - $("div.morehover").removeClass("hover"); }); - - /* some global variable setup */ - resizePackagesNav = $("#resize-packages-nav"); - classesNav = $("#classes-nav"); - devdocNav = $("#devdoc-nav"); - - var cookiePath = ""; - if (location.href.indexOf("/reference/") != -1) { - cookiePath = "reference_"; - } else if (location.href.indexOf("/guide/") != -1) { - cookiePath = "guide_"; - } else if (location.href.indexOf("/tools/") != -1) { - cookiePath = "tools_"; - } else if (location.href.indexOf("/training/") != -1) { - cookiePath = "training_"; - } else if (location.href.indexOf("/design/") != -1) { - cookiePath = "design_"; - } else if (location.href.indexOf("/distribute/") != -1) { - cookiePath = "distribute_"; - } - - - /* setup shadowbox for any videos that want it */ - var $videoLinks = $("a.video-shadowbox-button, a.notice-developers-video"); - if ($videoLinks.length) { - // if there's at least one, add the shadowbox HTML to the body - $('body').prepend( -'<div id="video-container">'+ - '<div id="video-frame">'+ - '<div class="video-close">'+ - '<span id="icon-video-close" onclick="closeVideo()"> </span>'+ - '</div>'+ - '<div id="youTubePlayer"></div>'+ - '</div>'+ -'</div>'); - - // loads the IFrame Player API code asynchronously. - $.getScript("https://www.youtube.com/iframe_api"); - - $videoLinks.each(function() { - var videoId = $(this).attr('href').split('?v=')[1]; - $(this).click(function(event) { - event.preventDefault(); - startYouTubePlayer(videoId); - }); - }); - } -}); -// END of the onload event - - -var youTubePlayer; -function onYouTubeIframeAPIReady() { -} - -/* Returns the height the shadowbox video should be. It's based on the current - height of the "video-frame" element, which is 100% height for the window. - Then minus the margin so the video isn't actually the full window height. */ -function getVideoHeight() { - var frameHeight = $("#video-frame").height(); - var marginTop = $("#video-frame").css('margin-top').split('px')[0]; - return frameHeight - (marginTop * 2); -} - -var mPlayerPaused = false; - -function startYouTubePlayer(videoId) { - $("#video-container").show(); - $("#video-frame").show(); - mPlayerPaused = false; - - // compute the size of the player so it's centered in window - var maxWidth = 940; // the width of the web site content - var videoAspect = .5625; // based on 1280x720 resolution - var maxHeight = maxWidth * videoAspect; - var videoHeight = getVideoHeight(); - var videoWidth = videoHeight / videoAspect; - if (videoWidth > maxWidth) { - videoWidth = maxWidth; - videoHeight = maxHeight; - } - $("#video-frame").css('width', videoWidth); - - // check if we've already created this player - if (youTubePlayer == null) { - // check if there's a start time specified - var idAndHash = videoId.split("#"); - var startTime = 0; - if (idAndHash.length > 1) { - startTime = idAndHash[1].split("t=")[1] != undefined ? idAndHash[1].split("t=")[1] : 0; - } - // enable localized player - var lang = getLangPref(); - var captionsOn = lang == 'en' ? 0 : 1; - - youTubePlayer = new YT.Player('youTubePlayer', { - height: videoHeight, - width: videoWidth, - videoId: idAndHash[0], - playerVars: {start: startTime, hl: lang, cc_load_policy: captionsOn}, - events: { - 'onReady': onPlayerReady, - 'onStateChange': onPlayerStateChange - } - }); - } else { - // reset the size in case the user adjusted the window since last play - youTubePlayer.setSize(videoWidth, videoHeight); - // if a video different from the one already playing was requested, cue it up - if (videoId != youTubePlayer.getVideoUrl().split('?v=')[1].split('&')[0].split('%')[0]) { - youTubePlayer.cueVideoById(videoId); - } - youTubePlayer.playVideo(); - } -} - -function onPlayerReady(event) { - event.target.playVideo(); - mPlayerPaused = false; -} - -function closeVideo() { - try { - youTubePlayer.pauseVideo(); - } catch(e) { - } - $("#video-container").fadeOut(200); -} - -/* Track youtube playback for analytics */ -function onPlayerStateChange(event) { - // Video starts, send the video ID - if (event.data == YT.PlayerState.PLAYING) { - if (mPlayerPaused) { - ga('send', 'event', 'Videos', 'Resume', - youTubePlayer.getVideoUrl().split('?v=')[1].split('&')[0].split('%')[0]); - } else { - // track the start playing event so we know from which page the video was selected - ga('send', 'event', 'Videos', 'Start: ' + - youTubePlayer.getVideoUrl().split('?v=')[1].split('&')[0].split('%')[0], - 'on: ' + document.location.href); - } - mPlayerPaused = false; - } - // Video paused, send video ID and video elapsed time - if (event.data == YT.PlayerState.PAUSED) { - ga('send', 'event', 'Videos', 'Paused', - youTubePlayer.getVideoUrl().split('?v=')[1].split('&')[0].split('%')[0], - youTubePlayer.getCurrentTime()); - mPlayerPaused = true; - } - // Video finished, send video ID and video elapsed time - if (event.data == YT.PlayerState.ENDED) { - ga('send', 'event', 'Videos', 'Finished', - youTubePlayer.getVideoUrl().split('?v=')[1].split('&')[0].split('%')[0], - youTubePlayer.getCurrentTime()); - mPlayerPaused = true; - } -} - - - -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'); - resizeNav(); - }); - } 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); - - // now expand me - section.closest('li').addClass('expanded'); - section.children('ul').slideDown(250, function() { - resizeNav(); - }); - } - }); - - // Stop expand/collapse behavior when clicking on nav section links - // (since we're navigating away from the page) - // This selector captures the first instance of <a>, but not those with "#" as the href. - $('.nav-section-header').find('a:eq(0)').not('a[href="#"]').click(function(evt) { - window.location.href = $(this).attr('href'); - return false; - }); -} - - -/** Create the list of breadcrumb links in the sticky header */ -function buildBreadcrumbs() { - var $breadcrumbUl = $("#sticky-header ul.breadcrumb"); - // Add the secondary horizontal nav item, if provided - var $selectedSecondNav = $("div#nav-x ul.nav-x a.selected").clone().removeClass("selected"); - if ($selectedSecondNav.length) { - $breadcrumbUl.prepend($("<li>").append($selectedSecondNav)) - } - // Add the primary horizontal nav - var $selectedFirstNav = $("div#header-wrap ul.nav-x a.selected").clone().removeClass("selected"); - // If there's no header nav item, use the logo link and title from alt text - if ($selectedFirstNav.length < 1) { - $selectedFirstNav = $("<a>") - .attr('href', $("div#header .logo a").attr('href')) - .text($("div#header .logo img").attr('alt')); - } - $breadcrumbUl.prepend($("<li>").append($selectedFirstNav)); -} - - - -/** Highlight the current page in sidenav, expanding children as appropriate */ -function highlightSidenav() { - // if something is already highlighted, undo it. This is for dynamic navigation (Samples index) - if ($("ul#nav li.selected").length) { - unHighlightSidenav(); - } - // look for URL in sidenav, including the hash - var $selNavLink = $('#nav').find('a[href="' + mPagePath + location.hash + '"]'); - - // If the selNavLink is still empty, look for it without the hash - if ($selNavLink.length == 0) { - $selNavLink = $('#nav').find('a[href="' + mPagePath + '"]'); - } - - var $selListItem; - if ($selNavLink.length) { - // Find this page's <li> in sidenav and set selected - $selListItem = $selNavLink.closest('li'); - $selListItem.addClass('selected'); - - // Traverse up the tree and expand all parent nav-sections - $selNavLink.parents('li.nav-section').each(function() { - $(this).addClass('expanded'); - $(this).children('ul').show(); - }); - } -} - -function unHighlightSidenav() { - $("ul#nav li.selected").removeClass("selected"); - $('ul#nav li.nav-section.expanded').removeClass('expanded').children('ul').hide(); -} - -function toggleFullscreen(enable) { - var delay = 20; - var enabled = true; - var stylesheet = $('link[rel="stylesheet"][class="fullscreen"]'); - if (enable) { - // Currently NOT USING fullscreen; enable fullscreen - stylesheet.removeAttr('disabled'); - $('#nav-swap .fullscreen').removeClass('disabled'); - $('#devdoc-nav').css({left:''}); - setTimeout(updateSidenavFullscreenWidth,delay); // need to wait a moment for css to switch - enabled = true; - } else { - // Currently USING fullscreen; disable fullscreen - stylesheet.attr('disabled', 'disabled'); - $('#nav-swap .fullscreen').addClass('disabled'); - setTimeout(updateSidenavFixedWidth,delay); // need to wait a moment for css to switch - enabled = false; - } - writeCookie("fullscreen", enabled, null); - setNavBarLeftPos(); - resizeNav(delay); - updateSideNavPosition(); - setTimeout(initSidenavHeightResize,delay); -} - - -function setNavBarLeftPos() { - navBarLeftPos = $('#body-content').offset().left; -} - - -function updateSideNavPosition() { - var newLeft = $(window).scrollLeft() - navBarLeftPos; - $('#devdoc-nav').css({left: -newLeft}); - $('#devdoc-nav .totop').css({left: -(newLeft - parseInt($('#side-nav').css('margin-left')))}); -} - -// TODO: use $(document).ready instead -function addLoadEvent(newfun) { - var current = window.onload; - if (typeof window.onload != 'function') { - window.onload = newfun; - } else { - window.onload = function() { - current(); - newfun(); - } - } -} - -var agent = navigator['userAgent'].toLowerCase(); -// If a mobile phone, set flag and do mobile setup -if ((agent.indexOf("mobile") != -1) || // android, iphone, ipod - (agent.indexOf("blackberry") != -1) || - (agent.indexOf("webos") != -1) || - (agent.indexOf("mini") != -1)) { // opera mini browsers - isMobile = true; -} - - -$(document).ready(function() { - $("pre:not(.no-pretty-print)").addClass("prettyprint"); - prettyPrint(); -}); - - - - -/* ######### RESIZE THE SIDENAV HEIGHT ########## */ - -function resizeNav(delay) { - var $nav = $("#devdoc-nav"); - var $window = $(window); - var navHeight; - - // Get the height of entire window and the total header height. - // Then figure out based on scroll position whether the header is visible - var windowHeight = $window.height(); - var scrollTop = $window.scrollTop(); - var headerHeight = $('#header-wrapper').outerHeight(); - var headerVisible = scrollTop < stickyTop; - - // get the height of space between nav and top of window. - // Could be either margin or top position, depending on whether the nav is fixed. - var topMargin = (parseInt($nav.css('margin-top')) || parseInt($nav.css('top'))) + 1; - // add 1 for the #side-nav bottom margin - - // Depending on whether the header is visible, set the side nav's height. - if (headerVisible) { - // The sidenav height grows as the header goes off screen - navHeight = windowHeight - (headerHeight - scrollTop) - topMargin; - } else { - // Once header is off screen, the nav height is almost full window height - navHeight = windowHeight - topMargin; - } - - - - $scrollPanes = $(".scroll-pane"); - if ($scrollPanes.length > 1) { - // subtract the height of the api level widget and nav swapper from the available nav height - navHeight -= ($('#api-nav-header').outerHeight(true) + $('#nav-swap').outerHeight(true)); - - $("#swapper").css({height:navHeight + "px"}); - if ($("#nav-tree").is(":visible")) { - $("#nav-tree").css({height:navHeight}); - } - - var classesHeight = navHeight - parseInt($("#resize-packages-nav").css("height")) - 10 + "px"; - //subtract 10px to account for drag bar - - // if the window becomes small enough to make the class panel height 0, - // then the package panel should begin to shrink - if (parseInt(classesHeight) <= 0) { - $("#resize-packages-nav").css({height:navHeight - 10}); //subtract 10px for drag bar - $("#packages-nav").css({height:navHeight - 10}); - } - - $("#classes-nav").css({'height':classesHeight, 'margin-top':'10px'}); - $("#classes-nav .jspContainer").css({height:classesHeight}); - - - } else { - $nav.height(navHeight); - } - - if (delay) { - updateFromResize = true; - delayedReInitScrollbars(delay); - } else { - reInitScrollbars(); - } - -} - -var updateScrollbars = false; -var updateFromResize = false; - -/* Re-initialize the scrollbars to account for changed nav size. - * This method postpones the actual update by a 1/4 second in order to optimize the - * scroll performance while the header is still visible, because re-initializing the - * scroll panes is an intensive process. - */ -function delayedReInitScrollbars(delay) { - // If we're scheduled for an update, but have received another resize request - // before the scheduled resize has occured, just ignore the new request - // (and wait for the scheduled one). - if (updateScrollbars && updateFromResize) { - updateFromResize = false; - return; - } - - // We're scheduled for an update and the update request came from this method's setTimeout - if (updateScrollbars && !updateFromResize) { - reInitScrollbars(); - updateScrollbars = false; - } else { - updateScrollbars = true; - updateFromResize = false; - setTimeout('delayedReInitScrollbars()',delay); - } -} - -/* Re-initialize the scrollbars to account for changed nav size. */ -function reInitScrollbars() { - var pane = $(".scroll-pane").each(function(){ - var api = $(this).data('jsp'); - if (!api) { setTimeout(reInitScrollbars,300); return;} - api.reinitialise( {verticalGutter:0} ); - }); - $(".scroll-pane").removeAttr("tabindex"); // get rid of tabindex added by jscroller -} - - -/* Resize the height of the nav panels in the reference, - * and save the new size to a cookie */ -function saveNavPanels() { - var basePath = getBaseUri(location.pathname); - var section = basePath.substring(1,basePath.indexOf("/",1)); - writeCookie("height", resizePackagesNav.css("height"), section); -} - - - -function restoreHeight(packageHeight) { - $("#resize-packages-nav").height(packageHeight); - $("#packages-nav").height(packageHeight); - // var classesHeight = navHeight - packageHeight; - // $("#classes-nav").css({height:classesHeight}); - // $("#classes-nav .jspContainer").css({height:classesHeight}); -} - - - -/* ######### END RESIZE THE SIDENAV HEIGHT ########## */ - - - - - -/** Scroll the jScrollPane to make the currently selected item visible - This is called when the page finished loading. */ -function scrollIntoView(nav) { - var $nav = $("#"+nav); - var element = $nav.jScrollPane({/* ...settings... */}); - var api = element.data('jsp'); - - if ($nav.is(':visible')) { - var $selected = $(".selected", $nav); - if ($selected.length == 0) { - // If no selected item found, exit - return; - } - // get the selected item's offset from its container nav by measuring the item's offset - // relative to the document then subtract the container nav's offset relative to the document - var selectedOffset = $selected.offset().top - $nav.offset().top; - if (selectedOffset > $nav.height() * .8) { // multiply nav height by .8 so we move up the item - // if it's more than 80% down the nav - // scroll the item up by an amount equal to 80% the container nav's height - api.scrollTo(0, selectedOffset - ($nav.height() * .8), false); - } - } -} - - - - - - -/* Show popup dialogs */ -function showDialog(id) { - $dialog = $("#"+id); - $dialog.prepend('<div class="box-border"><div class="top"> <div class="left"></div> <div class="right"></div></div><div class="bottom"> <div class="left"></div> <div class="right"></div> </div> </div>'); - $dialog.wrapInner('<div/>'); - $dialog.removeClass("hide"); -} - - - - - -/* ######### COOKIES! ########## */ - -function readCookie(cookie) { - var myCookie = cookie_namespace+"_"+cookie+"="; - if (document.cookie) { - var index = document.cookie.indexOf(myCookie); - if (index != -1) { - var valStart = index + myCookie.length; - var valEnd = document.cookie.indexOf(";", valStart); - if (valEnd == -1) { - valEnd = document.cookie.length; - } - var val = document.cookie.substring(valStart, valEnd); - return val; - } - } - return 0; -} - -function writeCookie(cookie, val, section) { - if (val==undefined) return; - section = section == null ? "_" : "_"+section+"_"; - var age = 2*365*24*60*60; // set max-age to 2 years - var cookieValue = cookie_namespace + section + cookie + "=" + val - + "; max-age=" + age +"; path=/"; - document.cookie = cookieValue; -} - -/* ######### END COOKIES! ########## */ - - -var sticky = false; -var stickyTop; -var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll -/* Sets the vertical scoll position at which the sticky bar should appear. - This method is called to reset the position when search results appear or hide */ -function setStickyTop() { - stickyTop = $('#header-wrapper').outerHeight() - $('#sticky-header').outerHeight(); -} - -/* - * Displays sticky nav bar on pages when dac header scrolls out of view - */ -$(window).scroll(function(event) { - - setStickyTop(); - var hiding = false; - var $stickyEl = $('#sticky-header'); - var $menuEl = $('.menu-container'); - // Exit if there's no sidenav - if ($('#side-nav').length == 0) return; - // Exit if the mouse target is a DIV, because that means the event is coming - // from a scrollable div and so there's no need to make adjustments to our layout - if ($(event.target).nodeName == "DIV") { - return; - } - - var top = $(window).scrollTop(); - // we set the navbar fixed when the scroll position is beyond the height of the site header... - var shouldBeSticky = top >= stickyTop; - // ... except if the document content is shorter than the sidenav height. - // (this is necessary to avoid crazy behavior on OSX Lion due to overscroll bouncing) - if ($("#doc-col").height() < $("#side-nav").height()) { - shouldBeSticky = false; - } - // Account for horizontal scroll - var scrollLeft = $(window).scrollLeft(); - // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match - if (sticky && (scrollLeft != prevScrollLeft)) { - updateSideNavPosition(); - prevScrollLeft = scrollLeft; - } - - // Don't continue if the header is sufficently far away - // (to avoid intensive resizing that slows scrolling) - if (sticky == shouldBeSticky) { - return; - } - - // If sticky header visible and position is now near top, hide sticky - if (sticky && !shouldBeSticky) { - sticky = false; - hiding = true; - // make the sidenav static again - $('#devdoc-nav') - .removeClass('fixed') - .css({'width':'auto','margin':''}) - .prependTo('#side-nav'); - // delay hide the sticky - $menuEl.removeClass('sticky-menu'); - $stickyEl.fadeOut(250); - hiding = false; - - // update the sidenaav position for side scrolling - updateSideNavPosition(); - } else if (!sticky && shouldBeSticky) { - sticky = true; - $stickyEl.fadeIn(10); - $menuEl.addClass('sticky-menu'); - - // make the sidenav fixed - var width = $('#devdoc-nav').width(); - $('#devdoc-nav') - .addClass('fixed') - .css({'width':width+'px'}) - .prependTo('#body-content'); - - // update the sidenaav position for side scrolling - updateSideNavPosition(); - - } else if (hiding && top < 15) { - $menuEl.removeClass('sticky-menu'); - $stickyEl.hide(); - hiding = false; - } - resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance -}); - -/* - * Manages secion card states and nav resize to conclude loading - */ -(function() { - $(document).ready(function() { - - // Stack hover states - $('.section-card-menu').each(function(index, el) { - var height = $(el).height(); - $(el).css({height:height+'px', position:'relative'}); - var $cardInfo = $(el).find('.card-info'); - - $cardInfo.css({position: 'absolute', bottom:'0px', left:'0px', right:'0px', overflow:'visible'}); - }); - - }); - -})(); - - - - - - - - - - - - - - -/* MISC LIBRARY FUNCTIONS */ - - - - - -function toggle(obj, slide) { - var ul = $("ul:first", obj); - var li = ul.parent(); - if (li.hasClass("closed")) { - if (slide) { - ul.slideDown("fast"); - } else { - ul.show(); - } - li.removeClass("closed"); - li.addClass("open"); - $(".toggle-img", li).attr("title", "hide pages"); - } else { - ul.slideUp("fast"); - li.removeClass("open"); - li.addClass("closed"); - $(".toggle-img", li).attr("title", "show pages"); - } -} - - -function buildToggleLists() { - $(".toggle-list").each( - function(i) { - $("div:first", this).append("<a class='toggle-img' href='#' title='show pages' onClick='toggle(this.parentNode.parentNode, true); return false;'></a>"); - $(this).addClass("closed"); - }); -} - - - -function hideNestedItems(list, toggle) { - $list = $(list); - // hide nested lists - if($list.hasClass('showing')) { - $("li ol", $list).hide('fast'); - $list.removeClass('showing'); - // show nested lists - } else { - $("li ol", $list).show('fast'); - $list.addClass('showing'); - } - $(".more,.less",$(toggle)).toggle(); -} - - -/* Call this to add listeners to a <select> element for Studio/Eclipse/Other docs */ -function setupIdeDocToggle() { - $( "select.ide" ).change(function() { - var selected = $(this).find("option:selected").attr("value"); - $(".select-ide").hide(); - $(".select-ide."+selected).show(); - - $("select.ide").val(selected); - }); -} - - - - - - - - - - - - - - - - - - - - - - - - -/* REFERENCE NAV SWAP */ - - -function getNavPref() { - var v = readCookie('reference_nav'); - if (v != NAV_PREF_TREE) { - v = NAV_PREF_PANELS; - } - return v; -} - -function chooseDefaultNav() { - nav_pref = getNavPref(); - if (nav_pref == NAV_PREF_TREE) { - $("#nav-panels").toggle(); - $("#panel-link").toggle(); - $("#nav-tree").toggle(); - $("#tree-link").toggle(); - } -} - -function swapNav() { - if (nav_pref == NAV_PREF_TREE) { - nav_pref = NAV_PREF_PANELS; - } else { - nav_pref = NAV_PREF_TREE; - init_default_navtree(toRoot); - } - writeCookie("nav", nav_pref, "reference"); - - $("#nav-panels").toggle(); - $("#panel-link").toggle(); - $("#nav-tree").toggle(); - $("#tree-link").toggle(); - - resizeNav(); - - // Gross nasty hack to make tree view show up upon first swap by setting height manually - $("#nav-tree .jspContainer:visible") - .css({'height':$("#nav-tree .jspContainer .jspPane").height() +'px'}); - // Another nasty hack to make the scrollbar appear now that we have height - resizeNav(); - - if ($("#nav-tree").is(':visible')) { - scrollIntoView("nav-tree"); - } else { - scrollIntoView("packages-nav"); - scrollIntoView("classes-nav"); - } -} - - - -/* ############################################ */ -/* ########## LOCALIZATION ############ */ -/* ############################################ */ - -function getBaseUri(uri) { - var intlUrl = (uri.substring(0,6) == "/intl/"); - if (intlUrl) { - base = uri.substring(uri.indexOf('intl/')+5,uri.length); - base = base.substring(base.indexOf('/')+1, base.length); - //alert("intl, returning base url: /" + base); - return ("/" + base); - } else { - //alert("not intl, returning uri as found."); - return uri; - } -} - -function requestAppendHL(uri) { -//append "?hl=<lang> to an outgoing request (such as to blog) - var lang = getLangPref(); - if (lang) { - var q = 'hl=' + lang; - uri += '?' + q; - window.location = uri; - return false; - } else { - return true; - } -} - - -function changeNavLang(lang) { - var $links = $("#devdoc-nav,#header,#nav-x,.training-nav-top,.content-footer").find("a["+lang+"-lang]"); - $links.each(function(i){ // for each link with a translation - var $link = $(this); - if (lang != "en") { // No need to worry about English, because a language change invokes new request - // put the desired language from the attribute as the text - $link.text($link.attr(lang+"-lang")) - } - }); -} - -function changeLangPref(lang, submit) { - writeCookie("pref_lang", lang, null); - - // ####### 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 (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); - } - } -} - -function loadLangPref() { - var lang = readCookie("pref_lang"); - if (lang != 0) { - $("#language").find("option[value='"+lang+"']").attr("selected",true); - } -} - -function getLangPref() { - var lang = $("#language").find(":selected").attr("value"); - if (!lang) { - lang = readCookie("pref_lang"); - } - return (lang != 0) ? lang : 'en'; -} - -/* ########## END LOCALIZATION ############ */ - - - - - - -/* Used to hide and reveal supplemental content, such as long code samples. - See the companion CSS in android-developer-docs.css */ -function toggleContent(obj) { - var div = $(obj).closest(".toggle-content"); - var toggleMe = $(".toggle-content-toggleme:eq(0)",div); - if (div.hasClass("closed")) { // if it's closed, open it - toggleMe.slideDown(); - $(".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"); - } 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(); - div.removeClass("open").addClass("closed"); - 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"); - }); - } - return false; -} - - -/* New version of expandable content */ -function toggleExpandable(link,id) { - if($(id).is(':visible')) { - $(id).slideUp(); - $(link).removeClass('expanded'); - } else { - $(id).slideDown(); - $(link).addClass('expanded'); - } -} - -function hideExpandable(ids) { - $(ids).slideUp(); - $(ids).prev('h4').find('a.expandable').removeClass('expanded'); -} - - - - - -/* - * Slideshow 1.0 - * Used on /index.html and /develop/index.html for carousel - * - * Sample usage: - * HTML - - * <div class="slideshow-container"> - * <a href="" class="slideshow-prev">Prev</a> - * <a href="" class="slideshow-next">Next</a> - * <ul> - * <li class="item"><img src="images/marquee1.jpg"></li> - * <li class="item"><img src="images/marquee2.jpg"></li> - * <li class="item"><img src="images/marquee3.jpg"></li> - * <li class="item"><img src="images/marquee4.jpg"></li> - * </ul> - * </div> - * - * <script type="text/javascript"> - * $('.slideshow-container').dacSlideshow({ - * auto: true, - * btnPrev: '.slideshow-prev', - * btnNext: '.slideshow-next' - * }); - * </script> - * - * Options: - * btnPrev: optional identifier for previous button - * btnNext: optional identifier for next button - * btnPause: optional identifier for pause button - * auto: whether or not to auto-proceed - * speed: animation speed - * autoTime: time between auto-rotation - * easing: easing function for transition - * start: item to select by default - * scroll: direction to scroll in - * pagination: whether or not to include dotted pagination - * - */ - - (function($) { - $.fn.dacSlideshow = function(o) { - - //Options - see above - o = $.extend({ - btnPrev: null, - btnNext: null, - btnPause: null, - auto: true, - speed: 500, - autoTime: 12000, - easing: null, - start: 0, - scroll: 1, - pagination: true - - }, o || {}); - - //Set up a carousel for each - return this.each(function() { - - var running = false; - var animCss = o.vertical ? "top" : "left"; - var sizeCss = o.vertical ? "height" : "width"; - var div = $(this); - var ul = $("ul", div); - var tLi = $("li", ul); - var tl = tLi.size(); - var timer = null; - - var li = $("li", ul); - var itemLength = li.size(); - var curr = o.start; - - li.css({float: o.vertical ? "none" : "left"}); - ul.css({margin: "0", padding: "0", position: "relative", "list-style-type": "none", "z-index": "1"}); - div.css({position: "relative", "z-index": "2", left: "0px"}); - - var liSize = o.vertical ? height(li) : width(li); - var ulSize = liSize * itemLength; - var divSize = liSize; - - li.css({width: li.width(), height: li.height()}); - ul.css(sizeCss, ulSize+"px").css(animCss, -(curr*liSize)); - - div.css(sizeCss, divSize+"px"); - - //Pagination - if (o.pagination) { - var pagination = $("<div class='pagination'></div>"); - var pag_ul = $("<ul></ul>"); - if (tl > 1) { - for (var i=0;i<tl;i++) { - var li = $("<li>"+i+"</li>"); - pag_ul.append(li); - if (i==o.start) li.addClass('active'); - li.click(function() { - go(parseInt($(this).text())); - }) - } - pagination.append(pag_ul); - div.append(pagination); - } - } - - //Previous button - if(o.btnPrev) - $(o.btnPrev).click(function(e) { - e.preventDefault(); - return go(curr-o.scroll); - }); - - //Next button - if(o.btnNext) - $(o.btnNext).click(function(e) { - e.preventDefault(); - return go(curr+o.scroll); - }); - - //Pause button - if(o.btnPause) - $(o.btnPause).click(function(e) { - e.preventDefault(); - if ($(this).hasClass('paused')) { - startRotateTimer(); - } else { - pauseRotateTimer(); - } - }); - - //Auto rotation - if(o.auto) startRotateTimer(); - - function startRotateTimer() { - clearInterval(timer); - timer = setInterval(function() { - if (curr == tl-1) { - go(0); - } else { - go(curr+o.scroll); - } - }, o.autoTime); - $(o.btnPause).removeClass('paused'); - } - - function pauseRotateTimer() { - clearInterval(timer); - $(o.btnPause).addClass('paused'); - } - - //Go to an item - function go(to) { - if(!running) { - - if(to<0) { - to = itemLength-1; - } else if (to>itemLength-1) { - to = 0; - } - curr = to; - - running = true; - - ul.animate( - animCss == "left" ? { left: -(curr*liSize) } : { top: -(curr*liSize) } , o.speed, o.easing, - function() { - running = false; - } - ); - - $(o.btnPrev + "," + o.btnNext).removeClass("disabled"); - $( (curr-o.scroll<0 && o.btnPrev) - || - (curr+o.scroll > itemLength && o.btnNext) - || - [] - ).addClass("disabled"); - - - var nav_items = $('li', pagination); - nav_items.removeClass('active'); - nav_items.eq(to).addClass('active'); - - - } - if(o.auto) startRotateTimer(); - return false; - }; - }); - }; - - function css(el, prop) { - return parseInt($.css(el[0], prop)) || 0; - }; - function width(el) { - return el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight'); - }; - function height(el) { - return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom'); - }; - - })(jQuery); - - -/* - * dacSlideshow 1.0 - * Used on develop/index.html for side-sliding tabs - * - * Sample usage: - * HTML - - * <div class="slideshow-container"> - * <a href="" class="slideshow-prev">Prev</a> - * <a href="" class="slideshow-next">Next</a> - * <ul> - * <li class="item"><img src="images/marquee1.jpg"></li> - * <li class="item"><img src="images/marquee2.jpg"></li> - * <li class="item"><img src="images/marquee3.jpg"></li> - * <li class="item"><img src="images/marquee4.jpg"></li> - * </ul> - * </div> - * - * <script type="text/javascript"> - * $('.slideshow-container').dacSlideshow({ - * auto: true, - * btnPrev: '.slideshow-prev', - * btnNext: '.slideshow-next' - * }); - * </script> - * - * Options: - * btnPrev: optional identifier for previous button - * btnNext: optional identifier for next button - * auto: whether or not to auto-proceed - * speed: animation speed - * autoTime: time between auto-rotation - * easing: easing function for transition - * start: item to select by default - * scroll: direction to scroll in - * pagination: whether or not to include dotted pagination - * - */ - (function($) { - $.fn.dacTabbedList = function(o) { - - //Options - see above - o = $.extend({ - speed : 250, - easing: null, - nav_id: null, - frame_id: null - }, o || {}); - - //Set up a carousel for each - return this.each(function() { - - var curr = 0; - var running = false; - var animCss = "margin-left"; - var sizeCss = "width"; - var div = $(this); - - var nav = $(o.nav_id, div); - var nav_li = $("li", nav); - var nav_size = nav_li.size(); - var frame = div.find(o.frame_id); - var content_width = $(frame).find('ul').width(); - //Buttons - $(nav_li).click(function(e) { - go($(nav_li).index($(this))); - }) - - //Go to an item - function go(to) { - if(!running) { - curr = to; - running = true; - - frame.animate({ 'margin-left' : -(curr*content_width) }, o.speed, o.easing, - function() { - running = false; - } - ); - - - nav_li.removeClass('active'); - nav_li.eq(to).addClass('active'); - - - } - return false; - }; - }); - }; - - function css(el, prop) { - return parseInt($.css(el[0], prop)) || 0; - }; - function width(el) { - return el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight'); - }; - function height(el) { - return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom'); - }; - - })(jQuery); - - - - - -/* ######################################################## */ -/* ################ SEARCH SUGGESTIONS ################## */ -/* ######################################################## */ - - - -var gSelectedIndex = -1; // the index position of currently highlighted suggestion -var gSelectedColumn = -1; // which column of suggestion lists is currently focused - -var gMatches = new Array(); -var gLastText = ""; -var gInitialized = false; -var ROW_COUNT_FRAMEWORK = 20; // max number of results in list -var gListLength = 0; - - -var gGoogleMatches = new Array(); -var ROW_COUNT_GOOGLE = 15; // max number of results in list -var gGoogleListLength = 0; - -var gDocsMatches = new Array(); -var ROW_COUNT_DOCS = 100; // max number of results in list -var gDocsListLength = 0; - -function onSuggestionClick(link) { - // When user clicks a suggested document, track it - ga('send', 'event', 'Suggestion Click', 'clicked: ' + $(link).attr('href'), - 'query: ' + $("#search_autocomplete").val().toLowerCase()); -} - -function set_item_selected($li, selected) -{ - if (selected) { - $li.attr('class','jd-autocomplete jd-selected'); - } else { - $li.attr('class','jd-autocomplete'); - } -} - -function set_item_values(toroot, $li, match) -{ - var $link = $('a',$li); - $link.html(match.__hilabel || match.label); - $link.attr('href',toroot + match.link); -} - -function set_item_values_jd(toroot, $li, match) -{ - var $link = $('a',$li); - $link.html(match.title); - $link.attr('href',toroot + match.url); -} - -function new_suggestion($list) { - var $li = $("<li class='jd-autocomplete'></li>"); - $list.append($li); - - $li.mousedown(function() { - window.location = this.firstChild.getAttribute("href"); - }); - $li.mouseover(function() { - $('.search_filtered_wrapper li').removeClass('jd-selected'); - $(this).addClass('jd-selected'); - gSelectedColumn = $(".search_filtered:visible").index($(this).closest('.search_filtered')); - gSelectedIndex = $("li", $(".search_filtered:visible")[gSelectedColumn]).index(this); - }); - $li.append("<a onclick='onSuggestionClick(this)'></a>"); - $li.attr('class','show-item'); - return $li; -} - -function sync_selection_table(toroot) -{ - var $li; //list item jquery object - var i; //list item iterator - - // if there are NO results at all, hide all columns - if (!(gMatches.length > 0) && !(gGoogleMatches.length > 0) && !(gDocsMatches.length > 0)) { - $('.suggest-card').hide(300); - return; - } - - // if there are api results - if ((gMatches.length > 0) || (gGoogleMatches.length > 0)) { - // reveal suggestion list - $('.suggest-card.dummy').show(); - $('.suggest-card.reference').show(); - var listIndex = 0; // list index position - - // reset the lists - $(".search_filtered_wrapper.reference li").remove(); - - // ########### ANDROID RESULTS ############# - if (gMatches.length > 0) { - - // determine android results to show - gListLength = gMatches.length < ROW_COUNT_FRAMEWORK ? - gMatches.length : ROW_COUNT_FRAMEWORK; - for (i=0; i<gListLength; i++) { - var $li = new_suggestion($(".suggest-card.reference ul")); - set_item_values(toroot, $li, gMatches[i]); - set_item_selected($li, i == gSelectedIndex); - } - } - - // ########### GOOGLE RESULTS ############# - if (gGoogleMatches.length > 0) { - // show header for list - $(".suggest-card.reference ul").append("<li class='header'>in Google Services:</li>"); - - // determine google results to show - gGoogleListLength = gGoogleMatches.length < ROW_COUNT_GOOGLE ? gGoogleMatches.length : ROW_COUNT_GOOGLE; - for (i=0; i<gGoogleListLength; i++) { - var $li = new_suggestion($(".suggest-card.reference ul")); - set_item_values(toroot, $li, gGoogleMatches[i]); - set_item_selected($li, i == gSelectedIndex); - } - } - } else { - $('.suggest-card.reference').hide(); - $('.suggest-card.dummy').hide(); - } - - // ########### JD DOC RESULTS ############# - if (gDocsMatches.length > 0) { - // reset the lists - $(".search_filtered_wrapper.docs li").remove(); - - // determine google results to show - // NOTE: The order of the conditions below for the sugg.type MUST BE SPECIFIC: - // The order must match the reverse order that each section appears as a card in - // the suggestion UI... this may be only for the "develop" grouped items though. - gDocsListLength = gDocsMatches.length < ROW_COUNT_DOCS ? gDocsMatches.length : ROW_COUNT_DOCS; - for (i=0; i<gDocsListLength; i++) { - var sugg = gDocsMatches[i]; - var $li; - if (sugg.type == "design") { - $li = new_suggestion($(".suggest-card.design ul")); - } else - if (sugg.type == "distribute") { - $li = new_suggestion($(".suggest-card.distribute ul")); - } else - if (sugg.type == "samples") { - $li = new_suggestion($(".suggest-card.develop .child-card.samples")); - } else - if (sugg.type == "training") { - $li = new_suggestion($(".suggest-card.develop .child-card.training")); - } else - if (sugg.type == "about"||"guide"||"tools"||"google") { - $li = new_suggestion($(".suggest-card.develop .child-card.guides")); - } else { - continue; - } - - set_item_values_jd(toroot, $li, sugg); - set_item_selected($li, i == gSelectedIndex); - } - - // add heading and show or hide card - if ($(".suggest-card.design li").length > 0) { - $(".suggest-card.design ul").prepend("<li class='header'>Design:</li>"); - $(".suggest-card.design").show(300); - } else { - $('.suggest-card.design').hide(300); - } - if ($(".suggest-card.distribute li").length > 0) { - $(".suggest-card.distribute ul").prepend("<li class='header'>Distribute:</li>"); - $(".suggest-card.distribute").show(300); - } else { - $('.suggest-card.distribute').hide(300); - } - if ($(".child-card.guides li").length > 0) { - $(".child-card.guides").prepend("<li class='header'>Guides:</li>"); - $(".child-card.guides li").appendTo(".suggest-card.develop ul"); - } - if ($(".child-card.training li").length > 0) { - $(".child-card.training").prepend("<li class='header'>Training:</li>"); - $(".child-card.training li").appendTo(".suggest-card.develop ul"); - } - if ($(".child-card.samples li").length > 0) { - $(".child-card.samples").prepend("<li class='header'>Samples:</li>"); - $(".child-card.samples li").appendTo(".suggest-card.develop ul"); - } - - if ($(".suggest-card.develop li").length > 0) { - $(".suggest-card.develop").show(300); - } else { - $('.suggest-card.develop').hide(300); - } - - } else { - $('.search_filtered_wrapper.docs .suggest-card:not(.dummy)').hide(300); - } -} - -/** Called by the search input's onkeydown and onkeyup events. - * Handles navigation with keyboard arrows, Enter key to invoke search, - * otherwise invokes search suggestions on key-up event. - * @param e The JS event - * @param kd True if the event is key-down - * @param toroot A string for the site's root path - * @returns True if the event should bubble up - */ -function search_changed(e, kd, toroot) -{ - var currentLang = getLangPref(); - var search = document.getElementById("search_autocomplete"); - var text = search.value.replace(/(^ +)|( +$)/g, ''); - // get the ul hosting the currently selected item - gSelectedColumn = gSelectedColumn >= 0 ? gSelectedColumn : 0; - var $columns = $(".search_filtered_wrapper").find(".search_filtered:visible"); - var $selectedUl = $columns[gSelectedColumn]; - - // show/hide the close button - if (text != '') { - $(".search .close").removeClass("hide"); - } else { - $(".search .close").addClass("hide"); - } - // 27 = esc - if (e.keyCode == 27) { - // close all search results - if (kd) $('.search .close').trigger('click'); - return true; - } - // 13 = enter - else if (e.keyCode == 13) { - if (gSelectedIndex < 0) { - $('.suggest-card').hide(); - if ($("#searchResults").is(":hidden") && (search.value != "")) { - // if results aren't showing (and text not empty), return true to allow search to execute - $('body,html').animate({scrollTop:0}, '500', 'swing'); - return true; - } else { - // otherwise, results are already showing, so allow ajax to auto refresh the results - // and ignore this Enter press to avoid the reload. - return false; - } - } else if (kd && gSelectedIndex >= 0) { - // click the link corresponding to selected item - $("a",$("li",$selectedUl)[gSelectedIndex]).get()[0].click(); - return false; - } - } - // If Google results are showing, return true to allow ajax search to execute - else if ($("#searchResults").is(":visible")) { - // Also, if search_results is scrolled out of view, scroll to top to make results visible - if ((sticky ) && (search.value != "")) { - $('body,html').animate({scrollTop:0}, '500', 'swing'); - } - return true; - } - // 38 UP ARROW - else if (kd && (e.keyCode == 38)) { - // if the next item is a header, skip it - if ($($("li", $selectedUl)[gSelectedIndex-1]).hasClass("header")) { - gSelectedIndex--; - } - if (gSelectedIndex >= 0) { - $('li', $selectedUl).removeClass('jd-selected'); - gSelectedIndex--; - $('li:nth-child('+(gSelectedIndex+1)+')', $selectedUl).addClass('jd-selected'); - // If user reaches top, reset selected column - if (gSelectedIndex < 0) { - gSelectedColumn = -1; - } - } - return false; - } - // 40 DOWN ARROW - else if (kd && (e.keyCode == 40)) { - // if the next item is a header, skip it - if ($($("li", $selectedUl)[gSelectedIndex+1]).hasClass("header")) { - gSelectedIndex++; - } - if ((gSelectedIndex < $("li", $selectedUl).length-1) || - ($($("li", $selectedUl)[gSelectedIndex+1]).hasClass("header"))) { - $('li', $selectedUl).removeClass('jd-selected'); - gSelectedIndex++; - $('li:nth-child('+(gSelectedIndex+1)+')', $selectedUl).addClass('jd-selected'); - } - return false; - } - // Consider left/right arrow navigation - // NOTE: Order of suggest columns are reverse order (index position 0 is on right) - else if (kd && $columns.length > 1 && gSelectedColumn >= 0) { - // 37 LEFT ARROW - // go left only if current column is not left-most column (last column) - if (e.keyCode == 37 && gSelectedColumn < $columns.length - 1) { - $('li', $selectedUl).removeClass('jd-selected'); - gSelectedColumn++; - $selectedUl = $columns[gSelectedColumn]; - // keep or reset the selected item to last item as appropriate - gSelectedIndex = gSelectedIndex > - $("li", $selectedUl).length-1 ? - $("li", $selectedUl).length-1 : gSelectedIndex; - // if the corresponding item is a header, move down - if ($($("li", $selectedUl)[gSelectedIndex]).hasClass("header")) { - gSelectedIndex++; - } - // set item selected - $('li:nth-child('+(gSelectedIndex+1)+')', $selectedUl).addClass('jd-selected'); - return false; - } - // 39 RIGHT ARROW - // go right only if current column is not the right-most column (first column) - else if (e.keyCode == 39 && gSelectedColumn > 0) { - $('li', $selectedUl).removeClass('jd-selected'); - gSelectedColumn--; - $selectedUl = $columns[gSelectedColumn]; - // keep or reset the selected item to last item as appropriate - gSelectedIndex = gSelectedIndex > - $("li", $selectedUl).length-1 ? - $("li", $selectedUl).length-1 : gSelectedIndex; - // if the corresponding item is a header, move down - if ($($("li", $selectedUl)[gSelectedIndex]).hasClass("header")) { - gSelectedIndex++; - } - // set item selected - $('li:nth-child('+(gSelectedIndex+1)+')', $selectedUl).addClass('jd-selected'); - return false; - } - } - - // if key-up event and not arrow down/up/left/right, - // read the search query and add suggestions to gMatches - else if (!kd && (e.keyCode != 40) - && (e.keyCode != 38) - && (e.keyCode != 37) - && (e.keyCode != 39)) { - gSelectedIndex = -1; - gMatches = new Array(); - matchedCount = 0; - gGoogleMatches = new Array(); - matchedCountGoogle = 0; - gDocsMatches = new Array(); - matchedCountDocs = 0; - - // Search for Android matches - for (var i=0; i<DATA.length; i++) { - var s = DATA[i]; - if (text.length != 0 && - s.label.toLowerCase().indexOf(text.toLowerCase()) != -1) { - gMatches[matchedCount] = s; - matchedCount++; - } - } - rank_autocomplete_api_results(text, gMatches); - for (var i=0; i<gMatches.length; i++) { - var s = gMatches[i]; - } - - - // Search for Google matches - for (var i=0; i<GOOGLE_DATA.length; i++) { - var s = GOOGLE_DATA[i]; - if (text.length != 0 && - s.label.toLowerCase().indexOf(text.toLowerCase()) != -1) { - gGoogleMatches[matchedCountGoogle] = s; - matchedCountGoogle++; - } - } - rank_autocomplete_api_results(text, gGoogleMatches); - for (var i=0; i<gGoogleMatches.length; i++) { - var s = gGoogleMatches[i]; - } - - highlight_autocomplete_result_labels(text); - - - - // Search for matching JD docs - if (text.length >= 2) { - // Regex to match only the beginning of a word - var textRegex = new RegExp("\\b" + text.toLowerCase(), "g"); - - - // Search for Training classes - for (var i=0; i<TRAINING_RESOURCES.length; i++) { - // current search comparison, with counters for tag and title, - // used later to improve ranking - var s = TRAINING_RESOURCES[i]; - s.matched_tag = 0; - s.matched_title = 0; - var matched = false; - - // Check if query matches any tags; work backwards toward 1 to assist ranking - for (var j = s.keywords.length - 1; j >= 0; j--) { - // it matches a tag - if (s.keywords[j].toLowerCase().match(textRegex)) { - matched = true; - s.matched_tag = j + 1; // add 1 to index position - } - } - // Don't consider doc title for lessons (only for class landing pages), - // unless the lesson has a tag that already matches - if ((s.lang == currentLang) && - (!(s.type == "training" && s.url.indexOf("index.html") == -1) || matched)) { - // it matches the doc title - if (s.title.toLowerCase().match(textRegex)) { - matched = true; - s.matched_title = 1; - } - } - if (matched) { - gDocsMatches[matchedCountDocs] = s; - matchedCountDocs++; - } - } - - - // Search for API Guides - for (var i=0; i<GUIDE_RESOURCES.length; i++) { - // current search comparison, with counters for tag and title, - // used later to improve ranking - var s = GUIDE_RESOURCES[i]; - s.matched_tag = 0; - s.matched_title = 0; - var matched = false; - - // Check if query matches any tags; work backwards toward 1 to assist ranking - for (var j = s.keywords.length - 1; j >= 0; j--) { - // it matches a tag - if (s.keywords[j].toLowerCase().match(textRegex)) { - matched = true; - s.matched_tag = j + 1; // add 1 to index position - } - } - // Check if query matches the doc title, but only for current language - if (s.lang == currentLang) { - // if query matches the doc title - if (s.title.toLowerCase().match(textRegex)) { - matched = true; - s.matched_title = 1; - } - } - if (matched) { - gDocsMatches[matchedCountDocs] = s; - matchedCountDocs++; - } - } - - - // Search for Tools Guides - for (var i=0; i<TOOLS_RESOURCES.length; i++) { - // current search comparison, with counters for tag and title, - // used later to improve ranking - var s = TOOLS_RESOURCES[i]; - s.matched_tag = 0; - s.matched_title = 0; - var matched = false; - - // Check if query matches any tags; work backwards toward 1 to assist ranking - for (var j = s.keywords.length - 1; j >= 0; j--) { - // it matches a tag - if (s.keywords[j].toLowerCase().match(textRegex)) { - matched = true; - s.matched_tag = j + 1; // add 1 to index position - } - } - // Check if query matches the doc title, but only for current language - if (s.lang == currentLang) { - // if query matches the doc title - if (s.title.toLowerCase().match(textRegex)) { - matched = true; - s.matched_title = 1; - } - } - if (matched) { - gDocsMatches[matchedCountDocs] = s; - matchedCountDocs++; - } - } - - - // Search for About docs - for (var i=0; i<ABOUT_RESOURCES.length; i++) { - // current search comparison, with counters for tag and title, - // used later to improve ranking - var s = ABOUT_RESOURCES[i]; - s.matched_tag = 0; - s.matched_title = 0; - var matched = false; - - // Check if query matches any tags; work backwards toward 1 to assist ranking - for (var j = s.keywords.length - 1; j >= 0; j--) { - // it matches a tag - if (s.keywords[j].toLowerCase().match(textRegex)) { - matched = true; - s.matched_tag = j + 1; // add 1 to index position - } - } - // Check if query matches the doc title, but only for current language - if (s.lang == currentLang) { - // if query matches the doc title - if (s.title.toLowerCase().match(textRegex)) { - matched = true; - s.matched_title = 1; - } - } - if (matched) { - gDocsMatches[matchedCountDocs] = s; - matchedCountDocs++; - } - } - - - // Search for Design guides - for (var i=0; i<DESIGN_RESOURCES.length; i++) { - // current search comparison, with counters for tag and title, - // used later to improve ranking - var s = DESIGN_RESOURCES[i]; - s.matched_tag = 0; - s.matched_title = 0; - var matched = false; - - // Check if query matches any tags; work backwards toward 1 to assist ranking - for (var j = s.keywords.length - 1; j >= 0; j--) { - // it matches a tag - if (s.keywords[j].toLowerCase().match(textRegex)) { - matched = true; - s.matched_tag = j + 1; // add 1 to index position - } - } - // Check if query matches the doc title, but only for current language - if (s.lang == currentLang) { - // if query matches the doc title - if (s.title.toLowerCase().match(textRegex)) { - matched = true; - s.matched_title = 1; - } - } - if (matched) { - gDocsMatches[matchedCountDocs] = s; - matchedCountDocs++; - } - } - - - // Search for Distribute guides - for (var i=0; i<DISTRIBUTE_RESOURCES.length; i++) { - // current search comparison, with counters for tag and title, - // used later to improve ranking - var s = DISTRIBUTE_RESOURCES[i]; - s.matched_tag = 0; - s.matched_title = 0; - var matched = false; - - // Check if query matches any tags; work backwards toward 1 to assist ranking - for (var j = s.keywords.length - 1; j >= 0; j--) { - // it matches a tag - if (s.keywords[j].toLowerCase().match(textRegex)) { - matched = true; - s.matched_tag = j + 1; // add 1 to index position - } - } - // Check if query matches the doc title, but only for current language - if (s.lang == currentLang) { - // if query matches the doc title - if (s.title.toLowerCase().match(textRegex)) { - matched = true; - s.matched_title = 1; - } - } - if (matched) { - gDocsMatches[matchedCountDocs] = s; - matchedCountDocs++; - } - } - - - // Search for Google guides - for (var i=0; i<GOOGLE_RESOURCES.length; i++) { - // current search comparison, with counters for tag and title, - // used later to improve ranking - var s = GOOGLE_RESOURCES[i]; - s.matched_tag = 0; - s.matched_title = 0; - var matched = false; - - // Check if query matches any tags; work backwards toward 1 to assist ranking - for (var j = s.keywords.length - 1; j >= 0; j--) { - // it matches a tag - if (s.keywords[j].toLowerCase().match(textRegex)) { - matched = true; - s.matched_tag = j + 1; // add 1 to index position - } - } - // Check if query matches the doc title, but only for current language - if (s.lang == currentLang) { - // if query matches the doc title - if (s.title.toLowerCase().match(textRegex)) { - matched = true; - s.matched_title = 1; - } - } - if (matched) { - gDocsMatches[matchedCountDocs] = s; - matchedCountDocs++; - } - } - - - // Search for Samples - for (var i=0; i<SAMPLES_RESOURCES.length; i++) { - // current search comparison, with counters for tag and title, - // used later to improve ranking - var s = SAMPLES_RESOURCES[i]; - s.matched_tag = 0; - s.matched_title = 0; - var matched = false; - // Check if query matches any tags; work backwards toward 1 to assist ranking - for (var j = s.keywords.length - 1; j >= 0; j--) { - // it matches a tag - if (s.keywords[j].toLowerCase().match(textRegex)) { - matched = true; - s.matched_tag = j + 1; // add 1 to index position - } - } - // Check if query matches the doc title, but only for current language - if (s.lang == currentLang) { - // if query matches the doc title.t - if (s.title.toLowerCase().match(textRegex)) { - matched = true; - s.matched_title = 1; - } - } - if (matched) { - gDocsMatches[matchedCountDocs] = s; - matchedCountDocs++; - } - } - - // Rank/sort all the matched pages - rank_autocomplete_doc_results(text, gDocsMatches); - } - - // draw the suggestions - sync_selection_table(toroot); - return true; // allow the event to bubble up to the search api - } -} - -/* Order the jd doc result list based on match quality */ -function rank_autocomplete_doc_results(query, matches) { - query = query || ''; - if (!matches || !matches.length) - return; - - var _resultScoreFn = function(match) { - var score = 1.0; - - // if the query matched a tag - if (match.matched_tag > 0) { - // multiply score by factor relative to position in tags list (max of 3) - score *= 3 / match.matched_tag; - - // if it also matched the title - if (match.matched_title > 0) { - score *= 2; - } - } else if (match.matched_title > 0) { - score *= 3; - } - - return score; - }; - - for (var i=0; i<matches.length; i++) { - matches[i].__resultScore = _resultScoreFn(matches[i]); - } - - matches.sort(function(a,b){ - var n = b.__resultScore - a.__resultScore; - if (n == 0) // lexicographical sort if scores are the same - n = (a.label < b.label) ? -1 : 1; - return n; - }); -} - -/* Order the result list based on match quality */ -function rank_autocomplete_api_results(query, matches) { - query = query || ''; - if (!matches || !matches.length) - return; - - // helper function that gets the last occurence index of the given regex - // in the given string, or -1 if not found - var _lastSearch = function(s, re) { - if (s == '') - return -1; - var l = -1; - var tmp; - while ((tmp = s.search(re)) >= 0) { - if (l < 0) l = 0; - l += tmp; - s = s.substr(tmp + 1); - } - return l; - }; - - // helper function that counts the occurrences of a given character in - // a given string - var _countChar = function(s, c) { - var n = 0; - for (var i=0; i<s.length; i++) - if (s.charAt(i) == c) ++n; - return n; - }; - - var queryLower = query.toLowerCase(); - var queryAlnum = (queryLower.match(/\w+/) || [''])[0]; - var partPrefixAlnumRE = new RegExp('\\b' + queryAlnum); - var partExactAlnumRE = new RegExp('\\b' + queryAlnum + '\\b'); - - var _resultScoreFn = function(result) { - // scores are calculated based on exact and prefix matches, - // and then number of path separators (dots) from the last - // match (i.e. favoring classes and deep package names) - var score = 1.0; - var labelLower = result.label.toLowerCase(); - var t; - t = _lastSearch(labelLower, partExactAlnumRE); - if (t >= 0) { - // exact part match - var partsAfter = _countChar(labelLower.substr(t + 1), '.'); - score *= 200 / (partsAfter + 1); - } else { - t = _lastSearch(labelLower, partPrefixAlnumRE); - if (t >= 0) { - // part prefix match - var partsAfter = _countChar(labelLower.substr(t + 1), '.'); - score *= 20 / (partsAfter + 1); - } - } - - return score; - }; - - for (var i=0; i<matches.length; i++) { - // if the API is deprecated, default score is 0; otherwise, perform scoring - if (matches[i].deprecated == "true") { - matches[i].__resultScore = 0; - } else { - matches[i].__resultScore = _resultScoreFn(matches[i]); - } - } - - matches.sort(function(a,b){ - var n = b.__resultScore - a.__resultScore; - if (n == 0) // lexicographical sort if scores are the same - n = (a.label < b.label) ? -1 : 1; - return n; - }); -} - -/* Add emphasis to part of string that matches query */ -function highlight_autocomplete_result_labels(query) { - query = query || ''; - if ((!gMatches || !gMatches.length) && (!gGoogleMatches || !gGoogleMatches.length)) - return; - - var queryLower = query.toLowerCase(); - var queryAlnumDot = (queryLower.match(/[\w\.]+/) || [''])[0]; - var queryRE = new RegExp( - '(' + queryAlnumDot.replace(/\./g, '\\.') + ')', 'ig'); - for (var i=0; i<gMatches.length; i++) { - gMatches[i].__hilabel = gMatches[i].label.replace( - queryRE, '<b>$1</b>'); - } - for (var i=0; i<gGoogleMatches.length; i++) { - gGoogleMatches[i].__hilabel = gGoogleMatches[i].label.replace( - queryRE, '<b>$1</b>'); - } -} - -function search_focus_changed(obj, focused) -{ - if (!focused) { - if(obj.value == ""){ - $(".search .close").addClass("hide"); - } - $(".suggest-card").hide(); - } -} - -function submit_search() { - var query = document.getElementById('search_autocomplete').value; - location.hash = 'q=' + query; - loadSearchResults(); - $("#searchResults").slideDown('slow', setStickyTop); - return false; -} - - -function hideResults() { - $("#searchResults").slideUp('fast', setStickyTop); - $(".search .close").addClass("hide"); - location.hash = ''; - - $("#search_autocomplete").val("").blur(); - - // reset the ajax search callback to nothing, so results don't appear unless ENTER - searchControl.setSearchStartingCallback(this, function(control, searcher, query) {}); - - // forcefully regain key-up event control (previously jacked by search api) - $("#search_autocomplete").keyup(function(event) { - return search_changed(event, false, toRoot); - }); - - return false; -} - - - -/* ########################################################## */ -/* ################ CUSTOM SEARCH ENGINE ################## */ -/* ########################################################## */ - -var searchControl; -google.load('search', '1', {"callback" : function() { - searchControl = new google.search.SearchControl(); - } }); - -function loadSearchResults() { - document.getElementById("search_autocomplete").style.color = "#000"; - - searchControl = new google.search.SearchControl(); - - // use our existing search form and use tabs when multiple searchers are used - drawOptions = new google.search.DrawOptions(); - drawOptions.setDrawMode(google.search.SearchControl.DRAW_MODE_TABBED); - drawOptions.setInput(document.getElementById("search_autocomplete")); - - // configure search result options - searchOptions = new google.search.SearcherOptions(); - searchOptions.setExpandMode(GSearchControl.EXPAND_MODE_OPEN); - - // configure each of the searchers, for each tab - devSiteSearcher = new google.search.WebSearch(); - devSiteSearcher.setUserDefinedLabel("All"); - devSiteSearcher.setSiteRestriction("001482626316274216503:zu90b7s047u"); - - designSearcher = new google.search.WebSearch(); - designSearcher.setUserDefinedLabel("Design"); - designSearcher.setSiteRestriction("http://developer.android.com/design/"); - - trainingSearcher = new google.search.WebSearch(); - trainingSearcher.setUserDefinedLabel("Training"); - trainingSearcher.setSiteRestriction("http://developer.android.com/training/"); - - guidesSearcher = new google.search.WebSearch(); - guidesSearcher.setUserDefinedLabel("Guides"); - guidesSearcher.setSiteRestriction("http://developer.android.com/guide/"); - - referenceSearcher = new google.search.WebSearch(); - referenceSearcher.setUserDefinedLabel("Reference"); - referenceSearcher.setSiteRestriction("http://developer.android.com/reference/"); - - googleSearcher = new google.search.WebSearch(); - googleSearcher.setUserDefinedLabel("Google Services"); - googleSearcher.setSiteRestriction("http://developer.android.com/google/"); - - blogSearcher = new google.search.WebSearch(); - blogSearcher.setUserDefinedLabel("Blog"); - blogSearcher.setSiteRestriction("http://android-developers.blogspot.com"); - - // add each searcher to the search control - searchControl.addSearcher(devSiteSearcher, searchOptions); - searchControl.addSearcher(designSearcher, searchOptions); - searchControl.addSearcher(trainingSearcher, searchOptions); - searchControl.addSearcher(guidesSearcher, searchOptions); - searchControl.addSearcher(referenceSearcher, searchOptions); - searchControl.addSearcher(googleSearcher, searchOptions); - searchControl.addSearcher(blogSearcher, searchOptions); - - // configure result options - searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET); - searchControl.setLinkTarget(google.search.Search.LINK_TARGET_SELF); - searchControl.setTimeoutInterval(google.search.SearchControl.TIMEOUT_SHORT); - searchControl.setNoResultsString(google.search.SearchControl.NO_RESULTS_DEFAULT_STRING); - - // upon ajax search, refresh the url and search title - searchControl.setSearchStartingCallback(this, function(control, searcher, query) { - updateResultTitle(query); - var query = document.getElementById('search_autocomplete').value; - location.hash = 'q=' + query; - }); - - // once search results load, set up click listeners - searchControl.setSearchCompleteCallback(this, function(control, searcher, query) { - addResultClickListeners(); - }); - - // draw the search results box - searchControl.draw(document.getElementById("leftSearchControl"), drawOptions); - - // get query and execute the search - searchControl.execute(decodeURI(getQuery(location.hash))); - - document.getElementById("search_autocomplete").focus(); - addTabListeners(); -} -// End of loadSearchResults - - -google.setOnLoadCallback(function(){ - if (location.hash.indexOf("q=") == -1) { - // if there's no query in the url, don't search and make sure results are hidden - $('#searchResults').hide(); - return; - } else { - // first time loading search results for this page - $('#searchResults').slideDown('slow', setStickyTop); - $(".search .close").removeClass("hide"); - loadSearchResults(); - } -}, true); - -/* Adjust the scroll position to account for sticky header, only if the hash matches an id. - This does not handle <a name=""> tags. Some CSS fixes those, but only for reference docs. */ -function offsetScrollForSticky() { - // Ignore if there's no search bar (some special pages have no header) - if ($("#search-container").length < 1) return; - - var hash = escape(location.hash.substr(1)); - var $matchingElement = $("#"+hash); - // Sanity check that there's an element with that ID on the page - if ($matchingElement.length) { - // If the position of the target element is near the top of the page (<20px, where we expect it - // to be because we need to move it down 60px to become in view), then move it down 60px - if (Math.abs($matchingElement.offset().top - $(window).scrollTop()) < 20) { - $(window).scrollTop($(window).scrollTop() - 60); - } - } -} - -// when an event on the browser history occurs (back, forward, load) requery hash and do search -$(window).hashchange( function(){ - // Ignore if there's no search bar (some special pages have no header) - if ($("#search-container").length < 1) return; - - // If the hash isn't a search query or there's an error in the query, - // then adjust the scroll position to account for sticky header, then exit. - if ((location.hash.indexOf("q=") == -1) || (query == "undefined")) { - // If the results pane is open, close it. - if (!$("#searchResults").is(":hidden")) { - hideResults(); - } - offsetScrollForSticky(); - return; - } - - // Otherwise, we have a search to do - var query = decodeURI(getQuery(location.hash)); - searchControl.execute(query); - $('#searchResults').slideDown('slow', setStickyTop); - $("#search_autocomplete").focus(); - $(".search .close").removeClass("hide"); - - updateResultTitle(query); -}); - -function updateResultTitle(query) { - $("#searchTitle").html("Results for <em>" + escapeHTML(query) + "</em>"); -} - -// forcefully regain key-up event control (previously jacked by search api) -$("#search_autocomplete").keyup(function(event) { - return search_changed(event, false, toRoot); -}); - -// add event listeners to each tab so we can track the browser history -function addTabListeners() { - var tabHeaders = $(".gsc-tabHeader"); - for (var i = 0; i < tabHeaders.length; i++) { - $(tabHeaders[i]).attr("id",i).click(function() { - /* - // make a copy of the page numbers for the search left pane - setTimeout(function() { - // remove any residual page numbers - $('#searchResults .gsc-tabsArea .gsc-cursor-box.gs-bidi-start-align').remove(); - // move the page numbers to the left position; make a clone, - // because the element is drawn to the DOM only once - // and because we're going to remove it (previous line), - // we need it to be available to move again as the user navigates - $('#searchResults .gsc-webResult .gsc-cursor-box.gs-bidi-start-align:visible') - .clone().appendTo('#searchResults .gsc-tabsArea'); - }, 200); - */ - }); - } - setTimeout(function(){$(tabHeaders[0]).click()},200); -} - -// add analytics tracking events to each result link -function addResultClickListeners() { - $("#searchResults a.gs-title").each(function(index, link) { - // When user clicks enter for Google search results, track it - $(link).click(function() { - ga('send', 'event', 'Google Click', 'clicked: ' + $(this).attr('href'), - 'query: ' + $("#search_autocomplete").val().toLowerCase()); - }); - }); -} - - -function getQuery(hash) { - var queryParts = hash.split('='); - return queryParts[1]; -} - -/* returns the given string with all HTML brackets converted to entities - TODO: move this to the site's JS library */ -function escapeHTML(string) { - return string.replace(/</g,"<") - .replace(/>/g,">"); -} - - - - - - - -/* ######################################################## */ -/* ################# 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(); - initSidenavHeightResize() - }); - } -} - -var API_LEVEL_COOKIE = "api_level"; -var minLevel = 1; -var maxLevel = 1; - -/******* SIDENAV DIMENSIONS ************/ - - function initSidenavHeightResize() { - // Change the drag bar size to nicely fit the scrollbar positions - var $dragBar = $(".ui-resizable-s"); - $dragBar.css({'width': $dragBar.parent().width() - 5 + "px"}); - - $( "#resize-packages-nav" ).resizable({ - containment: "#nav-panels", - handles: "s", - alsoResize: "#packages-nav", - resize: function(event, ui) { resizeNav(); }, /* resize the nav while dragging */ - stop: function(event, ui) { saveNavPanels(); } /* once stopped, save the sizes to cookie */ - }); - - } - -function updateSidenavFixedWidth() { - if (!sticky) return; - $('#devdoc-nav').css({ - 'width' : $('#side-nav').css('width'), - 'margin' : $('#side-nav').css('margin') - }); - $('#devdoc-nav a.totop').css({'display':'block','width':$("#nav").innerWidth()+'px'}); - - initSidenavHeightResize(); -} - -function updateSidenavFullscreenWidth() { - if (!sticky) return; - $('#devdoc-nav').css({ - 'width' : $('#side-nav').css('width'), - 'margin' : $('#side-nav').css('margin') - }); - $('#devdoc-nav .totop').css({'left': 'inherit'}); - - initSidenavHeightResize(); -} - -function buildApiLevelSelector() { - maxLevel = SINCE_DATA.length; - var userApiLevel = parseInt(readCookie(API_LEVEL_COOKIE)); - userApiLevel = userApiLevel == 0 ? maxLevel : userApiLevel; // If there's no cookie (zero), use the max by default - - minLevel = parseInt($("#doc-api-level").attr("class")); - // Handle provisional api levels; the provisional level will always be the highest possible level - // Provisional api levels will also have a length; other stuff that's just missing a level won't, - // so leave those kinds of entities at the default level of 1 (for example, the R.styleable class) - if (isNaN(minLevel) && minLevel.length) { - minLevel = maxLevel; - } - var select = $("#apiLevelSelector").html("").change(changeApiLevel); - for (var i = maxLevel-1; i >= 0; i--) { - var option = $("<option />").attr("value",""+SINCE_DATA[i]).append(""+SINCE_DATA[i]); - // if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames) - select.append(option); - } - - // get the DOM element and use setAttribute cuz IE6 fails when using jquery .attr('selected',true) - var selectedLevelItem = $("#apiLevelSelector option[value='"+userApiLevel+"']").get(0); - selectedLevelItem.setAttribute('selected',true); -} - -function changeApiLevel() { - maxLevel = SINCE_DATA.length; - var selectedLevel = maxLevel; - - selectedLevel = parseInt($("#apiLevelSelector option:selected").val()); - toggleVisisbleApis(selectedLevel, "body"); - - writeCookie(API_LEVEL_COOKIE, selectedLevel, null); - - if (selectedLevel < minLevel) { - var thing = ($("#jd-header").html().indexOf("package") != -1) ? "package" : "class"; - $("#naMessage").show().html("<div><p><strong>This " + thing - + " 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(); - } -} - -function toggleVisisbleApis(selectedLevel, context) { - var apis = $(".api",context); - apis.each(function(i) { - var obj = $(this); - var className = obj.attr("class"); - var apiLevelIndex = className.lastIndexOf("-")+1; - var apiLevelEndIndex = className.indexOf(" ", apiLevelIndex); - apiLevelEndIndex = apiLevelEndIndex != -1 ? apiLevelEndIndex : className.length; - var apiLevel = className.substring(apiLevelIndex, apiLevelEndIndex); - if (apiLevel.length == 0) { // for odd cases when the since data is actually missing, just bail - return; - } - apiLevel = parseInt(apiLevel); - - // Handle provisional api levels; if this item's level is the provisional one, set it to the max - var selectedLevelNum = parseInt(selectedLevel) - var apiLevelNum = parseInt(apiLevel); - if (isNaN(apiLevelNum)) { - apiLevelNum = maxLevel; - } - - // Grey things out that aren't available and give a tooltip title - if (apiLevelNum > selectedLevelNum) { - obj.addClass("absent").attr("title","Requires API Level \"" - + apiLevel + "\" or higher. To reveal, change the target API level " - + "above the left navigation."); - } - else obj.removeClass("absent").removeAttr("title"); - }); -} - - - - -/* ################# SIDENAV TREE VIEW ################### */ - -function new_node(me, mom, text, link, children_data, api_level) -{ - var node = new Object(); - node.children = Array(); - node.children_data = children_data; - node.depth = mom.depth + 1; - - node.li = document.createElement("li"); - mom.get_children_ul().appendChild(node.li); - - node.label_div = document.createElement("div"); - node.label_div.className = "label"; - if (api_level != null) { - $(node.label_div).addClass("api"); - $(node.label_div).addClass("api-level-"+api_level); - } - node.li.appendChild(node.label_div); - - if (children_data != null) { - node.expand_toggle = document.createElement("a"); - node.expand_toggle.href = "javascript:void(0)"; - node.expand_toggle.onclick = function() { - if (node.expanded) { - $(node.get_children_ul()).slideUp("fast"); - node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png"; - node.expanded = false; - } else { - expand_node(me, node); - } - }; - node.label_div.appendChild(node.expand_toggle); - - node.plus_img = document.createElement("img"); - node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png"; - node.plus_img.className = "plus"; - node.plus_img.width = "8"; - node.plus_img.border = "0"; - node.expand_toggle.appendChild(node.plus_img); - - node.expanded = false; - } - - var a = document.createElement("a"); - node.label_div.appendChild(a); - node.label = document.createTextNode(text); - a.appendChild(node.label); - if (link) { - a.href = me.toroot + link; - } else { - if (children_data != null) { - a.className = "nolink"; - a.href = "javascript:void(0)"; - a.onclick = node.expand_toggle.onclick; - // This next line shouldn't be necessary. I'll buy a beer for the first - // person who figures out how to remove this line and have the link - // toggle shut on the first try. --joeo@android.com - node.expanded = false; - } - } - - - node.children_ul = null; - node.get_children_ul = function() { - if (!node.children_ul) { - node.children_ul = document.createElement("ul"); - node.children_ul.className = "children_ul"; - node.children_ul.style.display = "none"; - node.li.appendChild(node.children_ul); - } - return node.children_ul; - }; - - return node; -} - - - - -function expand_node(me, node) -{ - if (node.children_data && !node.expanded) { - if (node.children_visited) { - $(node.get_children_ul()).slideDown("fast"); - } else { - get_node(me, node); - if ($(node.label_div).hasClass("absent")) { - $(node.get_children_ul()).addClass("absent"); - } - $(node.get_children_ul()).slideDown("fast"); - } - node.plus_img.src = me.toroot + "assets/images/triangle-opened-small.png"; - node.expanded = true; - - // perform api level toggling because new nodes are new to the DOM - var selectedLevel = $("#apiLevelSelector option:selected").val(); - toggleVisisbleApis(selectedLevel, "#side-nav"); - } -} - -function get_node(me, mom) -{ - mom.children_visited = true; - for (var i in mom.children_data) { - var node_data = mom.children_data[i]; - mom.children[i] = new_node(me, mom, node_data[0], node_data[1], - node_data[2], node_data[3]); - } -} - -function this_page_relative(toroot) -{ - var full = document.location.pathname; - var file = ""; - if (toroot.substr(0, 1) == "/") { - if (full.substr(0, toroot.length) == toroot) { - return full.substr(toroot.length); - } else { - // the file isn't under toroot. Fail. - return null; - } - } else { - if (toroot != "./") { - toroot = "./" + toroot; - } - do { - if (toroot.substr(toroot.length-3, 3) == "../" || toroot == "./") { - var pos = full.lastIndexOf("/"); - file = full.substr(pos) + file; - full = full.substr(0, pos); - toroot = toroot.substr(0, toroot.length-3); - } - } while (toroot != "" && toroot != "/"); - return file.substr(1); - } -} - -function find_page(url, data) -{ - var nodes = data; - var result = null; - for (var i in nodes) { - var d = nodes[i]; - if (d[1] == url) { - return new Array(i); - } - else if (d[2] != null) { - result = find_page(url, d[2]); - if (result != null) { - return (new Array(i).concat(result)); - } - } - } - return null; -} - -function init_default_navtree(toroot) { - // load json file for navtree data - $.getScript(toRoot + 'navtree_data.js', function(data, textStatus, jqxhr) { - // when the file is loaded, initialize the tree - if(jqxhr.status === 200) { - init_navtree("tree-list", toroot, NAVTREE_DATA); - } - }); - - // perform api level toggling because because the whole tree is new to the DOM - var selectedLevel = $("#apiLevelSelector option:selected").val(); - toggleVisisbleApis(selectedLevel, "#side-nav"); -} - -function init_navtree(navtree_id, toroot, root_nodes) -{ - var me = new Object(); - me.toroot = toroot; - me.node = new Object(); - - me.node.li = document.getElementById(navtree_id); - me.node.children_data = root_nodes; - me.node.children = new Array(); - me.node.children_ul = document.createElement("ul"); - me.node.get_children_ul = function() { return me.node.children_ul; }; - //me.node.children_ul.className = "children_ul"; - me.node.li.appendChild(me.node.children_ul); - me.node.depth = 0; - - get_node(me, me.node); - - me.this_page = this_page_relative(toroot); - me.breadcrumbs = find_page(me.this_page, root_nodes); - if (me.breadcrumbs != null && me.breadcrumbs.length != 0) { - var mom = me.node; - for (var i in me.breadcrumbs) { - var j = me.breadcrumbs[i]; - mom = mom.children[j]; - expand_node(me, mom); - } - mom.label_div.className = mom.label_div.className + " selected"; - addLoadEvent(function() { - scrollIntoView("nav-tree"); - }); - } -} - - - - - - - - -/* TODO: eliminate redundancy with non-google functions */ -function init_google_navtree(navtree_id, toroot, root_nodes) -{ - var me = new Object(); - me.toroot = toroot; - me.node = new Object(); - - me.node.li = document.getElementById(navtree_id); - me.node.children_data = root_nodes; - me.node.children = new Array(); - me.node.children_ul = document.createElement("ul"); - me.node.get_children_ul = function() { return me.node.children_ul; }; - //me.node.children_ul.className = "children_ul"; - me.node.li.appendChild(me.node.children_ul); - me.node.depth = 0; - - get_google_node(me, me.node); -} - -function new_google_node(me, mom, text, link, children_data, api_level) -{ - var node = new Object(); - var child; - node.children = Array(); - node.children_data = children_data; - node.depth = mom.depth + 1; - node.get_children_ul = function() { - if (!node.children_ul) { - node.children_ul = document.createElement("ul"); - node.children_ul.className = "tree-list-children"; - node.li.appendChild(node.children_ul); - } - return node.children_ul; - }; - node.li = document.createElement("li"); - - mom.get_children_ul().appendChild(node.li); - - - if(link) { - child = document.createElement("a"); - - } - else { - child = document.createElement("span"); - child.className = "tree-list-subtitle"; - - } - if (children_data != null) { - node.li.className="nav-section"; - node.label_div = document.createElement("div"); - node.label_div.className = "nav-section-header-ref"; - node.li.appendChild(node.label_div); - get_google_node(me, node); - node.label_div.appendChild(child); - } - else { - node.li.appendChild(child); - } - if(link) { - child.href = me.toroot + link; - } - node.label = document.createTextNode(text); - child.appendChild(node.label); - - node.children_ul = null; - - return node; -} - -function get_google_node(me, mom) -{ - mom.children_visited = true; - var linkText; - for (var i in mom.children_data) { - var node_data = mom.children_data[i]; - linkText = node_data[0]; - - if(linkText.match("^"+"com.google.android")=="com.google.android"){ - linkText = linkText.substr(19, linkText.length); - } - mom.children[i] = new_google_node(me, mom, linkText, node_data[1], - node_data[2], node_data[3]); - } -} - - - - - - -/****** NEW version of script to build google and sample navs dynamically ******/ -// TODO: update Google reference docs to tolerate this new implementation - -var NODE_NAME = 0; -var NODE_HREF = 1; -var NODE_GROUP = 2; -var NODE_TAGS = 3; -var NODE_CHILDREN = 4; - -function init_google_navtree2(navtree_id, data) -{ - var $containerUl = $("#"+navtree_id); - for (var i in data) { - var node_data = data[i]; - $containerUl.append(new_google_node2(node_data)); - } - - // Make all third-generation list items 'sticky' to prevent them from collapsing - $containerUl.find('li li li.nav-section').addClass('sticky'); - - initExpandableNavItems("#"+navtree_id); -} - -function new_google_node2(node_data) -{ - var linkText = node_data[NODE_NAME]; - if(linkText.match("^"+"com.google.android")=="com.google.android"){ - linkText = linkText.substr(19, linkText.length); - } - var $li = $('<li>'); - var $a; - if (node_data[NODE_HREF] != null) { - $a = $('<a href="' + toRoot + node_data[NODE_HREF] + '" title="' + linkText + '" >' - + linkText + '</a>'); - } else { - $a = $('<a href="#" onclick="return false;" title="' + linkText + '" >' - + linkText + '/</a>'); - } - var $childUl = $('<ul>'); - if (node_data[NODE_CHILDREN] != null) { - $li.addClass("nav-section"); - $a = $('<div class="nav-section-header">').append($a); - if (node_data[NODE_HREF] == null) $a.addClass('empty'); - - for (var i in node_data[NODE_CHILDREN]) { - var child_node_data = node_data[NODE_CHILDREN][i]; - $childUl.append(new_google_node2(child_node_data)); - } - $li.append($childUl); - } - $li.prepend($a); - - return $li; -} - - - - - - - - - - - -function showGoogleRefTree() { - init_default_google_navtree(toRoot); - init_default_gcm_navtree(toRoot); -} - -function init_default_google_navtree(toroot) { - // load json file for navtree data - $.getScript(toRoot + 'gms_navtree_data.js', function(data, textStatus, jqxhr) { - // when the file is loaded, initialize the tree - if(jqxhr.status === 200) { - init_google_navtree("gms-tree-list", toroot, GMS_NAVTREE_DATA); - highlightSidenav(); - resizeNav(); - } - }); -} - -function init_default_gcm_navtree(toroot) { - // load json file for navtree data - $.getScript(toRoot + 'gcm_navtree_data.js', function(data, textStatus, jqxhr) { - // when the file is loaded, initialize the tree - if(jqxhr.status === 200) { - init_google_navtree("gcm-tree-list", toroot, GCM_NAVTREE_DATA); - highlightSidenav(); - resizeNav(); - } - }); -} - -function showSamplesRefTree() { - init_default_samples_navtree(toRoot); -} - -function init_default_samples_navtree(toroot) { - // load json file for navtree data - $.getScript(toRoot + 'samples_navtree_data.js', function(data, textStatus, jqxhr) { - // when the file is loaded, initialize the tree - if(jqxhr.status === 200) { - // hack to remove the "about the samples" link then put it back in - // after we nuke the list to remove the dummy static list of samples - var $firstLi = $("#nav.samples-nav > li:first-child").clone(); - $("#nav.samples-nav").empty(); - $("#nav.samples-nav").append($firstLi); - - init_google_navtree2("nav.samples-nav", SAMPLES_NAVTREE_DATA); - highlightSidenav(); - resizeNav(); - if ($("#jd-content #samples").length) { - showSamples(); - } - } - }); -} - -/* TOGGLE INHERITED MEMBERS */ - -/* Toggle an inherited class (arrow toggle) - * @param linkObj The link that was clicked. - * @param expand 'true' to ensure it's expanded. 'false' to ensure it's closed. - * 'null' to simply toggle. - */ -function toggleInherited(linkObj, expand) { - var base = linkObj.getAttribute("id"); - var list = document.getElementById(base + "-list"); - var summary = document.getElementById(base + "-summary"); - var trigger = document.getElementById(base + "-trigger"); - var a = $(linkObj); - if ( (expand == null && a.hasClass("closed")) || expand ) { - list.style.display = "none"; - summary.style.display = "block"; - trigger.src = toRoot + "assets/images/triangle-opened.png"; - a.removeClass("closed"); - a.addClass("opened"); - } else if ( (expand == null && a.hasClass("opened")) || (expand == false) ) { - list.style.display = "block"; - summary.style.display = "none"; - trigger.src = toRoot + "assets/images/triangle-closed.png"; - a.removeClass("opened"); - a.addClass("closed"); - } - return false; -} - -/* Toggle all inherited classes in a single table (e.g. all inherited methods) - * @param linkObj The link that was clicked. - * @param expand 'true' to ensure it's expanded. 'false' to ensure it's closed. - * 'null' to simply toggle. - */ -function toggleAllInherited(linkObj, expand) { - var a = $(linkObj); - var table = $(a.parent().parent().parent()); // ugly way to get table/tbody - var expandos = $(".jd-expando-trigger", table); - if ( (expand == null && a.text() == "[Expand]") || expand ) { - expandos.each(function(i) { - toggleInherited(this, true); - }); - a.text("[Collapse]"); - } else if ( (expand == null && a.text() == "[Collapse]") || (expand == false) ) { - expandos.each(function(i) { - toggleInherited(this, false); - }); - a.text("[Expand]"); - } - return false; -} - -/* Toggle all inherited members in the class (link in the class title) - */ -function toggleAllClassInherited() { - var a = $("#toggleAllClassInherited"); // get toggle link from class title - var toggles = $(".toggle-all", $("#body-content")); - if (a.text() == "[Expand All]") { - toggles.each(function(i) { - toggleAllInherited(this, true); - }); - a.text("[Collapse All]"); - } else { - toggles.each(function(i) { - toggleAllInherited(this, false); - }); - a.text("[Expand All]"); - } - return false; -} - -/* Expand all inherited members in the class. Used when initiating page search */ -function ensureAllInheritedExpanded() { - var toggles = $(".toggle-all", $("#body-content")); - toggles.each(function(i) { - toggleAllInherited(this, true); - }); - $("#toggleAllClassInherited").text("[Collapse All]"); -} - - -/* HANDLE KEY EVENTS - * - Listen for Ctrl+F (Cmd on Mac) and expand all inherited members (to aid page search) - */ -var agent = navigator['userAgent'].toLowerCase(); -var mac = agent.indexOf("macintosh") != -1; - -$(document).keydown( function(e) { -var control = mac ? e.metaKey && !e.ctrlKey : e.ctrlKey; // get ctrl key - if (control && e.which == 70) { // 70 is "F" - ensureAllInheritedExpanded(); - } -}); - - - - - - -/* On-demand functions */ - -/** Move sample code line numbers out of PRE block and into non-copyable column */ -function initCodeLineNumbers() { - var numbers = $("#codesample-block a.number"); - if (numbers.length) { - $("#codesample-line-numbers").removeClass("hidden").append(numbers); - } - - $(document).ready(function() { - // select entire line when clicked - $("span.code-line").click(function() { - if (!shifted) { - selectText(this); - } - }); - // invoke line link on double click - $(".code-line").dblclick(function() { - document.location.hash = $(this).attr('id'); - }); - // highlight the line when hovering on the number - $("#codesample-line-numbers a.number").mouseover(function() { - var id = $(this).attr('href'); - $(id).css('background','#e7e7e7'); - }); - $("#codesample-line-numbers a.number").mouseout(function() { - var id = $(this).attr('href'); - $(id).css('background','none'); - }); - }); -} - -// create SHIFT key binder to avoid the selectText method when selecting multiple lines -var shifted = false; -$(document).bind('keyup keydown', function(e){shifted = e.shiftKey; return true;} ); - -// courtesy of jasonedelman.com -function selectText(element) { - var doc = document - , range, selection - ; - if (doc.body.createTextRange) { //ms - range = doc.body.createTextRange(); - range.moveToElementText(element); - range.select(); - } else if (window.getSelection) { //all others - selection = window.getSelection(); - range = doc.createRange(); - range.selectNodeContents(element); - selection.removeAllRanges(); - selection.addRange(range); - } -} - - - - -/** Display links and other information about samples that match the - group specified by the URL */ -function showSamples() { - var group = $("#samples").attr('class'); - $("#samples").html("<p>Here are some samples for <b>" + group + "</b> apps:</p>"); - - var $ul = $("<ul>"); - $selectedLi = $("#nav li.selected"); - - $selectedLi.children("ul").children("li").each(function() { - var $li = $("<li>").append($(this).find("a").first().clone()); - $ul.append($li); - }); - - $("#samples").append($ul); - -} - - - -/* ########################################################## */ -/* ################### RESOURCE CARDS ##################### */ -/* ########################################################## */ - -/** Handle resource queries, collections, and grids (sections). Requires - jd_tag_helpers.js and the *_unified_data.js to be loaded. */ - -(function() { - // Prevent the same resource from being loaded more than once per page. - var addedPageResources = {}; - - $(document).ready(function() { - $('.resource-widget').each(function() { - initResourceWidget(this); - }); - - /* Pass the line height to ellipsisfade() to adjust the height of the - text container to show the max number of lines possible, without - showing lines that are cut off. This works with the css ellipsis - classes to fade last text line and apply an ellipsis char. */ - - //card text currently uses 15px line height. - var lineHeight = 15; - $('.card-info .text').ellipsisfade(lineHeight); - }); - - /* - Three types of resource layouts: - Flow - Uses a fixed row-height flow using float left style. - Carousel - Single card slideshow all same dimension absolute. - Stack - Uses fixed columns and flexible element height. - */ - function initResourceWidget(widget) { - var $widget = $(widget); - var isFlow = $widget.hasClass('resource-flow-layout'), - isCarousel = $widget.hasClass('resource-carousel-layout'), - isStack = $widget.hasClass('resource-stack-layout'); - - // find size of widget by pulling out its class name - var sizeCols = 1; - var m = $widget.get(0).className.match(/\bcol-(\d+)\b/); - if (m) { - sizeCols = parseInt(m[1], 10); - } - - var opts = { - cardSizes: ($widget.data('cardsizes') || '').split(','), - maxResults: parseInt($widget.data('maxresults') || '100', 10), - itemsPerPage: $widget.data('itemsperpage'), - sortOrder: $widget.data('sortorder'), - query: $widget.data('query'), - section: $widget.data('section'), - sizeCols: sizeCols, - /* Added by LFL 6/6/14 */ - resourceStyle: $widget.data('resourcestyle') || 'card', - stackSort: $widget.data('stacksort') || 'true' - }; - - // run the search for the set of resources to show - - var resources = buildResourceList(opts); - - if (isFlow) { - drawResourcesFlowWidget($widget, opts, resources); - } else if (isCarousel) { - drawResourcesCarouselWidget($widget, opts, resources); - } else if (isStack) { - /* Looks like this got removed and is not used, so repurposing for the - homepage style layout. - Modified by LFL 6/6/14 - */ - //var sections = buildSectionList(opts); - opts['numStacks'] = $widget.data('numstacks'); - drawResourcesStackWidget($widget, opts, resources/*, sections*/); - } - } - - /* Initializes a Resource Carousel Widget */ - function drawResourcesCarouselWidget($widget, opts, resources) { - $widget.empty(); - var plusone = true; //always show plusone on carousel - - $widget.addClass('resource-card slideshow-container') - .append($('<a>').addClass('slideshow-prev').text('Prev')) - .append($('<a>').addClass('slideshow-next').text('Next')); - - var css = { 'width': $widget.width() + 'px', - 'height': $widget.height() + 'px' }; - - var $ul = $('<ul>'); - - for (var i = 0; i < resources.length; ++i) { - var $card = $('<a>') - .attr('href', cleanUrl(resources[i].url)) - .decorateResourceCard(resources[i],plusone); - - $('<li>').css(css) - .append($card) - .appendTo($ul); - } - - $('<div>').addClass('frame') - .append($ul) - .appendTo($widget); - - $widget.dacSlideshow({ - auto: true, - btnPrev: '.slideshow-prev', - btnNext: '.slideshow-next' - }); - }; - - /* Initializes a Resource Card Stack Widget (column-based layout) - Modified by LFL 6/6/14 - */ - function drawResourcesStackWidget($widget, opts, resources, sections) { - // Don't empty widget, grab all items inside since they will be the first - // items stacked, followed by the resource query - var plusone = true; //by default show plusone on section cards - var cards = $widget.find('.resource-card').detach().toArray(); - var numStacks = opts.numStacks || 1; - var $stacks = []; - var urlString; - - for (var i = 0; i < numStacks; ++i) { - $stacks[i] = $('<div>').addClass('resource-card-stack') - .appendTo($widget); - } - - var sectionResources = []; - - // Extract any subsections that are actually resource cards - if (sections) { - for (var i = 0; i < sections.length; ++i) { - if (!sections[i].sections || !sections[i].sections.length) { - // Render it as a resource card - sectionResources.push( - $('<a>') - .addClass('resource-card section-card') - .attr('href', cleanUrl(sections[i].resource.url)) - .decorateResourceCard(sections[i].resource,plusone)[0] - ); - - } else { - cards.push( - $('<div>') - .addClass('resource-card section-card-menu') - .decorateResourceSection(sections[i],plusone)[0] - ); - } - } - } - - cards = cards.concat(sectionResources); - - for (var i = 0; i < resources.length; ++i) { - var $card = createResourceElement(resources[i], opts); - - if (opts.resourceStyle.indexOf('related') > -1) { - $card.addClass('related-card'); - } - - cards.push($card[0]); - } - - if (opts.stackSort != 'false') { - for (var i = 0; i < cards.length; ++i) { - // Find the stack with the shortest height, but give preference to - // left to right order. - var minHeight = $stacks[0].height(); - var minIndex = 0; - - for (var j = 1; j < numStacks; ++j) { - var height = $stacks[j].height(); - if (height < minHeight - 45) { - minHeight = height; - minIndex = j; - } - } - - $stacks[minIndex].append($(cards[i])); - } - } - - }; - - /* - Create a resource card using the given resource object and a list of html - configured options. Returns a jquery object containing the element. - */ - function createResourceElement(resource, opts, plusone) { - var $el; - - // The difference here is that generic cards are not entirely clickable - // so its a div instead of an a tag, also the generic one is not given - // the resource-card class so it appears with a transparent background - // and can be styled in whatever way the css setup. - if (opts.resourceStyle == 'generic') { - $el = $('<div>') - .addClass('resource') - .attr('href', cleanUrl(resource.url)) - .decorateResource(resource, opts); - } else { - var cls = 'resource resource-card'; - - $el = $('<a>') - .addClass(cls) - .attr('href', cleanUrl(resource.url)) - .decorateResourceCard(resource, plusone); - } - - return $el; - } - - /* Initializes a flow widget, see distribute.scss for generating accompanying css */ - function drawResourcesFlowWidget($widget, opts, resources) { - $widget.empty(); - var cardSizes = opts.cardSizes || ['6x6']; - var i = 0, j = 0; - var plusone = true; // by default show plusone on resource cards - - while (i < resources.length) { - var cardSize = cardSizes[j++ % cardSizes.length]; - cardSize = cardSize.replace(/^\s+|\s+$/,''); - // Some card sizes do not get a plusone button, such as where space is constrained - // or for cards commonly embedded in docs (to improve overall page speed). - plusone = !((cardSize == "6x2") || (cardSize == "6x3") || - (cardSize == "9x2") || (cardSize == "9x3") || - (cardSize == "12x2") || (cardSize == "12x3")); - - // A stack has a third dimension which is the number of stacked items - var isStack = cardSize.match(/(\d+)x(\d+)x(\d+)/); - var stackCount = 0; - var $stackDiv = null; - - if (isStack) { - // Create a stack container which should have the dimensions defined - // by the product of the items inside. - $stackDiv = $('<div>').addClass('resource-card-stack resource-card-' + isStack[1] - + 'x' + isStack[2] * isStack[3]) .appendTo($widget); - } - - // Build each stack item or just a single item - do { - var resource = resources[i]; - - var $card = createResourceElement(resources[i], opts, plusone); - - $card.addClass('resource-card-' + cardSize + - ' resource-card-' + resource.type); - - if (isStack) { - $card.addClass('resource-card-' + isStack[1] + 'x' + isStack[2]); - if (++stackCount == parseInt(isStack[3])) { - $card.addClass('resource-card-row-stack-last'); - stackCount = 0; - } - } else { - stackCount = 0; - } - - $card.appendTo($stackDiv || $widget); - - } while (++i < resources.length && stackCount > 0); - } - } - - /* Build a site map of resources using a section as a root. */ - function buildSectionList(opts) { - if (opts.section && SECTION_BY_ID[opts.section]) { - return SECTION_BY_ID[opts.section].sections || []; - } - return []; - } - - function buildResourceList(opts) { - var maxResults = opts.maxResults || 100; - - var query = opts.query || ''; - var expressions = parseResourceQuery(query); - var addedResourceIndices = {}; - var results = []; - - for (var i = 0; i < expressions.length; i++) { - var clauses = expressions[i]; - - // build initial set of resources from first clause - var firstClause = clauses[0]; - var resources = []; - switch (firstClause.attr) { - case 'type': - resources = ALL_RESOURCES_BY_TYPE[firstClause.value]; - break; - case 'lang': - resources = ALL_RESOURCES_BY_LANG[firstClause.value]; - break; - case 'tag': - resources = ALL_RESOURCES_BY_TAG[firstClause.value]; - break; - case 'collection': - var urls = RESOURCE_COLLECTIONS[firstClause.value].resources || []; - resources = urls.map(function(url){ return ALL_RESOURCES_BY_URL[url]; }); - break; - case 'section': - var urls = SITE_MAP[firstClause.value].sections || []; - resources = urls.map(function(url){ return ALL_RESOURCES_BY_URL[url]; }); - break; - } - // console.log(firstClause.attr + ':' + firstClause.value); - resources = resources || []; - - // use additional clauses to filter corpus - if (clauses.length > 1) { - var otherClauses = clauses.slice(1); - resources = resources.filter(getResourceMatchesClausesFilter(otherClauses)); - } - - // filter out resources already added - if (i > 1) { - resources = resources.filter(getResourceNotAlreadyAddedFilter(addedResourceIndices)); - } - - // add to list of already added indices - for (var j = 0; j < resources.length; j++) { - // console.log(resources[j].title); - addedResourceIndices[resources[j].index] = 1; - } - - // concat to final results list - results = results.concat(resources); - } - - if (opts.sortOrder && results.length) { - var attr = opts.sortOrder; - - if (opts.sortOrder == 'random') { - var i = results.length, j, temp; - while (--i) { - j = Math.floor(Math.random() * (i + 1)); - temp = results[i]; - results[i] = results[j]; - results[j] = temp; - } - } else { - var desc = attr.charAt(0) == '-'; - if (desc) { - attr = attr.substring(1); - } - results = results.sort(function(x,y) { - return (desc ? -1 : 1) * (parseInt(x[attr], 10) - parseInt(y[attr], 10)); - }); - } - } - - results = results.filter(getResourceNotAlreadyAddedFilter(addedPageResources)); - results = results.slice(0, maxResults); - - for (var j = 0; j < results.length; ++j) { - addedPageResources[results[j].index] = 1; - } - - return results; - } - - - function getResourceNotAlreadyAddedFilter(addedResourceIndices) { - return function(resource) { - return !addedResourceIndices[resource.index]; - }; - } - - - function getResourceMatchesClausesFilter(clauses) { - return function(resource) { - return doesResourceMatchClauses(resource, clauses); - }; - } - - - function doesResourceMatchClauses(resource, clauses) { - for (var i = 0; i < clauses.length; i++) { - var map; - switch (clauses[i].attr) { - case 'type': - map = IS_RESOURCE_OF_TYPE[clauses[i].value]; - break; - case 'lang': - map = IS_RESOURCE_IN_LANG[clauses[i].value]; - break; - case 'tag': - map = IS_RESOURCE_TAGGED[clauses[i].value]; - break; - } - - if (!map || (!!clauses[i].negative ? map[resource.index] : !map[resource.index])) { - return clauses[i].negative; - } - } - return true; - } - - function cleanUrl(url) - { - if (url && url.indexOf('//') === -1) { - url = toRoot + url; - } - - return url; - } - - - function parseResourceQuery(query) { - // Parse query into array of expressions (expression e.g. 'tag:foo + type:video') - var expressions = []; - var expressionStrs = query.split(',') || []; - for (var i = 0; i < expressionStrs.length; i++) { - var expr = expressionStrs[i] || ''; - - // Break expression into clauses (clause e.g. 'tag:foo') - var clauses = []; - var clauseStrs = expr.split(/(?=[\+\-])/); - for (var j = 0; j < clauseStrs.length; j++) { - var clauseStr = clauseStrs[j] || ''; - - // Get attribute and value from clause (e.g. attribute='tag', value='foo') - var parts = clauseStr.split(':'); - var clause = {}; - - clause.attr = parts[0].replace(/^\s+|\s+$/g,''); - if (clause.attr) { - if (clause.attr.charAt(0) == '+') { - clause.attr = clause.attr.substring(1); - } else if (clause.attr.charAt(0) == '-') { - clause.negative = true; - clause.attr = clause.attr.substring(1); - } - } - - if (parts.length > 1) { - clause.value = parts[1].replace(/^\s+|\s+$/g,''); - } - - clauses.push(clause); - } - - if (!clauses.length) { - continue; - } - - expressions.push(clauses); - } - - return expressions; - } -})(); - -(function($) { - - /* - Utility method for creating dom for the description area of a card. - Used in decorateResourceCard and decorateResource. - */ - function buildResourceCardDescription(resource, plusone) { - var $description = $('<div>').addClass('description ellipsis'); - - $description.append($('<div>').addClass('text').html(resource.summary)); - - if (resource.cta) { - $description.append($('<a>').addClass('cta').html(resource.cta)); - } - - if (plusone) { - var plusurl = resource.url.indexOf("//") > -1 ? resource.url : - "//developer.android.com/" + resource.url; - - $description.append($('<div>').addClass('util') - .append($('<div>').addClass('g-plusone') - .attr('data-size', 'small') - .attr('data-align', 'right') - .attr('data-href', plusurl))); - } - - return $description; - } - - - /* Simple jquery function to create dom for a standard resource card */ - $.fn.decorateResourceCard = function(resource,plusone) { - var section = resource.group || resource.type; - var imgUrl = resource.image || - 'assets/images/resource-card-default-android.jpg'; - - if (imgUrl.indexOf('//') === -1) { - imgUrl = toRoot + imgUrl; - } - - $('<div>').addClass('card-bg') - .css('background-image', 'url(' + (imgUrl || toRoot + - 'assets/images/resource-card-default-android.jpg') + ')') - .appendTo(this); - - $('<div>').addClass('card-info' + (!resource.summary ? ' empty-desc' : '')) - .append($('<div>').addClass('section').text(section)) - .append($('<div>').addClass('title').html(resource.title)) - .append(buildResourceCardDescription(resource, plusone)) - .appendTo(this); - - return this; - }; - - /* Simple jquery function to create dom for a resource section card (menu) */ - $.fn.decorateResourceSection = function(section,plusone) { - var resource = section.resource; - //keep url clean for matching and offline mode handling - var urlPrefix = resource.image.indexOf("//") > -1 ? "" : toRoot; - var $base = $('<a>') - .addClass('card-bg') - .attr('href', resource.url) - .append($('<div>').addClass('card-section-icon') - .append($('<div>').addClass('icon')) - .append($('<div>').addClass('section').html(resource.title))) - .appendTo(this); - - var $cardInfo = $('<div>').addClass('card-info').appendTo(this); - - if (section.sections && section.sections.length) { - // Recurse the section sub-tree to find a resource image. - var stack = [section]; - - while (stack.length) { - if (stack[0].resource.image) { - $base.css('background-image', 'url(' + urlPrefix + stack[0].resource.image + ')'); - break; - } - - if (stack[0].sections) { - stack = stack.concat(stack[0].sections); - } - - stack.shift(); - } - - var $ul = $('<ul>') - .appendTo($cardInfo); - - var max = section.sections.length > 3 ? 3 : section.sections.length; - - for (var i = 0; i < max; ++i) { - - var subResource = section.sections[i]; - if (!plusone) { - $('<li>') - .append($('<a>').attr('href', subResource.url) - .append($('<div>').addClass('title').html(subResource.title)) - .append($('<div>').addClass('description ellipsis') - .append($('<div>').addClass('text').html(subResource.summary)) - .append($('<div>').addClass('util')))) - .appendTo($ul); - } else { - $('<li>') - .append($('<a>').attr('href', subResource.url) - .append($('<div>').addClass('title').html(subResource.title)) - .append($('<div>').addClass('description ellipsis') - .append($('<div>').addClass('text').html(subResource.summary)) - .append($('<div>').addClass('util') - .append($('<div>').addClass('g-plusone') - .attr('data-size', 'small') - .attr('data-align', 'right') - .attr('data-href', resource.url))))) - .appendTo($ul); - } - } - - // Add a more row - if (max < section.sections.length) { - $('<li>') - .append($('<a>').attr('href', resource.url) - .append($('<div>') - .addClass('title') - .text('More'))) - .appendTo($ul); - } - } else { - // No sub-resources, just render description? - } - - return this; - }; - - - - - /* Render other types of resource styles that are not cards. */ - $.fn.decorateResource = function(resource, opts) { - var imgUrl = resource.image || - 'assets/images/resource-card-default-android.jpg'; - var linkUrl = resource.url; - - if (imgUrl.indexOf('//') === -1) { - imgUrl = toRoot + imgUrl; - } - - if (linkUrl && linkUrl.indexOf('//') === -1) { - linkUrl = toRoot + linkUrl; - } - - $(this).append( - $('<div>').addClass('image') - .css('background-image', 'url(' + imgUrl + ')'), - $('<div>').addClass('info').append( - $('<h4>').addClass('title').html(resource.title), - $('<p>').addClass('summary').html(resource.summary), - $('<a>').attr('href', linkUrl).addClass('cta').html('Learn More') - ) - ); - - return this; - }; -})(jQuery); - - -/* Calculate the vertical area remaining */ -(function($) { - $.fn.ellipsisfade= function(lineHeight) { - this.each(function() { - // get element text - var $this = $(this); - var remainingHeight = $this.parent().parent().height(); - $this.parent().siblings().each(function () - { - if ($(this).is(":visible")) { - var h = $(this).height(); - remainingHeight = remainingHeight - h; - } - }); - - adjustedRemainingHeight = ((remainingHeight)/lineHeight>>0)*lineHeight - $this.parent().css({'height': adjustedRemainingHeight}); - $this.css({'height': "auto"}); - }); - - return this; - }; -}) (jQuery); - -/* - Fullscreen Carousel - - The following allows for an area at the top of the page that takes over the - entire browser height except for its top offset and an optional bottom - padding specified as a data attribute. - - HTML: - - <div class="fullscreen-carousel"> - <div class="fullscreen-carousel-content"> - <!-- content here --> - </div> - <div class="fullscreen-carousel-content"> - <!-- content here --> - </div> - - etc ... - - </div> - - Control over how the carousel takes over the screen can mostly be defined in - a css file. Setting min-height on the .fullscreen-carousel-content elements - will prevent them from shrinking to far vertically when the browser is very - short, and setting max-height on the .fullscreen-carousel itself will prevent - the area from becoming to long in the case that the browser is stretched very - tall. - - There is limited functionality for having multiple sections since that request - was removed, but it is possible to add .next-arrow and .prev-arrow elements to - scroll between multiple content areas. -*/ - -(function() { - $(document).ready(function() { - $('.fullscreen-carousel').each(function() { - initWidget(this); - }); - }); - - function initWidget(widget) { - var $widget = $(widget); - - var topOffset = $widget.offset().top; - var padBottom = parseInt($widget.data('paddingbottom')) || 0; - var maxHeight = 0; - var minHeight = 0; - var $content = $widget.find('.fullscreen-carousel-content'); - var $nextArrow = $widget.find('.next-arrow'); - var $prevArrow = $widget.find('.prev-arrow'); - var $curSection = $($content[0]); - - if ($content.length <= 1) { - $nextArrow.hide(); - $prevArrow.hide(); - } else { - $nextArrow.click(function() { - var index = ($content.index($curSection) + 1); - $curSection.hide(); - $curSection = $($content[index >= $content.length ? 0 : index]); - $curSection.show(); - }); - - $prevArrow.click(function() { - var index = ($content.index($curSection) - 1); - $curSection.hide(); - $curSection = $($content[index < 0 ? $content.length - 1 : 0]); - $curSection.show(); - }); - } - - // Just hide all content sections except first. - $content.each(function(index) { - if ($(this).height() > minHeight) minHeight = $(this).height(); - $(this).css({position: 'absolute', display: index > 0 ? 'none' : ''}); - }); - - // Register for changes to window size, and trigger. - $(window).resize(resizeWidget); - resizeWidget(); - - function resizeWidget() { - var height = $(window).height() - topOffset - padBottom; - $widget.width($(window).width()); - $widget.height(height < minHeight ? minHeight : - (maxHeight && height > maxHeight ? maxHeight : height)); - } - } -})(); - - - - - -/* - Tab Carousel - - The following allows tab widgets to be installed via the html below. Each - tab content section should have a data-tab attribute matching one of the - nav items'. Also each tab content section should have a width matching the - tab carousel. - - HTML: - - <div class="tab-carousel"> - <ul class="tab-nav"> - <li><a href="#" data-tab="handsets">Handsets</a> - <li><a href="#" data-tab="wearable">Wearable</a> - <li><a href="#" data-tab="tv">TV</a> - </ul> - - <div class="tab-carousel-content"> - <div data-tab="handsets"> - <!--Full width content here--> - </div> - - <div data-tab="wearable"> - <!--Full width content here--> - </div> - - <div data-tab="tv"> - <!--Full width content here--> - </div> - </div> - </div> - -*/ -(function() { - $(document).ready(function() { - $('.tab-carousel').each(function() { - initWidget(this); - }); - }); - - function initWidget(widget) { - var $widget = $(widget); - var $nav = $widget.find('.tab-nav'); - var $anchors = $nav.find('[data-tab]'); - var $li = $nav.find('li'); - var $contentContainer = $widget.find('.tab-carousel-content'); - var $tabs = $contentContainer.find('[data-tab]'); - var $curTab = $($tabs[0]); // Current tab is first tab. - var width = $widget.width(); - - // Setup nav interactivity. - $anchors.click(function(evt) { - evt.preventDefault(); - var query = '[data-tab=' + $(this).data('tab') + ']'; - transitionWidget($tabs.filter(query)); - }); - - // Add highlight for navigation on first item. - var $highlight = $('<div>').addClass('highlight') - .css({left:$li.position().left + 'px', width:$li.outerWidth() + 'px'}) - .appendTo($nav); - - // Store height since we will change contents to absolute. - $contentContainer.height($contentContainer.height()); - - // Absolutely position tabs so they're ready for transition. - $tabs.each(function(index) { - $(this).css({position: 'absolute', left: index > 0 ? width + 'px' : '0'}); - }); - - function transitionWidget($toTab) { - if (!$curTab.is($toTab)) { - var curIndex = $tabs.index($curTab[0]); - var toIndex = $tabs.index($toTab[0]); - var dir = toIndex > curIndex ? 1 : -1; - - // Animate content sections. - $toTab.css({left:(width * dir) + 'px'}); - $curTab.animate({left:(width * -dir) + 'px'}); - $toTab.animate({left:'0'}); - - // Animate navigation highlight. - $highlight.animate({left:$($li[toIndex]).position().left + 'px', - width:$($li[toIndex]).outerWidth() + 'px'}) - - // Store new current section. - $curTab = $toTab; - } - } - } -})(); diff --git a/tools/droiddoc/templates-ndk/assets/js/prettify.js b/tools/droiddoc/templates-ndk/assets/js/prettify.js deleted file mode 100644 index eef5ad7e6a..0000000000 --- a/tools/droiddoc/templates-ndk/assets/js/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c< -f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&& -(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r= -{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length, -t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b=== -"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value", -m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m= -a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue= -j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m, -250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit", -PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})(); diff --git a/tools/droiddoc/templates-ndk/class.cs b/tools/droiddoc/templates-ndk/class.cs deleted file mode 100644 index e55ac3176d..0000000000 --- a/tools/droiddoc/templates-ndk/class.cs +++ /dev/null @@ -1,679 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<?cs include:"macros_override.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs include:"head_tag.cs" ?> -<body class="gc-documentation <?cs if:(reference.gms || reference.gcm) ?>google<?cs /if ?> - <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs - if:reference ?> reference<?cs - /if ?><?cs - elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?>" itemscope itemtype="http://schema.org/Article"> - <div id="doc-api-level" class="<?cs var:class.since ?>" style="display:none"></div> - <a name="top"></a> -<?cs include:"header.cs" ?> - -<div class="col-12" id="doc-col"> - -<div id="api-info-block"> - -<?cs # are there inherited members ?> -<?cs each:cl=class.inherited ?> - <?cs if:subcount(cl.methods) ?> - <?cs set:inhmethods = #1 ?> - <?cs /if ?> - <?cs if:subcount(cl.constants) ?> - <?cs set:inhconstants = #1 ?> - <?cs /if ?> - <?cs if:subcount(cl.fields) ?> - <?cs set:inhfields = #1 ?> - <?cs /if ?> - <?cs if:subcount(cl.attrs) ?> - <?cs set:inhattrs = #1 ?> - <?cs /if ?> -<?cs /each ?> - -<div class="sum-details-links"> -<?cs if:inhattrs || inhconstants || inhfields || inhmethods || (!class.subclasses.hidden && - (subcount(class.subclasses.direct) || subcount(class.subclasses.indirect))) ?> -Summary: -<?cs if:subcount(class.inners) ?> - <a href="#nestedclasses">Nested Classes</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:subcount(class.attrs) ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#lattrs">XML Attrs</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:inhattrs ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#inhattrs">Inherited XML Attrs</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:subcount(class.enumConstants) ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#enumconstants">Enums</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:subcount(class.constants) ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#constants">Constants</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:inhconstants ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#inhconstants">Inherited Constants</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:subcount(class.fields) ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#lfields">Fields</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:inhfields ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#inhfields">Inherited Fields</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:subcount(class.ctors.public) ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#pubctors">Ctors</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:subcount(class.ctors.protected) ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#proctors">Protected Ctors</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:subcount(class.methods.public) ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#pubmethods">Methods</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:subcount(class.methods.protected) ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#promethods">Protected Methods</a> - <?cs set:linkcount = #1 ?> -<?cs /if ?> -<?cs if:inhmethods ?> - <?cs if:linkcount ?>| <?cs /if ?><a href="#inhmethods">Inherited Methods</a> -<?cs /if ?> -| <a href="#" onclick="return toggleAllClassInherited()" id="toggleAllClassInherited">[Expand All]</a> -<?cs /if ?> -</div><!-- end sum-details-links --> -<div class="api-level"> - <?cs call:since_tags(class) ?><?cs - if:class.deprecatedsince - ?><br>Deprecated since <a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html#ApiLevels" - >API level <?cs var:class.deprecatedsince ?></a><?cs - /if ?> - <?cs call:federated_refs(class) ?> -</div> -</div><!-- end api-info-block --> - -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ======== START OF CLASS DATA ======== --> - -<div id="jd-header"> - <?cs var:class.scope ?> - <?cs var:class.static ?> - <?cs var:class.final ?> - <?cs var:class.abstract ?> - <?cs var:class.kind ?> -<h1 itemprop="name"><?cs var:class.name ?></h1> - -<?cs set:colspan = subcount(class.inheritance) ?> -<?cs each:supr = class.inheritance ?> - <?cs if:colspan == 2 ?> - extends <?cs call:type_link(supr.short_class) ?><br/> - <?cs /if ?> - <?cs if:last(supr) && subcount(supr.interfaces) ?> - implements - <?cs each:t=supr.interfaces ?> - <?cs call:type_link(t) ?> - <?cs /each ?> - <?cs /if ?> - <?cs set:colspan = colspan-1 ?> -<?cs /each ?> -<?cs call:show_annotations_list(class) ?> - -</div><!-- end header --> - -<div id="naMessage"></div> - -<div id="jd-content" class="api apilevel-<?cs var:class.since ?>"> -<table class="jd-inheritance-table"> -<?cs set:colspan = subcount(class.inheritance) ?> -<?cs each:supr = class.inheritance ?> - <tr> - <?cs loop:i = 1, (subcount(class.inheritance)-colspan), 1 ?> - <td class="jd-inheritance-space"> <?cs if:(subcount(class.inheritance)-colspan) == i ?> ↳<?cs /if ?></td> - <?cs /loop ?> - <td colspan="<?cs var:colspan ?>" class="jd-inheritance-class-cell"><?cs - if:colspan == 1 - ?><?cs call:class_name(class.qualifiedType) ?><?cs - else - ?><?cs call:type_link(supr.class) ?><?cs - /if ?></td> - </tr> - <?cs set:colspan = colspan-1 ?> -<?cs /each ?> -</table> - -<?cs # this next line must be exactly like this to be parsed by eclipse ?> - -<?cs if:subcount(class.subclasses.direct) && !class.subclasses.hidden ?> -<table class="jd-sumtable jd-sumtable-subclasses"><tr><td colspan="12" style="border:none;margin:0;padding:0;"> -<?cs call:expando_trigger("subclasses-direct", "closed") ?>Known Direct Subclasses -<?cs call:expandable_class_list("subclasses-direct", class.subclasses.direct, "list") ?> -</td></tr></table> -<?cs /if ?> - -<?cs if:subcount(class.subclasses.indirect) && !class.subclasses.hidden ?> -<table class="jd-sumtable jd-sumtable-subclasses"><tr><td colspan="12" style="border:none;margin:0;padding:0;"> -<?cs call:expando_trigger("subclasses-indirect", "closed") ?>Known Indirect Subclasses -<?cs call:expandable_class_list("subclasses-indirect", class.subclasses.indirect, "list") ?> -</td></tr></table> -<?cs /if ?> - -<div class="jd-descr"> -<?cs call:deprecated_warning(class) ?> -<?cs if:subcount(class.descr) ?> -<h2>Class Overview</h2> -<p itemprop="articleBody"><?cs call:tag_list(class.descr) ?></p> -<?cs /if ?> - -<?cs call:see_also_tags(class.seeAlso) ?> - -</div><!-- jd-descr --> - - -<?cs # summary macros ?> - -<?cs def:write_method_summary(methods, included) ?> -<?cs set:count = #1 ?> -<?cs each:method = methods ?> - <?cs # The apilevel-N class MUST BE LAST in the sequence of class names ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:method.since ?>" > - <td class="jd-typecol"><nobr> - <?cs var:method.abstract ?> - <?cs var:method.default ?> - <?cs var:method.static ?> - <?cs var:method.final ?> - <?cs call:type_link(method.generic) ?> - <?cs call:type_link(method.returnType) ?></nobr> - </td> - <td class="jd-linkcol" width="100%"><nobr> - <span class="sympad"><?cs call:cond_link(method.name, toroot, method.href, included) ?></span>(<?cs call:parameter_list(method.params) ?>)</nobr> - <?cs if:subcount(method.shortDescr) || subcount(method.deprecated) ?> - <div class="jd-descrdiv"> - <?cs call:short_descr(method) ?> - <?cs call:show_annotations_list(method) ?> - </div> - <?cs /if ?> - </td></tr> -<?cs set:count = count + #1 ?> -<?cs /each ?> -<?cs /def ?> - -<?cs def:write_field_summary(fields, included) ?> -<?cs set:count = #1 ?> - <?cs each:field=fields ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:field.since ?>" > - <td class="jd-typecol"><nobr> - <?cs var:field.scope ?> - <?cs var:field.static ?> - <?cs var:field.final ?> - <?cs call:type_link(field.type) ?></nobr></td> - <td class="jd-linkcol"><?cs call:cond_link(field.name, toroot, field.href, included) ?></td> - <td class="jd-descrcol" width="100%"> - <?cs call:short_descr(field) ?> - <?cs call:show_annotations_list(field) ?> - </td> - </tr> - <?cs set:count = count + #1 ?> - <?cs /each ?> -<?cs /def ?> - -<?cs def:write_constant_summary(fields, included) ?> -<?cs set:count = #1 ?> - <?cs each:field=fields ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:field.since ?>" > - <td class="jd-typecol"><?cs call:type_link(field.type) ?></td> - <td class="jd-linkcol"><?cs call:cond_link(field.name, toroot, field.href, included) ?></td> - <td class="jd-descrcol" width="100%"> - <?cs call:short_descr(field) ?> - <?cs call:show_annotations_list(field) ?> - </td> - </tr> - <?cs set:count = count + #1 ?> - <?cs /each ?> -<?cs /def ?> - -<?cs def:write_attr_summary(attrs, included) ?> -<?cs set:count = #1 ?> - <tr> - <td><nobr><em>Attribute Name</em></nobr></td> - <td><nobr><em>Related Method</em></nobr></td> - <td><nobr><em>Description</em></nobr></td> - </tr> - <?cs each:attr=attrs ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:attr.since ?>" > - <td class="jd-linkcol"><?cs if:included ?><a href="<?cs var:toroot ?><?cs var:attr.href ?>"><?cs /if ?><?cs var:attr.name ?><?cs if:included ?></a><?cs /if ?></td> - <td class="jd-linkcol"><?cs each:m=attr.methods ?> - <?cs call:cond_link(m.name, toroot, m.href, included) ?> - <?cs /each ?> - </td> - <td class="jd-descrcol" width="100%"> - <?cs call:short_descr(attr) ?> - <?cs call:show_annotations_list(attr) ?> - </td> - </tr> - <?cs set:count = count + #1 ?> - <?cs /each ?> -<?cs /def ?> - -<?cs def:write_inners_summary(classes) ?> -<?cs set:count = #1 ?> - <?cs each:cl=class.inners ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:cl.since ?>" > - <td class="jd-typecol"><nobr> - <?cs var:cl.scope ?> - <?cs var:cl.static ?> - <?cs var:cl.final ?> - <?cs var:cl.abstract ?> - <?cs var:cl.kind ?></nobr></td> - <td class="jd-linkcol"><?cs call:type_link(cl.type) ?></td> - <td class="jd-descrcol" width="100%"> - <?cs call:short_descr(cl) ?> - <?cs call:show_annotations_list(cl) ?> - </td> - </tr> - <?cs set:count = count + #1 ?> - <?cs /each ?> -<?cs /def ?> - -<?cs # end macros ?> - -<div class="jd-descr"> -<?cs # make sure there's a summary view to display ?> -<?cs if:subcount(class.inners) - || subcount(class.attrs) - || inhattrs - || subcount(class.enumConstants) - || subcount(class.constants) - || inhconstants - || subcount(class.fields) - || inhfields - || subcount(class.ctors.public) - || subcount(class.ctors.protected) - || subcount(class.methods.public) - || subcount(class.methods.protected) - || inhmethods ?> -<h2>Summary</h2> - -<?cs if:subcount(class.inners) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ======== NESTED CLASS SUMMARY ======== --> -<table id="nestedclasses" class="jd-sumtable"><tr><th colspan="12">Nested Classes</th></tr> -<?cs call:write_inners_summary(class.inners) ?> -<?cs /if ?> - -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<?cs if:subcount(class.attrs) ?> -<!-- =========== FIELD SUMMARY =========== --> -<table id="lattrs" class="jd-sumtable"><tr><th colspan="12">XML Attributes</th></tr> -<?cs call:write_attr_summary(class.attrs, 1) ?> -<?cs /if ?> - -<?cs # if there are inherited attrs, write the table ?> -<?cs if:inhattrs ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- =========== FIELD SUMMARY =========== --> -<table id="inhattrs" class="jd-sumtable"><tr><th> - <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a> - <div style="clear:left;">Inherited XML Attributes</div></th></tr> -<?cs each:cl=class.inherited ?> -<?cs if:subcount(cl.attrs) ?> -<tr class="api apilevel-<?cs var:cl.since ?>" > -<td colspan="12"> -<?cs call:expando_trigger("inherited-attrs-"+cl.qualified, "closed") ?>From <?cs var:cl.kind ?> -<?cs call:cond_link(cl.qualified, toroot, cl.link, cl.included) ?> -<div id="inherited-attrs-<?cs var:cl.qualified ?>"> - <div id="inherited-attrs-<?cs var:cl.qualified ?>-list" - class="jd-inheritedlinks"> - </div> - <div id="inherited-attrs-<?cs var:cl.qualified ?>-summary" style="display: none;"> - <table class="jd-sumtable-expando"> - <?cs call:write_attr_summary(cl.attrs, cl.included) ?></table> - </div> -</div> -</td></tr> -<?cs /if ?> -<?cs /each ?> -</table> -<?cs /if ?> - -<?cs if:subcount(class.enumConstants) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- =========== ENUM CONSTANT SUMMARY =========== --> -<table id="enumconstants" class="jd-sumtable"><tr><th colspan="12">Enum Values</th></tr> -<?cs set:count = #1 ?> - <?cs each:field=class.enumConstants ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:field.since ?>" > - <td class="jd-descrcol"><?cs call:type_link(field.type) ?> </td> - <td class="jd-linkcol"><?cs call:cond_link(field.name, toroot, field.href, cl.included) ?> </td> - <td class="jd-descrcol" width="100%"> - <?cs call:short_descr(field) ?> - <?cs call:show_annotations_list(field) ?> - </td> - </tr> - <?cs set:count = count + #1 ?> - <?cs /each ?> -<?cs /if ?> - -<?cs if:subcount(class.constants) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- =========== ENUM CONSTANT SUMMARY =========== --> -<table id="constants" class="jd-sumtable"><tr><th colspan="12">Constants</th></tr> -<?cs call:write_constant_summary(class.constants, 1) ?> -</table> -<?cs /if ?> - -<?cs # if there are inherited constants, write the table ?> -<?cs if:inhconstants ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- =========== ENUM CONSTANT SUMMARY =========== --> -<table id="inhconstants" class="jd-sumtable"><tr><th> - <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a> - <div style="clear:left;">Inherited Constants</div></th></tr> -<?cs each:cl=class.inherited ?> -<?cs if:subcount(cl.constants) ?> -<tr class="api apilevel-<?cs var:cl.since ?>" > -<td colspan="12"> -<?cs call:expando_trigger("inherited-constants-"+cl.qualified, "closed") ?>From <?cs var:cl.kind ?> -<?cs call:cond_link(cl.qualified, toroot, cl.link, cl.included) ?> -<div id="inherited-constants-<?cs var:cl.qualified ?>"> - <div id="inherited-constants-<?cs var:cl.qualified ?>-list" - class="jd-inheritedlinks"> - </div> - <div id="inherited-constants-<?cs var:cl.qualified ?>-summary" style="display: none;"> - <table class="jd-sumtable-expando"> - <?cs call:write_constant_summary(cl.constants, cl.included) ?></table> - </div> -</div> -</td></tr> -<?cs /if ?> -<?cs /each ?> -</table> -<?cs /if ?> - -<?cs if:subcount(class.fields) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- =========== FIELD SUMMARY =========== --> -<table id="lfields" class="jd-sumtable"><tr><th colspan="12">Fields</th></tr> -<?cs call:write_field_summary(class.fields, 1) ?> -</table> -<?cs /if ?> - -<?cs # if there are inherited fields, write the table ?> -<?cs if:inhfields ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- =========== FIELD SUMMARY =========== --> -<table id="inhfields" class="jd-sumtable"><tr><th> - <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a> - <div style="clear:left;">Inherited Fields</div></th></tr> -<?cs each:cl=class.inherited ?> -<?cs if:subcount(cl.fields) ?> -<tr class="api apilevel-<?cs var:cl.since ?>" > -<td colspan="12"> -<?cs call:expando_trigger("inherited-fields-"+cl.qualified, "closed") ?>From <?cs var:cl.kind ?> -<?cs call:cond_link(cl.qualified, toroot, cl.link, cl.included) ?> -<div id="inherited-fields-<?cs var:cl.qualified ?>"> - <div id="inherited-fields-<?cs var:cl.qualified ?>-list" - class="jd-inheritedlinks"> - </div> - <div id="inherited-fields-<?cs var:cl.qualified ?>-summary" style="display: none;"> - <table class="jd-sumtable-expando"> - <?cs call:write_field_summary(cl.fields, cl.included) ?></table> - </div> -</div> -</td></tr> -<?cs /if ?> -<?cs /each ?> -</table> -<?cs /if ?> - -<?cs if:subcount(class.ctors.public) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ======== CONSTRUCTOR SUMMARY ======== --> -<table id="pubctors" class="jd-sumtable"><tr><th colspan="12">Public Constructors</th></tr> -<?cs call:write_method_summary(class.ctors.public, 1) ?> -</table> -<?cs /if ?> - -<?cs if:subcount(class.ctors.protected) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ======== CONSTRUCTOR SUMMARY ======== --> -<table id="proctors" class="jd-sumtable"><tr><th colspan="12">Protected Constructors</th></tr> -<?cs call:write_method_summary(class.ctors.protected, 1) ?> -</table> -<?cs /if ?> - -<?cs if:subcount(class.methods.public) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========== METHOD SUMMARY =========== --> -<table id="pubmethods" class="jd-sumtable"><tr><th colspan="12">Public Methods</th></tr> -<?cs call:write_method_summary(class.methods.public, 1) ?> -</table> -<?cs /if ?> - -<?cs if:subcount(class.methods.protected) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========== METHOD SUMMARY =========== --> -<table id="promethods" class="jd-sumtable"><tr><th colspan="12">Protected Methods</th></tr> -<?cs call:write_method_summary(class.methods.protected, 1) ?> -</table> -<?cs /if ?> - -<?cs # if there are inherited methods, write the table ?> -<?cs if:inhmethods ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========== METHOD SUMMARY =========== --> -<table id="inhmethods" class="jd-sumtable"><tr><th> - <a href="#" class="toggle-all" onclick="return toggleAllInherited(this, null)">[Expand]</a> - <div style="clear:left;">Inherited Methods</div></th></tr> -<?cs each:cl=class.inherited ?> -<?cs if:subcount(cl.methods) ?> -<tr class="api apilevel-<?cs var:cl.since ?>" > -<td colspan="12"><?cs call:expando_trigger("inherited-methods-"+cl.qualified, "closed") ?> -From <?cs var:cl.kind ?> -<?cs if:cl.included ?> - <a href="<?cs var:toroot ?><?cs var:cl.link ?>"><?cs var:cl.qualified ?></a> -<?cs elif:cl.federated ?> - <a href="<?cs var:cl.link ?>"><?cs var:cl.qualified ?></a> -<?cs else ?> - <?cs var:cl.qualified ?> -<?cs /if ?> -<div id="inherited-methods-<?cs var:cl.qualified ?>"> - <div id="inherited-methods-<?cs var:cl.qualified ?>-list" - class="jd-inheritedlinks"> - </div> - <div id="inherited-methods-<?cs var:cl.qualified ?>-summary" style="display: none;"> - <table class="jd-sumtable-expando"> - <?cs call:write_method_summary(cl.methods, cl.included) ?></table> - </div> -</div> -</td></tr> -<?cs /if ?> -<?cs /each ?> -</table> -<?cs /if ?> -<?cs /if ?> -</div><!-- jd-descr (summary) --> - -<!-- Details --> - -<?cs def:write_field_details(fields) ?> -<?cs each:field=fields ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<?cs # the A tag in the next line must remain where it is, so that Eclipse can parse the docs ?> -<A NAME="<?cs var:field.anchor ?>"></A> -<?cs # The apilevel-N class MUST BE LAST in the sequence of class names ?> -<div class="jd-details api apilevel-<?cs var:field.since ?>"> - <h4 class="jd-details-title"> - <span class="normal"> - <?cs var:field.scope ?> - <?cs var:field.static ?> - <?cs var:field.final ?> - <?cs call:type_link(field.type) ?> - </span> - <?cs var:field.name ?> - </h4> - <div class="api-level"> - <?cs call:since_tags(field) ?> - <?cs call:federated_refs(field) ?> - </div> - <div class="jd-details-descr"> - <?cs call:show_annotations_list(field) ?> - <?cs call:description(field) ?> - <?cs if:subcount(field.constantValue) ?> - <div class="jd-tagdata"> - <span class="jd-tagtitle">Constant Value: </span> - <span> - <?cs if:field.constantValue.isString ?> - <?cs var:field.constantValue.str ?> - <?cs else ?> - <?cs var:field.constantValue.dec ?> - (<?cs var:field.constantValue.hex ?>) - <?cs /if ?> - </span> - </div> - <?cs /if ?> - </div> -</div> -<?cs /each ?> -<?cs /def ?> - -<?cs def:write_method_details(methods) ?> -<?cs each:method=methods ?> -<?cs # the A tag in the next line must remain where it is, so that Eclipse can parse the docs ?> -<A NAME="<?cs var:method.anchor ?>"></A> -<?cs # The apilevel-N class MUST BE LAST in the sequence of class names ?> -<div class="jd-details api apilevel-<?cs var:method.since ?>"> - <h4 class="jd-details-title"> - <span class="normal"> - <?cs var:method.scope ?> - <?cs var:method.abstract ?> - <?cs var:method.default ?> - <?cs var:method.static ?> - <?cs var:method.final ?> - <?cs call:type_link(method.returnType) ?> - </span> - <span class="sympad"><?cs var:method.name ?></span> - <span class="normal">(<?cs call:parameter_list(method.params) ?>)</span> - </h4> - <div class="api-level"> - <div><?cs call:since_tags(method) ?></div> - <?cs call:federated_refs(method) ?> - </div> - <div class="jd-details-descr"> - <?cs call:show_annotations_list(method) ?> - <?cs call:description(method) ?> - </div> -</div> -<?cs /each ?> -<?cs /def ?> - -<?cs def:write_attr_details(attrs) ?> -<?cs each:attr=attrs ?> -<?cs # the A tag in the next line must remain where it is, so that Eclipse can parse the docs ?> -<A NAME="<?cs var:attr.anchor ?>"></A> -<div class="jd-details"> - <h4 class="jd-details-title"><?cs var:attr.name ?> - </h4> - <div class="jd-details-descr"> - <?cs call:show_annotations_list(attr) ?> - <?cs call:description(attr) ?> - - <div class="jd-tagdata"> - <h5 class="jd-tagtitle">Related Methods</h5> - <ul class="nolist"> - <?cs each:m=attr.methods ?> - <li><a href="<?cs var:toroot ?><?cs var:m.href ?>"><?cs var:m.name ?></a></li> - <?cs /each ?> - </ul> - </div> - </div> -</div> -<?cs /each ?> -<?cs /def ?> - - -<!-- XML Attributes --> -<?cs if:subcount(class.attrs) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========= FIELD DETAIL ======== --> -<h2>XML Attributes</h2> -<?cs call:write_attr_details(class.attrs) ?> -<?cs /if ?> - -<!-- Enum Values --> -<?cs if:subcount(class.enumConstants) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========= ENUM CONSTANTS DETAIL ======== --> -<h2>Enum Values</h2> -<?cs call:write_field_details(class.enumConstants) ?> -<?cs /if ?> - -<!-- Constants --> -<?cs if:subcount(class.constants) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========= ENUM CONSTANTS DETAIL ======== --> -<h2>Constants</h2> -<?cs call:write_field_details(class.constants) ?> -<?cs /if ?> - -<!-- Fields --> -<?cs if:subcount(class.fields) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========= FIELD DETAIL ======== --> -<h2>Fields</h2> -<?cs call:write_field_details(class.fields) ?> -<?cs /if ?> - -<!-- Public ctors --> -<?cs if:subcount(class.ctors.public) ?> -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========= CONSTRUCTOR DETAIL ======== --> -<h2>Public Constructors</h2> -<?cs call:write_method_details(class.ctors.public) ?> -<?cs /if ?> - -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========= CONSTRUCTOR DETAIL ======== --> -<!-- Protected ctors --> -<?cs if:subcount(class.ctors.protected) ?> -<h2>Protected Constructors</h2> -<?cs call:write_method_details(class.ctors.protected) ?> -<?cs /if ?> - -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========= METHOD DETAIL ======== --> -<!-- Public methdos --> -<?cs if:subcount(class.methods.public) ?> -<h2>Public Methods</h2> -<?cs call:write_method_details(class.methods.public) ?> -<?cs /if ?> - -<?cs # this next line must be exactly like this to be parsed by eclipse ?> -<!-- ========= METHOD DETAIL ======== --> -<?cs if:subcount(class.methods.protected) ?> -<h2>Protected Methods</h2> -<?cs call:write_method_details(class.methods.protected) ?> -<?cs /if ?> - -<?cs # the next two lines must be exactly like this to be parsed by eclipse ?> -<!-- ========= END OF CLASS DATA ========= --> -<A NAME="navbar_top"></A> - -<?cs include:"footer.cs" ?> -</div> <!-- jd-content --> - -</div><!-- end doc-content --> - -<?cs include:"trailer.cs" ?> - -</body> -</html> diff --git a/tools/droiddoc/templates-ndk/classes.cs b/tools/droiddoc/templates-ndk/classes.cs deleted file mode 100644 index 405892d673..0000000000 --- a/tools/droiddoc/templates-ndk/classes.cs +++ /dev/null @@ -1,53 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<?cs include:"macros_override.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs include:"head_tag.cs" ?> -<body class="gc-documentation <?cs if:(reference.gms || reference.gcm) ?>google<?cs /if ?> - <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs - if:reference ?> reference<?cs - /if ?><?cs - elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?>" itemscope itemtype="http://schema.org/Article"> - <a name="top"></a> -<?cs include:"header.cs" ?> - -<div class="col-12" id="doc-col"> - -<div id="jd-header"> -<h1><?cs var:page.title ?></h1> -</div> - -<div id="jd-content"> -<p>These are the Android API classes. See all <a href="packages.html">API packages</a>.</p> -<div class="jd-letterlist"><?cs each:letter=docs.classes ?> - <a href="#letter_<?cs name:letter ?>"><?cs name:letter ?></a> <?cs /each?> -</div> - -<?cs each:letter=docs.classes ?> -<?cs set:count = #1 ?> -<h2 id="letter_<?cs name:letter ?>"><?cs name:letter ?></h2> -<table class="jd-sumtable"> - <?cs set:cur_row = #0 ?> - <?cs each:cl = letter ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:cl.since ?>" > - <td class="jd-linkcol"><?cs call:type_link(cl.type) ?></td> - <td class="jd-descrcol" width="100%"> - <?cs call:short_descr(cl) ?> - <?cs call:show_annotations_list(cl) ?> - </td> - </tr> - <?cs set:count = count + #1 ?> - <?cs /each ?> -</table> -<?cs /each ?> - -<?cs include:"footer.cs" ?> -</div><!-- end jd-content --> -</div><!-- end doc-content --> - -<?cs include:"trailer.cs" ?> - -</body> -</html>
\ No newline at end of file diff --git a/tools/droiddoc/templates-ndk/components/masthead.cs b/tools/droiddoc/templates-ndk/components/masthead.cs deleted file mode 100644 index 01d0e5559e..0000000000 --- a/tools/droiddoc/templates-ndk/components/masthead.cs +++ /dev/null @@ -1,180 +0,0 @@ -<?cs def:custom_masthead() ?> -<?cs if:preview ?> - <?cs call:preview_masthead() ?> -<?cs else ?> -<a name="top"></a> - -<!-- dialog to prompt lang pref change when loaded from hardcoded URL -<div id="langMessage" style="display:none"> - <div> - <div class="lang en"> - <p>You requested a page in English, would you like to proceed with this language setting?</p> - </div> - <div class="lang es"> - <p>You requested a page in Spanish (Español), would you like to proceed with this language setting?</p> - </div> - <div class="lang ja"> - <p>You requested a page in Japanese (日本語), would you like to proceed with this language setting?</p> - </div> - <div class="lang ko"> - <p>You requested a page in Korean (한국어), would you like to proceed with this language setting?</p> - </div> - <div class="lang ru"> - <p>You requested a page in Russian (Русский), would you like to proceed with this language setting?</p> - </div> - <div class="lang zh-cn"> - <p>You requested a page in Simplified Chinese (简体中文), would you like to proceed with this language setting?</p> - </div> - <div class="lang zh-tw"> - <p>You requested a page in Traditional Chinese (繁體中文), would you like to proceed with this language setting?</p> - </div> - <a href="#" class="button yes" onclick="return false;"> - <span class="lang en">Yes</span> - <span class="lang es">Sí</span> - <span class="lang ja">Yes</span> - <span class="lang ko">Yes</span> - <span class="lang ru">Yes</span> - <span class="lang zh-cn">是的</span> - <span class="lang zh-tw">没有</span> - </a> - <a href="#" class="button" onclick="$('#langMessage').hide();return false;"> - <span class="lang en">No</span> - <span class="lang es">No</span> - <span class="lang ja">No</span> - <span class="lang ko">No</span> - <span class="lang ru">No</span> - <span class="lang zh-cn">没有</span> - <span class="lang zh-tw">没有</span> - </a> - </div> -</div> --> - -<?cs if:!devsite ?><?cs # leave out the global header for devsite; it is in devsite template ?> - <!-- Header --> - <div id="header-wrapper"> - <div id="header"><?cs call:butter_bar() ?> - <div class="wrap" id="header-wrap"> - <div class="col-3 logo"> - <a href="<?cs var:toroot ?>index.html"> - <img src="<?cs var:toroot ?>assets/images/dac_logo.png" - srcset="<?cs var:toroot ?>assets/images/dac_logo@2x.png 2x" - width="123" height="25" alt="Android Developers" /> - </a> - <div class="btn-quicknav" id="btn-quicknav"> - <a href="#" class="arrow-inactive">Quicknav</a> - <a href="#" class="arrow-active">Quicknav</a> - </div> - </div> - - <?cs # design/dev/dist tabs usually here ?> - - <?cs # call:header_search_widget() ?> - - </div><!-- end header-wrap.wrap --> - </div><!-- end header --> - - - <!-- Secondary x-nav --> - <div id="nav-x"> - <div class="wrap" style="position:relative;z-index:1"> - - <ul class="nav-x col-9 develop" style="width:100%"> - <li class="guide"><a href="<?cs var:toroot ?>ndk/guides/index.html"> - Guides</a></li> - <li class="reference"><a href="<?cs var:toroot ?>ndk/reference/index.html"> - Reference</a></li> - <li class="samples"><a href="<?cs var:toroot ?>ndk/samples/index.html"> - Samples</a></li> - <li class="downloads"><a href="<?cs var:toroot ?>ndk/downloads/index.html"> - Downloads</a></li> - </li> - </ul> - </div> - </div> - - - <div id="searchResults" class="wrap" style="display:none;"> - <h2 id="searchTitle">Results</h2> - <div id="leftSearchControl" class="search-control">Loading...</div> - </div> - </div> <!--end header-wrapper --> - - <div id="sticky-header"> - <div> - <a class="logo" href="#top"></a> - <a class="top" href="#top"></a> - <ul class="breadcrumb"> - <?cs # More <li> elements added here with javascript ?> - <?cs if:!section.landing ?><li class="current"><?cs var:page.title ?></li><?cs - /if ?> - </ul> - </div> - </div> - -<?cs /if ?><?cs # end if/else !devsite ?> -<?cs /if ?><?cs # end if/else preview ?><?cs -/def ?> - -<?cs def:preview_masthead() ?> -<a name="top"></a> - - -<!-- Header --> -<div id="header-wrapper"> - <div id="header"><?cs call:butter_bar() ?> - <div class="wrap" id="header-wrap"> - <div class="col_3 logo landing-logo" style="width:240px"> - <a href="<?cs var:toroot ?>preview/index.html"> - <img src="<?cs var:toroot ?>assets/images/android.png" height="25" alt="Android" - style="margin:-3px 0 0" /> - </a> - </div> - <div class="col-8" style="margin:0"><h1 style="margin: 4px 0 0 0px;padding:0;line-height:16px; -color:#666;font-weight:100;font-size:27px;">L Developer Preview</h1></div> - - <?cs # ADD SEARCH AND MENU ?> - <?cs # call:header_search_widget() ?> - - </div><!-- end header-wrap --> - </div><!-- /Header --> - - - <div id="searchResults" class="wrap" style="display:none;"> - <h2 id="searchTitle">Results</h2> - <div id="leftSearchControl" class="search-control">Loading...</div> - </div> -</div> <!--end header-wrapper --> - -<div id="sticky-header"> - <div> - <a class="logo" href="#top"></a> - <a class="top" href="#top"></a> - <ul class="breadcrumb"> - <?cs # More <li> elements added here with javascript ?> - <?cs if:!section.landing ?><li class="current"><?cs var:page.title ?></li><?cs - /if ?> - </ul> - </div> -</div> - - <?cs -/def ?> - - -<?cs # (UN)COMMENT THE INSIDE OF THIS METHOD TO TOGGLE VISIBILITY ?> -<?cs def:butter_bar() ?> - -<?cs # HIDE THE BUTTER BAR - - <div style="height:20px"><!-- spacer to bump header down --></div> - <div id="butterbar-wrapper"> - <div id="butterbar"> - <a href="http://googleblog.blogspot.com/" id="butterbar-message"> - The Android 5.0 SDK will be available on October 17th! - </a> - </div> - </div> - -?> - -<?cs /def ?> diff --git a/tools/droiddoc/templates-ndk/customizations.cs b/tools/droiddoc/templates-ndk/customizations.cs deleted file mode 100644 index 808bc818d6..0000000000 --- a/tools/droiddoc/templates-ndk/customizations.cs +++ /dev/null @@ -1,701 +0,0 @@ -<?cs -def:fullpage() ?> - <div id="body-content"> -<?cs /def ?> -<?cs -def:sdk_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - -<?cs - include:"../../../../../frameworks/base/docs/html/sdk/sdk_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> -<?cs /def ?><?cs - -def:no_nav() ?> - <div class="wrap clearfix" id="body-content"> -<?cs /def ?><?cs - -def:tools_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs - include:"../../../../../frameworks/base/docs/html/tools/tools_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> -<?cs - -def:ndk_guides_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs - include:"../../../../../frameworks/base/docs/html-ndk/ndk/guides/guides_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs - -def:ndk_reference_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs - include:"../../../../../frameworks/base/docs/html-ndk/ndk/reference/reference_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs - -def:ndk_samples_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs - include:"../../../../../frameworks/base/docs/html-ndk/ndk/samples/samples_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs - -def:ndk_downloads_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs - include:"../../../../../frameworks/base/docs/html-ndk/ndk/downloads/downloads_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs -def:training_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - - -<?cs - include:"../../../../../frameworks/base/docs/html/training/training_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:googleplay_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs include:"../../../../../frameworks/base/docs/html/distribute/googleplay/googleplay_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:essentials_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs include:"../../../../../frameworks/base/docs/html/distribute/essentials/essentials_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:users_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs include:"../../../../../frameworks/base/docs/html/distribute/users/users_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:engage_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs include:"../../../../../frameworks/base/docs/html/distribute/engage/engage_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:analyze_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs include:"../../../../../frameworks/base/docs/html/distribute/analyze/analyze_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:monetize_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs include:"../../../../../frameworks/base/docs/html/distribute/monetize/monetize_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:disttools_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs include:"../../../../../frameworks/base/docs/html/distribute/tools/disttools_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:stories_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> -<?cs include:"../../../../../frameworks/base/docs/html/distribute/stories/stories_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?><?cs - -def:guide_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - -<?cs - include:"../../../../../frameworks/base/docs/html/guide/guide_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> -<?cs -def:design_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - - -<?cs - include:"../../../../../frameworks/base/docs/html/design/design_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> -<?cs -def:distribute_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - -<?cs - include:"../../../../../frameworks/base/docs/html/distribute/distribute_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs -def:samples_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - -<?cs - include:"../../../../../frameworks/base/docs/html/samples/samples_toc.cs" ?> - - </div> - - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs -def:google_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - -<?cs - include:"../../../../../frameworks/base/docs/html/google/google_toc.cs" ?> - - - </div> - <script type="text/javascript"> - showGoogleRefTree(); - - </script> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs -def:about_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-3" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - -<?cs - include:"../../../../../frameworks/base/docs/html/about/about_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - - -<?cs -def:wear_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - -<?cs - include:"../../../../../frameworks/base/docs/html/wear/wear_toc.cs" ?> - - - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs -def:preview_nav() ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav" class="scroll-pane"> - <?cs - include:"../../../../../frameworks/base/docs/html/preview/preview_toc.cs" ?> - </div> - </div> <!-- end side-nav --> - <script> - $(document).ready(function() { - scrollIntoView("devdoc-nav"); - }); - </script> -<?cs /def ?> - -<?cs # The default side navigation for the reference docs ?><?cs -def:default_left_nav() ?> -<?cs if:reference.gcm || reference.gms ?> - <?cs call:google_nav() ?> -<?cs else ?> - <div class="wrap clearfix" id="body-content"> - <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div id="devdoc-nav"> - <div id="api-nav-header"> - <div id="api-level-toggle"> - <label for="apiLevelCheckbox" class="disabled" - title="Select your target API level to dim unavailable APIs">API level: </label> - <div class="select-wrapper"> - <select id="apiLevelSelector"> - <!-- option elements added by buildApiLevelSelector() --> - </select> - </div> - </div><!-- end toggle --> - <div id="api-nav-title">Android APIs</div> - </div><!-- end nav header --> - <script> - var SINCE_DATA = [ <?cs - each:since = since ?>'<?cs - var:since.name ?>'<?cs - if:!last(since) ?>, <?cs /if ?><?cs - /each - ?> ]; - buildApiLevelSelector(); - </script> - - <div id="swapper"> - <div id="nav-panels"> - <div id="resize-packages-nav"> - <div id="packages-nav" class="scroll-pane"> - - <ul> - <?cs call:package_link_list(docs.packages) ?> - </ul><br/> - - </div> <!-- end packages-nav --> - </div> <!-- end resize-packages --> - <div id="classes-nav" class="scroll-pane"> - - -<?cs - if:subcount(class.package) ?> - <ul> - <?cs call:list("Annotations", class.package.annotations) ?> - <?cs call:list("Interfaces", class.package.interfaces) ?> - <?cs call:list("Classes", class.package.classes) ?> - <?cs call:list("Enums", class.package.enums) ?> - <?cs call:list("Exceptions", class.package.exceptions) ?> - <?cs call:list("Errors", class.package.errors) ?> - </ul><?cs - elif:subcount(package) ?> - <ul> - <?cs call:class_link_list("Annotations", package.annotations) ?> - <?cs call:class_link_list("Interfaces", package.interfaces) ?> - <?cs call:class_link_list("Classes", package.classes) ?> - <?cs call:class_link_list("Enums", package.enums) ?> - <?cs call:class_link_list("Exceptions", package.exceptions) ?> - <?cs call:class_link_list("Errors", package.errors) ?> - </ul><?cs - else ?> - <p style="padding:10px">Select a package to view its members</p><?cs - /if ?><br/> - - - </div><!-- end classes --> - </div><!-- end nav-panels --> - <div id="nav-tree" style="display:none" class="scroll-pane"> - <div id="tree-list"></div> - </div><!-- end nav-tree --> - </div><!-- end swapper --> - <div id="nav-swap"> - <a class="fullscreen">fullscreen</a> - <a href='#' onclick='swapNav();return false;'><span id='tree-link'>Use Tree Navigation</span><span id='panel-link' style='display:none'>Use Panel Navigation</span></a> - </div> - </div> <!-- end devdoc-nav --> - </div> <!-- end side-nav --> - <script type="text/javascript"> - // init fullscreen based on user pref - var fullscreen = readCookie("fullscreen"); - if (fullscreen != 0) { - if (fullscreen == "false") { - toggleFullscreen(false); - } else { - toggleFullscreen(true); - } - } - // init nav version for mobile - if (isMobile) { - swapNav(); // tree view should be used on mobile - $('#nav-swap').hide(); - } else { - chooseDefaultNav(); - if ($("#nav-tree").is(':visible')) { - init_default_navtree("<?cs var:toroot ?>"); - } - } - // scroll the selected page into view - $(document).ready(function() { - scrollIntoView("packages-nav"); - scrollIntoView("classes-nav"); - }); - </script> -<?cs /if ?> - <?cs -/def ?> - - -<?cs -def:header_search_widget() ?> -<div class="menu-container"> - <div class="moremenu"> - <div id="more-btn"></div> - </div> - <div class="morehover" id="moremenu"> - <div class="top"></div> - <div class="mid"> - <div class="header">Links</div> - <ul> - <li><a href="https://play.google.com/apps/publish/" target="_googleplay">Google Play Developer Console</a></li> - <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li> - <li><a href="<?cs var:toroot ?>about/index.html">About Android</a></li> - </ul> - <div class="header">Android Sites</div> - <ul> - <li><a href="http://www.android.com">Android.com</a></li> - <li class="active"><a>Android Developers</a></li> - <li><a href="http://source.android.com">Android Open Source Project</a></li> - </ul> - - <?cs # Include language switcher only in online docs ?> - <?cs if:android.whichdoc == "online" ?> - <div class="header">Language</div> - <div id="language" class="locales"> - <select name="language" onChange="changeLangPref(this.value, true)"> - <option value="en">English</option> - <option value="es">Español</option> - <option value="ja">日本語</option> - <option value="ko">한국어</option> - <option value="ru">Русский</option> - <option value="zh-cn">中文(简体)</option> - <option value="zh-tw">中文(繁體)</option> - </select> - </div> - <script type="text/javascript"> - <!-- - loadLangPref(); - //--> - </script> - <?cs /if ?> - <?cs # End of lang switcher ?> - <br class="clearfix" /> - </div><!-- end 'mid' --> - <div class="bottom"></div> - </div><!-- end 'moremenu' --> - - <div class="search" id="search-container"> - <div class="search-inner"> - <div id="search-btn"></div> - <div class="left"></div> - <form onsubmit="return submit_search()"> - <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q" - onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)" - onkeydown="return search_changed(event, true, '<?cs var:toroot ?>')" - onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" /> - </form> - <div class="right"></div> - <a class="close hide">close</a> - <div class="left"></div> - <div class="right"></div> - </div><!-- end search-inner --> - </div><!-- end search-container --> - - <div class="search_filtered_wrapper reference"> - <div class="suggest-card reference no-display"> - <ul class="search_filtered"> - </ul> - </div> - </div> - - <div class="search_filtered_wrapper docs"> - <div class="suggest-card dummy no-display"> </div> - <div class="suggest-card develop no-display"> - <ul class="search_filtered"> - </ul> - <div class="child-card guides no-display"> - </div> - <div class="child-card training no-display"> - </div> - <div class="child-card samples no-display"> - </div> - </div> - <div class="suggest-card design no-display"> - <ul class="search_filtered"> - </ul> - </div> - <div class="suggest-card distribute no-display"> - <ul class="search_filtered"> - </ul> - </div> - </div> -</div><!-- end menu-container (search and menu widget) --> -<?cs /def ?> - - - -<?cs -def:custom_left_nav() ?><?cs - if:fullpage ?><?cs - call:fullpage() ?><?cs - elif:nonavpage ?><?cs - call:no_nav() ?><?cs - elif:ndk ?><?cs - if:guide ?><?cs - call:ndk_guides_nav() ?><?cs - elif:reference ?><?cs - call:ndk_reference_nav() ?><?cs - elif:samples ?><?cs - call:ndk_samples_nav() ?><?cs - elif:downloads ?><?cs - call:ndk_downloads_nav() ?><?cs - /if ?><?cs - elif:guide ?><?cs - call:guide_nav() ?><?cs - elif:design ?><?cs - call:design_nav() ?><?cs - elif:training ?><?cs - call:training_nav() ?><?cs - elif:tools ?><?cs - call:tools_nav() ?><?cs - elif:google ?><?cs - call:google_nav() ?><?cs - elif:samples ?><?cs - call:samples_nav() ?><?cs - elif:distribute ?><?cs - if:googleplay ?><?cs - call:googleplay_nav() ?><?cs - elif:essentials ?><?cs - call:essentials_nav() ?><?cs - elif:users ?><?cs - call:users_nav() ?><?cs - elif:engage ?><?cs - call:engage_nav() ?><?cs - elif:monetize ?><?cs - call:monetize_nav() ?><?cs - elif:analyze ?><?cs - call:analyze_nav() ?><?cs - elif:disttools ?><?cs - call:disttools_nav() ?><?cs - elif:stories ?><?cs - call:stories_nav() ?><?cs - /if ?><?cs - elif:about ?><?cs - call:about_nav() ?><?cs - elif:distribute ?><?cs - call:distribute_nav() ?><?cs - elif:wear ?><?cs - call:wear_nav() ?><?cs - elif:preview ?><?cs - call:preview_nav() ?><?cs - else ?><?cs - call:default_left_nav() ?> <?cs - /if ?><?cs -/def ?> - -<?cs # appears at the bottom of every page ?><?cs -def:custom_cc_copyright() ?> - Except as noted, this content is - licensed under <a href="http://creativecommons.org/licenses/by/2.5/"> - Creative Commons Attribution 2.5</a>. For details and - restrictions, see the <a href="<?cs var:toroot ?>license.html">Content - License</a>.<?cs -/def ?> - -<?cs -def:custom_copyright() ?> - Except as noted, this content is licensed under <a - href="http://www.apache.org/licenses/LICENSE-2.0">Apache 2.0</a>. - For details and restrictions, see the <a href="<?cs var:toroot ?>license.html"> - Content License</a>.<?cs -/def ?> - -<?cs -def:custom_footerlinks() ?> - <p> - <a href="<?cs var:toroot ?>about/index.html">About Android</a> | - <a href="<?cs var:toroot ?>legal.html">Legal</a> | - <a href="<?cs var:toroot ?>support.html">Support</a> - </p><?cs -/def ?> - -<?cs # appears on the right side of the blue bar at the bottom off every page ?><?cs -def:custom_buildinfo() ?><?cs - if:!google && !reference.gcm && !reference.gms ?> - Android <?cs var:sdk.version ?> r<?cs var:sdk.rel.id ?> — <?cs - /if ?> -<script src="<?cs var:toroot ?>timestamp.js" type="text/javascript"></script> -<script>document.write(BUILD_TIMESTAMP)</script> -<?cs /def ?> - diff --git a/tools/droiddoc/templates-ndk/data.hdf b/tools/droiddoc/templates-ndk/data.hdf deleted file mode 100644 index 9411b78718..0000000000 --- a/tools/droiddoc/templates-ndk/data.hdf +++ /dev/null @@ -1,4 +0,0 @@ -template { - which = normal -} - diff --git a/tools/droiddoc/templates-ndk/designpage.cs b/tools/droiddoc/templates-ndk/designpage.cs deleted file mode 100644 index 2be179d4f0..0000000000 --- a/tools/droiddoc/templates-ndk/designpage.cs +++ /dev/null @@ -1,110 +0,0 @@ -<!DOCTYPE html> -<?cs include:"macros.cs" ?> -<html lang="en"> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - <title> - Android Design<?cs if:page.title ?> - <?cs var:page.title ?><?cs /if ?> - </title> - <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico"> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic"> - <link rel="stylesheet" href="<?cs var:toroot ?>assets/yui-3.3.0-reset-min.css"> - <link rel="stylesheet" href="<?cs var:toroot ?>assets/design/default.css"> - <script src="<?cs var:toroot ?>assets/jquery-1.6.2.min.js"></script> - <script>var SITE_ROOT = '<?cs var:toroot ?>design';</script> - <script src="<?cs var:toroot ?>assets/design/default.js"></script> - </head> - <body class="gc-documentation - <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs - elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?>" itemscope itemtype="http://schema.org/Article"> - <a name="top"></a> - - <div id="page-container"> - - <div id="page-header" itemscope itemtype="http://schema.org/WPHeader"><a href="<?cs var:toroot ?>design/index.html">Android Design</a></div> - - <div id="main-row"> - - <div id="nav-container" itemscope itemtype="http://schema.org/SiteNavigationElement"> - - <?cs call:design_nav() ?> - - </div> - - <div id="content"> - -<?cs if:header.hide ?> -<?cs else ?> -<div class="layout-content-row content-header <?cs if:header.justLinks ?>just-links<?cs /if ?>"> - <div class="layout-content-col span-9"> - <?cs if:header.justLinks ?> - <?cs elif:header.title ?><h2><?cs var:header.title ?></h2> - <?cs else ?><h2><?cs var:page.title ?></h2> - <?cs /if ?> - </div> - <div class="paging-links layout-content-col span-4" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <a href="#" class="prev-page-link">Previous</a> - <a href="#" class="next-page-link">Next</a> - </div> -</div> -<?cs /if ?> - -<?cs call:tag_list(root.descr) ?> - -<?cs if:footer.hide ?> -<?cs else ?> -<div class="layout-content-row content-footer" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div class="paging-links layout-content-col span-9"> </div> - <div class="paging-links layout-content-col span-4"> - <a href="#" class="prev-page-link">Previous</a> - <a href="#" class="next-page-link">Next</a> - </div> -</div> -<?cs /if ?> - - </div> - - </div> - - <div id="page-footer" itemscope itemtype="http://schema.org/WPFooter"> - - <p id="copyright"> - Except as noted, this content is licensed under - <a href="http://creativecommons.org/licenses/by/2.5/"> - Creative Commons Attribution 2.5</a>.<br> - For details and restrictions, see the - <a href="http://developer.android.com/license.html">Content License</a>. - </p> - - <p> - <a href="http://www.android.com/terms.html">Site Terms of Service</a> – - <a href="http://www.android.com/privacy.html">Privacy Policy</a> – - <a href="http://www.android.com/branding.html">Brand Guidelines</a> - </p> - - </div> - </div> - - <script type="text/javascript"> - var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); - document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); - </script> - <script type="text/javascript"> - var pageTracker = _gat._getTracker("UA-5831155-1"); - pageTracker._trackPageview(); - </script> - -<!-- Start of Tag --> -<script type="text/javascript"> -var axel = Math.random() + ""; -var a = axel * 10000000000000; -document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>'); -</script> -<noscript> -<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe> -</noscript> -<!-- End of Tag --> - </body> -</html> diff --git a/tools/droiddoc/templates-ndk/docpage.cs b/tools/droiddoc/templates-ndk/docpage.cs deleted file mode 100644 index fa6dde60a2..0000000000 --- a/tools/droiddoc/templates-ndk/docpage.cs +++ /dev/null @@ -1,190 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs include:"head_tag.cs" ?> -<body class="gc-documentation develop <?cs - if:guide ?> guide<?cs /if ?><?cs - if:reference ?> reference<?cs /if ?><?cs - if:samples ?> samples<?cs /if ?><?cs - if:downloads ?> downloads<?cs /if ?>" itemscope itemtype="http://schema.org/Article"><?cs -include:"header.cs" ?> - -<div <?cs - if:fullpage - ?>class="fullpage"<?cs - elif:(design||tools||about||sdk||googleplay||essentials||users||monetize||disttools) && !nonavpage - ?>class="col-13" id="doc-col"<?cs - elif:!nonavpage - ?>class="col-12" id="doc-col"<?cs /if ?> > - -<?cs if:(design||training||walkthru) && !page.trainingcourse && !page.article ?><?cs # header logic for docs that provide previous/next buttons ?> - <?cs if:header.hide ?> - <?cs else ?> - <div class="layout-content-row content-header <?cs if:header.justLinks ?>just-links<?cs /if ?>"> - <div class="layout-content-col <?cs if:training ?>span-7<?cs else ?>span-9<?cs /if ?>"> - <?cs if:header.justLinks ?> - <?cs else ?><h1 itemprop="name"><?cs var:page.title ?></h1> - <?cs /if ?> - </div> - <?cs if:training ?> - <div class="training-nav-top layout-content-col span-5" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <a href="#" class="prev-page-link hide" - zh-tw-lang="上一堂課" - zh-cn-lang="上一课" - ru-lang="Предыдущий" - ko-lang="이전" - ja-lang="前へ" - es-lang="Anterior" - >Previous</a> - <a href="#" class="next-page-link hide" - zh-tw-lang="下一堂課" - zh-cn-lang="下一课" - ru-lang="Следующий" - ko-lang="다음" - ja-lang="次へ" - es-lang="Siguiente" - >Next</a> - <a href="#" class="start-class-link hide" - zh-tw-lang="開始上課" - zh-cn-lang="开始" - ru-lang="Начало работы" - ko-lang="시작하기" - ja-lang="開始する" - es-lang="Empezar" - >Get started</a> - </div> - <?cs elif:!page.trainingcourse ?> - <div class="paging-links layout-content-col span-4" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <a href="#" class="prev-page-link hide" - zh-tw-lang="上一堂課" - zh-cn-lang="上一课" - ru-lang="Предыдущий" - ko-lang="이전" - ja-lang="前へ" - es-lang="Anterior" - >Previous</a> - <a href="#" class="next-page-link hide" - zh-tw-lang="下一堂課" - zh-cn-lang="下一课" - ru-lang="Следующий" - ko-lang="다음" - ja-lang="次へ" - es-lang="Siguiente" - >Next</a> - </div> - <?cs /if ?><?cs # end if training ?> - </div> - <?cs /if ?><?cs # end if header.hide ?> - -<?cs elif:samplesProjectIndex ?> - <div id="api-info-block"> - <div class="sum-details-links"> - Overview - | <a href="<?cs var:toroot ?>samples/<?cs var:projectDir ?>/project.html">Project</a> - | <a href="<?cs var:toroot ?>downloads/samples/<?cs var:projectDir ?>.zip">Download</a> - </div><!-- end sum-details-links --> - </div><!-- end breadcurmb block --> - <h1 itemprop="name"><?cs var:projectDir ?></h1> - -<?cs else ?> - <?cs if:training ?> -<?cs # horrible horrible hack to move TOC up when the next/prev links are not there ?> -<style> - #tb-wrapper { - margin-top:6px; - } -</style> - <?cs /if ?> - - <?cs if:(!fullpage && !header.hide) ?> - <?cs if:page.landing ?><?cs # header logic for docs that are landing pages ?> - <div class="landing-banner"> - <?cs if:page.landing.image ?><?cs # use two-column layout only if there is an image ?> - <div class="col-6"> - <img src="<?cs var:toroot ?><?cs var:page.landing.image ?>" alt="" /> - </div> - <div class="col-6"> - <?cs /if ?> - <h1 itemprop="name" style="margin-bottom:0;"><?cs var:page.title ?></h1> - <p itemprop="description"><?cs var:page.landing.intro ?></p> - - <p><a class="next-page-link topic-start-link"></a></p> - <?cs if:page.landing.image ?> - </div> - <?cs /if ?> - </div> - <?cs else ?> - <?cs if:tab1 ?><div id="title-tabs-wrapper"><?cs /if ?> - <h1 itemprop="name" <?cs if:tab1 ?>class="with-title-tabs"<?cs /if ?>><?cs var:page.title ?></h1><?cs - if:tab1 ?><ul id="title-tabs"> - <li class="selected"><a href="<?cs var:tab1.link ?>"><?cs var:tab1 ?></a></li> - <?cs if:tab2 ?> - <li><a href="<?cs var:tab2.link ?>"><?cs var:tab2 ?></a></li><?cs /if ?> - <?cs if:tab3 ?> - <li><a href="<?cs var:tab3.link ?>"><?cs var:tab3 ?></a></li><?cs /if ?> - </ul> - <?cs /if ?> - <?cs if:tab1 ?></div><!-- end tab-wrapper --><?cs /if ?> - <?cs /if ?> - <?cs /if ?> -<?cs /if ?><?cs # end if design ?> - - <?cs # THIS IS THE MAIN DOC CONTENT ?> - <div id="jd-content"> - - - <div class="jd-descr" itemprop="articleBody"> - <?cs call:tag_list(root.descr) ?> - </div> - - <div class="content-footer <?cs - if:fullpage ?>wrap<?cs - else ?>layout-content-row<?cs /if ?>" - itemscope itemtype="http://schema.org/SiteNavigationElement"> - <?cs if:!fullscreen ?> - <div class="paging-links layout-content-col col-10"> - <?cs if:(design||training||walkthru) && !page.landing && !page.trainingcourse && !footer.hide ?> - <a href="#" class="next-page-link hide" - zh-tw-lang="下一堂課" - zh-cn-lang="下一课" - ru-lang="Следующий" - ko-lang="다음" - ja-lang="次へ" - es-lang="Siguiente" - >Next</a> - <a href="#" class="start-class-link hide" - zh-tw-lang="開始上課" - zh-cn-lang="开始" - ru-lang="Начало работы" - ko-lang="시작하기" - ja-lang="開始する" - es-lang="Empezar" - >Get started</a> - <a href="#" class="next-class-link hide">Next class</a> - <?cs /if ?> - </div> - <div class="layout-content-col plus-container col-2" > - <?cs if:!page.noplus ?><?cs if:fullpage ?><style>#___plusone_0 {float:right !important;}</style><?cs /if ?> - <div class="g-plusone" data-size="medium"></div> - <?cs /if ?> - </div> - <?cs /if ?> - </div> - - </div> <!-- end jd-content --> - -<?cs include:"footer.cs" ?> -</div><!-- end doc-content --> - -<?cs include:"trailer.cs" ?> - <script src="https://developer.android.com/ytblogger_lists_unified.js" type="text/javascript"></script> - <script src="<?cs var:toroot ?>jd_lists_unified.js?v=8" type="text/javascript"></script> - <script src="<?cs var:toroot ?>jd_extras.js?v=10" type="text/javascript"></script> - <script src="<?cs var:toroot ?>jd_collections.js?v=10" type="text/javascript"></script> - <script src="<?cs var:toroot ?>jd_tag_helpers.js?v=5" type="text/javascript"></script> - -</body> -</html> - - - diff --git a/tools/droiddoc/templates-ndk/footer.cs b/tools/droiddoc/templates-ndk/footer.cs deleted file mode 100644 index b609d3b8cf..0000000000 --- a/tools/droiddoc/templates-ndk/footer.cs +++ /dev/null @@ -1,20 +0,0 @@ -<div id="footer" class="wrap" <?cs if:fullpage ?>style="width:940px"<?cs /if ?>> - -<?cs if:reference ?> - <div id="copyright"> - <?cs call:custom_copyright() ?> - </div> - <div id="build_info"> - <?cs call:custom_buildinfo() ?> - </div> -<?cs elif:!hide_license_footer ?> - <div id="copyright"> - <?cs call:custom_cc_copyright() ?> - </div> -<?cs /if ?> -<?cs if:!no_footer_links ?> - <div id="footerlinks"> - <?cs call:custom_footerlinks() ?> - </div> -<?cs /if ?> -</div> <!-- end footer -->
\ No newline at end of file diff --git a/tools/droiddoc/templates-ndk/gcm_navtree_data.cs b/tools/droiddoc/templates-ndk/gcm_navtree_data.cs deleted file mode 100644 index 6f33d8850b..0000000000 --- a/tools/droiddoc/templates-ndk/gcm_navtree_data.cs +++ /dev/null @@ -1,3 +0,0 @@ -var GCM_NAVTREE_DATA = -<?cs var:reference_tree ?> -; diff --git a/tools/droiddoc/templates-ndk/gms_navtree_data.cs b/tools/droiddoc/templates-ndk/gms_navtree_data.cs deleted file mode 100644 index 66b7d553fb..0000000000 --- a/tools/droiddoc/templates-ndk/gms_navtree_data.cs +++ /dev/null @@ -1,3 +0,0 @@ -var GMS_NAVTREE_DATA = -<?cs var:reference_tree ?> -; diff --git a/tools/droiddoc/templates-ndk/head_tag.cs b/tools/droiddoc/templates-ndk/head_tag.cs deleted file mode 100644 index d9dca8b34a..0000000000 --- a/tools/droiddoc/templates-ndk/head_tag.cs +++ /dev/null @@ -1,80 +0,0 @@ -<head> -<?cs - ####### If building devsite, add some meta data needed for when generating the top nav ######### ?> -<?cs - if:devsite ?><?cs - if:guide||develop||training||reference||tools||sdk||google||samples - ?><meta name="top_category" value="develop" /><?cs - elif:google - ?><meta name="top_category" value="google" /><?cs - elif:reference && !(reference.gms || reference.gcm) - ?><meta name="top_category" value="css-fullscreen" /><?cs - /if ?> - <?cs - /if -?><?cs - # END if/else devsite ?> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="viewport" content="width=<?cs - if:page.viewport_width ?><?cs - var:page.viewport_width ?><?cs - else ?>device-width<?cs /if ?>" /> -<?cs - if:page.metaDescription ?> -<meta name="Description" content="<?cs var:page.metaDescription ?>"><?cs - /if ?> -<link rel="shortcut icon" type="image/x-icon" href="<?cs var:toroot ?>favicon.ico" /> -<title><?cs - if:page.title ?><?cs - var:page.title ?> | <?cs - /if ?>Android Developers</title> - -<!-- STYLESHEETS --> -<link rel="stylesheet" -href="<?cs -if:android.whichdoc != 'online' ?>http:<?cs -/if ?>//fonts.googleapis.com/css?family=Roboto+Condensed"> -<link rel="stylesheet" href="<?cs -if:android.whichdoc != 'online' ?>http:<?cs -/if ?>//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" - title="roboto"> -<link href="<?cs var:toroot ?>assets/css/default.css?v=5" rel="stylesheet" type="text/css"> - -<!-- JAVASCRIPT --> -<script src="<?cs if:android.whichdoc != 'online' ?>http:<?cs /if ?>//www.google.com/jsapi" type="text/javascript"></script> -<?cs -if:devsite - ?><script src="<?cs var:toroot ?>_static/js/android_3p-bundle.js" type="text/javascript"></script><?cs -else - ?><script src="<?cs var:toroot ?>assets/js/android_3p-bundle.js" type="text/javascript"></script><?cs -/if ?><?cs - if:page.customHeadTag ?> -<?cs var:page.customHeadTag ?><?cs - /if ?> -<script type="text/javascript"> - var toRoot = "<?cs var:toroot ?>"; - var metaTags = [<?cs var:meta.tags ?>]; - var devsite = <?cs if:devsite ?>true<?cs else ?>false<?cs /if ?>; -</script> -<script src="<?cs var:toroot ?>assets/js/docs.js?v=3" type="text/javascript"></script> - -<?cs if:helpoutsWidget ?> -<script type="text/javascript" src="https://helpouts.google.com/ps/res/embed.js" defer async - data-helpouts-embed data-helpouts-vertical="programming" - data-helpouts-tags="<?cs var:page.tags ?>" data-helpouts-prefix="android" - data-helpouts-standalone="true"></script> -<?cs /if ?> - -<script> - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - - ga('create', 'UA-5831155-1', 'android.com'); - ga('create', 'UA-49880327-2', 'android.com', {'name': 'universal'}); // New tracker); - ga('send', 'pageview'); - ga('universal.send', 'pageview'); // Send page view for new tracker. -</script> - -</head> diff --git a/tools/droiddoc/templates-ndk/header.cs b/tools/droiddoc/templates-ndk/header.cs deleted file mode 100644 index e8301bed93..0000000000 --- a/tools/droiddoc/templates-ndk/header.cs +++ /dev/null @@ -1,3 +0,0 @@ -<?cs call:custom_masthead() ?> -<?cs call:custom_left_nav() ?> - diff --git a/tools/droiddoc/templates-ndk/header_tabs.cs b/tools/droiddoc/templates-ndk/header_tabs.cs deleted file mode 100644 index 38c9da80fc..0000000000 --- a/tools/droiddoc/templates-ndk/header_tabs.cs +++ /dev/null @@ -1,2 +0,0 @@ - -<!-- CURRENTLY NOT USED... ALL TABS ARE IN masthead.cs --> diff --git a/tools/droiddoc/templates-ndk/jd_lists_unified.cs b/tools/droiddoc/templates-ndk/jd_lists_unified.cs deleted file mode 100644 index 417a5c1b2e..0000000000 --- a/tools/droiddoc/templates-ndk/jd_lists_unified.cs +++ /dev/null @@ -1 +0,0 @@ -<?cs var:reference_tree ?> diff --git a/tools/droiddoc/templates-ndk/macros_override.cs b/tools/droiddoc/templates-ndk/macros_override.cs deleted file mode 100644 index 0a945986e5..0000000000 --- a/tools/droiddoc/templates-ndk/macros_override.cs +++ /dev/null @@ -1,36 +0,0 @@ -<?cs # Create a comma separated list of annotations on obj that were in showAnnotations in Doclava ?> -<?cs # pre is an HTML string to start the list, post is an HTML string to close the list ?> -<?cs # for example call:show_annotations_list(cl, "<td>Annotations: ", "</td>") ?> -<?cs # if obj has nothing on obj.showAnnotations, nothing will be output ?> -<?cs def:show_annotations_list(obj) ?> - <?cs each:anno = obj.showAnnotations ?> - <?cs if:first(anno) ?> - <span class='annotation-message'> - Included in documentation by the annotations: - <?cs /if ?> - @<?cs var:anno.type.label ?> - <?cs if:last(anno) == 0 ?> - , - <?cs /if ?> - <?cs if:last(anno)?> - </span> - <?cs /if ?> - <?cs /each ?> -<?cs /def ?> - -<?cs # Override default class_link_table to display annotations ?> -<?cs def:class_link_table(classes) ?> - <?cs set:count = #1 ?> - <table class="jd-sumtable-expando"> - <?cs each:cl=classes ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:cl.type.since ?>" > - <td class="jd-linkcol"><?cs call:type_link(cl.type) ?></td> - <td class="jd-descrcol" width="100%"> - <?cs call:short_descr(cl) ?> - <?cs call:show_annotations_list(cl) ?> - </td> - </tr> - <?cs set:count = count + #1 ?> - <?cs /each ?> - </table> -<?cs /def ?>
\ No newline at end of file diff --git a/tools/droiddoc/templates-ndk/navtree_data.cs b/tools/droiddoc/templates-ndk/navtree_data.cs deleted file mode 100644 index 73aa19963d..0000000000 --- a/tools/droiddoc/templates-ndk/navtree_data.cs +++ /dev/null @@ -1,3 +0,0 @@ -var NAVTREE_DATA = -<?cs var:reference_tree ?> -; diff --git a/tools/droiddoc/templates-ndk/nosidenavpage.cs b/tools/droiddoc/templates-ndk/nosidenavpage.cs deleted file mode 100644 index 8e5969361e..0000000000 --- a/tools/droiddoc/templates-ndk/nosidenavpage.cs +++ /dev/null @@ -1,27 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs include:"head_tag.cs" ?> -<body class="gc-documentation - <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs - elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?>" itemscope itemtype="http://schema.org/Article"> -<a name="top"></a> -<?cs call:custom_masthead() ?> - -<div id="body-content"> -<div id="doc-content" style="position:relative;"> - -<?cs call:tag_list(root.descr) ?> - -<?cs include:"footer.cs" ?> -</div><!-- end doc-content --> - -<?cs include:"trailer.cs" ?> - -</body> -</html> - - - diff --git a/tools/droiddoc/templates-ndk/package.cs b/tools/droiddoc/templates-ndk/package.cs deleted file mode 100644 index 22255650bd..0000000000 --- a/tools/droiddoc/templates-ndk/package.cs +++ /dev/null @@ -1,65 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<?cs include:"macros_override.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs include:"head_tag.cs" ?> - -<body class="gc-documentation <?cs if:(reference.gms || reference.gcm) ?>google<?cs /if ?> - <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs - if:reference ?> reference<?cs - /if ?><?cs - elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?>"> - <div id="doc-api-level" class="<?cs var:package.since ?>" style="display:none"></div> - <a name="top"></a> -<?cs include:"header.cs" ?> - -<div class="col-12" id="doc-col"> - -<div id="api-info-block"> -<div class="api-level"> - <?cs call:since_tags(package) ?> - <?cs call:federated_refs(package) ?> -</div> -</div> - -<div id="jd-header"> - package - <h1><?cs var:package.name ?></h1> -</div><!-- end header --> - -<div id="naMessage"></div> - -<div id="jd-content" class="api apilevel-<?cs var:package.since ?>"> - -<?cs if:subcount(package.descr) ?> - <div class="jd-descr"> - <?cs call:tag_list(package.descr) ?> - </div> -<?cs /if ?> - -<?cs def:class_table(label, classes) ?> - <?cs if:subcount(classes) ?> - <h2><?cs var:label ?></h2> - <div class="jd-sumtable"> - <?cs call:class_link_table(classes) ?> - </div> - <?cs /if ?> -<?cs /def ?> - -<?cs call:class_table("Annotations", package.annotations) ?> -<?cs call:class_table("Interfaces", package.interfaces) ?> -<?cs call:class_table("Classes", package.classes) ?> -<?cs call:class_table("Enums", package.enums) ?> -<?cs call:class_table("Exceptions", package.exceptions) ?> -<?cs call:class_table("Errors", package.errors) ?> - -<?cs include:"footer.cs" ?> -</div><!-- end jd-content --> -</div><!-- doc-content --> - -<?cs include:"trailer.cs" ?> - -</body> -</html> diff --git a/tools/droiddoc/templates-ndk/packages.cs b/tools/droiddoc/templates-ndk/packages.cs deleted file mode 100644 index 5056d3a5d7..0000000000 --- a/tools/droiddoc/templates-ndk/packages.cs +++ /dev/null @@ -1,45 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs include:"head_tag.cs" ?> -<body class="gc-documentation <?cs if:(reference.gms || reference.gcm) ?>google<?cs /if ?> - <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs - if:reference ?> reference<?cs - /if ?><?cs - elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?>"> - <a name="top"></a> -<?cs include:"header.cs" ?> - -<div class="col-12" id="doc-col"> - -<div id="jd-header"> -<h1><?cs var:page.title ?></h1> -</div> - -<div id="jd-content"> - -<div class="jd-descr"> -<p><?cs call:tag_list(root.descr) ?></p> -</div> - -<?cs set:count = #1 ?> -<table class="jd-sumtable"> -<?cs each:pkg = docs.packages ?> - <tr class="<?cs if:count % #2 ?>alt-color<?cs /if ?> api apilevel-<?cs var:pkg.since ?>" > - <td class="jd-linkcol"><?cs call:package_link(pkg) ?></td> - <td class="jd-descrcol" width="100%"><?cs call:tag_list(pkg.shortDescr) ?></td> - </tr> -<?cs set:count = count + #1 ?> -<?cs /each ?> -</table> - -<?cs include:"footer.cs" ?> -</div><!-- end jd-content --> -</div> <!-- end doc-content --> - -<?cs include:"trailer.cs" ?> - -</body> -</html> diff --git a/tools/droiddoc/templates-ndk/sample.cs b/tools/droiddoc/templates-ndk/sample.cs deleted file mode 100644 index 32a0788efc..0000000000 --- a/tools/droiddoc/templates-ndk/sample.cs +++ /dev/null @@ -1,151 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs include:"head_tag.cs" ?> -<body class="gc-documentation develop samples" itemscope itemtype="http://schema.org/Article"> -<?cs include:"header.cs" ?> - -<div <?cs if:fullpage -?>class="fullpage"<?cs elif:design||tools||about||sdk||distribute -?>class="col-13" id="doc-col"<?cs else -?>class="col-12" id="doc-col"<?cs /if ?> > - -<!-- start breadcrumb block --> -<div id="api-info-block"> - <div class="sum-details-links"> - - <!-- related links --> - <a href="<?cs var:toroot ?>samples/<?cs var:projectDir ?>/index.html">Overview</a> - | <a href="<?cs var:toroot ?>samples/<?cs var:projectDir ?>/project.html">Project</a> - | <a href="<?cs var:toroot ?>downloads/samples/<?cs var:projectDir ?>.zip" - onclick="ga('send', 'event', 'Samples', 'Download', <?cs var:projectDir ?>);" - >Download</a> - -</div><!-- end sum-details-links --> - -</div><!-- end breadcurmb block --> - -<div id="jd-header" style="border:0;"> - -<div id="pathCrumb"> -<?cs each:item = parentdirs ?> - <?cs if:LinkifyPathCrumb - ?><a href="<?cs var:toroot ?><?cs var:item.Link ?>"><?cs var:item.Name ?></a> / - <?cs else - ?><?cs var:item.Name ?> / <?cs /if ?> -<?cs /each ?> -</div> - - <h1 itemprop="name"><?cs var:page.title ?></h1> -</div> -<!-- end breadcrumb block --> - - -<?cs # THIS IS THE MAIN DOC CONTENT ?> -<div id="jd-content"> - -<?cs if:android.whichdoc == "online" ?> - -<?cs # If this is the online docs, build the src code navigation links ?> - - -<?cs var:summary ?> - -<!-- begin file contents --> - -<?cs # embed image/videos if below maxsize (show message otherwise), else display source code ?> -<?cs if:resType == "img" ?> - <div id="codesample-resource" - <?cs if:noDisplay ?> - class="noDisplay"><div class="noDisplay-message"></div> - <?cs else ?> - ><img src="<?cs var:realFile ?>" title="<?cs var:page.title ?>"> - <?cs /if ?> - </div> -<?cs elif:resType == "video" ?> - <div id="codesample-resource" - <?cs if:noDisplay ?> - class="noDisplay"><div class="noDisplay-message"></div> - <?cs else ?> - ><video class="play-on-hover" controls style="border:1px solid #ececec;background-color:#f9f9f9;" poster=""> - <source src="<?cs var:page.title ?>"> - </video> - <?cs /if ?> - </div> -<?cs else ?> - <div id="codesample-wrapper"> - <pre id="codesample-line-numbers" class="no-pretty-print hidden"></pre> - <pre id="codesample-block"><?cs var:fileContents ?></pre> - </div> - <script type="text/javascript"> - initCodeLineNumbers(); - </script> -<?cs /if ?> - -<!-- end file contents --> - -<?cs else ?><?cs - # else, this means it's offline docs, - so don't show src links (we dont have the pages!) ?> - -<?cs /if ?><?cs # end if/else online docs ?> - - <div class="content-footer <?cs - if:fullpage ?>wrap<?cs - else ?>layout-content-row<?cs /if ?>" - itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div class="layout-content-col <?cs - if:fullpage ?>col-16<?cs - elif:training||guide ?>col-8<?cs - else ?>col-9<?cs /if ?>" style="padding-top:4px"> - <?cs if:!page.noplus ?><?cs if:fullpage ?><style>#___plusone_0 {float:right !important;}</style><?cs /if ?> - <div class="g-plusone" data-size="medium"></div> - <?cs /if ?> - </div> - <?cs if:!fullscreen ?> - <div class="paging-links layout-content-col col-4"> - <?cs if:(design||training||walkthru) && !page.landing && !page.trainingcourse && !footer.hide ?> - <a href="#" class="prev-page-link hide" - zh-tw-lang="上一堂課" - zh-cn-lang="上一课" - ru-lang="Предыдущий" - ko-lang="이전" - ja-lang="前へ" - es-lang="Anterior" - >Previous</a> - <a href="#" class="next-page-link hide" - zh-tw-lang="下一堂課" - zh-cn-lang="下一课" - ru-lang="Следующий" - ko-lang="다음" - ja-lang="次へ" - es-lang="Siguiente" - >Next</a> - <?cs /if ?> - </div> - <?cs /if ?> - </div> - - <?cs # for training classes, provide a different kind of link when the next page is a different class ?> - <?cs if:training && !page.article ?> - <div class="layout-content-row content-footer next-class" style="display:none" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <a href="#" class="next-class-link hide">Next class: </a> - </div> - <?cs /if ?> - - </div> <!-- end jd-content --> - -<?cs include:"footer.cs" ?> -</div><!-- end doc-content --> - -<?cs include:"trailer.cs" ?> - -</body> -</html> - - - - - - - diff --git a/tools/droiddoc/templates-ndk/sampleindex.cs b/tools/droiddoc/templates-ndk/sampleindex.cs deleted file mode 100644 index 1bacb53ad1..0000000000 --- a/tools/droiddoc/templates-ndk/sampleindex.cs +++ /dev/null @@ -1,136 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs include:"head_tag.cs" ?> -<body class="gc-documentation develop samples" itemscope itemtype="http://schema.org/Article"> -<?cs include:"header.cs" ?> - -<div <?cs if:fullpage -?>class="fullpage"<?cs elif:design||tools||about||sdk||distribute -?>class="col-13" id="doc-col"<?cs else -?>class="col-12" id="doc-col"<?cs /if ?> > - -<!-- start breadcrumb block --> -<div id="api-info-block"> -<div class="sum-details-links"> - -<!-- related links --> -<?cs if:projectStructure ?> -<a href="<?cs var:toroot ?>samples/<?cs var:projectDir ?>/index.html">Overview</a> -| Project<?cs else ?>Overview -| <a href="<?cs var:toroot ?>samples/<?cs var:projectDir ?>/project.html">Project</a> -<?cs /if ?> -| <a href="<?cs var:toroot ?>downloads/samples/<?cs var:projectDir ?>.zip" - onclick="ga('send', 'event', 'Samples', 'Download', <?cs var:projectDir ?>);" - >Download</a> - -</div><!-- end sum-details-links --> - -</div><!-- end breadcurmb block --> - -<h1 itemprop="name"><?cs var:projectDir ?></h1> - -<div id="jd-content"> -<?cs def:display_files(files) ?> - - <?cs each:file = files ?> - <?cs if:file.Type != "dir" ?> - <div class="structure-<?cs var:file.Type ?>"> - <a href="<?cs var:toroot ?><?cs var:file.Href ?>"><?cs var:file.Name ?></a> - </div> - <?cs else ?> - <div class="toggle-content opened structure-dir"> - <a href="#" onclick="return toggleContent(this)"> - <img src="<?cs var:toroot ?>assets/images/triangle-opened.png" - class="toggle-content-img structure-toggle-img" height="9px" width="9px" /> - <?cs var:file.Name ?></a><?cs - if:file.SummaryFlag == "true" ?><span class="dirInfo" - >[ <a href="file.SummaryHref">Info</a> ]</a></span><?cs - /if ?> - <div class="toggle-content-toggleme structure-toggleme"> - <?cs if:file.Sub.0.Name ?> - <?cs call:display_files(file.Sub) ?> - <?cs /if ?> - </div> <?cs # /toggleme ?> - </div> <?cs # /toggle-content ?> - <?cs /if ?> - <?cs /each ?> -<?cs /def ?> - -<?cs if:android.whichdoc == "online" ?> - <?cs # If this is the online docs, build the src code navigation links ?> - - <?cs if:projectStructure ?> - - <?cs call:display_files(Files) ?> - - <?cs else ?> <?cs # else not project structure doc ?> - - <?cs var:summary ?> - - <?cs # Remove project structure from landing pages for now - # <h2>Project Structure</h2> - # <p>Decide what to do with this ...</p> - # <?cs call:display_files(Files) ?> - - <?cs /if ?> <?cs # end if projectStructure ?> - -<?cs else ?><?cs - # else, this means it's offline docs, - so don't show src links (we dont have the pages!) ?> - -<?cs /if ?><?cs # end if/else online docs ?> - <div class="content-footer <?cs - if:fullpage ?>wrap<?cs - else ?>layout-content-row<?cs /if ?>" - itemscope itemtype="http://schema.org/SiteNavigationElement"> - <div class="layout-content-col <?cs - if:fullpage ?>col-16<?cs - elif:training||guide ?>col-8<?cs - else ?>col-9<?cs /if ?>" style="padding-top:4px"> - <?cs if:!page.noplus ?><?cs if:fullpage ?><style>#___plusone_0 {float:right !important;}</style><?cs /if ?> - <div class="g-plusone" data-size="medium"></div> - <?cs /if ?> - </div> - <?cs if:!fullscreen ?> - <div class="paging-links layout-content-col col-4"> - <?cs if:(design||training||walkthru) && !page.landing && !page.trainingcourse && !footer.hide ?> - <a href="#" class="prev-page-link hide" - zh-tw-lang="上一堂課" - zh-cn-lang="上一课" - ru-lang="Предыдущий" - ko-lang="이전" - ja-lang="前へ" - es-lang="Anterior" - >Previous</a> - <a href="#" class="next-page-link hide" - zh-tw-lang="下一堂課" - zh-cn-lang="下一课" - ru-lang="Следующий" - ko-lang="다음" - ja-lang="次へ" - es-lang="Siguiente" - >Next</a> - <?cs /if ?> - </div> - <?cs /if ?> - </div> - - <?cs # for training classes, provide a different kind of link when the next page is a different class ?> - <?cs if:training && !page.article ?> - <div class="layout-content-row content-footer next-class" style="display:none" itemscope itemtype="http://schema.org/SiteNavigationElement"> - <a href="#" class="next-class-link hide">Next class: </a> - </div> - <?cs /if ?> - - </div> <!-- end jd-content --> - -<?cs include:"footer.cs" ?> -</div><!-- end doc-content --> - -<?cs include:"trailer.cs" ?> - -</body> -</html> - - diff --git a/tools/droiddoc/templates-ndk/samples_navtree_data.cs b/tools/droiddoc/templates-ndk/samples_navtree_data.cs deleted file mode 100644 index 24ac7b77cb..0000000000 --- a/tools/droiddoc/templates-ndk/samples_navtree_data.cs +++ /dev/null @@ -1,3 +0,0 @@ -var SAMPLES_NAVTREE_DATA = -<?cs var:reference_tree ?> -; diff --git a/tools/droiddoc/templates-ndk/sdkpage.cs b/tools/droiddoc/templates-ndk/sdkpage.cs deleted file mode 100644 index ffad465cdb..0000000000 --- a/tools/droiddoc/templates-ndk/sdkpage.cs +++ /dev/null @@ -1,577 +0,0 @@ -<?cs include:"doctype.cs" ?> -<?cs include:"macros.cs" ?> -<html<?cs if:devsite ?> devsite<?cs /if ?>> -<?cs if:sdk.redirect ?> - <head> - <title>Redirecting...</title> - <meta http-equiv="refresh" content="0;url=<?cs var:toroot ?>sdk/<?cs - if:sdk.redirect.path ?><?cs var:sdk.redirect.path ?><?cs - else ?>index.html<?cs /if ?>"> - </head> -<?cs else ?> - <?cs include:"head_tag.cs" ?> -<?cs /if ?> -<body class="gc-documentation - <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs - elif:design ?>design<?cs - elif:distribute ?>distribute<?cs - /if ?>" itemscope itemtype="http://schema.org/CreativeWork"> - <a name="top"></a> -<?cs include:"header.cs" ?> - - -<div <?cs if:fullpage -?><?cs else -?>class="col-13" id="doc-col"<?cs /if ?> > - -<?cs if:sdk.redirect ?> - -<div class="g-unit"> - <div id="jd-content"> - <p>Redirecting to - <a href="<?cs var:toroot ?>sdk/<?cs - if:sdk.redirect.path ?><?cs var:sdk.redirect.path ?><?cs - else ?>index.html<?cs /if ?>"><?cs - if:sdk.redirect.path ?><?cs var:sdk.redirect.path ?><?cs - else ?>Download the SDK<?cs /if ?> - </a> ...</p> - -<?cs else ?> -<?cs # else, if NOT redirect ... -# -# -# The following is for SDK/NDK pages -# -# -?> - -<?cs if:header.hide ?><?cs else ?> -<h1 itemprop="name"><?cs var:page.title ?></h1> -<?cs /if ?> - <div id="jd-content" itemprop="description"> - -<?cs if:sdk.not_latest_version ?> - <div class="special"> - <p><strong>This is NOT the current Android SDK release.</strong></p> - <p><a href="/sdk/index.html">Download the current Android SDK</a></p> - </div> -<?cs /if ?> - - -<?cs if:ndk ?> -<?cs # -# -# -# -# -# -# -# the following is for the NDK -# -# (nested in if/else redirect) -# -# -# -# -?> - - <table class="download" id="download-table"> - <tr> - <th>Platform</th> - <th>Package</th> - <th style="white-space:nowrap">Size (Bytes)</th> - <th>SHA1 Checksum</th> - </tr> - <tr> - <td>Windows 32-bit</td> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.win32_download ?>"><?cs var:ndk.win32_download ?></a> - </td> - <td><?cs var:ndk.win32_bytes ?></td> - <td><?cs var:ndk.win32_checksum ?></td> - </tr> - <!-- <tr> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.win32.legacy_download ?>"><?cs var:ndk.win32.legacy_download ?></a> - </td> - <td><?cs var:ndk.win32.legacy_bytes ?></td> - <td><?cs var:ndk.win32.legacy_checksum ?></td> - </tr> --> - <tr> - <td>Windows 64-bit</td> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.win64_download ?>"><?cs var:ndk.win64_download ?></a> - </td> - <td><?cs var:ndk.win64_bytes ?></td> - <td><?cs var:ndk.win64_checksum ?></td> - </tr> - <!-- <tr> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.win64.legacy_download ?>"><?cs var:ndk.win64.legacy_download ?></a> - </td> - <td><?cs var:ndk.win64.legacy_bytes ?></td> - <td><?cs var:ndk.win64.legacy_checksum ?></td> - </tr> --> - <tr> - <td>Mac OS X 32-bit</td> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.mac32_download ?>"><?cs var:ndk.mac32_download ?></a> - </td> - <td><?cs var:ndk.mac32_bytes ?></td> - <td><?cs var:ndk.mac32_checksum ?></td> - </tr> - <!-- <tr> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.mac32.legacy_download ?>"><?cs var:ndk.mac32.legacy_download ?></a> - </td> - <td><?cs var:ndk.mac32.legacy_bytes ?></td> - <td><?cs var:ndk.mac32.legacy_checksum ?></td> - </tr> --> - <td>Mac OS X 64-bit</td> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.mac64_download ?>"><?cs var:ndk.mac64_download ?></a> - </td> - <td><?cs var:ndk.mac64_bytes ?></td> - <td><?cs var:ndk.mac64_checksum ?></td> - </tr> - <!-- <tr> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.mac64.legacy_download ?>"><?cs var:ndk.mac64.legacy_download ?></a> - </td> - <td><?cs var:ndk.mac64.legacy_bytes ?></td> - <td><?cs var:ndk.mac64.legacy_checksum ?></td> - </tr> --> - <!-- <tr> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.linux32.legacy_download ?>"><?cs var:ndk.linux32.legacy_download ?></a> - </td> - <td><?cs var:ndk.linux32.legacy_bytes ?></td> - <td><?cs var:ndk.linux32.legacy_checksum ?></td> - </tr> --> - <tr> - <td>Linux 64-bit (x86)</td> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.linux64_download ?>"><?cs var:ndk.linux64_download ?></a> - </td> - <td><?cs var:ndk.linux64_bytes ?></td> - <td><?cs var:ndk.linux64_checksum ?></td> - </tr> - <!-- <tr> - <td> - <a onClick="return onDownload(this)" - href="http://dl.google.com/android/repository/<?cs var:ndk.linux64.legacy_download ?>"><?cs var:ndk.linux64.legacy_download ?></a> - </td> - <td><?cs var:ndk.linux64.legacy_bytes ?></td> - <td><?cs var:ndk.linux64.legacy_checksum ?></td> - </tr> --> - - </table> - - <?cs ######## HERE IS THE JD DOC CONTENT ######### ?> - <?cs call:tag_list(root.descr) ?> - - - -<script> - function onDownload(link) { - - $("#downloadForRealz").html("Download " + $(link).text()); - $("#downloadForRealz").attr('href',$(link).attr('href')); - - $("#tos").fadeIn('slow'); - - location.hash = "download"; - return false; - } - - - function onAgreeChecked() { - if ($("input#agree").is(":checked")) { - $("a#downloadForRealz").removeClass('disabled'); - } else { - $("a#downloadForRealz").addClass('disabled'); - } - } - - function onDownloadNdkForRealz(link) { - if ($("input#agree").is(':checked')) { - $("#tos").fadeOut('slow'); - - $('html, body').animate({ - scrollTop: $("#Installing").offset().top - }, 800, function() { - $("#Installing").click(); - }); - - return true; - } else { - $("label#agreeLabel").parent().stop().animate({color: "#258AAF"}, 200, - function() {$("label#agreeLabel").parent().stop().animate({color: "#222"}, 200)} - ); - return false; - } - } - - $(window).hashchange( function(){ - if (location.hash == "") { - location.reload(); - } - }); - -</script> - - <?cs else ?> -<?cs # end if NDK ... -# -# -# -# -# -# -# the following is for the SDK -# -# (nested in if/else redirect and if/else NDK) -# -# -# -# -?> - <?cs if:android.whichdoc == "online" ?> - - -<?cs ######## HERE IS THE JD DOC CONTENT FOR ONLINE ######### ?> -<?cs call:tag_list(root.descr) ?> - - - - -<div class="pax col-13 online" style="margin:0;"> - - -<h3>SDK Tools Only</h3> - -<p>If you prefer to use a different IDE or run the tools from the -command line or with build scripts, you can instead download the stand-alone Android SDK Tools. -These packages provide the basic SDK tools for app development, without an IDE. -Also see the <a href="<?cs var:toroot ?>tools/sdk/tools-notes.html">SDK tools release notes</a>.</p> - - <table class="download"> - <tr> - <th>Platform</th> - <th>Package</th> - <th>Size</th> - <th>SHA-1 Checksum</th> - </tr> - <tr> - <td rowspan="2">Windows</td> - <td> - <a onclick="return onDownload(this)" id="win-tools" href="http://dl.google.com/android/<?cs -var:sdk.win_installer -?>"><?cs var:sdk.win_installer ?></a> (Recommended) - </td> - <td><?cs var:sdk.win_installer_bytes ?> bytes</td> - <td><?cs var:sdk.win_installer_checksum ?></td> - </tr> - <tr> - <!-- blank TD from Windows rowspan --> - <td> - <a onclick="return onDownload(this)" href="http://dl.google.com/android/<?cs var:sdk.win_download -?>"><?cs var:sdk.win_download ?></a> - </td> - <td><?cs var:sdk.win_bytes ?> bytes</td> - <td><?cs var:sdk.win_checksum ?></td> - </tr> - <tr> - <td><nobr>Mac OS X</nobr></td> - <td> - <a onclick="return onDownload(this)" id="mac-tools" href="http://dl.google.com/android/<?cs -var:sdk.mac_download -?>"><?cs var:sdk.mac_download ?></a> - </td> - <td><?cs var:sdk.mac_bytes ?> bytes</td> - <td><?cs var:sdk.mac_checksum ?></td> - </tr> - <tr> - <td>Linux</td> - <td> - <a onclick="return onDownload(this)" id="linux-tools" href="http://dl.google.com/android/<?cs -var:sdk.linux_download -?>"><?cs var:sdk.linux_download ?></a> - </td> - <td><?cs var:sdk.linux_bytes ?> bytes</td> - <td><?cs var:sdk.linux_checksum ?></td> - </tr> - </table> - - - -<h3>All Android Studio Packages</h3> - -<p>Select a specific Android Studio package for your platform. Also see the -<a href="<?cs var:toroot ?>tools/revisions/studio.html">Android Studio release notes</a>.</p> - - <table class="download"> - <tr> - <th>Platform</th> - <th>Package</th> - <th>Size</th> - <th>SHA-1 Checksum</th> - </tr> - - <tr> - <td rowspan="3">Windows</td> - <td> - <a onclick="return onDownload(this)" id="win-bundle" - href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.win_bundle_exe_download ?>" - ><?cs var:studio.win_bundle_exe_download ?></a><br>(Recommended) - </td> - <td><?cs var:studio.win_bundle_exe_bytes ?> bytes</td> - <td><?cs var:studio.win_bundle_exe_checksum ?></td> - </tr> - - <tr> - <!-- blank TD from Windows rowspan --> - <td> - <a onclick="return onDownload(this)" - href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.win_notools_exe_download ?>" - ><?cs var:studio.win_notools_exe_download ?></a><br>(No SDK tools included) - </td> - <td><?cs var:studio.win_notools_exe_bytes ?> bytes</td> - <td><?cs var:studio.win_notools_exe_checksum ?></td> - </tr> - - <tr> - <!-- blank TD from Windows rowspan --> - <td> - <a onclick="return onDownload(this)" - href="https://dl.google.com/dl/android/studio/ide-zips/<?cs var:studio.version ?>/<?cs var:studio.win_bundle_download ?>" - ><?cs var:studio.win_bundle_download ?></a> - </td> - <td><?cs var:studio.win_bundle_bytes ?> bytes</td> - <td><?cs var:studio.win_bundle_checksum ?></td> - </tr> - - <tr> - <td><nobr>Mac OS X</nobr></td> - <td> - <a onclick="return onDownload(this)" id="mac-bundle" - href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.mac_bundle_download ?>" - ><?cs var:studio.mac_bundle_download ?></a> - </td> - <td><?cs var:studio.mac_bundle_bytes ?> bytes</td> - <td><?cs var:studio.mac_bundle_checksum ?></td> - </tr> - - <tr> - <td>Linux</td> - <td> - <a onclick="return onDownload(this)" id="linux-bundle" - href="https://dl.google.com/dl/android/studio/ide-zips/<?cs var:studio.version ?>/<?cs var:studio.linux_bundle_download ?>" - ><?cs var:studio.linux_bundle_download ?></a> - </td> - <td><?cs var:studio.linux_bundle_bytes ?> bytes</td> - <td><?cs var:studio.linux_bundle_checksum ?></td> - </tr> - </table> - - - -</div><!-- end pax --> - - - -</div><!-- end col-13 for lower-half content --> - - - - -<script> - if (location.hash == "#Requirements") { - $('.reqs').show(); - } else if (location.hash == "#ExistingIDE") { - $('.ide').show(); - } - - var os; - var bundlename; - var $toolslink; - - if (navigator.appVersion.indexOf("Mobile")!=-1) { - // Do nothing for any "mobile" user agent - } else if (navigator.appVersion.indexOf("Win")!=-1) { - os = "Windows"; - bundlename = '#win-bundle'; - $toolslink = $('#win-tools'); - } else if (navigator.appVersion.indexOf("Mac")!=-1) { - os = "Mac"; - bundlename = '#mac-bundle'; - $toolslink = $('#mac-tools'); - } else if (navigator.appVersion.indexOf("Linux")!=-1 && navigator.appVersion.indexOf("Android")==-1) { - os = "Linux"; - bundlename = '#linux-bundle'; - $toolslink = $('#linux-tools'); - } - - if (os != undefined) { - $('#not-supported').hide(); - - /* set up primary Android Studio download button */ - $('.download-bundle-button').append(" <br/><span class='small'>for " + os + "</span>"); - $('.download-bundle-button').click(function() {return onDownload(this,true,true);}).attr('href', bundlename); - } - - - function onDownload(link, button, bundle) { - - /* set text for download button */ - if (button) { - $("#downloadForRealz").html($(link).text()); - } else { - $("#downloadForRealz").html("Download " + $(link).text()); - } - - $("#downloadForRealz").attr('bundle', bundle); - $("a#downloadForRealz").attr("name", $(link).attr('href')); - - $("#tos").show(); - $("#landing").hide(); - - location.hash = "top"; - return false; - } - - - function onAgreeChecked() { - /* verify that the TOS is agreed */ - if ($("input#agree").is(":checked")) { - - /* if downloading the bundle */ - if ($("#downloadForRealz").attr('bundle')) { - /* construct the name of the link we want */ - linkId = $("a#downloadForRealz").attr("name"); - /* set the real url for download */ - $("a#downloadForRealz").attr("href", $(linkId).attr("href")); - } else { - $("a#downloadForRealz").attr("href", $("a#downloadForRealz").attr("name")); - } - - /* reveal the download button */ - $("a#downloadForRealz").removeClass('disabled'); - } else { - $("a#downloadForRealz").addClass('disabled'); - } - } - - function onDownloadForRealz(link) { - if ($("input#agree").is(':checked')) { - location.hash = ""; - location.hash = "top"; - $("div.sdk-terms").slideUp(); - $("h1#tos-header").text('Now downloading...'); - $(".sdk-terms-intro").text('You\'ll be redirected to the install instructions in a moment.'); - $("#sdk-terms-form").fadeOut('slow', function() { - setTimeout(function() { - if ($("#downloadForRealz").attr('bundle') == 'true') { - // User downloaded the studio Bundle - window.location = "/sdk/installing/index.html?pkg=studio"; - } else { - // User downloaded the SDK Tools - window.location = "/sdk/installing/index.html?pkg=tools"; - } - }, 3000); - }); - ga('send', 'event', 'SDK', 'IDE and Tools', $("#downloadForRealz").html()); - return true; - } else { - $("label#agreeLabel").parent().stop().animate({color: "#258AAF"}, 200, - function() {$("label#agreeLabel").parent().stop().animate({color: "#222"}, 200)} - ); - return false; - } - } - - $(window).hashchange( function(){ - if (location.hash == "") { - location.reload(); - } - }); - -</script> - - - -</div><!-- end the wrapper used for relative/absolute positions --> -<?cs # THIS DIV WAS OPENED IN INDEX.JD ?> - - - - - <?cs else ?> <?cs # end if online ?> - - <?cs if:sdk.preview ?><?cs # it's preview offline docs ?> - <p>Welcome developers! We are pleased to provide you with a preview SDK for the upcoming - Android 3.0 release, to give you a head-start on developing applications for it. - </p> - - <p>See the <a - href="<?cs var:toroot ?>sdk/preview/start.html">Getting Started</a> document for more information - about how to set up the preview SDK and get started.</p> - <style type="text/css"> - .non-preview { display:none; } - </style> - - <?cs else ?><?cs # it's normal offline docs ?> - - <?cs ######## HERE IS THE JD DOC CONTENT FOR OFFLINE ######### ?> - <?cs call:tag_list(root.descr) ?> - <style type="text/css"> - body .offline { display:block; } - body .online { display:none; } - </style> - <script> - $('.reqs').show(); - </script> - <?cs /if ?> - - <?cs /if ?> <?cs # end if/else online ?> - -<?cs /if ?> <?cs # end if/else NDK ?> - -<?cs /if ?> <?cs # end if/else redirect ?> - - -</div><!-- end jd-content --> - -<?cs if:!sdk.redirect ?> -<?cs include:"footer.cs" ?> -<?cs /if ?> - -</div><!-- end g-unit --> - -<?cs include:"trailer.cs" ?> - -<!-- Start of Tag --> -<script type="text/javascript"> -var axel = Math.random() + ""; -var a = axel * 10000000000000; -document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>'); -</script> -<noscript> -<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe> -</noscript> -<!-- End of Tag --> -</body> -</html> - - - diff --git a/tools/droiddoc/templates-ndk/timestamp.cs b/tools/droiddoc/templates-ndk/timestamp.cs deleted file mode 100644 index 4bf502a0bf..0000000000 --- a/tools/droiddoc/templates-ndk/timestamp.cs +++ /dev/null @@ -1 +0,0 @@ -var BUILD_TIMESTAMP = "<?cs var:page.now ?>"; diff --git a/tools/droiddoc/templates-ndk/trailer.cs b/tools/droiddoc/templates-ndk/trailer.cs deleted file mode 100644 index 337f8d346c..0000000000 --- a/tools/droiddoc/templates-ndk/trailer.cs +++ /dev/null @@ -1,20 +0,0 @@ -</div> <!-- end body-content --> <?cs # normally opened by header.cs ?> - -<?cs if:carousel ?> -<script type="text/javascript"> -$('.slideshow-container').dacSlideshow({ - btnPrev: '.slideshow-prev', - btnNext: '.slideshow-next', - btnPause: '#pauseButton' -}); -</script> -<?cs /if ?> -<?cs if:tabbedList ?> -<script type="text/javascript"> -$(".feed").dacTabbedList({ - nav_id: '.feed-nav', - frame_id: '.feed-frame' -}); -</script> -<?cs /if ?> - diff --git a/tools/extract_kernel.py b/tools/extract_kernel.py index 8ca11d1cc6..0046b38faf 100755 --- a/tools/extract_kernel.py +++ b/tools/extract_kernel.py @@ -40,10 +40,10 @@ COMPRESSION_ALGO = ( # LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; LINUX_BANNER_PREFIX = b'Linux version ' LINUX_BANNER_REGEX = LINUX_BANNER_PREFIX + \ - r'([0-9]+[.][0-9]+[.][0-9]+).* \(.*@.*\) \(.*\) .*\n' + r'(?P<release>(?P<version>[0-9]+[.][0-9]+[.][0-9]+).*) \(.*@.*\) \((?P<compiler>.*)\) .*\n' -def get_version(input_bytes, start_idx): +def get_from_release(input_bytes, start_idx, key): null_idx = input_bytes.find('\x00', start_idx) if null_idx < 0: return None @@ -53,24 +53,51 @@ def get_version(input_bytes, start_idx): return None mo = re.match(LINUX_BANNER_REGEX, linux_banner) if mo: - return mo.group(1) + return mo.group(key) return None -def dump_version(input_bytes): +def dump_from_release(input_bytes, key): + """ + Helper of dump_version and dump_release + """ idx = 0 while True: idx = input_bytes.find(LINUX_BANNER_PREFIX, idx) if idx < 0: return None - version = get_version(input_bytes, idx) - if version: - return version + value = get_from_release(input_bytes, idx, key) + if value: + return value idx += len(LINUX_BANNER_PREFIX) +def dump_version(input_bytes): + """ + Dump kernel version, w.x.y, from input_bytes. Search for the string + "Linux version " and do pattern matching after it. See LINUX_BANNER_REGEX. + """ + return dump_from_release(input_bytes, "version") + + +def dump_compiler(input_bytes): + """ + Dump kernel version, w.x.y, from input_bytes. Search for the string + "Linux version " and do pattern matching after it. See LINUX_BANNER_REGEX. + """ + return dump_from_release(input_bytes, "compiler") + + +def dump_release(input_bytes): + """ + Dump kernel release, w.x.y-..., from input_bytes. Search for the string + "Linux version " and do pattern matching after it. See LINUX_BANNER_REGEX. + """ + return dump_from_release(input_bytes, "release") + + def dump_configs(input_bytes): """ Dump kernel configuration from input_bytes. This can be done when @@ -140,6 +167,23 @@ def decompress_dump(func, input_bytes): if o: return o + +def dump_to_file(f, dump_fn, input_bytes, desc): + """ + Call decompress_dump(dump_fn, input_bytes) and write to f. If it fails, return + False; otherwise return True. + """ + if f is not None: + o = decompress_dump(dump_fn, input_bytes) + if o: + f.write(o) + else: + sys.stderr.write( + "Cannot extract kernel {}".format(desc)) + return False + return True + + def main(): parser = argparse.ArgumentParser( formatter_class=argparse.RawTextHelpFormatter, @@ -165,6 +209,20 @@ def main(): nargs='?', type=argparse.FileType('wb'), const=sys.stdout) + parser.add_argument('--output-release', + help='If specified, write kernel release. Use stdout if ' + 'no file is specified.', + metavar='FILE', + nargs='?', + type=argparse.FileType('wb'), + const=sys.stdout) + parser.add_argument('--output-compiler', + help='If specified, write the compiler information. Use stdout if no file ' + 'is specified.', + metavar='FILE', + nargs='?', + type=argparse.FileType('wb'), + const=sys.stdout) parser.add_argument('--tools', help='Decompression tools to use. If not specified, PATH ' 'is searched.', @@ -181,25 +239,22 @@ def main(): input_bytes = args.input.read() ret = 0 - if args.output_configs is not None: - o = decompress_dump(dump_configs, input_bytes) - if o: - args.output_configs.write(o) - else: - sys.stderr.write( - "Cannot extract kernel configs in {}".format(args.input.name)) - ret = 1 - if args.output_version is not None: - o = decompress_dump(dump_version, input_bytes) - if o: - args.output_version.write(o) - else: - sys.stderr.write( - "Cannot extract kernel versions in {}".format(args.input.name)) - ret = 1 + if not dump_to_file(args.output_configs, dump_configs, input_bytes, + "configs in {}".format(args.input.name)): + ret = 1 + if not dump_to_file(args.output_version, dump_version, input_bytes, + "version in {}".format(args.input.name)): + ret = 1 + if not dump_to_file(args.output_release, dump_release, input_bytes, + "kernel release in {}".format(args.input.name)): + ret = 1 + + if not dump_to_file(args.output_compiler, dump_compiler, input_bytes, + "kernel compiler in {}".format(args.input.name)): + ret = 1 return ret if __name__ == '__main__': - exit(main()) + sys.exit(main()) diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk index 64fabe62f7..41e8ca5664 100644 --- a/tools/fs_config/Android.mk +++ b/tools/fs_config/Android.mk @@ -27,11 +27,13 @@ endif system_android_filesystem_config := system/core/include/private/android_filesystem_config.h system_capability_header := bionic/libc/kernel/uapi/linux/capability.h -# List of supported vendor, oem, odm, product and system_ext Partitions +# List of supported vendor, oem, odm, vendor_dlkm, odm_dlkm, product and system_ext Partitions fs_config_generate_extra_partition_list := $(strip \ $(if $(BOARD_USES_VENDORIMAGE)$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),vendor) \ $(if $(BOARD_USES_OEMIMAGE)$(BOARD_OEMIMAGE_FILE_SYSTEM_TYPE),oem) \ $(if $(BOARD_USES_ODMIMAGE)$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),odm) \ + $(if $(BOARD_USES_VENDOR_DLKMIMAGE)$(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE),vendor_dlkm) \ + $(if $(BOARD_USES_ODM_DLKMIMAGE)$(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE),odm_dlkm) \ $(if $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),product) \ $(if $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),system_ext) \ ) @@ -282,6 +284,108 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_G endif +ifneq ($(filter vendor_dlkm,$(fs_config_generate_extra_partition_list)),) +################################## +# Generate the vendor_dlkm/etc/fs_config_dirs binary file for the target +# Add fs_config_dirs or fs_config_dirs_vendor_dlkm to PRODUCT_PACKAGES in +# the device make file to enable +include $(CLEAR_VARS) + +LOCAL_MODULE := fs_config_dirs_vendor_dlkm +LOCAL_MODULE_CLASS := ETC +LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_DLKM)/etc +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) + @mkdir -p $(dir $@) + $< fsconfig \ + --aid-header $(PRIVATE_ANDROID_FS_HDR) \ + --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ + --partition vendor_dlkm \ + --dirs \ + --out_file $@ \ + $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) + +################################## +# Generate the vendor_dlkm/etc/fs_config_files binary file for the target +# Add fs_config_files of fs_config_files_vendor_dlkm to PRODUCT_PACKAGES in +# the device make file to enable +include $(CLEAR_VARS) + +LOCAL_MODULE := fs_config_files_vendor_dlkm +LOCAL_MODULE_CLASS := ETC +LOCAL_INSTALLED_MODULE_STEM := fs_config_files +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_DLKM)/etc +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) + @mkdir -p $(dir $@) + $< fsconfig \ + --aid-header $(PRIVATE_ANDROID_FS_HDR) \ + --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ + --partition vendor_dlkm \ + --files \ + --out_file $@ \ + $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) + +endif + +ifneq ($(filter odm_dlkm,$(fs_config_generate_extra_partition_list)),) +################################## +# Generate the odm_dlkm/etc/fs_config_dirs binary file for the target +# Add fs_config_dirs or fs_config_dirs_odm_dlkm to PRODUCT_PACKAGES in +# the device make file to enable +include $(CLEAR_VARS) + +LOCAL_MODULE := fs_config_dirs_odm_dlkm +LOCAL_MODULE_CLASS := ETC +LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs +LOCAL_MODULE_PATH := $(TARGET_OUT_ODM_DLKM)/etc +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) + @mkdir -p $(dir $@) + $< fsconfig \ + --aid-header $(PRIVATE_ANDROID_FS_HDR) \ + --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ + --partition odm_dlkm \ + --dirs \ + --out_file $@ \ + $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) + +################################## +# Generate the odm_dlkm/etc/fs_config_files binary file for the target +# Add fs_config_files of fs_config_files_odm_dlkm to PRODUCT_PACKAGES in +# the device make file to enable +include $(CLEAR_VARS) + +LOCAL_MODULE := fs_config_files_odm_dlkm +LOCAL_MODULE_CLASS := ETC +LOCAL_INSTALLED_MODULE_STEM := fs_config_files +LOCAL_MODULE_PATH := $(TARGET_OUT_ODM_DLKM)/etc +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) + @mkdir -p $(dir $@) + $< fsconfig \ + --aid-header $(PRIVATE_ANDROID_FS_HDR) \ + --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ + --partition odm_dlkm \ + --files \ + --out_file $@ \ + $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) + +endif + ifneq ($(filter product,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the product/etc/fs_config_dirs binary file for the target diff --git a/tools/fs_config/README b/tools/fs_config/README deleted file mode 100644 index 21bdeb82b9..0000000000 --- a/tools/fs_config/README +++ /dev/null @@ -1,137 +0,0 @@ - _____ _____ _____ _____ __ __ _____ -/ _ \/ __\/ _ \| _ \/ \/ \/ __\ -| _ <| __|| _ || | || \/ || __| -\__|\_/\_____/\__|__/|_____/\__ \__/\_____/ - -The fs_config_generator.py tool uses the platform android_filesystem_config.h and the -TARGET_FS_CONFIG_GEN files to generate the fs_config_dirs and fs_config_files files for each -partition, as well as passwd and group files, and the generated_oem_aid.h header. - -The fs_config_dirs and fs_config_files binary files are interpreted by the libcutils fs_config() -function, along with the built-in defaults, to serve as overrides to complete the results. The -Target files are used by filesystem and adb tools to ensure that the file and directory properties -are preserved during runtime operations. The host files in the ${OUT} directory are used in the -final stages when building the filesystem images to set the file and directory properties. - -See ./fs_config_generator.py fsconfig --help for how these files are generated. - -The passwd and group files are formatted as documented in man pages passwd(5) and group(5) and used -by bionic for implementing getpwnam() and related functions. - -See ./fs_config_generator.py passwd --help and ./fs_config_generator.py group --help for how these -files are generated. - -The generated_oem_aid.h creates identifiers for non-platform AIDs for developers wishing to use them -in their native code. To do so, include the oemaids_headers header library in the corresponding -makefile and #include "generated_oem_aid.h" in the code wishing to use these identifiers. - -See ./fs_config_generator.py oemaid --help for how this file is generated. - -The parsing of the TARGET_FS_CONFIG_GEN files follows the Python ConfigParser specification, with -the sections and fields as defined below. There are two types of sections, both sections require all -options to be specified. The first section type is the "caps" section. - -The "caps" section follows the following syntax: - -[path] -mode: Octal file mode -user: AID_<user> -group: AID_<group> -caps: cap* - -Where: - -[path] - The filesystem path to configure. A path ending in / is considered a dir, - else its a file. - -mode: - A valid octal file mode of at least 3 digits. If 3 is specified, it is - prefixed with a 0, else mode is used as is. - -user: - Either the C define for a valid AID or the friendly name. For instance both - AID_RADIO and radio are acceptable. Note custom AIDs can be defined in the - AID section documented below. - -group: - Same as user. - -caps: - The name as declared in - system/core/include/private/android_filesystem_capability.h without the - leading CAP_. Mixed case is allowed. Caps can also be the raw: - * binary (0b0101) - * octal (0455) - * int (42) - * hex (0xFF) - For multiple caps, just separate by whitespace. - -It is an error to specify multiple sections with the same [path] in different -files. Note that the same file may contain sections that override the previous -section in Python versions <= 3.2. In Python 3.2 it's set to strict mode. - - -The next section type is the "AID" section, for specifying OEM specific AIDS. - -The AID section follows the following syntax: - -[AID_<name>] -value: <number> - -Where: - -[AID_<name>] - The <name> can contain characters in the set uppercase, numbers - and underscores. - -value: - A valid C style number string. Hex, octal, binary and decimal are supported. - See "caps" above for more details on number formatting. - -It is an error to specify multiple sections with the same [AID_<name>]. With -the same constraints as [path] described above. It is also an error to specify -multiple sections with the same value option. It is also an error to specify a -value that is outside of the inclusive OEM ranges: - * AID_OEM_RESERVED_START(2900) - AID_OEM_RESERVED_END(2999) - * AID_OEM_RESERVED_2_START(5000) - AID_OEM_RESERVED_2_END(5999) - -as defined by system/core/include/private/android_filesystem_config.h. - -Ordering within the TARGET_FS_CONFIG_GEN files is not relevant. The paths for files are sorted -like so within their respective array definition: - * specified path before prefix match - ** ie foo before f* - * lexicographical less than before other - ** ie boo before foo - -Given these paths: - -paths=['ac', 'a', 'acd', 'an', 'a*', 'aa', 'ac*'] - -The sort order would be: -paths=['a', 'aa', 'ac', 'acd', 'an', 'ac*', 'a*'] - -Thus the fs_config tools will match on specified paths before attempting prefix, and match on the -longest matching prefix. - -The declared AIDS are sorted in ascending numerical order based on the option "value". The string -representation of value is preserved. Both choices were made for maximum readability of the generated -file and to line up files. Sync lines are placed with the source file as comments in the generated -header file. - -Unit Tests: - -From within the fs_config directory, unit tests can be executed like so: -$ python -m unittest test_fs_config_generator.Tests -............. ----------------------------------------------------------------------- -Ran 13 tests in 0.004s - -OK - -One could also use nose if they would like: -$ nose2 - -To add new tests, simply add a test_<xxx> method to the test class. It will automatically -get picked up and added to the test suite. diff --git a/tools/fs_config/README.md b/tools/fs_config/README.md new file mode 100644 index 0000000000..bad5e10410 --- /dev/null +++ b/tools/fs_config/README.md @@ -0,0 +1,84 @@ +# FS Config Generator + +The `fs_config_generator.py` tool uses the platform `android_filesystem_config.h` and the +`TARGET_FS_CONFIG_GEN` files to generate the following: +* `fs_config_dirs` and `fs_config_files` files for each partition +* `passwd` and `group` files for each partition +* The `generated_oem_aid.h` header + +## Outputs + +### `fs_config_dirs` and `fs_config_files` + +The `fs_config_dirs` and `fs_config_files` binary files are interpreted by the libcutils +`fs_config()` function, along with the built-in defaults, to serve as overrides to complete the +results. The Target files are used by filesystem and adb tools to ensure that the file and directory +properties are preserved during runtime operations. The host files in the `$OUT` directory are used +in the final stages when building the filesystem images to set the file and directory properties. + +See `./fs_config_generator.py fsconfig --help` for how these files are generated. + +### `passwd` and `group` files + +The `passwd` and `group` files are formatted as documented in man pages passwd(5) and group(5) and +used by bionic for implementing `getpwnam()` and related functions. + +See `./fs_config_generator.py passwd --help` and `./fs_config_generator.py group --help` for how +these files are generated. + +### The `generated_oem_aid.h` header + +The `generated_oem_aid.h` creates identifiers for non-platform AIDs for developers wishing to use +them in their native code. To do so, include the `oemaids_headers` header library in the +corresponding makefile and `#include "generated_oem_aid.h"` in the code wishing to use these +identifiers. + +See `./fs_config_generator.py oemaid --help` for how this file is generated. + +## Parsing + +See the documentation on [source.android.com](https://source.android.com/devices/tech/config/filesystem#configuring-aids) for details and examples. + + +## Ordering + +Ordering within the `TARGET_FS_CONFIG_GEN` files is not relevant. The paths for files are sorted +like so within their respective array definition: + * specified path before prefix match + * for example: foo before f* + * lexicographical less than before other + * for example: boo before foo + +Given these paths: + + paths=['ac', 'a', 'acd', 'an', 'a*', 'aa', 'ac*'] + +The sort order would be: + + paths=['a', 'aa', 'ac', 'acd', 'an', 'ac*', 'a*'] + +Thus the `fs_config` tools will match on specified paths before attempting prefix, and match on the +longest matching prefix. + +The declared AIDs are sorted in ascending numerical order based on the option "value". The string +representation of value is preserved. Both choices were made for maximum readability of the +generated file and to line up files. Sync lines are placed with the source file as comments in the +generated header file. + +## Unit Tests + +From within the `fs_config` directory, unit tests can be executed like so: + + $ python -m unittest test_fs_config_generator.Tests + ............. + ---------------------------------------------------------------------- + Ran 13 tests in 0.004s + + OK + +One could also use nose if they would like: + + $ nose2 + +To add new tests, simply add a `test_<xxx>` method to the test class. It will automatically +get picked up and added to the test suite. diff --git a/tools/fs_config/fs_config.c b/tools/fs_config/fs_config.c index 2952875f64..2a75add096 100644 --- a/tools/fs_config/fs_config.c +++ b/tools/fs_config/fs_config.c @@ -26,6 +26,7 @@ #include <selinux/label.h> #include "private/android_filesystem_config.h" +#include "private/fs_config.h" // This program takes a list of files and directories (indicated by a // trailing slash) on the stdin, and prints to stdout each input diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py index 1405fd3bc5..940a398726 100755 --- a/tools/fs_config/fs_config_generator.py +++ b/tools/fs_config/fs_config_generator.py @@ -299,11 +299,10 @@ class AIDHeaderParser(object): Parses a C header file and extracts lines starting with #define AID_<name> while capturing the OEM defined ranges and ignoring other ranges. It also skips some hardcoded AIDs it doesn't need to generate a mapping for. - It provides some basic sanity checks. The information extracted from this - file can later be used to sanity check other things (like oem ranges) as - well as generating a mapping of names to uids. It was primarily designed to - parse the private/android_filesystem_config.h, but any C header should - work. + It provides some basic checks. The information extracted from this file can + later be used to quickly check other things (like oem ranges) as well as + generating a mapping of names to uids. It was primarily designed to parse + the private/android_filesystem_config.h, but any C header should work. """ _SKIP_AIDS = [ @@ -394,7 +393,7 @@ class AIDHeaderParser(object): def _handle_aid(self, identifier, value): """Handle an AID C #define. - Handles an AID, sanity checking, generating the friendly name and + Handles an AID, quick checking, generating the friendly name and adding it to the internal maps. Internal use only. Args: @@ -422,7 +421,7 @@ class AIDHeaderParser(object): """Process, check and populate internal data structures. After parsing and generating the internal data structures, this method - is responsible for sanity checking ALL of the acquired data. + is responsible for quickly checking ALL of the acquired data. Raises: ValueError: With the message set to indicate the specific error. diff --git a/tools/fs_get_stats/fs_get_stats.c b/tools/fs_get_stats/fs_get_stats.c index 159e2aa912..64ef0e2312 100644 --- a/tools/fs_get_stats/fs_get_stats.c +++ b/tools/fs_get_stats/fs_get_stats.c @@ -4,6 +4,7 @@ #include <unistd.h> #include <private/android_filesystem_config.h> +#include <private/fs_config.h> #define DO_DEBUG 1 diff --git a/tools/generate-notice-files.py b/tools/generate-notice-files.py index 49011b20f6..18f2166fbd 100755 --- a/tools/generate-notice-files.py +++ b/tools/generate-notice-files.py @@ -73,10 +73,10 @@ body { padding: 0; font-family: sans-serif; } </style> """ -def combine_notice_files_html(file_hash, input_dir, output_filename): +def combine_notice_files_html(file_hash, input_dirs, output_filename): """Combine notice files in FILE_HASH and output a HTML version to OUTPUT_FILENAME.""" - SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt") + SRC_DIR_STRIP_RE = re.compile("(?:" + "|".join(input_dirs) + ")(/.*).txt") # Set up a filename to row id table (anchors inside tables don't work in # most browsers, but href's to table row ids do) @@ -131,10 +131,10 @@ def combine_notice_files_html(file_hash, input_dir, output_filename): print >> output_file, "</body></html>" output_file.close() -def combine_notice_files_text(file_hash, input_dir, output_filename, file_title): +def combine_notice_files_text(file_hash, input_dirs, output_filename, file_title): """Combine notice files in FILE_HASH and output a text version to OUTPUT_FILENAME.""" - SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt") + SRC_DIR_STRIP_RE = re.compile("(?:" + "|".join(input_dirs) + ")(/.*).txt") output_file = open(output_filename, "wb") print >> output_file, file_title for value in file_hash: @@ -146,10 +146,10 @@ def combine_notice_files_text(file_hash, input_dir, output_filename, file_title) print >> output_file, open(value[0]).read() output_file.close() -def combine_notice_files_xml(files_with_same_hash, input_dir, output_filename): +def combine_notice_files_xml(files_with_same_hash, input_dirs, output_filename): """Combine notice files in FILE_HASH and output a XML version to OUTPUT_FILENAME.""" - SRC_DIR_STRIP_RE = re.compile(input_dir + "(/.*).txt") + SRC_DIR_STRIP_RE = re.compile("(?:" + "|".join(input_dirs) + ")(/.*).txt") # Set up a filename to row id table (anchors inside tables don't work in # most browsers, but href's to table row ids do) @@ -205,7 +205,7 @@ def get_args(): '-t', '--title', required=True, help='The file title.') parser.add_argument( - '-s', '--source-dir', required=True, + '-s', '--source-dir', required=True, action='append', help='The directory containing notices.') parser.add_argument( '-i', '--included-subdirs', action='append', @@ -229,39 +229,40 @@ def main(argv): if args.excluded_subdirs is not None: excluded_subdirs = args.excluded_subdirs + input_dirs = [os.path.normpath(source_dir) for source_dir in args.source_dir] # Find all the notice files and md5 them - input_dir = os.path.normpath(args.source_dir) - files_with_same_hash = defaultdict(list) - for root, dir, files in os.walk(input_dir): - for file in files: - matched = True - if len(included_subdirs) > 0: - matched = False - for subdir in included_subdirs: - if (root == (input_dir + '/' + subdir) or - root.startswith(input_dir + '/' + subdir + '/')): - matched = True - break - elif len(excluded_subdirs) > 0: - for subdir in excluded_subdirs: - if (root == (input_dir + '/' + subdir) or - root.startswith(input_dir + '/' + subdir + '/')): - matched = False - break - if matched and file.endswith(".txt"): - filename = os.path.join(root, file) - file_md5sum = md5sum(filename) - files_with_same_hash[file_md5sum].append(filename) - - filesets = [sorted(files_with_same_hash[md5]) for md5 in sorted(files_with_same_hash.keys())] - - combine_notice_files_text(filesets, input_dir, txt_output_file, file_title) + for input_dir in input_dirs: + files_with_same_hash = defaultdict(list) + for root, dir, files in os.walk(input_dir): + for file in files: + matched = True + if len(included_subdirs) > 0: + matched = False + for subdir in included_subdirs: + if (root == (input_dir + '/' + subdir) or + root.startswith(input_dir + '/' + subdir + '/')): + matched = True + break + elif len(excluded_subdirs) > 0: + for subdir in excluded_subdirs: + if (root == (input_dir + '/' + subdir) or + root.startswith(input_dir + '/' + subdir + '/')): + matched = False + break + if matched and file.endswith(".txt"): + filename = os.path.join(root, file) + file_md5sum = md5sum(filename) + files_with_same_hash[file_md5sum].append(filename) + + filesets = [sorted(files_with_same_hash[md5]) for md5 in sorted(files_with_same_hash.keys())] + + combine_notice_files_text(filesets, input_dirs, txt_output_file, file_title) if html_output_file is not None: - combine_notice_files_html(filesets, input_dir, html_output_file) + combine_notice_files_html(filesets, input_dirs, html_output_file) if xml_output_file is not None: - combine_notice_files_xml(files_with_same_hash, input_dir, xml_output_file) + combine_notice_files_xml(files_with_same_hash, input_dirs, xml_output_file) if __name__ == "__main__": main(sys.argv) diff --git a/tools/mk2bp_catalog.py b/tools/mk2bp_catalog.py new file mode 100755 index 0000000000..c2afb9b948 --- /dev/null +++ b/tools/mk2bp_catalog.py @@ -0,0 +1,1035 @@ +#!/usr/bin/env python3 + +""" +Command to print info about makefiles remaining to be converted to soong. + +See usage / argument parsing below for commandline options. +""" + +import argparse +import csv +import itertools +import json +import os +import re +import sys + +DIRECTORY_PATTERNS = [x.split("/") for x in ( + "device/*", + "frameworks/*", + "hardware/*", + "packages/*", + "vendor/*", + "*", +)] + +def match_directory_group(pattern, filename): + match = [] + filename = filename.split("/") + if len(filename) < len(pattern): + return None + for i in range(len(pattern)): + pattern_segment = pattern[i] + filename_segment = filename[i] + if pattern_segment == "*" or pattern_segment == filename_segment: + match.append(filename_segment) + else: + return None + if match: + return os.path.sep.join(match) + else: + return None + +def directory_group(filename): + for pattern in DIRECTORY_PATTERNS: + match = match_directory_group(pattern, filename) + if match: + return match + return os.path.dirname(filename) + +class Analysis(object): + def __init__(self, filename, line_matches): + self.filename = filename; + self.line_matches = line_matches + +def analyze_lines(filename, lines, func): + line_matches = [] + for i in range(len(lines)): + line = lines[i] + stripped = line.strip() + if stripped.startswith("#"): + continue + if func(stripped): + line_matches.append((i+1, line)) + if line_matches: + return Analysis(filename, line_matches); + +def analyze_has_conditional(line): + return (line.startswith("ifeq") or line.startswith("ifneq") + or line.startswith("ifdef") or line.startswith("ifndef")) + +NORMAL_INCLUDES = [re.compile(pattern) for pattern in ( + "include \$+\(CLEAR_VARS\)", # These are in defines which are tagged separately + "include \$+\(BUILD_.*\)", + "include \$\(call first-makefiles-under, *\$\(LOCAL_PATH\)\)", + "include \$\(call all-subdir-makefiles\)", + "include \$\(all-subdir-makefiles\)", + "include \$\(call all-makefiles-under, *\$\(LOCAL_PATH\)\)", + "include \$\(call all-makefiles-under, *\$\(call my-dir\).*\)", + "include \$\(BUILD_SYSTEM\)/base_rules.mk", # called out separately + "include \$\(call all-named-subdir-makefiles,.*\)", + "include \$\(subdirs\)", +)] +def analyze_has_wacky_include(line): + if not (line.startswith("include") or line.startswith("-include") + or line.startswith("sinclude")): + return False + for matcher in NORMAL_INCLUDES: + if matcher.fullmatch(line): + return False + return True + +BASE_RULES_RE = re.compile("include \$\(BUILD_SYSTEM\)/base_rules.mk") + +class Analyzer(object): + def __init__(self, title, func): + self.title = title; + self.func = func + + +ANALYZERS = ( + Analyzer("ifeq / ifneq", analyze_has_conditional), + Analyzer("Wacky Includes", analyze_has_wacky_include), + Analyzer("Calls base_rules", lambda line: BASE_RULES_RE.fullmatch(line)), + Analyzer("Calls define", lambda line: line.startswith("define ")), + Analyzer("Has ../", lambda line: "../" in line), + Analyzer("dist-for-​goals", lambda line: "dist-for-goals" in line), + Analyzer(".PHONY", lambda line: ".PHONY" in line), + Analyzer("render-​script", lambda line: ".rscript" in line), + Analyzer("vts src", lambda line: ".vts" in line), + Analyzer("COPY_​HEADERS", lambda line: "LOCAL_COPY_HEADERS" in line), +) + +class Summary(object): + def __init__(self): + self.makefiles = dict() + self.directories = dict() + + def Add(self, makefile): + self.makefiles[makefile.filename] = makefile + self.directories.setdefault(directory_group(makefile.filename), []).append(makefile) + +class Makefile(object): + def __init__(self, filename): + self.filename = filename + + # Analyze the file + with open(filename, "r", errors="ignore") as f: + try: + lines = f.readlines() + except UnicodeDecodeError as ex: + sys.stderr.write("Filename: %s\n" % filename) + raise ex + lines = [line.strip() for line in lines] + + self.analyses = dict([(analyzer, analyze_lines(filename, lines, analyzer.func)) for analyzer + in ANALYZERS]) + +def find_android_mk(): + cwd = os.getcwd() + for root, dirs, files in os.walk(cwd): + for filename in files: + if filename == "Android.mk": + yield os.path.join(root, filename)[len(cwd) + 1:] + for ignore in (".git", ".repo"): + if ignore in dirs: + dirs.remove(ignore) + +def is_aosp(dirname): + for d in ("device/sample", "hardware/interfaces", "hardware/libhardware", + "hardware/ril"): + if dirname.startswith(d): + return True + for d in ("device/", "hardware/", "vendor/"): + if dirname.startswith(d): + return False + return True + +def is_google(dirname): + for d in ("device/google", + "hardware/google", + "test/sts", + "vendor/auto", + "vendor/google", + "vendor/unbundled_google", + "vendor/widevine", + "vendor/xts"): + if dirname.startswith(d): + return True + return False + +def is_clean(makefile): + for analysis in makefile.analyses.values(): + if analysis: + return False + return True + +def clean_and_only_blocked_by_clean(soong, all_makefiles, makefile): + if not is_clean(makefile): + return False + modules = soong.reverse_makefiles[makefile.filename] + for module in modules: + for dep in soong.transitive_deps(module): + for filename in soong.makefiles.get(dep, []): + m = all_makefiles.get(filename) + if m and not is_clean(m): + return False + return True + +class Annotations(object): + def __init__(self): + self.entries = [] + self.count = 0 + + def Add(self, makefiles, modules): + self.entries.append((makefiles, modules)) + self.count += 1 + return self.count-1 + +class SoongData(object): + def __init__(self, reader): + """Read the input file and store the modules and dependency mappings. + """ + self.problems = dict() + self.deps = dict() + self.reverse_deps = dict() + self.module_types = dict() + self.makefiles = dict() + self.reverse_makefiles = dict() + self.installed = dict() + self.reverse_installed = dict() + self.modules = set() + + for (module, module_type, problem, dependencies, makefiles, installed) in reader: + self.modules.add(module) + makefiles = [f for f in makefiles.strip().split(' ') if f != ""] + self.module_types[module] = module_type + self.problems[module] = problem + self.deps[module] = [d for d in dependencies.strip().split(' ') if d != ""] + for dep in self.deps[module]: + if not dep in self.reverse_deps: + self.reverse_deps[dep] = [] + self.reverse_deps[dep].append(module) + self.makefiles[module] = makefiles + for f in makefiles: + self.reverse_makefiles.setdefault(f, []).append(module) + for f in installed.strip().split(' '): + self.installed[f] = module + self.reverse_installed.setdefault(module, []).append(f) + + def transitive_deps(self, module): + results = set() + def traverse(module): + for dep in self.deps.get(module, []): + if not dep in results: + results.add(dep) + traverse(module) + traverse(module) + return results + + def contains_unblocked_modules(self, filename): + for m in self.reverse_makefiles[filename]: + if len(self.deps[m]) == 0: + return True + return False + + def contains_blocked_modules(self, filename): + for m in self.reverse_makefiles[filename]: + if len(self.deps[m]) > 0: + return True + return False + +def count_deps(depsdb, module, seen): + """Based on the depsdb, count the number of transitive dependencies. + + You can pass in an reversed dependency graph to count the number of + modules that depend on the module.""" + count = 0 + seen.append(module) + if module in depsdb: + for dep in depsdb[module]: + if dep in seen: + continue + count += 1 + count_deps(depsdb, dep, seen) + return count + +OTHER_PARTITON = "_other" +HOST_PARTITON = "_host" + +def get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT, filename): + host_prefix = HOST_OUT_ROOT + "/" + device_prefix = PRODUCT_OUT + "/" + + if filename.startswith(host_prefix): + return HOST_PARTITON + + elif filename.startswith(device_prefix): + index = filename.find("/", len(device_prefix)) + if index < 0: + return OTHER_PARTITON + return filename[len(device_prefix):index] + + return OTHER_PARTITON + +def format_module_link(module): + return "<a class='ModuleLink' href='#module_%s'>%s</a>" % (module, module) + +def format_module_list(modules): + return "".join(["<div>%s</div>" % format_module_link(m) for m in modules]) + +def print_analysis_header(link, title): + print(""" + <a name="%(link)s"></a> + <h2>%(title)s</h2> + <table> + <tr> + <th class="RowTitle">Directory</th> + <th class="Count">Total</th> + <th class="Count Clean">Easy</th> + <th class="Count Clean">Unblocked Clean</th> + <th class="Count Unblocked">Unblocked</th> + <th class="Count Blocked">Blocked</th> + <th class="Count Clean">Clean</th> + """ % { + "link": link, + "title": title + }) + for analyzer in ANALYZERS: + print("""<th class="Count Warning">%s</th>""" % analyzer.title) + print(" </tr>") + +def main(): + parser = argparse.ArgumentParser(description="Info about remaining Android.mk files.") + parser.add_argument("--device", type=str, required=True, + help="TARGET_DEVICE") + parser.add_argument("--title", type=str, + help="page title") + parser.add_argument("--codesearch", type=str, + default="https://cs.android.com/android/platform/superproject/+/master:", + help="page title") + parser.add_argument("--out_dir", type=str, + default=None, + help="Equivalent of $OUT_DIR, which will also be checked if" + + " --out_dir is unset. If neither is set, default is" + + " 'out'.") + parser.add_argument("--mode", type=str, + default="html", + help="output format: csv or html") + + args = parser.parse_args() + + # Guess out directory name + if not args.out_dir: + args.out_dir = os.getenv("OUT_DIR", "out") + while args.out_dir.endswith("/") and len(args.out_dir) > 1: + args.out_dir = args.out_dir[:-1] + + TARGET_DEVICE = args.device + global HOST_OUT_ROOT + HOST_OUT_ROOT = args.out_dir + "/host" + global PRODUCT_OUT + PRODUCT_OUT = args.out_dir + "/target/product/%s" % TARGET_DEVICE + + # Read target information + # TODO: Pull from configurable location. This is also slightly different because it's + # only a single build, where as the tree scanning we do below is all Android.mk files. + with open("%s/obj/PACKAGING/soong_conversion_intermediates/soong_conv_data" + % PRODUCT_OUT, "r", errors="ignore") as csvfile: + soong = SoongData(csv.reader(csvfile)) + + # Read the makefiles + all_makefiles = dict() + for filename, modules in soong.reverse_makefiles.items(): + if filename.startswith(args.out_dir + "/"): + continue + all_makefiles[filename] = Makefile(filename) + + if args.mode == "html": + HtmlProcessor(args=args, soong=soong, all_makefiles=all_makefiles).execute() + elif args.mode == "csv": + CsvProcessor(args=args, soong=soong, all_makefiles=all_makefiles).execute() + +class HtmlProcessor(object): + def __init__(self, args, soong, all_makefiles): + self.args = args + self.soong = soong + self.all_makefiles = all_makefiles + self.annotations = Annotations() + + def execute(self): + if self.args.title: + page_title = self.args.title + else: + page_title = "Remaining Android.mk files" + + # Which modules are installed where + modules_by_partition = dict() + partitions = set() + for installed, module in self.soong.installed.items(): + partition = get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT, installed) + modules_by_partition.setdefault(partition, []).append(module) + partitions.add(partition) + + print(""" + <html> + <head> + <title>%(page_title)s</title> + <style type="text/css"> + body, table { + font-family: Roboto, sans-serif; + font-size: 9pt; + } + body { + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + height: 100vh; + } + #container { + flex: 1; + display: flex; + flex-direction: row; + overflow: hidden; + } + #tables { + padding: 0 20px 40px 20px; + overflow: scroll; + flex: 2 2 600px; + } + #details { + display: none; + overflow: scroll; + flex: 1 1 650px; + padding: 0 20px 0 20px; + } + h1 { + margin: 16px 0 16px 20px; + } + h2 { + margin: 12px 0 4px 0; + } + .RowTitle { + text-align: left; + width: 200px; + min-width: 200px; + } + .Count { + text-align: center; + width: 60px; + min-width: 60px; + max-width: 60px; + } + th.Clean, + th.Unblocked { + background-color: #1e8e3e; + } + th.Blocked { + background-color: #d93025; + } + th.Warning { + background-color: #e8710a; + } + th { + background-color: #1a73e8; + color: white; + font-weight: bold; + } + td.Unblocked { + background-color: #81c995; + } + td.Blocked { + background-color: #f28b82; + } + td, th { + padding: 2px 4px; + border-right: 2px solid white; + } + tr.TotalRow td { + background-color: white; + border-right-color: white; + } + tr.AospDir td { + background-color: #e6f4ea; + border-right-color: #e6f4ea; + } + tr.GoogleDir td { + background-color: #e8f0fe; + border-right-color: #e8f0fe; + } + tr.PartnerDir td { + background-color: #fce8e6; + border-right-color: #fce8e6; + } + table { + border-spacing: 0; + border-collapse: collapse; + } + div.Makefile { + margin: 12px 0 0 0; + } + div.Makefile:first { + margin-top: 0; + } + div.FileModules { + padding: 4px 0 0 20px; + } + td.LineNo { + vertical-align: baseline; + padding: 6px 0 0 20px; + width: 50px; + vertical-align: baseline; + } + td.LineText { + vertical-align: baseline; + font-family: monospace; + padding: 6px 0 0 0; + } + a.CsLink { + font-family: monospace; + } + div.Help { + width: 550px; + } + table.HelpColumns tr { + border-bottom: 2px solid white; + } + .ModuleName { + vertical-align: baseline; + padding: 6px 0 0 20px; + width: 275px; + } + .ModuleDeps { + vertical-align: baseline; + padding: 6px 0 0 0; + } + table#Modules td { + vertical-align: baseline; + } + tr.Alt { + background-color: #ececec; + } + tr.Alt td { + border-right-color: #ececec; + } + .AnalysisCol { + width: 300px; + padding: 2px; + line-height: 21px; + } + .Analysis { + color: white; + font-weight: bold; + background-color: #e8710a; + border-radius: 6px; + margin: 4px; + padding: 2px 6px; + white-space: nowrap; + } + .Nav { + margin: 4px 0 16px 20px; + } + .NavSpacer { + display: inline-block; + width: 6px; + } + .ModuleDetails { + margin-top: 20px; + } + .ModuleDetails td { + vertical-align: baseline; + } + </style> + </head> + <body> + <h1>%(page_title)s</h1> + <div class="Nav"> + <a href='#help'>Help</a> + <span class='NavSpacer'></span><span class='NavSpacer'> </span> + Partitions: + """ % { + "page_title": page_title, + }) + for partition in sorted(partitions): + print("<a href='#partition_%s'>%s</a><span class='NavSpacer'></span>" % (partition, partition)) + + print(""" + <span class='NavSpacer'></span><span class='NavSpacer'> </span> + <a href='#summary'>Overall Summary</a> + </div> + <div id="container"> + <div id="tables"> + <a name="help"></a> + <div class="Help"> + <p> + This page analyzes the remaining Android.mk files in the Android Source tree. + <p> + The modules are first broken down by which of the device filesystem partitions + they are installed to. This also includes host tools and testcases which don't + actually reside in their own partition but convenitely group together. + <p> + The makefiles for each partition are further are grouped into a set of directories + aritrarily picked to break down the problem size by owners. + <ul style="width: 300px"> + <li style="background-color: #e6f4ea">AOSP directories are colored green.</li> + <li style="background-color: #e8f0fe">Google directories are colored blue.</li> + <li style="background-color: #fce8e6">Other partner directories are colored red.</li> + </ul> + Each of the makefiles are scanned for issues that are likely to come up during + conversion to soong. Clicking the number in each cell shows additional information, + including the line that triggered the warning. + <p> + <table class="HelpColumns"> + <tr> + <th>Total</th> + <td>The total number of makefiles in this each directory.</td> + </tr> + <tr> + <th class="Clean">Easy</th> + <td>The number of makefiles that have no warnings themselves, and also + none of their dependencies have warnings either.</td> + </tr> + <tr> + <th class="Clean">Unblocked Clean</th> + <td>The number of makefiles that are both Unblocked and Clean.</td> + </tr> + + <tr> + <th class="Unblocked">Unblocked</th> + <td>Makefiles containing one or more modules that don't have any + additional dependencies pending before conversion.</td> + </tr> + <tr> + <th class="Blocked">Blocked</th> + <td>Makefiles containiong one or more modules which <i>do</i> have + additional prerequesite depenedencies that are not yet converted.</td> + </tr> + <tr> + <th class="Clean">Clean</th> + <td>The number of makefiles that have none of the following warnings.</td> + </tr> + <tr> + <th class="Warning">ifeq / ifneq</th> + <td>Makefiles that use <code>ifeq</code> or <code>ifneq</code>. i.e. + conditionals.</td> + </tr> + <tr> + <th class="Warning">Wacky Includes</th> + <td>Makefiles that <code>include</code> files other than the standard build-system + defined template and macros.</td> + </tr> + <tr> + <th class="Warning">Calls base_rules</th> + <td>Makefiles that include base_rules.mk directly.</td> + </tr> + <tr> + <th class="Warning">Calls define</th> + <td>Makefiles that define their own macros. Some of these are easy to convert + to soong <code>defaults</code>, but others are complex.</td> + </tr> + <tr> + <th class="Warning">Has ../</th> + <td>Makefiles containing the string "../" outside of a comment. These likely + access files outside their directories.</td> + </tr> + <tr> + <th class="Warning">dist-for-goals</th> + <td>Makefiles that call <code>dist-for-goals</code> directly.</td> + </tr> + <tr> + <th class="Warning">.PHONY</th> + <td>Makefiles that declare .PHONY targets.</td> + </tr> + <tr> + <th class="Warning">renderscript</th> + <td>Makefiles defining targets that depend on <code>.rscript</code> source files.</td> + </tr> + <tr> + <th class="Warning">vts src</th> + <td>Makefiles defining targets that depend on <code>.vts</code> source files.</td> + </tr> + <tr> + <th class="Warning">COPY_HEADERS</th> + <td>Makefiles using LOCAL_COPY_HEADERS.</td> + </tr> + </table> + <p> + Following the list of directories is a list of the modules that are installed on + each partition. Potential issues from their makefiles are listed, as well as the + total number of dependencies (both blocking that module and blocked by that module) + and the list of direct dependencies. Note: The number is the number of all transitive + dependencies and the list of modules is only the direct dependencies. + </div> + """) + + overall_summary = Summary() + + # For each partition + for partition in sorted(partitions): + modules = modules_by_partition[partition] + + makefiles = set(itertools.chain.from_iterable( + [self.soong.makefiles[module] for module in modules])) + + # Read makefiles + summary = Summary() + for filename in makefiles: + makefile = self.all_makefiles.get(filename) + if makefile: + summary.Add(makefile) + overall_summary.Add(makefile) + + # Categorize directories by who is responsible + aosp_dirs = [] + google_dirs = [] + partner_dirs = [] + for dirname in sorted(summary.directories.keys()): + if is_aosp(dirname): + aosp_dirs.append(dirname) + elif is_google(dirname): + google_dirs.append(dirname) + else: + partner_dirs.append(dirname) + + print_analysis_header("partition_" + partition, partition) + + for dirgroup, rowclass in [(aosp_dirs, "AospDir"), + (google_dirs, "GoogleDir"), + (partner_dirs, "PartnerDir"),]: + for dirname in dirgroup: + self.print_analysis_row(summary, modules, + dirname, rowclass, summary.directories[dirname]) + + self.print_analysis_row(summary, modules, + "Total", "TotalRow", + set(itertools.chain.from_iterable(summary.directories.values()))) + print(""" + </table> + """) + + module_details = [(count_deps(self.soong.deps, m, []), + -count_deps(self.soong.reverse_deps, m, []), m) + for m in modules] + module_details.sort() + module_details = [m[2] for m in module_details] + print(""" + <table class="ModuleDetails">""") + print("<tr>") + print(" <th>Module Name</th>") + print(" <th>Issues</th>") + print(" <th colspan='2'>Blocked By</th>") + print(" <th colspan='2'>Blocking</th>") + print("</tr>") + altRow = True + for module in module_details: + analyses = set() + for filename in self.soong.makefiles[module]: + makefile = summary.makefiles.get(filename) + if makefile: + for analyzer, analysis in makefile.analyses.items(): + if analysis: + analyses.add(analyzer.title) + + altRow = not altRow + print("<tr class='%s'>" % ("Alt" if altRow else "",)) + print(" <td><a name='module_%s'></a>%s</td>" % (module, module)) + print(" <td class='AnalysisCol'>%s</td>" % " ".join(["<span class='Analysis'>%s</span>" % title + for title in analyses])) + print(" <td>%s</td>" % count_deps(self.soong.deps, module, [])) + print(" <td>%s</td>" % format_module_list(self.soong.deps.get(module, []))) + print(" <td>%s</td>" % count_deps(self.soong.reverse_deps, module, [])) + print(" <td>%s</td>" % format_module_list(self.soong.reverse_deps.get(module, []))) + print("</tr>") + print("""</table>""") + + print_analysis_header("summary", "Overall Summary") + + modules = [module for installed, module in self.soong.installed.items()] + self.print_analysis_row(overall_summary, modules, + "All Makefiles", "TotalRow", + set(itertools.chain.from_iterable(overall_summary.directories.values()))) + print(""" + </table> + """) + + print(""" + <script type="text/javascript"> + function close_details() { + document.getElementById('details').style.display = 'none'; + } + + class LineMatch { + constructor(lineno, text) { + this.lineno = lineno; + this.text = text; + } + } + + class Analysis { + constructor(filename, modules, line_matches) { + this.filename = filename; + this.modules = modules; + this.line_matches = line_matches; + } + } + + class Module { + constructor(deps) { + this.deps = deps; + } + } + + function make_module_link(module) { + var a = document.createElement('a'); + a.className = 'ModuleLink'; + a.innerText = module; + a.href = '#module_' + module; + return a; + } + + function update_details(id) { + document.getElementById('details').style.display = 'block'; + + var analyses = ANALYSIS[id]; + + var details = document.getElementById("details_data"); + while (details.firstChild) { + details.removeChild(details.firstChild); + } + + for (var i=0; i<analyses.length; i++) { + var analysis = analyses[i]; + + var makefileDiv = document.createElement('div'); + makefileDiv.className = 'Makefile'; + details.appendChild(makefileDiv); + + var fileA = document.createElement('a'); + makefileDiv.appendChild(fileA); + fileA.className = 'CsLink'; + fileA.href = '%(codesearch)s' + analysis.filename; + fileA.innerText = analysis.filename; + fileA.target = "_blank"; + + if (analysis.modules.length > 0) { + var moduleTable = document.createElement('table'); + details.appendChild(moduleTable); + + for (var j=0; j<analysis.modules.length; j++) { + var moduleRow = document.createElement('tr'); + moduleTable.appendChild(moduleRow); + + var moduleNameCell = document.createElement('td'); + moduleRow.appendChild(moduleNameCell); + moduleNameCell.className = 'ModuleName'; + moduleNameCell.appendChild(make_module_link(analysis.modules[j])); + + var moduleData = MODULE_DATA[analysis.modules[j]]; + console.log(moduleData); + + var depCell = document.createElement('td'); + moduleRow.appendChild(depCell); + + if (moduleData.deps.length == 0) { + depCell.className = 'ModuleDeps Unblocked'; + depCell.innerText = 'UNBLOCKED'; + } else { + depCell.className = 'ModuleDeps Blocked'; + + for (var k=0; k<moduleData.deps.length; k++) { + depCell.appendChild(make_module_link(moduleData.deps[k])); + depCell.appendChild(document.createElement('br')); + } + } + } + } + + if (analysis.line_matches.length > 0) { + var lineTable = document.createElement('table'); + details.appendChild(lineTable); + + for (var j=0; j<analysis.line_matches.length; j++) { + var line_match = analysis.line_matches[j]; + + var lineRow = document.createElement('tr'); + lineTable.appendChild(lineRow); + + var linenoCell = document.createElement('td'); + lineRow.appendChild(linenoCell); + linenoCell.className = 'LineNo'; + + var linenoA = document.createElement('a'); + linenoCell.appendChild(linenoA); + linenoA.className = 'CsLink'; + linenoA.href = '%(codesearch)s' + analysis.filename + + ';l=' + line_match.lineno; + linenoA.innerText = line_match.lineno; + linenoA.target = "_blank"; + + var textCell = document.createElement('td'); + lineRow.appendChild(textCell); + textCell.className = 'LineText'; + textCell.innerText = line_match.text; + } + } + } + } + + var ANALYSIS = [ + """ % { + "codesearch": self.args.codesearch, + }) + for entry, mods in self.annotations.entries: + print(" [") + for analysis in entry: + print(" new Analysis('%(filename)s', %(modules)s, [%(line_matches)s])," % { + "filename": analysis.filename, + #"modules": json.dumps([m for m in mods if m in filename in self.soong.makefiles[m]]), + "modules": json.dumps( + [m for m in self.soong.reverse_makefiles[analysis.filename] if m in mods]), + "line_matches": ", ".join([ + "new LineMatch(%d, %s)" % (lineno, json.dumps(text)) + for lineno, text in analysis.line_matches]), + }) + print(" ],") + print(""" + ]; + var MODULE_DATA = { + """) + for module in self.soong.modules: + print(" '%(name)s': new Module(%(deps)s)," % { + "name": module, + "deps": json.dumps(self.soong.deps[module]), + }) + print(""" + }; + </script> + + """) + + print(""" + </div> <!-- id=tables --> + <div id="details"> + <div style="text-align: right;"> + <a href="javascript:close_details();"> + <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> + </a> + </div> + <div id="details_data"></div> + </div> + </body> + </html> + """) + + def traverse_ready_makefiles(self, summary, makefiles): + return [Analysis(makefile.filename, []) for makefile in makefiles + if clean_and_only_blocked_by_clean(self.soong, self.all_makefiles, makefile)] + + def print_analysis_row(self, summary, modules, rowtitle, rowclass, makefiles): + all_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles] + clean_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles + if is_clean(makefile)] + easy_makefiles = self.traverse_ready_makefiles(summary, makefiles) + unblocked_clean_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles + if (self.soong.contains_unblocked_modules(makefile.filename) + and is_clean(makefile))] + unblocked_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles + if self.soong.contains_unblocked_modules(makefile.filename)] + blocked_makefiles = [Analysis(makefile.filename, []) for makefile in makefiles + if self.soong.contains_blocked_modules(makefile.filename)] + + print(""" + <tr class="%(rowclass)s"> + <td class="RowTitle">%(rowtitle)s</td> + <td class="Count">%(makefiles)s</td> + <td class="Count">%(easy)s</td> + <td class="Count">%(unblocked_clean)s</td> + <td class="Count">%(unblocked)s</td> + <td class="Count">%(blocked)s</td> + <td class="Count">%(clean)s</td> + """ % { + "rowclass": rowclass, + "rowtitle": rowtitle, + "makefiles": self.make_annotation_link(all_makefiles, modules), + "unblocked": self.make_annotation_link(unblocked_makefiles, modules), + "blocked": self.make_annotation_link(blocked_makefiles, modules), + "clean": self.make_annotation_link(clean_makefiles, modules), + "unblocked_clean": self.make_annotation_link(unblocked_clean_makefiles, modules), + "easy": self.make_annotation_link(easy_makefiles, modules), + }) + + for analyzer in ANALYZERS: + analyses = [m.analyses.get(analyzer) for m in makefiles if m.analyses.get(analyzer)] + print("""<td class="Count">%s</td>""" + % self.make_annotation_link(analyses, modules)) + + print(" </tr>") + + def make_annotation_link(self, analysis, modules): + if analysis: + return "<a href='javascript:update_details(%d)'>%s</a>" % ( + self.annotations.Add(analysis, modules), + len(analysis) + ) + else: + return ""; + +class CsvProcessor(object): + def __init__(self, args, soong, all_makefiles): + self.args = args + self.soong = soong + self.all_makefiles = all_makefiles + + def execute(self): + csvout = csv.writer(sys.stdout) + + # Title row + row = ["Filename", "Module", "Partitions", "Easy", "Unblocked Clean", "Unblocked", + "Blocked", "Clean"] + for analyzer in ANALYZERS: + row.append(analyzer.title) + csvout.writerow(row) + + # Makefile & module data + for filename in sorted(self.all_makefiles.keys()): + makefile = self.all_makefiles[filename] + for module in self.soong.reverse_makefiles[filename]: + row = [filename, module] + # Partitions + row.append(";".join(sorted(set([get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT, + installed) + for installed + in self.soong.reverse_installed.get(module, [])])))) + # Easy + row.append(1 + if clean_and_only_blocked_by_clean(self.soong, self.all_makefiles, makefile) + else "") + # Unblocked Clean + row.append(1 + if (self.soong.contains_unblocked_modules(makefile.filename) and is_clean(makefile)) + else "") + # Unblocked + row.append(1 if self.soong.contains_unblocked_modules(makefile.filename) else "") + # Blocked + row.append(1 if self.soong.contains_blocked_modules(makefile.filename) else "") + # Clean + row.append(1 if is_clean(makefile) else "") + # Analysis + for analyzer in ANALYZERS: + row.append(1 if makefile.analyses.get(analyzer) else "") + # Write results + csvout.writerow(row) + +if __name__ == "__main__": + main() + diff --git a/tools/post_process_props.py b/tools/post_process_props.py index 9ddd5d7677..d8c9cb157f 100755 --- a/tools/post_process_props.py +++ b/tools/post_process_props.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright (C) 2009 The Android Open Source Project # @@ -14,131 +14,226 @@ # See the License for the specific language governing permissions and # limitations under the License. +import argparse import sys -# Usage: post_process_props.py file.prop [blacklist_key, ...] -# Blacklisted keys are removed from the property file, if present +# Usage: post_process_props.py file.prop [disallowed_key, ...] +# Disallowed keys are removed from the property file, if present # See PROP_VALUE_MAX in system_properties.h. # The constant in system_properties.h includes the terminating NUL, # so we decrease the value by 1 here. PROP_VALUE_MAX = 91 -# Put the modifications that you need to make into the /system/build.prop into this -# function. The prop object has get(name) and put(name,value) methods. -def mangle_build_prop(prop): - pass - -# Put the modifications that you need to make into /vendor/default.prop and -# /odm/default.prop into this function. The prop object has get(name) and -# put(name,value) methods. -def mangle_default_prop_override(prop): - pass - -# Put the modifications that you need to make into the /system/etc/prop.default into this -# function. The prop object has get(name) and put(name,value) methods. -def mangle_default_prop(prop): +# Put the modifications that you need to make into the */build.prop into this +# function. +def mangle_build_prop(prop_list): # If ro.debuggable is 1, then enable adb on USB by default # (this is for userdebug builds) - if prop.get("ro.debuggable") == "1": - val = prop.get("persist.sys.usb.config") + if prop_list.get_value("ro.debuggable") == "1": + val = prop_list.get_value("persist.sys.usb.config") if "adb" not in val: if val == "": val = "adb" else: val = val + ",adb" - prop.put("persist.sys.usb.config", val) + prop_list.put("persist.sys.usb.config", val) # UsbDeviceManager expects a value here. If it doesn't get it, it will # default to "adb". That might not the right policy there, but it's better # to be explicit. - if not prop.get("persist.sys.usb.config"): - prop.put("persist.sys.usb.config", "none"); + if not prop_list.get_value("persist.sys.usb.config"): + prop_list.put("persist.sys.usb.config", "none"); -def validate(prop): +def validate(prop_list): """Validate the properties. + If the value of a sysprop exceeds the max limit (91), it's an error, unless + the sysprop is a read-only one. + + Checks if there is no optional prop assignments. + Returns: True if nothing is wrong. """ check_pass = True - buildprops = prop.to_dict() - for key, value in buildprops.iteritems(): - # Check build properties' length. - if len(value) > PROP_VALUE_MAX and not key.startswith("ro."): + for p in prop_list.get_all_props(): + if len(p.value) > PROP_VALUE_MAX and not p.name.startswith("ro."): check_pass = False sys.stderr.write("error: %s cannot exceed %d bytes: " % - (key, PROP_VALUE_MAX)) - sys.stderr.write("%s (%d)\n" % (value, len(value))) + (p.name, PROP_VALUE_MAX)) + sys.stderr.write("%s (%d)\n" % (p.value, len(p.value))) + + if p.is_optional(): + check_pass = False + sys.stderr.write("error: found unresolved optional prop assignment:\n") + sys.stderr.write(str(p) + "\n") + return check_pass -class PropFile: +def override_optional_props(prop_list, allow_dup=False): + """Override a?=b with a=c, if the latter exists - def __init__(self, lines): - self.lines = [s.strip() for s in lines] + Overriding is done by deleting a?=b + When there are a?=b and a?=c, then only the last one survives + When there are a=b and a=c, then it's an error. - def to_dict(self): - props = {} - for line in self.lines: - if not line or line.startswith("#"): + Returns: + True if the override was successful + """ + success = True + for name in prop_list.get_all_names(): + props = prop_list.get_props(name) + optional_props = [p for p in props if p.is_optional()] + overriding_props = [p for p in props if not p.is_optional()] + if len(overriding_props) > 1: + # duplicated props are allowed when the all have the same value + if all(overriding_props[0].value == p.value for p in overriding_props): + for p in optional_props: + p.delete("overridden by %s" % str(overriding_props[0])) + continue + # or if dup is explicitly allowed for compat reason + if allow_dup: + # this could left one or more optional props unresolved. + # Convert them into non-optional because init doesn't understand ?= + # syntax + for p in optional_props: + p.optional = False continue - if "=" in line: - key, value = line.split("=", 1) - props[key] = value - return props - - def get(self, name): - key = name + "=" - for line in self.lines: - if line.startswith(key): - return line[len(key):] - return "" - - def put(self, name, value): - key = name + "=" - for i in range(0,len(self.lines)): - if self.lines[i].startswith(key): - self.lines[i] = key + value - return - self.lines.append(key + value) - def delete(self, name): - key = name + "=" - self.lines = [ line for line in self.lines if not line.startswith(key) ] + success = False + sys.stderr.write("error: found duplicate sysprop assignments:\n") + for p in overriding_props: + sys.stderr.write("%s\n" % str(p)) + elif len(overriding_props) == 1: + for p in optional_props: + p.delete("overridden by %s" % str(overriding_props[0])) + else: + if len(optional_props) > 1: + for p in optional_props[:-1]: + p.delete("overridden by %s" % str(optional_props[-1])) + # Make the last optional one as non-optional + optional_props[-1].optional = False + + return success + +class Prop: + + def __init__(self, name, value, optional=False, comment=None): + self.name = name.strip() + self.value = value.strip() + if comment != None: + self.comments = [comment] + else: + self.comments = [] + self.optional = optional + + @staticmethod + def from_line(line): + line = line.rstrip('\n') + if line.startswith("#"): + return Prop("", "", comment=line) + elif "?=" in line: + name, value = line.split("?=", 1) + return Prop(name, value, optional=True) + elif "=" in line: + name, value = line.split("=", 1) + return Prop(name, value, optional=False) + else: + # don't fail on invalid line + # TODO(jiyong) make this a hard error + return Prop("", "", comment=line) + + def is_comment(self): + return bool(self.comments and not self.name) + + def is_optional(self): + return (not self.is_comment()) and self.optional + + def make_as_comment(self): + # Prepend "#" to the last line which is the prop assignment + if not self.is_comment(): + assignment = str(self).rsplit("\n", 1)[-1] + self.comments.append("#" + assignment) + self.name = "" + self.value = "" + + def delete(self, reason): + self.comments.append("# Removed by post_process_props.py because " + reason) + self.make_as_comment() + + def __str__(self): + assignment = [] + if not self.is_comment(): + operator = "?=" if self.is_optional() else "=" + assignment.append(self.name + operator + self.value) + return "\n".join(self.comments + assignment) + +class PropList: + + def __init__(self, filename): + with open(filename) as f: + self.props = [Prop.from_line(l) + for l in f.readlines() if l.strip() != ""] + + def get_all_props(self): + return [p for p in self.props if not p.is_comment()] + + def get_all_names(self): + return set([p.name for p in self.get_all_props()]) + + def get_props(self, name): + return [p for p in self.get_all_props() if p.name == name] + + def get_value(self, name): + # Caution: only the value of the first sysprop having the name is returned. + return next((p.value for p in self.props if p.name == name), "") - def write(self, f): - f.write("\n".join(self.lines)) - f.write("\n") + def put(self, name, value): + # Note: when there is an optional prop for the name, its value isn't changed. + # Instead a new non-optional prop is appended, which will override the + # optional prop. Otherwise, the new value might be overridden by an existing + # non-optional prop of the same name. + index = next((i for i,p in enumerate(self.props) + if p.name == name and not p.is_optional()), -1) + if index == -1: + self.props.append(Prop(name, value, + comment="# Auto-added by post_process_props.py")) + else: + self.props[index].comments.append( + "# Value overridden by post_process_props.py. Original value: %s" % + self.props[index].value) + self.props[index].value = value + + def write(self, filename): + with open(filename, 'w+') as f: + for p in self.props: + f.write(str(p) + "\n") def main(argv): - filename = argv[1] - f = open(filename) - lines = f.readlines() - f.close() - - properties = PropFile(lines) - - if filename.endswith("/build.prop"): - mangle_build_prop(properties) - elif (filename.endswith("/vendor/default.prop") or - filename.endswith("/odm/default.prop")): - mangle_default_prop_override(properties) - elif (filename.endswith("/default.prop") or # legacy - filename.endswith("/prop.default")): - mangle_default_prop(properties) - else: + parser = argparse.ArgumentParser(description="Post-process build.prop file") + parser.add_argument("--allow-dup", dest="allow_dup", action="store_true", + default=False) + parser.add_argument("filename") + parser.add_argument("disallowed_keys", metavar="KEY", type=str, nargs="*") + args = parser.parse_args() + + if not args.filename.endswith("/build.prop"): sys.stderr.write("bad command line: " + str(argv) + "\n") sys.exit(1) - if not validate(properties): + props = PropList(args.filename) + mangle_build_prop(props) + if not override_optional_props(props, args.allow_dup): + sys.exit(1) + if not validate(props): sys.exit(1) - # Drop any blacklisted keys - for key in argv[2:]: - properties.delete(key) + # Drop any disallowed keys + for key in args.disallowed_keys: + for p in props.get_props(key): + p.delete("%s is a disallowed key" % key) - f = open(filename, 'w+') - properties.write(f) - f.close() + props.write(args.filename) if __name__ == "__main__": main(sys.argv) diff --git a/tools/post_process_props_unittest.xml b/tools/post_process_props_unittest.xml new file mode 100644 index 0000000000..4a6ecc2c6a --- /dev/null +++ b/tools/post_process_props_unittest.xml @@ -0,0 +1,6 @@ +<configuration description="Config to run post_process_props_unittest"> + <test class="com.android.tradefed.testtype.python.PythonBinaryHostTest" > + <option name="par-file-name" value="post_process_props_unittest" /> + <option name="test-timeout" value="1m" /> + </test> +</configuration> diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp index 5785688473..45e05142be 100644 --- a/tools/releasetools/Android.bp +++ b/tools/releasetools/Android.bp @@ -49,6 +49,7 @@ python_defaults { required: [ "blk_alloc_to_base_fs", "e2fsck", + "mkuserimg_mke2fs", "simg2img", "tune2fs", ], @@ -73,9 +74,6 @@ python_defaults { "releasetools_build_super_image", "releasetools_common", ], - required: [ - "zip2zip", - ], } python_defaults { @@ -91,14 +89,35 @@ python_defaults { ], } +python_library_host { + name: "ota_metadata_proto", + version: { + py2: { + enabled: true, + }, + py3: { + enabled: true, + }, + }, + srcs: [ + "ota_metadata.proto", + ], + proto: { + canonical_path_from_root: false, + }, +} + python_defaults { name: "releasetools_ota_from_target_files_defaults", srcs: [ "edify_generator.py", + "non_ab_ota.py", "ota_from_target_files.py", + "ota_utils.py", "target_files_diff.py", ], libs: [ + "ota_metadata_proto", "releasetools_check_target_files_vintf", "releasetools_common", "releasetools_verity_utils", @@ -107,6 +126,12 @@ python_defaults { "brillo_update_payload", "checkvintf", ], + target: { + darwin: { + // required module "brillo_update_payload" is disabled on darwin + enabled: false, + }, + }, } // @@ -239,6 +264,18 @@ python_defaults { embedded_launcher: false, }, }, + // TODO (b/140144201) Build imgdiff from releasetools_common + required: [ + "aapt2", + "boot_signer", + "brotli", + "bsdiff", + "imgdiff", + "minigzip", + "lz4", + "mkbootfs", + "signapk", + ], } python_binary_host { @@ -290,6 +327,12 @@ python_binary_host { required: [ "delta_generator", ], + target: { + darwin: { + // required module "delta_generator" is disabled on darwin + enabled: false, + }, + }, } python_binary_host { @@ -362,6 +405,12 @@ python_binary_host { required: [ "checkvintf", ], + target: { + darwin: { + // libs dep "releasetools_ota_from_target_files" is disabled on darwin + enabled: false, + }, + }, } python_binary_host { @@ -459,9 +508,12 @@ python_defaults { data: [ "testdata/**/*", ], - required: [ - "otatools", - ], + target: { + darwin: { + // libs dep "releasetools_ota_from_target_files" is disabled on darwin + enabled: false, + }, + }, } python_test_host { diff --git a/tools/releasetools/OWNERS b/tools/releasetools/OWNERS index a8295d45b0..d7fc540807 100644 --- a/tools/releasetools/OWNERS +++ b/tools/releasetools/OWNERS @@ -1,3 +1,4 @@ +elsk@google.com nhdo@google.com xunchang@google.com zhaojiac@google.com diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py index f58b6978a8..a1f8e31b87 100644 --- a/tools/releasetools/add_img_to_target_files.py +++ b/tools/releasetools/add_img_to_target_files.py @@ -281,6 +281,37 @@ def AddOdm(output_zip): return img.name +def AddVendorDlkm(output_zip): + """Turn the contents of VENDOR_DLKM into an vendor_dlkm image and store it in output_zip.""" + + img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor_dlkm.img") + if os.path.exists(img.name): + logger.info("vendor_dlkm.img already exists; no need to rebuild...") + return img.name + + block_list = OutputFile( + output_zip, OPTIONS.input_tmp, "IMAGES", "vendor_dlkm.map") + CreateImage( + OPTIONS.input_tmp, OPTIONS.info_dict, "vendor_dlkm", img, + block_list=block_list) + return img.name + +def AddOdmDlkm(output_zip): + """Turn the contents of OdmDlkm into an odm_dlkm image and store it in output_zip.""" + + img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "odm_dlkm.img") + if os.path.exists(img.name): + logger.info("odm_dlkm.img already exists; no need to rebuild...") + return img.name + + block_list = OutputFile( + output_zip, OPTIONS.input_tmp, "IMAGES", "odm_dlkm.map") + CreateImage( + OPTIONS.input_tmp, OPTIONS.info_dict, "odm_dlkm", img, + block_list=block_list) + return img.name + + def AddDtbo(output_zip): """Adds the DTBO image. @@ -736,28 +767,51 @@ def AddImagesToTargetFiles(filename): has_boot = OPTIONS.info_dict.get("no_boot") != "true" has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true" - # {vendor,odm,product,system_ext}.img are unlike system.img or - # system_other.img. Because it could be built from source, or dropped into + # {vendor,odm,product,system_ext,vendor_dlkm,odm_dlkm}.img + # are unlike system.img or + # system_other.img, because it could be built from source, or dropped into # target_files.zip as a prebuilt blob. We consider either of them as # {vendor,product,system_ext}.img being available, which could be # used when generating vbmeta.img for AVB. - has_vendor = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "VENDOR")) or - os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES", - "vendor.img"))) - has_odm = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "ODM")) or - os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES", - "odm.img"))) - has_product = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "PRODUCT")) or - os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES", - "product.img"))) - has_system_ext = (os.path.isdir(os.path.join(OPTIONS.input_tmp, - "SYSTEM_EXT")) or - os.path.exists(os.path.join(OPTIONS.input_tmp, - "IMAGES", - "system_ext.img"))) - has_system = os.path.isdir(os.path.join(OPTIONS.input_tmp, "SYSTEM")) - has_system_other = os.path.isdir(os.path.join(OPTIONS.input_tmp, - "SYSTEM_OTHER")) + has_vendor = ((os.path.isdir(os.path.join(OPTIONS.input_tmp, "VENDOR")) and + OPTIONS.info_dict.get("building_vendor_image") == "true") or + os.path.exists( + os.path.join(OPTIONS.input_tmp, "IMAGES", "vendor.img"))) + has_odm = ((os.path.isdir(os.path.join(OPTIONS.input_tmp, "ODM")) and + OPTIONS.info_dict.get("building_odm_image") == "true") or + os.path.exists( + os.path.join(OPTIONS.input_tmp, "IMAGES", "odm.img"))) + has_vendor_dlkm = ((os.path.isdir(os.path.join(OPTIONS.input_tmp, + "VENDOR_DLKM")) and + OPTIONS.info_dict.get("building_vendor_dlkm_image") + == "true") or + os.path.exists( + os.path.join(OPTIONS.input_tmp, "IMAGES", + "vendor_dlkm.img"))) + has_odm_dlkm = ((os.path.isdir(os.path.join(OPTIONS.input_tmp, + "ODM_DLKM")) and + OPTIONS.info_dict.get("building_odm_dlkm_image") + == "true") or + os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES", + "odm_dlkm.img"))) + has_product = ((os.path.isdir(os.path.join(OPTIONS.input_tmp, "PRODUCT")) and + OPTIONS.info_dict.get("building_product_image") == "true") or + os.path.exists( + os.path.join(OPTIONS.input_tmp, "IMAGES", "product.img"))) + has_system_ext = ( + (os.path.isdir(os.path.join(OPTIONS.input_tmp, "SYSTEM_EXT")) and + OPTIONS.info_dict.get("building_system_ext_image") == "true") or + os.path.exists( + os.path.join(OPTIONS.input_tmp, "IMAGES", "system_ext.img"))) + has_system = ( + os.path.isdir(os.path.join(OPTIONS.input_tmp, "SYSTEM")) and + OPTIONS.info_dict.get("building_system_image") == "true") + + has_system_other = ( + os.path.isdir(os.path.join(OPTIONS.input_tmp, "SYSTEM_OTHER")) and + OPTIONS.info_dict.get("building_system_other_image") == "true") + has_userdata = OPTIONS.info_dict.get("building_userdata_image") == "true" + has_cache = OPTIONS.info_dict.get("building_cache_image") == "true" # Set up the output destination. It writes to the given directory for dir # mode; otherwise appends to the given ZIP. @@ -865,6 +919,14 @@ def AddImagesToTargetFiles(filename): banner("odm") partitions['odm'] = AddOdm(output_zip) + if has_vendor_dlkm: + banner("vendor_dlkm") + partitions['vendor_dlkm'] = AddVendorDlkm(output_zip) + + if has_odm_dlkm: + banner("odm_dlkm") + partitions['odm_dlkm'] = AddOdmDlkm(output_zip) + if has_system_other: banner("system_other") AddSystemOther(output_zip) diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py index 1c61938048..8783f25b46 100644 --- a/tools/releasetools/apex_utils.py +++ b/tools/releasetools/apex_utils.py @@ -51,6 +51,8 @@ class ApexApkSigner(object): self.apex_path = apex_path self.key_passwords = key_passwords self.codename_to_api_level_map = codename_to_api_level_map + self.debugfs_path = os.path.join( + OPTIONS.search_path, "bin", "debugfs_static") def ProcessApexFile(self, apk_keys, payload_key, signing_args=None): """Scans and signs the apk files and repack the apex @@ -61,7 +63,13 @@ class ApexApkSigner(object): Returns: The repacked apex file containing the signed apk files. """ - list_cmd = ['deapexer', 'list', self.apex_path] + if not os.path.exists(self.debugfs_path): + raise ApexSigningError( + "Couldn't find location of debugfs_static: " + + "Path {} does not exist. ".format(debugfs_path) + + "Make sure bin/debugfs_static can be found in -p <path>") + list_cmd = ['deapexer', '--debugfs_path', + self.debugfs_path, 'list', self.apex_path] entries_names = common.RunAndCheckOutput(list_cmd).split() apk_entries = [name for name in entries_names if name.endswith('.apk')] @@ -91,8 +99,14 @@ class ApexApkSigner(object): def ExtractApexPayloadAndSignApks(self, apk_entries, apk_keys): """Extracts the payload image and signs the containing apk files.""" + if not os.path.exists(self.debugfs_path): + raise ApexSigningError( + "Couldn't find location of debugfs_static: " + + "Path {} does not exist. ".format(debugfs_path) + + "Make sure bin/debugfs_static can be found in -p <path>") payload_dir = common.MakeTempDir() - extract_cmd = ['deapexer', 'extract', self.apex_path, payload_dir] + extract_cmd = ['deapexer', '--debugfs_path', + self.debugfs_path, 'extract', self.apex_path, payload_dir] common.RunAndCheckOutput(extract_cmd) has_signed_apk = False @@ -149,7 +163,8 @@ class ApexApkSigner(object): # Add quote to the signing_args as we will pass # --signing_args "--signing_helper_with_files=%path" to apexer if signing_args: - generate_image_cmd.extend(['--signing_args', '"{}"'.format(signing_args)]) + generate_image_cmd.extend( + ['--signing_args', '"{}"'.format(signing_args)]) # optional arguments for apex repacking manifest_json = os.path.join(apex_dir, 'apex_manifest.json') @@ -273,7 +288,7 @@ def ParseApexPayloadInfo(avbtool, payload_path): else: payload_info[key] = value - # Sanity check. + # Validation check. for key in ('Algorithm', 'Salt', 'apex.key', 'Hash Algorithm'): if key not in payload_info: raise ApexInfoError( diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py index 8b6a6900d5..d33c2f79d5 100644 --- a/tools/releasetools/blockimgdiff.py +++ b/tools/releasetools/blockimgdiff.py @@ -521,7 +521,7 @@ class BlockImageDiff(object): stashed_blocks -= free_size if common.OPTIONS.cache_size is not None: - # Sanity check: abort if we're going to need more stash space than + # Validation check: abort if we're going to need more stash space than # the allowed size (cache_size * threshold). There are two purposes # of having a threshold here. a) Part of the cache may have been # occupied by some recovery logs. b) It will buy us some time to deal diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py index 8cf074147e..9cc072fe0f 100755 --- a/tools/releasetools/build_image.py +++ b/tools/releasetools/build_image.py @@ -57,7 +57,7 @@ def GetDiskUsage(path): Returns: The number of bytes based on a 1K block_size. """ - cmd = ["du", "-k", "-s", path] + cmd = ["du", "-b", "-k", "-s", path] output = common.RunAndCheckOutput(cmd, verbose=False) return int(output.split()[0]) * 1024 @@ -708,6 +708,52 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): d["extfs_rsv_pct"] = "0" copy_prop("odm_reserved_size", "partition_reserved_size") copy_prop("odm_selinux_fc", "selinux_fc") + elif mount_point == "vendor_dlkm": + copy_prop("avb_vendor_dlkm_hashtree_enable", "avb_hashtree_enable") + copy_prop("avb_vendor_dlkm_add_hashtree_footer_args", + "avb_add_hashtree_footer_args") + copy_prop("avb_vendor_dlkm_key_path", "avb_key_path") + copy_prop("avb_vendor_dlkm_algorithm", "avb_algorithm") + copy_prop("avb_vendor_dlkm_salt", "avb_salt") + copy_prop("vendor_dlkm_fs_type", "fs_type") + copy_prop("vendor_dlkm_size", "partition_size") + if not copy_prop("vendor_dlkm_journal_size", "journal_size"): + d["journal_size"] = "0" + copy_prop("vendor_dlkm_verity_block_device", "verity_block_device") + copy_prop("ext4_share_dup_blocks", "ext4_share_dup_blocks") + copy_prop("vendor_dlkm_squashfs_compressor", "squashfs_compressor") + copy_prop("vendor_dlkm_squashfs_compressor_opt", "squashfs_compressor_opt") + copy_prop("vendor_dlkm_squashfs_block_size", "squashfs_block_size") + copy_prop("vendor_dlkm_squashfs_disable_4k_align", "squashfs_disable_4k_align") + copy_prop("vendor_dlkm_base_fs_file", "base_fs_file") + copy_prop("vendor_dlkm_extfs_inode_count", "extfs_inode_count") + if not copy_prop("vendor_dlkm_extfs_rsv_pct", "extfs_rsv_pct"): + d["extfs_rsv_pct"] = "0" + copy_prop("vendor_dlkm_reserved_size", "partition_reserved_size") + copy_prop("vendor_dlkm_selinux_fc", "selinux_fc") + elif mount_point == "odm_dlkm": + copy_prop("avb_odm_dlkm_hashtree_enable", "avb_hashtree_enable") + copy_prop("avb_odm_dlkm_add_hashtree_footer_args", + "avb_add_hashtree_footer_args") + copy_prop("avb_odm_dlkm_key_path", "avb_key_path") + copy_prop("avb_odm_dlkm_algorithm", "avb_algorithm") + copy_prop("avb_odm_dlkm_salt", "avb_salt") + copy_prop("odm_dlkm_fs_type", "fs_type") + copy_prop("odm_dlkm_size", "partition_size") + if not copy_prop("odm_dlkm_journal_size", "journal_size"): + d["journal_size"] = "0" + copy_prop("odm_dlkm_verity_block_device", "verity_block_device") + copy_prop("ext4_share_dup_blocks", "ext4_share_dup_blocks") + copy_prop("odm_dlkm_squashfs_compressor", "squashfs_compressor") + copy_prop("odm_dlkm_squashfs_compressor_opt", "squashfs_compressor_opt") + copy_prop("odm_dlkm_squashfs_block_size", "squashfs_block_size") + copy_prop("odm_dlkm_squashfs_disable_4k_align", "squashfs_disable_4k_align") + copy_prop("odm_dlkm_base_fs_file", "base_fs_file") + copy_prop("odm_dlkm_extfs_inode_count", "extfs_inode_count") + if not copy_prop("odm_dlkm_extfs_rsv_pct", "extfs_rsv_pct"): + d["extfs_rsv_pct"] = "0" + copy_prop("odm_dlkm_reserved_size", "partition_reserved_size") + copy_prop("odm_dlkm_selinux_fc", "selinux_fc") elif mount_point == "oem": copy_prop("fs_type", "fs_type") copy_prop("oem_size", "partition_size") @@ -752,6 +798,10 @@ def GlobalDictFromImageProp(image_prop, mount_point): copy_prop("partition_size", "vendor_size") elif mount_point == "odm": copy_prop("partition_size", "odm_size") + elif mount_point == "vendor_dlkm": + copy_prop("partition_size", "vendor_dlkm_size") + elif mount_point == "odm_dlkm": + copy_prop("partition_size", "odm_dlkm_size") elif mount_point == "product": copy_prop("partition_size", "product_size") elif mount_point == "system_ext": @@ -791,6 +841,10 @@ def main(argv): mount_point = "vendor" elif image_filename == "odm.img": mount_point = "odm" + elif image_filename == "vendor_dlkm.img": + mount_point = "vendor_dlkm" + elif image_filename == "odm_dlkm.img": + mount_point = "odm_dlkm" elif image_filename == "oem.img": mount_point = "oem" elif image_filename == "product.img": diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py index 8c1bb9a6ed..6e02e4d6f5 100755 --- a/tools/releasetools/check_target_files_signatures.py +++ b/tools/releasetools/check_target_files_signatures.py @@ -120,19 +120,18 @@ class CertDB(object): def __init__(self): self.certs = {} - def Add(self, cert, name=None): - if cert in self.certs: + def Add(self, cert_digest, subject, name=None): + if cert_digest in self.certs: if name: - self.certs[cert] = self.certs[cert] + "," + name + self.certs[cert_digest] = self.certs[cert_digest] + "," + name else: if name is None: - name = "unknown cert %s (%s)" % (common.sha1(cert).hexdigest()[:12], - GetCertSubject(cert)) - self.certs[cert] = name + name = "unknown cert %s (%s)" % (cert_digest[:12], subject) + self.certs[cert_digest] = name - def Get(self, cert): - """Return the name for a given cert.""" - return self.certs.get(cert, None) + def Get(self, cert_digest): + """Return the name for a given cert digest.""" + return self.certs.get(cert_digest, None) def FindLocalCerts(self): to_load = [] @@ -148,7 +147,10 @@ class CertDB(object): cert = common.ParseCertificate(f.read()) name, _ = os.path.splitext(i) name, _ = os.path.splitext(name) - self.Add(cert, name) + + cert_sha1 = common.sha1(cert).hexdigest() + cert_subject = GetCertSubject(cert) + self.Add(cert_sha1, cert_subject, name) ALL_CERTS = CertDB() @@ -184,7 +186,7 @@ class APK(object): def __init__(self, full_filename, filename): self.filename = filename - self.certs = None + self.cert_digests = frozenset() self.shared_uid = None self.package = None @@ -195,22 +197,68 @@ class APK(object): finally: Pop() - def RecordCerts(self, full_filename): - out = set() + def ReadCertsDeprecated(self, full_filename): + print("reading certs in deprecated way for {}".format(full_filename)) + cert_digests = set() with zipfile.ZipFile(full_filename) as apk: - pkcs7 = None for info in apk.infolist(): filename = info.filename if (filename.startswith("META-INF/") and info.filename.endswith((".DSA", ".RSA"))): pkcs7 = apk.read(filename) cert = CertFromPKCS7(pkcs7, filename) - out.add(cert) - ALL_CERTS.Add(cert) - if not pkcs7: - AddProblem("no signature") + if not cert: + continue + cert_sha1 = common.sha1(cert).hexdigest() + cert_subject = GetCertSubject(cert) + ALL_CERTS.Add(cert_sha1, cert_subject) + cert_digests.add(cert_sha1) + if not cert_digests: + AddProblem("No signature found") + return + self.cert_digests = frozenset(cert_digests) - self.certs = frozenset(out) + def RecordCerts(self, full_filename): + """Parse and save the signature of an apk file.""" + + # Dump the cert info with apksigner + cmd = ["apksigner", "verify", "--print-certs", full_filename] + p = common.Run(cmd, stdout=subprocess.PIPE) + output, _ = p.communicate() + if p.returncode != 0: + self.ReadCertsDeprecated(full_filename) + return + + # Sample output: + # Signer #1 certificate DN: ... + # Signer #1 certificate SHA-256 digest: ... + # Signer #1 certificate SHA-1 digest: ... + # ... + certs_info = {} + certificate_regex = re.compile(r"(Signer #[0-9]+) (certificate .*):(.*)") + for line in output.splitlines(): + m = certificate_regex.match(line) + if not m: + continue + signer, key, val = m.group(1), m.group(2), m.group(3) + if certs_info.get(signer): + certs_info[signer].update({key.strip(): val.strip()}) + else: + certs_info.update({signer: {key.strip(): val.strip()}}) + if not certs_info: + AddProblem("Failed to parse cert info") + return + + cert_digests = set() + for signer, props in certs_info.items(): + subject = props.get("certificate DN") + digest = props.get("certificate SHA-1 digest") + if not subject or not digest: + AddProblem("Failed to parse cert subject or digest") + return + ALL_CERTS.Add(digest, subject) + cert_digests.add(digest) + self.cert_digests = frozenset(cert_digests) def ReadManifest(self, full_filename): p = common.Run(["aapt2", "dump", "xmltree", full_filename, "--file", @@ -316,8 +364,8 @@ class TargetFiles(object): print("uid %s is shared by packages with different cert sets:" % (uid,)) for apk in apks: print("%-*s [%s]" % (self.max_pkg_len, apk.package, apk.filename)) - for cert in apk.certs: - print(" ", ALL_CERTS.Get(cert)) + for digest in apk.cert_digests: + print(" ", ALL_CERTS.Get(digest)) print() def CheckExternalSignatures(self): @@ -328,25 +376,30 @@ class TargetFiles(object): # predexopting. Consider it an error if this app is now # signed with any key that is present in our tree. apk = self.apks_by_basename[apk_filename] - name = ALL_CERTS.Get(apk.cert) - if not name.startswith("unknown "): + signed_with_external = False + for digest in apk.cert_digests: + name = ALL_CERTS.Get(digest) + if name and name.startswith("unknown "): + signed_with_external = True + + if not signed_with_external: Push(apk.filename) AddProblem("hasn't been signed with EXTERNAL cert") Pop() def PrintCerts(self): """Display a table of packages grouped by cert.""" - by_cert = {} + by_digest = {} for apk in self.apks.values(): - for cert in apk.certs: - by_cert.setdefault(cert, []).append((apk.package, apk)) + for digest in apk.cert_digests: + by_digest.setdefault(digest, []).append((apk.package, apk)) - order = [(-len(v), k) for (k, v) in by_cert.items()] + order = [(-len(v), k) for (k, v) in by_digest.items()] order.sort() - for _, cert in order: - print("%s:" % (ALL_CERTS.Get(cert),)) - apks = by_cert[cert] + for _, digest in order: + print("%s:" % (ALL_CERTS.Get(digest),)) + apks = by_digest[digest] apks.sort() for _, apk in apks: if apk.shared_uid: @@ -366,15 +419,15 @@ class TargetFiles(object): max_pkg_len = max(self.max_pkg_len, other.max_pkg_len) - by_certpair = {} + by_digestpair = {} for i in all_apks: if i in self.apks: if i in other.apks: # in both; should have same set of certs - if self.apks[i].certs != other.apks[i].certs: - by_certpair.setdefault((other.apks[i].certs, - self.apks[i].certs), []).append(i) + if self.apks[i].cert_digests != other.apks[i].cert_digests: + by_digestpair.setdefault((other.apks[i].cert_digests, + self.apks[i].cert_digests), []).append(i) else: print("%s [%s]: new APK (not in comparison target_files)" % ( i, self.apks[i].filename)) @@ -383,10 +436,10 @@ class TargetFiles(object): print("%s [%s]: removed APK (only in comparison target_files)" % ( i, other.apks[i].filename)) - if by_certpair: + if by_digestpair: AddProblem("some APKs changed certs") Banner("APK signing differences") - for (old, new), packages in sorted(by_certpair.items()): + for (old, new), packages in sorted(by_digestpair.items()): for i, o in enumerate(old): if i == 0: print("was", ALL_CERTS.Get(o)) diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py index 95d09cc177..0edefac9c1 100755 --- a/tools/releasetools/check_target_files_vintf.py +++ b/tools/releasetools/check_target_files_vintf.py @@ -46,6 +46,7 @@ DIR_SEARCH_PATHS = { '/product': ('PRODUCT', 'SYSTEM/product'), '/odm': ('ODM', 'VENDOR/odm', 'SYSTEM/vendor/odm'), '/system_ext': ('SYSTEM_EXT', 'SYSTEM/system_ext'), + # vendor_dlkm and odm_dlkm does not have VINTF files. } UNZIP_PATTERN = ['META/*', '*/build.prop'] @@ -219,6 +220,52 @@ def CheckVintf(inp, info_dict=None): raise ValueError('{} is not a valid directory or zip file'.format(inp)) +def CheckVintfIfTrebleEnabled(target_files, target_info): + """Checks compatibility info of the input target files. + + Metadata used for compatibility verification is retrieved from target_zip. + + Compatibility should only be checked for devices that have enabled + Treble support. + + Args: + target_files: Path to zip file containing the source files to be included + for OTA. Can also be the path to extracted directory. + target_info: The BuildInfo instance that holds the target build info. + """ + + # Will only proceed if the target has enabled the Treble support (as well as + # having a /vendor partition). + if not HasTrebleEnabled(target_files, target_info): + return + + # Skip adding the compatibility package as a workaround for b/114240221. The + # compatibility will always fail on devices without qualified kernels. + if OPTIONS.skip_compatibility_check: + return + + if not CheckVintf(target_files, target_info): + raise RuntimeError("VINTF compatibility check failed") + +def HasTrebleEnabled(target_files, target_info): + def HasVendorPartition(target_files): + if os.path.isdir(target_files): + return os.path.isdir(os.path.join(target_files, "VENDOR")) + if zipfile.is_zipfile(target_files): + return HasPartition(zipfile.ZipFile(target_files), "vendor") + raise ValueError("Unknown target_files argument") + + return (HasVendorPartition(target_files) and + target_info.GetBuildProp("ro.treble.enabled") == "true") + + +def HasPartition(target_files_zip, partition): + try: + target_files_zip.getinfo(partition.upper() + "/") + return True + except KeyError: + return False + def main(argv): args = common.ParseOptions(argv, __doc__) diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index ae7da2fb64..c77d8c68d5 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -17,6 +17,7 @@ from __future__ import print_function import base64 import collections import copy +import datetime import errno import fnmatch import getopt @@ -53,16 +54,17 @@ class Options(object): # running this function, user-supplied search path (`--path`) hasn't been # available. So the value set here is the default, which might be overridden # by commandline flag later. - exec_path = sys.argv[0] + exec_path = os.path.realpath(sys.argv[0]) if exec_path.endswith('.py'): script_name = os.path.basename(exec_path) # logger hasn't been initialized yet at this point. Use print to output # warnings. print( 'Warning: releasetools script should be invoked as hermetic Python ' - 'executable -- build and run `{}` directly.'.format(script_name[:-3]), + 'executable -- build and run `{}` directly.'.format( + script_name[:-3]), file=sys.stderr) - self.search_path = os.path.realpath(os.path.join(os.path.dirname(exec_path), '..')) + self.search_path = os.path.dirname(os.path.dirname(exec_path)) self.signapk_path = "framework/signapk.jar" # Relative to search_path self.signapk_shared_library_path = "lib64" # Relative to search_path @@ -77,6 +79,7 @@ class Options(object): self.boot_signer_args = [] self.verity_signer_path = None self.verity_signer_args = [] + self.aftl_tool_path = None self.aftl_server = None self.aftl_key_path = None self.aftl_manufacturer_key_path = None @@ -93,6 +96,7 @@ class Options(object): self.cache_size = None self.stash_threshold = 0.8 self.logfile = None + self.host_tools = {} OPTIONS = Options() @@ -107,13 +111,22 @@ SPECIAL_CERT_STRINGS = ("PRESIGNED", "EXTERNAL") # that system_other is not in the list because we don't want to include its # descriptor into vbmeta.img. AVB_PARTITIONS = ('boot', 'dtbo', 'odm', 'product', 'recovery', 'system', - 'system_ext', 'vendor', 'vendor_boot') + 'system_ext', 'vendor', 'vendor_boot', 'vendor_dlkm', + 'odm_dlkm') # Chained VBMeta partitions. AVB_VBMETA_PARTITIONS = ('vbmeta_system', 'vbmeta_vendor') # Partitions that should have their care_map added to META/care_map.pb -PARTITIONS_WITH_CARE_MAP = ('system', 'vendor', 'product', 'system_ext', 'odm') +PARTITIONS_WITH_CARE_MAP = [ + 'system', + 'vendor', + 'product', + 'system_ext', + 'odm', + 'vendor_dlkm', + 'odm_dlkm', +] class ErrorCode(object): @@ -190,17 +203,21 @@ def InitLogging(): if OPTIONS.logfile: config = copy.deepcopy(config) config['handlers']['logfile'] = { - 'class': 'logging.FileHandler', - 'formatter': 'standard', - 'level': 'INFO', - 'mode': 'w', - 'filename': OPTIONS.logfile, + 'class': 'logging.FileHandler', + 'formatter': 'standard', + 'level': 'INFO', + 'mode': 'w', + 'filename': OPTIONS.logfile, } config['loggers']['']['handlers'].append('logfile') logging.config.dictConfig(config) +def SetHostToolLocation(tool_name, location): + OPTIONS.host_tools[tool_name] = location + + def Run(args, verbose=None, **kwargs): """Creates and returns a subprocess.Popen object. @@ -222,8 +239,16 @@ def Run(args, verbose=None, **kwargs): kwargs['stderr'] = subprocess.STDOUT if 'universal_newlines' not in kwargs: kwargs['universal_newlines'] = True + + # If explicitly set host tool location before, use that location to avoid + # PATH violation. Make a copy of args in case client relies on the content + # of args later. + if args and args[0] in OPTIONS.host_tools: + args = args[:] + args[0] = OPTIONS.host_tools[args[0]] + # Don't log any if caller explicitly says so. - if verbose != False: + if verbose: logger.info(" Running: \"%s\"", " ".join(args)) return subprocess.Popen(args, **kwargs) @@ -273,7 +298,7 @@ def RunAndCheckOutput(args, verbose=None, **kwargs): if output is None: output = "" # Don't log any if caller explicitly says so. - if verbose != False: + if verbose: logger.info("%s", output.rstrip()) if proc.returncode != 0: raise ExternalError( @@ -374,7 +399,6 @@ class BuildInfo(object): 'Invalid build fingerprint: "{}". See the requirement in Android CDD ' "3.2.2. Build Parameters.".format(fingerprint)) - self._partition_fingerprints = {} for partition in PARTITIONS_WITH_CARE_MAP: try: @@ -521,7 +545,8 @@ class BuildInfo(object): self.GetPartitionBuildProp("ro.product.device", partition), self.GetPartitionBuildProp("ro.build.version.release", partition), self.GetPartitionBuildProp("ro.build.id", partition), - self.GetPartitionBuildProp("ro.build.version.incremental", partition), + self.GetPartitionBuildProp( + "ro.build.version.incremental", partition), self.GetPartitionBuildProp("ro.build.type", partition), self.GetPartitionBuildProp("ro.build.tags", partition)) @@ -589,7 +614,7 @@ def ReadFromInputFile(input_file, fn): def LoadInfoDict(input_file, repacking=False): """Loads the key/value pairs from the given input target_files. - It reads `META/misc_info.txt` file in the target_files input, does sanity + It reads `META/misc_info.txt` file in the target_files input, does validation checks and returns the parsed key/value pairs for to the given build. It's usually called early when working on input target_files files, e.g. when generating OTAs, or signing builds. Note that the function may be called @@ -652,7 +677,8 @@ def LoadInfoDict(input_file, repacking=False): input_file, "META", "root_filesystem_config.txt") # Redirect {partition}_base_fs_file for each of the named partitions. - for part_name in ["system", "vendor", "system_ext", "product", "odm"]: + for part_name in ["system", "vendor", "system_ext", "product", "odm", + "vendor_dlkm", "odm_dlkm"]: key_name = part_name + "_base_fs_file" if key_name not in d: continue @@ -682,7 +708,7 @@ def LoadInfoDict(input_file, repacking=False): if "boot_images" in d: boot_images = d["boot_images"] for b in boot_images.split(): - makeint(b.replace(".img","_size")) + makeint(b.replace(".img", "_size")) # Load recovery fstab if applicable. d["fstab"] = _FindAndLoadRecoveryFstab(d, input_file, read_helper) @@ -702,11 +728,15 @@ def LoadInfoDict(input_file, repacking=False): for partition in PARTITIONS_WITH_CARE_MAP: fingerprint = build_info.GetPartitionFingerprint(partition) if fingerprint: - d["avb_{}_salt".format(partition)] = sha256(fingerprint).hexdigest() - + d["avb_{}_salt".format(partition)] = sha256(fingerprint.encode()).hexdigest() + try: + d["ab_partitions"] = read_helper("META/ab_partitions.txt").split("\n") + except KeyError: + logger.warning("Can't find META/ab_partitions.txt") return d + def LoadListFromFile(file_path): with open(file_path) as f: return f.read().splitlines() @@ -748,6 +778,7 @@ class PartitionBuildProps(object): placeholders in the build.prop file. We expect exactly one value for each of the variables. """ + def __init__(self, input_file, name, placeholder_values=None): self.input_file = input_file self.partition = name @@ -807,7 +838,7 @@ class PartitionBuildProps(object): """Parses the build prop in a given import statement.""" tokens = line.split() - if tokens[0] != 'import' or (len(tokens) != 2 and len(tokens) != 3) : + if tokens[0] != 'import' or (len(tokens) != 2 and len(tokens) != 3): raise ValueError('Unrecognized import statement {}'.format(line)) if len(tokens) == 3: @@ -997,9 +1028,9 @@ def MergeDynamicPartitionInfoDicts(framework_dict, vendor_dict): # Pick virtual ab related flags from vendor dict, if defined. if "virtual_ab" in vendor_dict.keys(): - merged_dict["virtual_ab"] = vendor_dict["virtual_ab"] + merged_dict["virtual_ab"] = vendor_dict["virtual_ab"] if "virtual_ab_retrofit" in vendor_dict.keys(): - merged_dict["virtual_ab_retrofit"] = vendor_dict["virtual_ab_retrofit"] + merged_dict["virtual_ab_retrofit"] = vendor_dict["virtual_ab_retrofit"] return merged_dict @@ -1082,6 +1113,46 @@ def GetAvbChainedPartitionArg(partition, info_dict, key=None): return "{}:{}:{}".format(partition, rollback_index_location, pubkey_path) +def ConstructAftlMakeImageCommands(output_image): + """Constructs the command to append the aftl image to vbmeta.""" + + # Ensure the other AFTL parameters are set as well. + assert OPTIONS.aftl_tool_path is not None, 'No aftl tool provided.' + assert OPTIONS.aftl_key_path is not None, 'No AFTL key provided.' + assert OPTIONS.aftl_manufacturer_key_path is not None, \ + 'No AFTL manufacturer key provided.' + + vbmeta_image = MakeTempFile() + os.rename(output_image, vbmeta_image) + build_info = BuildInfo(OPTIONS.info_dict) + version_incremental = build_info.GetBuildProp("ro.build.version.incremental") + aftltool = OPTIONS.aftl_tool_path + server_argument_list = [OPTIONS.aftl_server, OPTIONS.aftl_key_path] + aftl_cmd = [aftltool, "make_icp_from_vbmeta", + "--vbmeta_image_path", vbmeta_image, + "--output", output_image, + "--version_incremental", version_incremental, + "--transparency_log_servers", ','.join(server_argument_list), + "--manufacturer_key", OPTIONS.aftl_manufacturer_key_path, + "--algorithm", "SHA256_RSA4096", + "--padding", "4096"] + if OPTIONS.aftl_signer_helper: + aftl_cmd.extend(shlex.split(OPTIONS.aftl_signer_helper)) + return aftl_cmd + + +def AddAftlInclusionProof(output_image): + """Appends the aftl inclusion proof to the vbmeta image.""" + + aftl_cmd = ConstructAftlMakeImageCommands(output_image) + RunAndCheckOutput(aftl_cmd) + + verify_cmd = ['aftltool', 'verify_image_icp', '--vbmeta_image_path', + output_image, '--transparency_log_pub_keys', + OPTIONS.aftl_key_path] + RunAndCheckOutput(verify_cmd) + + def BuildVBMeta(image_path, partitions, name, needed_partitions): """Creates a VBMeta image. @@ -1123,34 +1194,32 @@ def BuildVBMeta(image_path, partitions, name, needed_partitions): if args and args.strip(): split_args = shlex.split(args) for index, arg in enumerate(split_args[:-1]): - # Sanity check that the image file exists. Some images might be defined + # Check that the image file exists. Some images might be defined # as a path relative to source tree, which may not be available at the # same location when running this script (we have the input target_files # zip only). For such cases, we additionally scan other locations (e.g. # IMAGES/, RADIO/, etc) before bailing out. if arg == '--include_descriptors_from_image': - image_path = split_args[index + 1] - if os.path.exists(image_path): + chained_image = split_args[index + 1] + if os.path.exists(chained_image): continue found = False for dir_name in ['IMAGES', 'RADIO', 'PREBUILT_IMAGES']: alt_path = os.path.join( - OPTIONS.input_tmp, dir_name, os.path.basename(image_path)) + OPTIONS.input_tmp, dir_name, os.path.basename(chained_image)) if os.path.exists(alt_path): split_args[index + 1] = alt_path found = True break - assert found, 'Failed to find {}'.format(image_path) + assert found, 'Failed to find {}'.format(chained_image) cmd.extend(split_args) RunAndCheckOutput(cmd) + # Generate the AFTL inclusion proof. if OPTIONS.aftl_server is not None: - # Ensure the other AFTL parameters are set as well. - assert OPTIONS.aftl_key_path is not None, 'No AFTL key provided.' - assert OPTIONS.aftl_manufacturer_key_path is not None, 'No AFTL manufacturer key provided.' - assert OPTIONS.aftl_signer_helper is not None, 'No AFTL signer helper provided.' - # AFTL inclusion proof generation code will go here. + AddAftlInclusionProof(image_path) + def _MakeRamdisk(sourcedir, fs_config_file=None, lz4_ramdisks=False): ramdisk_img = tempfile.NamedTemporaryFile() @@ -1162,7 +1231,7 @@ def _MakeRamdisk(sourcedir, fs_config_file=None, lz4_ramdisks=False): cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")] p1 = Run(cmd, stdout=subprocess.PIPE) if lz4_ramdisks: - p2 = Run(["lz4", "-l", "-12" , "--favor-decSpeed"], stdin=p1.stdout, + p2 = Run(["lz4", "-l", "-12", "--favor-decSpeed"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno()) else: p2 = Run(["minigzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno()) @@ -1195,7 +1264,7 @@ def _BuildBootableImage(image_name, sourcedir, fs_config_file, info_dict=None, kernel = "kernel" else: kernel = image_name.replace("boot", "kernel") - kernel = kernel.replace(".img","") + kernel = kernel.replace(".img", "") if not os.access(os.path.join(sourcedir, kernel), os.F_OK): return None @@ -1319,7 +1388,7 @@ def _BuildBootableImage(image_name, sourcedir, fs_config_file, info_dict=None, if partition_name == "recovery": part_size = info_dict["recovery_size"] else: - part_size = info_dict[image_name.replace(".img","_size")] + part_size = info_dict[image_name.replace(".img", "_size")] cmd = [avbtool, "add_hash_footer", "--image", img.name, "--partition_size", str(part_size), "--partition_name", partition_name] @@ -1472,7 +1541,8 @@ def GetVendorBootImage(name, prebuilt_name, unpack_dir, tree_subdir, if info_dict is None: info_dict = OPTIONS.info_dict - data = _BuildVendorBootImage(os.path.join(unpack_dir, tree_subdir), info_dict) + data = _BuildVendorBootImage( + os.path.join(unpack_dir, tree_subdir), info_dict) if data: return File(name, data) return None @@ -1481,7 +1551,7 @@ def GetVendorBootImage(name, prebuilt_name, unpack_dir, tree_subdir, def Gunzip(in_filename, out_filename): """Gunzips the given gzip compressed file to a given output file.""" with gzip.open(in_filename, "rb") as in_file, \ - open(out_filename, "wb") as out_file: + open(out_filename, "wb") as out_file: shutil.copyfileobj(in_file, out_file) @@ -1583,8 +1653,7 @@ def GetUserImage(which, tmpdir, input_zip, if reset_file_map: img.ResetFileMap() return img - else: - return GetNonSparseImage(which, tmpdir, hashtree_info_generator) + return GetNonSparseImage(which, tmpdir, hashtree_info_generator) def GetNonSparseImage(which, tmpdir, hashtree_info_generator=None): @@ -1783,10 +1852,9 @@ def GetMinSdkVersionInt(apk_name, codename_to_api_level_map): # Not a decimal number. Codename? if version in codename_to_api_level_map: return codename_to_api_level_map[version] - else: - raise ExternalError( - "Unknown minSdkVersion: '{}'. Known codenames: {}".format( - version, codename_to_api_level_map)) + raise ExternalError( + "Unknown minSdkVersion: '{}'. Known codenames: {}".format( + version, codename_to_api_level_map)) def SignFile(input_name, output_name, key, password, min_api_level=None, @@ -1891,7 +1959,8 @@ def CheckSize(data, target, info_dict): msg = "%s size (%d) is %.2f%% of limit (%d)" % (target, size, pct, limit) if pct >= 99.0: raise ExternalError(msg) - elif pct >= 95.0: + + if pct >= 95.0: logger.warning("\n WARNING: %s\n", msg) else: logger.info(" %s", msg) @@ -2001,6 +2070,7 @@ Global options Put verbose logs to specified file (regardless of --verbose option.) """ + def Usage(docstring): print(docstring.rstrip("\n")) print(COMMON_DOCSTRING) @@ -2024,9 +2094,9 @@ def ParseOptions(argv, "java_path=", "java_args=", "android_jar_path=", "public_key_suffix=", "private_key_suffix=", "boot_signer_path=", "boot_signer_args=", "verity_signer_path=", "verity_signer_args=", "device_specific=", - "extra=", "logfile=", "aftl_server=", "aftl_key_path=", - "aftl_manufacturer_key_path=", "aftl_signer_helper="] + - list(extra_long_opts)) + "extra=", "logfile=", "aftl_tool_path=", "aftl_server=", + "aftl_key_path=", "aftl_manufacturer_key_path=", + "aftl_signer_helper="] + list(extra_long_opts)) except getopt.GetoptError as err: Usage(docstring) print("**", str(err), "**") @@ -2064,6 +2134,8 @@ def ParseOptions(argv, OPTIONS.verity_signer_path = a elif o in ("--verity_signer_args",): OPTIONS.verity_signer_args = shlex.split(a) + elif o in ("--aftl_tool_path",): + OPTIONS.aftl_tool_path = a elif o in ("--aftl_server",): OPTIONS.aftl_server = a elif o in ("--aftl_key_path",): @@ -2161,7 +2233,7 @@ class PasswordManager(object): current = self.UpdateAndReadFile(current) - def PromptResult(self, current): # pylint: disable=no-self-use + def PromptResult(self, current): # pylint: disable=no-self-use """Prompt the user to enter a value (password) for each key in 'current' whose value is fales. Returns a new dict with all the values. @@ -2224,7 +2296,6 @@ class PasswordManager(object): def ZipWrite(zip_file, filename, arcname=None, perms=0o644, compress_type=None): - import datetime # http://b/18015246 # Python 2.7's zipfile implementation wrongly thinks that zip64 is required @@ -2350,6 +2421,7 @@ def ZipClose(zip_file): class DeviceSpecificParams(object): module = None + def __init__(self, **kwargs): """Keyword arguments to the constructor become attributes of this object, which is passed to all functions in the device-specific @@ -2478,12 +2550,12 @@ class File(object): DIFF_PROGRAM_BY_EXT = { - ".gz" : "imgdiff", - ".zip" : ["imgdiff", "-z"], - ".jar" : ["imgdiff", "-z"], - ".apk" : ["imgdiff", "-z"], - ".img" : "imgdiff", - } + ".gz": "imgdiff", + ".zip": ["imgdiff", "-z"], + ".jar": ["imgdiff", "-z"], + ".apk": ["imgdiff", "-z"], + ".img": "imgdiff", +} class Difference(object): @@ -2522,6 +2594,7 @@ class Difference(object): cmd.append(ptemp.name) p = Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) err = [] + def run(): _, e = p.communicate() if e: @@ -2550,7 +2623,6 @@ class Difference(object): self.patch = diff return self.tf, self.sf, self.patch - def GetPatch(self): """Returns a tuple of (target_file, source_file, patch_data). @@ -2861,7 +2933,7 @@ class BlockDifference(object): new_data_name=new_data_name, code=code)) script.AppendExtra(script.WordWrap(call)) - def _HashBlocks(self, source, ranges): # pylint: disable=no-self-use + def _HashBlocks(self, source, ranges): # pylint: disable=no-self-use data = source.ReadRangeSet(ranges) ctx = sha1() @@ -2870,7 +2942,7 @@ class BlockDifference(object): return ctx.hexdigest() - def _HashZeroBlocks(self, num_blocks): # pylint: disable=no-self-use + def _HashZeroBlocks(self, num_blocks): # pylint: disable=no-self-use """Return the hash value for all zero blocks.""" zero_block = '\x00' * 4096 ctx = sha1() @@ -2893,6 +2965,7 @@ PARTITION_TYPES = { "squashfs": "EMMC" } + def GetTypeAndDevice(mount_point, info, check_no_slot=True): """ Use GetTypeAndDeviceExpr whenever possible. This function is kept for @@ -2903,11 +2976,10 @@ def GetTypeAndDevice(mount_point, info, check_no_slot=True): if fstab: if check_no_slot: assert not fstab[mount_point].slotselect, \ - "Use GetTypeAndDeviceExpr instead" + "Use GetTypeAndDeviceExpr instead" return (PARTITION_TYPES[fstab[mount_point].fs_type], fstab[mount_point].device) - else: - raise KeyError + raise KeyError def GetTypeAndDeviceExpr(mount_point, info): @@ -2922,8 +2994,7 @@ def GetTypeAndDeviceExpr(mount_point, info): if p.slotselect: device_expr = 'add_slot_suffix(%s)' % device_expr return (PARTITION_TYPES[fstab[mount_point].fs_type], device_expr) - else: - raise KeyError + raise KeyError def GetEntryForDevice(fstab, device): @@ -2938,6 +3009,7 @@ def GetEntryForDevice(fstab, device): return fstab[mount_point] return None + def ParseCertificate(data): """Parses and converts a PEM-encoded certificate into DER-encoded. @@ -3264,7 +3336,7 @@ class DynamicPartitionsDifference(object): for p, u in self._partition_updates.items(): if u.src_size and u.tgt_size and u.src_size > u.tgt_size: u.block_difference.WritePostInstallVerifyScript(script) - script.AppendExtra('unmap_partition("%s");' % p) # ignore errors + script.AppendExtra('unmap_partition("%s");' % p) # ignore errors for p, u in self._partition_updates.items(): if u.tgt_size and u.src_size <= u.tgt_size: @@ -3272,7 +3344,7 @@ class DynamicPartitionsDifference(object): u.block_difference.WriteScript(script, output_zip, progress=u.progress, write_verify_script=write_verify_script) if write_verify_script: - script.AppendExtra('unmap_partition("%s");' % p) # ignore errors + script.AppendExtra('unmap_partition("%s");' % p) # ignore errors script.Comment('--- End patching dynamic partitions ---') @@ -3329,7 +3401,8 @@ class DynamicPartitionsDifference(object): for p, u in self._partition_updates.items(): if u.tgt_size and u.src_size < u.tgt_size: - comment('Grow partition %s from %d to %d' % (p, u.src_size, u.tgt_size)) + comment('Grow partition %s from %d to %d' % + (p, u.src_size, u.tgt_size)) append('resize %s %d' % (p, u.tgt_size)) for p, u in self._partition_updates.items(): diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py index b9c9b197b3..033c02e60c 100644 --- a/tools/releasetools/edify_generator.py +++ b/tools/releasetools/edify_generator.py @@ -301,7 +301,7 @@ class EdifyGenerator(object): len(patchpairs) == 2), \ "Failed to handle unknown format. Use PatchPartition() instead." - # Also sanity check the args. + # Also validity check the args. assert tokens[3] == patchpairs[0], \ "Found mismatching values for source SHA-1: {} vs {}".format( tokens[3], patchpairs[0]) diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py index ab38d0d7f8..54091941ce 100755 --- a/tools/releasetools/img_from_target_files.py +++ b/tools/releasetools/img_from_target_files.py @@ -58,6 +58,7 @@ OPTIONS = common.OPTIONS OPTIONS.additional_entries = [] OPTIONS.bootable_only = False OPTIONS.put_super = None +OPTIONS.put_bootloader = None OPTIONS.dynamic_partition_list = None OPTIONS.super_device_list = None OPTIONS.retrofit_dap = None @@ -75,6 +76,7 @@ def LoadOptions(input_file): info = OPTIONS.info_dict = common.LoadInfoDict(input_zip) OPTIONS.put_super = info.get('super_image_in_update_package') == 'true' + OPTIONS.put_bootloader = info.get('bootloader_in_update_package') == 'true' OPTIONS.dynamic_partition_list = info.get('dynamic_partition_list', '').strip().split() OPTIONS.super_device_list = info.get('super_block_devices', @@ -122,9 +124,11 @@ def EntriesForUserImages(input_file): for image_path in [name for name in namelist if name.startswith('IMAGES/')]: image = os.path.basename(image_path) - if OPTIONS.bootable_only and image not in ('boot.img', 'recovery.img'): + if OPTIONS.bootable_only and image not in('boot.img', 'recovery.img', 'bootloader'): continue - if not image.endswith('.img'): + if not image.endswith('.img') and image != 'bootloader': + continue + if image == 'bootloader' and not OPTIONS.put_bootloader: continue # Filter out super_empty and the images that are already in super partition. if OPTIONS.put_super: diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py index dd7806bde0..45532f50d0 100755 --- a/tools/releasetools/merge_target_files.py +++ b/tools/releasetools/merge_target_files.py @@ -95,6 +95,8 @@ import ota_from_target_files logger = logging.getLogger(__name__) OPTIONS = common.OPTIONS +# Always turn on verbose logging. +OPTIONS.verbose = True OPTIONS.framework_target_files = None OPTIONS.framework_item_list = None OPTIONS.framework_misc_info_keys = None @@ -173,6 +175,9 @@ DEFAULT_FRAMEWORK_MISC_INFO_KEYS = ( 'ab_update', 'default_system_dev_certificate', 'system_size', + 'building_system_image', + 'building_system_ext_image', + 'building_product_image', ) # DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial @@ -192,6 +197,8 @@ DEFAULT_VENDOR_ITEM_LIST = ( 'PREBUILT_IMAGES/*', 'RADIO/*', 'VENDOR/*', + 'VENDOR_DLKM/*', + 'ODM_DLKM/*', ) # VENDOR_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the @@ -218,6 +225,8 @@ SINGLE_BUILD_PARTITIONS = ( 'SYSTEM/', 'SYSTEM_OTHER/', 'VENDOR/', + 'VENDOR_DLKM/', + 'ODM_DLKM/', ) @@ -1109,9 +1118,6 @@ def main(): common.Usage(__doc__) sys.exit(1) - # Always turn on verbose logging. - OPTIONS.verbose = True - if OPTIONS.framework_item_list: framework_item_list = common.LoadListFromFile(OPTIONS.framework_item_list) else: diff --git a/tools/releasetools/non_ab_ota.py b/tools/releasetools/non_ab_ota.py new file mode 100644 index 0000000000..471ef252a3 --- /dev/null +++ b/tools/releasetools/non_ab_ota.py @@ -0,0 +1,684 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import collections +import logging +import os +import zipfile + +import common +import edify_generator +import verity_utils +from check_target_files_vintf import CheckVintfIfTrebleEnabled, HasPartition +from common import OPTIONS +from ota_utils import UNZIP_PATTERN, FinalizeMetadata, GetPackageMetadata, PropertyFiles + +logger = logging.getLogger(__name__) + + +def GetBlockDifferences(target_zip, source_zip, target_info, source_info, + device_specific): + """Returns a ordered dict of block differences with partition name as key.""" + + def GetIncrementalBlockDifferenceForPartition(name): + if not HasPartition(source_zip, name): + raise RuntimeError( + "can't generate incremental that adds {}".format(name)) + + partition_src = common.GetUserImage(name, OPTIONS.source_tmp, source_zip, + info_dict=source_info, + allow_shared_blocks=allow_shared_blocks) + + hashtree_info_generator = verity_utils.CreateHashtreeInfoGenerator( + name, 4096, target_info) + partition_tgt = common.GetUserImage(name, OPTIONS.target_tmp, target_zip, + info_dict=target_info, + allow_shared_blocks=allow_shared_blocks, + hashtree_info_generator=hashtree_info_generator) + + # Check the first block of the source system partition for remount R/W only + # if the filesystem is ext4. + partition_source_info = source_info["fstab"]["/" + name] + check_first_block = partition_source_info.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). + partition_target_info = target_info["fstab"]["/" + name] + disable_imgdiff = (partition_source_info.fs_type == "squashfs" or + partition_target_info.fs_type == "squashfs") + return common.BlockDifference(name, partition_tgt, partition_src, + check_first_block, + version=blockimgdiff_version, + disable_imgdiff=disable_imgdiff) + + if source_zip: + # See notes in common.GetUserImage() + allow_shared_blocks = (source_info.get('ext4_share_dup_blocks') == "true" or + target_info.get('ext4_share_dup_blocks') == "true") + blockimgdiff_version = max( + int(i) for i in target_info.get( + "blockimgdiff_versions", "1").split(",")) + assert blockimgdiff_version >= 3 + + block_diff_dict = collections.OrderedDict() + partition_names = ["system", "vendor", "product", "odm", "system_ext", + "vendor_dlkm", "odm_dlkm"] + for partition in partition_names: + if not HasPartition(target_zip, partition): + continue + # Full OTA update. + if not source_zip: + tgt = common.GetUserImage(partition, OPTIONS.input_tmp, target_zip, + info_dict=target_info, + reset_file_map=True) + block_diff_dict[partition] = common.BlockDifference(partition, tgt, + src=None) + # Incremental OTA update. + else: + block_diff_dict[partition] = GetIncrementalBlockDifferenceForPartition( + partition) + assert "system" in block_diff_dict + + # Get the block diffs from the device specific script. If there is a + # duplicate block diff for a partition, ignore the diff in the generic script + # and use the one in the device specific script instead. + if source_zip: + device_specific_diffs = device_specific.IncrementalOTA_GetBlockDifferences() + function_name = "IncrementalOTA_GetBlockDifferences" + else: + device_specific_diffs = device_specific.FullOTA_GetBlockDifferences() + function_name = "FullOTA_GetBlockDifferences" + + if device_specific_diffs: + assert all(isinstance(diff, common.BlockDifference) + for diff in device_specific_diffs), \ + "{} is not returning a list of BlockDifference objects".format( + function_name) + for diff in device_specific_diffs: + if diff.partition in block_diff_dict: + logger.warning("Duplicate block difference found. Device specific block" + " diff for partition '%s' overrides the one in generic" + " script.", diff.partition) + block_diff_dict[diff.partition] = diff + + return block_diff_dict + + +def WriteFullOTAPackage(input_zip, output_file): + target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts) + + # We don't know what version it will be installed on top of. We expect the API + # just won't change very often. Similarly for fstab, it might have changed in + # the target build. + target_api_version = target_info["recovery_api_version"] + script = edify_generator.EdifyGenerator(target_api_version, target_info) + + if target_info.oem_props and not OPTIONS.oem_no_mount: + target_info.WriteMountOemScript(script) + + metadata = GetPackageMetadata(target_info) + + if not OPTIONS.no_signing: + staging_file = common.MakeTempFile(suffix='.zip') + else: + staging_file = output_file + + output_zip = zipfile.ZipFile( + staging_file, "w", compression=zipfile.ZIP_DEFLATED) + + device_specific = common.DeviceSpecificParams( + input_zip=input_zip, + input_version=target_api_version, + output_zip=output_zip, + script=script, + input_tmp=OPTIONS.input_tmp, + metadata=metadata, + info_dict=OPTIONS.info_dict) + + assert HasRecoveryPatch(input_zip, info_dict=OPTIONS.info_dict) + + # Assertions (e.g. downgrade check, device properties check). + ts = target_info.GetBuildProp("ro.build.date.utc") + ts_text = target_info.GetBuildProp("ro.build.date") + script.AssertOlderBuild(ts, ts_text) + + target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount) + device_specific.FullOTA_Assertions() + + block_diff_dict = GetBlockDifferences(target_zip=input_zip, source_zip=None, + target_info=target_info, + source_info=None, + device_specific=device_specific) + + # Two-step package strategy (in chronological order, which is *not* + # the order in which the generated script has things): + # + # if stage is not "2/3" or "3/3": + # write recovery image to boot partition + # set stage to "2/3" + # reboot to boot partition and restart recovery + # else if stage is "2/3": + # write recovery image to recovery partition + # set stage to "3/3" + # reboot to recovery partition and restart recovery + # else: + # (stage must be "3/3") + # set stage to "" + # do normal full package installation: + # wipe and install system, boot image, etc. + # set up system to update recovery partition on first boot + # complete script normally + # (allow recovery to mark itself finished and reboot) + + recovery_img = common.GetBootableImage("recovery.img", "recovery.img", + OPTIONS.input_tmp, "RECOVERY") + if OPTIONS.two_step: + if not target_info.get("multistage_support"): + assert False, "two-step packages not supported by this build" + fs = target_info["fstab"]["/misc"] + assert fs.fs_type.upper() == "EMMC", \ + "two-step packages only supported on devices with EMMC /misc partitions" + bcb_dev = {"bcb_dev": fs.device} + common.ZipWriteStr(output_zip, "recovery.img", recovery_img.data) + script.AppendExtra(""" +if get_stage("%(bcb_dev)s") == "2/3" then +""" % bcb_dev) + + # Stage 2/3: Write recovery image to /recovery (currently running /boot). + script.Comment("Stage 2/3") + script.WriteRawImage("/recovery", "recovery.img") + script.AppendExtra(""" +set_stage("%(bcb_dev)s", "3/3"); +reboot_now("%(bcb_dev)s", "recovery"); +else if get_stage("%(bcb_dev)s") == "3/3" then +""" % bcb_dev) + + # Stage 3/3: Make changes. + script.Comment("Stage 3/3") + + # Dump fingerprints + script.Print("Target: {}".format(target_info.fingerprint)) + + device_specific.FullOTA_InstallBegin() + + # All other partitions as well as the data wipe use 10% of the progress, and + # the update of the system partition takes the remaining progress. + system_progress = 0.9 - (len(block_diff_dict) - 1) * 0.1 + if OPTIONS.wipe_user_data: + system_progress -= 0.1 + progress_dict = {partition: 0.1 for partition in block_diff_dict} + progress_dict["system"] = system_progress + + if target_info.get('use_dynamic_partitions') == "true": + # Use empty source_info_dict to indicate that all partitions / groups must + # be re-added. + dynamic_partitions_diff = common.DynamicPartitionsDifference( + info_dict=OPTIONS.info_dict, + block_diffs=block_diff_dict.values(), + progress_dict=progress_dict) + dynamic_partitions_diff.WriteScript(script, output_zip, + write_verify_script=OPTIONS.verify) + else: + for block_diff in block_diff_dict.values(): + block_diff.WriteScript(script, output_zip, + progress=progress_dict.get(block_diff.partition), + write_verify_script=OPTIONS.verify) + + CheckVintfIfTrebleEnabled(OPTIONS.input_tmp, target_info) + + boot_img = common.GetBootableImage( + "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") + common.CheckSize(boot_img.data, "boot.img", target_info) + common.ZipWriteStr(output_zip, "boot.img", boot_img.data) + + script.WriteRawImage("/boot", "boot.img") + + script.ShowProgress(0.1, 10) + device_specific.FullOTA_InstallEnd() + + if OPTIONS.extra_script is not None: + script.AppendExtra(OPTIONS.extra_script) + + script.UnmountAll() + + if OPTIONS.wipe_user_data: + script.ShowProgress(0.1, 10) + script.FormatPartition("/data") + + if OPTIONS.two_step: + script.AppendExtra(""" +set_stage("%(bcb_dev)s", ""); +""" % bcb_dev) + script.AppendExtra("else\n") + + # Stage 1/3: Nothing to verify for full OTA. Write recovery image to /boot. + script.Comment("Stage 1/3") + _WriteRecoveryImageToBoot(script, output_zip) + + script.AppendExtra(""" +set_stage("%(bcb_dev)s", "2/3"); +reboot_now("%(bcb_dev)s", ""); +endif; +endif; +""" % bcb_dev) + + script.SetProgress(1) + script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) + metadata.required_cache = script.required_cache + + # We haven't written the metadata entry, which will be done in + # FinalizeMetadata. + common.ZipClose(output_zip) + + needed_property_files = ( + NonAbOtaPropertyFiles(), + ) + FinalizeMetadata(metadata, staging_file, output_file, needed_property_files) + + +def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file): + target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts) + source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts) + + target_api_version = target_info["recovery_api_version"] + source_api_version = source_info["recovery_api_version"] + if source_api_version == 0: + logger.warning( + "Generating edify script for a source that can't install it.") + + script = edify_generator.EdifyGenerator( + source_api_version, target_info, fstab=source_info["fstab"]) + + if target_info.oem_props or source_info.oem_props: + if not OPTIONS.oem_no_mount: + source_info.WriteMountOemScript(script) + + metadata = GetPackageMetadata(target_info, source_info) + + if not OPTIONS.no_signing: + staging_file = common.MakeTempFile(suffix='.zip') + else: + staging_file = output_file + + output_zip = zipfile.ZipFile( + staging_file, "w", compression=zipfile.ZIP_DEFLATED) + + device_specific = common.DeviceSpecificParams( + source_zip=source_zip, + source_version=source_api_version, + source_tmp=OPTIONS.source_tmp, + target_zip=target_zip, + target_version=target_api_version, + target_tmp=OPTIONS.target_tmp, + output_zip=output_zip, + script=script, + metadata=metadata, + info_dict=source_info) + + source_boot = common.GetBootableImage( + "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", source_info) + target_boot = common.GetBootableImage( + "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT", target_info) + updating_boot = (not OPTIONS.two_step and + (source_boot.data != target_boot.data)) + + target_recovery = common.GetBootableImage( + "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") + + block_diff_dict = GetBlockDifferences(target_zip=target_zip, + source_zip=source_zip, + target_info=target_info, + source_info=source_info, + device_specific=device_specific) + + CheckVintfIfTrebleEnabled(OPTIONS.target_tmp, target_info) + + # Assertions (e.g. device properties check). + target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount) + device_specific.IncrementalOTA_Assertions() + + # Two-step incremental package strategy (in chronological order, + # which is *not* the order in which the generated script has + # things): + # + # if stage is not "2/3" or "3/3": + # do verification on current system + # write recovery image to boot partition + # set stage to "2/3" + # reboot to boot partition and restart recovery + # else if stage is "2/3": + # write recovery image to recovery partition + # set stage to "3/3" + # reboot to recovery partition and restart recovery + # else: + # (stage must be "3/3") + # perform update: + # patch system files, etc. + # force full install of new boot image + # set up system to update recovery partition on first boot + # complete script normally + # (allow recovery to mark itself finished and reboot) + + if OPTIONS.two_step: + if not source_info.get("multistage_support"): + assert False, "two-step packages not supported by this build" + fs = source_info["fstab"]["/misc"] + assert fs.fs_type.upper() == "EMMC", \ + "two-step packages only supported on devices with EMMC /misc partitions" + bcb_dev = {"bcb_dev": fs.device} + common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data) + script.AppendExtra(""" +if get_stage("%(bcb_dev)s") == "2/3" then +""" % bcb_dev) + + # Stage 2/3: Write recovery image to /recovery (currently running /boot). + script.Comment("Stage 2/3") + script.AppendExtra("sleep(20);\n") + script.WriteRawImage("/recovery", "recovery.img") + script.AppendExtra(""" +set_stage("%(bcb_dev)s", "3/3"); +reboot_now("%(bcb_dev)s", "recovery"); +else if get_stage("%(bcb_dev)s") != "3/3" then +""" % bcb_dev) + + # Stage 1/3: (a) Verify the current system. + script.Comment("Stage 1/3") + + # Dump fingerprints + script.Print("Source: {}".format(source_info.fingerprint)) + script.Print("Target: {}".format(target_info.fingerprint)) + + script.Print("Verifying current system...") + + device_specific.IncrementalOTA_VerifyBegin() + + WriteFingerprintAssertion(script, target_info, source_info) + + # Check the required cache size (i.e. stashed blocks). + required_cache_sizes = [diff.required_cache for diff in + block_diff_dict.values()] + if updating_boot: + boot_type, boot_device_expr = common.GetTypeAndDeviceExpr("/boot", + source_info) + d = common.Difference(target_boot, source_boot) + _, _, d = d.ComputePatch() + if d is None: + include_full_boot = True + common.ZipWriteStr(output_zip, "boot.img", target_boot.data) + else: + include_full_boot = False + + logger.info( + "boot target: %d source: %d diff: %d", target_boot.size, + source_boot.size, len(d)) + + common.ZipWriteStr(output_zip, "boot.img.p", d) + + target_expr = 'concat("{}:",{},":{}:{}")'.format( + boot_type, boot_device_expr, target_boot.size, target_boot.sha1) + source_expr = 'concat("{}:",{},":{}:{}")'.format( + boot_type, boot_device_expr, source_boot.size, source_boot.sha1) + script.PatchPartitionExprCheck(target_expr, source_expr) + + required_cache_sizes.append(target_boot.size) + + if required_cache_sizes: + script.CacheFreeSpaceCheck(max(required_cache_sizes)) + + # Verify the existing partitions. + for diff in block_diff_dict.values(): + diff.WriteVerifyScript(script, touched_blocks_only=True) + + device_specific.IncrementalOTA_VerifyEnd() + + if OPTIONS.two_step: + # Stage 1/3: (b) Write recovery image to /boot. + _WriteRecoveryImageToBoot(script, output_zip) + + script.AppendExtra(""" +set_stage("%(bcb_dev)s", "2/3"); +reboot_now("%(bcb_dev)s", ""); +else +""" % bcb_dev) + + # Stage 3/3: Make changes. + script.Comment("Stage 3/3") + + script.Comment("---- start making changes here ----") + + device_specific.IncrementalOTA_InstallBegin() + + progress_dict = {partition: 0.1 for partition in block_diff_dict} + progress_dict["system"] = 1 - len(block_diff_dict) * 0.1 + + if OPTIONS.source_info_dict.get("use_dynamic_partitions") == "true": + if OPTIONS.target_info_dict.get("use_dynamic_partitions") != "true": + raise RuntimeError( + "can't generate incremental that disables dynamic partitions") + dynamic_partitions_diff = common.DynamicPartitionsDifference( + info_dict=OPTIONS.target_info_dict, + source_info_dict=OPTIONS.source_info_dict, + block_diffs=block_diff_dict.values(), + progress_dict=progress_dict) + dynamic_partitions_diff.WriteScript( + script, output_zip, write_verify_script=OPTIONS.verify) + else: + for block_diff in block_diff_dict.values(): + block_diff.WriteScript(script, output_zip, + progress=progress_dict.get(block_diff.partition), + write_verify_script=OPTIONS.verify) + + if OPTIONS.two_step: + common.ZipWriteStr(output_zip, "boot.img", target_boot.data) + script.WriteRawImage("/boot", "boot.img") + logger.info("writing full boot image (forced by two-step mode)") + + if not OPTIONS.two_step: + if updating_boot: + if include_full_boot: + logger.info("boot image changed; including full.") + script.Print("Installing boot image...") + script.WriteRawImage("/boot", "boot.img") + else: + # Produce the boot image by applying a patch to the current + # contents of the boot partition, and write it back to the + # partition. + logger.info("boot image changed; including patch.") + script.Print("Patching boot image...") + script.ShowProgress(0.1, 10) + target_expr = 'concat("{}:",{},":{}:{}")'.format( + boot_type, boot_device_expr, target_boot.size, target_boot.sha1) + source_expr = 'concat("{}:",{},":{}:{}")'.format( + boot_type, boot_device_expr, source_boot.size, source_boot.sha1) + script.PatchPartitionExpr(target_expr, source_expr, '"boot.img.p"') + else: + logger.info("boot image unchanged; skipping.") + + # Do device-specific installation (eg, write radio image). + device_specific.IncrementalOTA_InstallEnd() + + if OPTIONS.extra_script is not None: + script.AppendExtra(OPTIONS.extra_script) + + if OPTIONS.wipe_user_data: + script.Print("Erasing user data...") + script.FormatPartition("/data") + + if OPTIONS.two_step: + script.AppendExtra(""" +set_stage("%(bcb_dev)s", ""); +endif; +endif; +""" % bcb_dev) + + script.SetProgress(1) + # For downgrade OTAs, we prefer to use the update-binary in the source + # build that is actually newer than the one in the target build. + if OPTIONS.downgrade: + script.AddToZip(source_zip, output_zip, input_path=OPTIONS.updater_binary) + else: + script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) + metadata.required_cache = script.required_cache + + # We haven't written the metadata entry yet, which will be handled in + # FinalizeMetadata(). + common.ZipClose(output_zip) + + # Sign the generated zip package unless no_signing is specified. + needed_property_files = ( + NonAbOtaPropertyFiles(), + ) + FinalizeMetadata(metadata, staging_file, output_file, needed_property_files) + + +def GenerateNonAbOtaPackage(target_file, output_file, source_file=None): + """Generates a non-A/B OTA package.""" + # Check the loaded info dicts first. + if OPTIONS.info_dict.get("no_recovery") == "true": + raise common.ExternalError( + "--- target build has specified no recovery ---") + + # Non-A/B OTAs rely on /cache partition to store temporary files. + cache_size = OPTIONS.info_dict.get("cache_size") + if cache_size is None: + logger.warning("--- can't determine the cache partition size ---") + OPTIONS.cache_size = cache_size + + if OPTIONS.extra_script is not None: + with open(OPTIONS.extra_script) as fp: + OPTIONS.extra_script = fp.read() + + if OPTIONS.extracted_input is not None: + OPTIONS.input_tmp = OPTIONS.extracted_input + else: + logger.info("unzipping target target-files...") + OPTIONS.input_tmp = common.UnzipTemp(target_file, UNZIP_PATTERN) + OPTIONS.target_tmp = OPTIONS.input_tmp + + # If the caller explicitly specified the device-specific extensions path via + # -s / --device_specific, use that. Otherwise, use META/releasetools.py if it + # is present in the target target_files. Otherwise, take the path of the file + # from 'tool_extensions' in the info dict and look for that in the local + # filesystem, relative to the current directory. + if OPTIONS.device_specific is None: + from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py") + if os.path.exists(from_input): + logger.info("(using device-specific extensions from target_files)") + OPTIONS.device_specific = from_input + else: + OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions") + + if OPTIONS.device_specific is not None: + OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific) + + # Generate a full OTA. + if source_file is None: + with zipfile.ZipFile(target_file) as input_zip: + WriteFullOTAPackage( + input_zip, + output_file) + + # Generate an incremental OTA. + else: + logger.info("unzipping source target-files...") + OPTIONS.source_tmp = common.UnzipTemp( + OPTIONS.incremental_source, UNZIP_PATTERN) + with zipfile.ZipFile(target_file) as input_zip, \ + zipfile.ZipFile(source_file) as source_zip: + WriteBlockIncrementalOTAPackage( + input_zip, + source_zip, + output_file) + + +def WriteFingerprintAssertion(script, target_info, source_info): + source_oem_props = source_info.oem_props + target_oem_props = target_info.oem_props + + if source_oem_props is None and target_oem_props is None: + script.AssertSomeFingerprint( + source_info.fingerprint, target_info.fingerprint) + elif source_oem_props is not None and target_oem_props is not None: + script.AssertSomeThumbprint( + target_info.GetBuildProp("ro.build.thumbprint"), + source_info.GetBuildProp("ro.build.thumbprint")) + elif source_oem_props is None and target_oem_props is not None: + script.AssertFingerprintOrThumbprint( + source_info.fingerprint, + target_info.GetBuildProp("ro.build.thumbprint")) + else: + script.AssertFingerprintOrThumbprint( + target_info.fingerprint, + source_info.GetBuildProp("ro.build.thumbprint")) + + +class NonAbOtaPropertyFiles(PropertyFiles): + """The property-files for non-A/B OTA. + + For non-A/B OTA, the property-files string contains the info for METADATA + entry, with which a system updater can be fetched the package metadata prior + to downloading the entire package. + """ + + def __init__(self): + super(NonAbOtaPropertyFiles, self).__init__() + self.name = 'ota-property-files' + + +def _WriteRecoveryImageToBoot(script, output_zip): + """Find and write recovery image to /boot in two-step OTA. + + In two-step OTAs, we write recovery image to /boot as the first step so that + we can reboot to there and install a new recovery image to /recovery. + A special "recovery-two-step.img" will be preferred, which encodes the correct + path of "/boot". Otherwise the device may show "device is corrupt" message + when booting into /boot. + + Fall back to using the regular recovery.img if the two-step recovery image + doesn't exist. Note that rebuilding the special image at this point may be + infeasible, because we don't have the desired boot signer and keys when + calling ota_from_target_files.py. + """ + + recovery_two_step_img_name = "recovery-two-step.img" + recovery_two_step_img_path = os.path.join( + OPTIONS.input_tmp, "OTA", recovery_two_step_img_name) + if os.path.exists(recovery_two_step_img_path): + common.ZipWrite( + output_zip, + recovery_two_step_img_path, + arcname=recovery_two_step_img_name) + logger.info( + "two-step package: using %s in stage 1/3", recovery_two_step_img_name) + script.WriteRawImage("/boot", recovery_two_step_img_name) + else: + logger.info("two-step package: using recovery.img in stage 1/3") + # The "recovery.img" entry has been written into package earlier. + script.WriteRawImage("/boot", "recovery.img") + + +def HasRecoveryPatch(target_files_zip, info_dict): + board_uses_vendorimage = info_dict.get("board_uses_vendorimage") == "true" + + if board_uses_vendorimage: + target_files_dir = "VENDOR" + else: + target_files_dir = "SYSTEM/vendor" + + patch = "%s/recovery-from-boot.p" % target_files_dir + img = "%s/etc/recovery.img" % target_files_dir + + namelist = target_files_zip.namelist() + return patch in namelist or img in namelist diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py index 3b68439d8f..2833397ed8 100755 --- a/tools/releasetools/ota_from_target_files.py +++ b/tools/releasetools/ota_from_target_files.py @@ -206,9 +206,6 @@ A/B OTA specific options from __future__ import print_function -import collections -import copy -import itertools import logging import multiprocessing import os.path @@ -218,10 +215,13 @@ import struct import sys import zipfile -import check_target_files_vintf import common -import edify_generator -import verity_utils +import ota_utils +import target_files_diff +from check_target_files_vintf import CheckVintfIfTrebleEnabled +from non_ab_ota import GenerateNonAbOtaPackage +from ota_utils import (UNZIP_PATTERN, FinalizeMetadata, GetPackageMetadata, + PropertyFiles) if sys.hexversion < 0x02070000: print("Python 2.7 or newer is required.", file=sys.stderr) @@ -229,20 +229,16 @@ if sys.hexversion < 0x02070000: logger = logging.getLogger(__name__) -OPTIONS = common.OPTIONS -OPTIONS.package_key = None -OPTIONS.incremental_source = None +OPTIONS = ota_utils.OPTIONS OPTIONS.verify = False OPTIONS.patch_threshold = 0.95 OPTIONS.wipe_user_data = False -OPTIONS.downgrade = False OPTIONS.extra_script = None OPTIONS.worker_threads = multiprocessing.cpu_count() // 2 if OPTIONS.worker_threads == 0: OPTIONS.worker_threads = 1 OPTIONS.two_step = False OPTIONS.include_secondary = False -OPTIONS.no_signing = False OPTIONS.block_based = True OPTIONS.updater_binary = None OPTIONS.oem_dicts = None @@ -258,30 +254,25 @@ OPTIONS.payload_signer = None OPTIONS.payload_signer_args = [] OPTIONS.payload_signer_maximum_signature_size = None OPTIONS.extracted_input = None -OPTIONS.key_passwords = [] OPTIONS.skip_postinstall = False -OPTIONS.retrofit_dynamic_partitions = False OPTIONS.skip_compatibility_check = False -OPTIONS.output_metadata_path = None OPTIONS.disable_fec_computation = False -OPTIONS.force_non_ab = False -OPTIONS.boot_variable_file = None -METADATA_NAME = 'META-INF/com/android/metadata' POSTINSTALL_CONFIG = 'META/postinstall_config.txt' DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt' AB_PARTITIONS = 'META/ab_partitions.txt' -UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'OTA/*', 'RADIO/*'] + # Files to be unzipped for target diffing purpose. TARGET_DIFFING_UNZIP_PATTERN = ['BOOT', 'RECOVERY', 'SYSTEM/*', 'VENDOR/*', - 'PRODUCT/*', 'SYSTEM_EXT/*', 'ODM/*'] + 'PRODUCT/*', 'SYSTEM_EXT/*', 'ODM/*', + 'VENDOR_DLKM/*', 'ODM_DLKM/*'] RETROFIT_DAP_UNZIP_PATTERN = ['OTA/super_*.img', AB_PARTITIONS] # Images to be excluded from secondary payload. We essentially only keep # 'system_other' and bootloader partitions. SECONDARY_PAYLOAD_SKIPPED_IMAGES = [ - 'boot', 'dtbo', 'modem', 'odm', 'product', 'radio', 'recovery', + 'boot', 'dtbo', 'modem', 'odm', 'odm_dlkm', 'product', 'radio', 'recovery', 'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor', 'vendor_boot'] @@ -485,13 +476,6 @@ class Payload(object): compress_type=zipfile.ZIP_STORED) -def SignOutput(temp_zip_name, output_zip_name): - pw = OPTIONS.key_passwords[OPTIONS.package_key] - - common.SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw, - whole_file=True) - - def _LoadOemDicts(oem_source): """Returns the list of loaded OEM properties dict.""" if not oem_source: @@ -504,657 +488,6 @@ def _LoadOemDicts(oem_source): return oem_dicts -def _WriteRecoveryImageToBoot(script, output_zip): - """Find and write recovery image to /boot in two-step OTA. - - In two-step OTAs, we write recovery image to /boot as the first step so that - we can reboot to there and install a new recovery image to /recovery. - A special "recovery-two-step.img" will be preferred, which encodes the correct - path of "/boot". Otherwise the device may show "device is corrupt" message - when booting into /boot. - - Fall back to using the regular recovery.img if the two-step recovery image - doesn't exist. Note that rebuilding the special image at this point may be - infeasible, because we don't have the desired boot signer and keys when - calling ota_from_target_files.py. - """ - - recovery_two_step_img_name = "recovery-two-step.img" - recovery_two_step_img_path = os.path.join( - OPTIONS.input_tmp, "OTA", recovery_two_step_img_name) - if os.path.exists(recovery_two_step_img_path): - common.ZipWrite( - output_zip, - recovery_two_step_img_path, - arcname=recovery_two_step_img_name) - logger.info( - "two-step package: using %s in stage 1/3", recovery_two_step_img_name) - script.WriteRawImage("/boot", recovery_two_step_img_name) - else: - logger.info("two-step package: using recovery.img in stage 1/3") - # The "recovery.img" entry has been written into package earlier. - script.WriteRawImage("/boot", "recovery.img") - - -def HasRecoveryPatch(target_files_zip, info_dict): - board_uses_vendorimage = info_dict.get("board_uses_vendorimage") == "true" - - if board_uses_vendorimage: - target_files_dir = "VENDOR" - else: - target_files_dir = "SYSTEM/vendor" - - patch = "%s/recovery-from-boot.p" % target_files_dir - img = "%s/etc/recovery.img" %target_files_dir - - namelist = [name for name in target_files_zip.namelist()] - return (patch in namelist or img in namelist) - - -def HasPartition(target_files_zip, partition): - try: - target_files_zip.getinfo(partition.upper() + "/") - return True - except KeyError: - return False - - -def HasTrebleEnabled(target_files, target_info): - def HasVendorPartition(target_files): - if os.path.isdir(target_files): - return os.path.isdir(os.path.join(target_files, "VENDOR")) - if zipfile.is_zipfile(target_files): - return HasPartition(zipfile.ZipFile(target_files), "vendor") - raise ValueError("Unknown target_files argument") - - return (HasVendorPartition(target_files) and - target_info.GetBuildProp("ro.treble.enabled") == "true") - - -def WriteFingerprintAssertion(script, target_info, source_info): - source_oem_props = source_info.oem_props - target_oem_props = target_info.oem_props - - if source_oem_props is None and target_oem_props is None: - script.AssertSomeFingerprint( - source_info.fingerprint, target_info.fingerprint) - elif source_oem_props is not None and target_oem_props is not None: - script.AssertSomeThumbprint( - target_info.GetBuildProp("ro.build.thumbprint"), - source_info.GetBuildProp("ro.build.thumbprint")) - elif source_oem_props is None and target_oem_props is not None: - script.AssertFingerprintOrThumbprint( - source_info.fingerprint, - target_info.GetBuildProp("ro.build.thumbprint")) - else: - script.AssertFingerprintOrThumbprint( - target_info.fingerprint, - source_info.GetBuildProp("ro.build.thumbprint")) - - -def CheckVintfIfTrebleEnabled(target_files, target_info): - """Checks compatibility info of the input target files. - - Metadata used for compatibility verification is retrieved from target_zip. - - Compatibility should only be checked for devices that have enabled - Treble support. - - Args: - target_files: Path to zip file containing the source files to be included - for OTA. Can also be the path to extracted directory. - target_info: The BuildInfo instance that holds the target build info. - """ - - # Will only proceed if the target has enabled the Treble support (as well as - # having a /vendor partition). - if not HasTrebleEnabled(target_files, target_info): - return - - # Skip adding the compatibility package as a workaround for b/114240221. The - # compatibility will always fail on devices without qualified kernels. - if OPTIONS.skip_compatibility_check: - return - - if not check_target_files_vintf.CheckVintf(target_files, target_info): - raise RuntimeError("VINTF compatibility check failed") - - -def GetBlockDifferences(target_zip, source_zip, target_info, source_info, - device_specific): - """Returns a ordered dict of block differences with partition name as key.""" - - def GetIncrementalBlockDifferenceForPartition(name): - if not HasPartition(source_zip, name): - raise RuntimeError("can't generate incremental that adds {}".format(name)) - - partition_src = common.GetUserImage(name, OPTIONS.source_tmp, source_zip, - info_dict=source_info, - allow_shared_blocks=allow_shared_blocks) - - hashtree_info_generator = verity_utils.CreateHashtreeInfoGenerator( - name, 4096, target_info) - partition_tgt = common.GetUserImage(name, OPTIONS.target_tmp, target_zip, - info_dict=target_info, - allow_shared_blocks=allow_shared_blocks, - hashtree_info_generator= - hashtree_info_generator) - - # Check the first block of the source system partition for remount R/W only - # if the filesystem is ext4. - partition_source_info = source_info["fstab"]["/" + name] - check_first_block = partition_source_info.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). - partition_target_info = target_info["fstab"]["/" + name] - disable_imgdiff = (partition_source_info.fs_type == "squashfs" or - partition_target_info.fs_type == "squashfs") - return common.BlockDifference(name, partition_tgt, partition_src, - check_first_block, - version=blockimgdiff_version, - disable_imgdiff=disable_imgdiff) - - if source_zip: - # See notes in common.GetUserImage() - allow_shared_blocks = (source_info.get('ext4_share_dup_blocks') == "true" or - target_info.get('ext4_share_dup_blocks') == "true") - blockimgdiff_version = max( - int(i) for i in target_info.get( - "blockimgdiff_versions", "1").split(",")) - assert blockimgdiff_version >= 3 - - block_diff_dict = collections.OrderedDict() - partition_names = ["system", "vendor", "product", "odm", "system_ext"] - for partition in partition_names: - if not HasPartition(target_zip, partition): - continue - # Full OTA update. - if not source_zip: - tgt = common.GetUserImage(partition, OPTIONS.input_tmp, target_zip, - info_dict=target_info, - reset_file_map=True) - block_diff_dict[partition] = common.BlockDifference(partition, tgt, - src=None) - # Incremental OTA update. - else: - block_diff_dict[partition] = GetIncrementalBlockDifferenceForPartition( - partition) - assert "system" in block_diff_dict - - # Get the block diffs from the device specific script. If there is a - # duplicate block diff for a partition, ignore the diff in the generic script - # and use the one in the device specific script instead. - if source_zip: - device_specific_diffs = device_specific.IncrementalOTA_GetBlockDifferences() - function_name = "IncrementalOTA_GetBlockDifferences" - else: - device_specific_diffs = device_specific.FullOTA_GetBlockDifferences() - function_name = "FullOTA_GetBlockDifferences" - - if device_specific_diffs: - assert all(isinstance(diff, common.BlockDifference) - for diff in device_specific_diffs), \ - "{} is not returning a list of BlockDifference objects".format( - function_name) - for diff in device_specific_diffs: - if diff.partition in block_diff_dict: - logger.warning("Duplicate block difference found. Device specific block" - " diff for partition '%s' overrides the one in generic" - " script.", diff.partition) - block_diff_dict[diff.partition] = diff - - return block_diff_dict - - -def WriteFullOTAPackage(input_zip, output_file): - target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts) - - # We don't know what version it will be installed on top of. We expect the API - # just won't change very often. Similarly for fstab, it might have changed in - # the target build. - target_api_version = target_info["recovery_api_version"] - script = edify_generator.EdifyGenerator(target_api_version, target_info) - - if target_info.oem_props and not OPTIONS.oem_no_mount: - target_info.WriteMountOemScript(script) - - metadata = GetPackageMetadata(target_info) - - if not OPTIONS.no_signing: - staging_file = common.MakeTempFile(suffix='.zip') - else: - staging_file = output_file - - output_zip = zipfile.ZipFile( - staging_file, "w", compression=zipfile.ZIP_DEFLATED) - - device_specific = common.DeviceSpecificParams( - input_zip=input_zip, - input_version=target_api_version, - output_zip=output_zip, - script=script, - input_tmp=OPTIONS.input_tmp, - metadata=metadata, - info_dict=OPTIONS.info_dict) - - assert HasRecoveryPatch(input_zip, info_dict=OPTIONS.info_dict) - - # Assertions (e.g. downgrade check, device properties check). - ts = target_info.GetBuildProp("ro.build.date.utc") - ts_text = target_info.GetBuildProp("ro.build.date") - script.AssertOlderBuild(ts, ts_text) - - target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount) - device_specific.FullOTA_Assertions() - - block_diff_dict = GetBlockDifferences(target_zip=input_zip, source_zip=None, - target_info=target_info, - source_info=None, - device_specific=device_specific) - - # Two-step package strategy (in chronological order, which is *not* - # the order in which the generated script has things): - # - # if stage is not "2/3" or "3/3": - # write recovery image to boot partition - # set stage to "2/3" - # reboot to boot partition and restart recovery - # else if stage is "2/3": - # write recovery image to recovery partition - # set stage to "3/3" - # reboot to recovery partition and restart recovery - # else: - # (stage must be "3/3") - # set stage to "" - # do normal full package installation: - # wipe and install system, boot image, etc. - # set up system to update recovery partition on first boot - # complete script normally - # (allow recovery to mark itself finished and reboot) - - recovery_img = common.GetBootableImage("recovery.img", "recovery.img", - OPTIONS.input_tmp, "RECOVERY") - if OPTIONS.two_step: - if not target_info.get("multistage_support"): - assert False, "two-step packages not supported by this build" - fs = target_info["fstab"]["/misc"] - assert fs.fs_type.upper() == "EMMC", \ - "two-step packages only supported on devices with EMMC /misc partitions" - bcb_dev = {"bcb_dev": fs.device} - common.ZipWriteStr(output_zip, "recovery.img", recovery_img.data) - script.AppendExtra(""" -if get_stage("%(bcb_dev)s") == "2/3" then -""" % bcb_dev) - - # Stage 2/3: Write recovery image to /recovery (currently running /boot). - script.Comment("Stage 2/3") - script.WriteRawImage("/recovery", "recovery.img") - script.AppendExtra(""" -set_stage("%(bcb_dev)s", "3/3"); -reboot_now("%(bcb_dev)s", "recovery"); -else if get_stage("%(bcb_dev)s") == "3/3" then -""" % bcb_dev) - - # Stage 3/3: Make changes. - script.Comment("Stage 3/3") - - # Dump fingerprints - script.Print("Target: {}".format(target_info.fingerprint)) - - device_specific.FullOTA_InstallBegin() - - # All other partitions as well as the data wipe use 10% of the progress, and - # the update of the system partition takes the remaining progress. - system_progress = 0.9 - (len(block_diff_dict) - 1) * 0.1 - if OPTIONS.wipe_user_data: - system_progress -= 0.1 - progress_dict = {partition: 0.1 for partition in block_diff_dict} - progress_dict["system"] = system_progress - - if target_info.get('use_dynamic_partitions') == "true": - # Use empty source_info_dict to indicate that all partitions / groups must - # be re-added. - dynamic_partitions_diff = common.DynamicPartitionsDifference( - info_dict=OPTIONS.info_dict, - block_diffs=block_diff_dict.values(), - progress_dict=progress_dict) - dynamic_partitions_diff.WriteScript(script, output_zip, - write_verify_script=OPTIONS.verify) - else: - for block_diff in block_diff_dict.values(): - block_diff.WriteScript(script, output_zip, - progress=progress_dict.get(block_diff.partition), - write_verify_script=OPTIONS.verify) - - CheckVintfIfTrebleEnabled(OPTIONS.input_tmp, target_info) - - boot_img = common.GetBootableImage( - "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") - common.CheckSize(boot_img.data, "boot.img", target_info) - common.ZipWriteStr(output_zip, "boot.img", boot_img.data) - - script.WriteRawImage("/boot", "boot.img") - - script.ShowProgress(0.1, 10) - device_specific.FullOTA_InstallEnd() - - if OPTIONS.extra_script is not None: - script.AppendExtra(OPTIONS.extra_script) - - script.UnmountAll() - - if OPTIONS.wipe_user_data: - script.ShowProgress(0.1, 10) - script.FormatPartition("/data") - - if OPTIONS.two_step: - script.AppendExtra(""" -set_stage("%(bcb_dev)s", ""); -""" % bcb_dev) - script.AppendExtra("else\n") - - # Stage 1/3: Nothing to verify for full OTA. Write recovery image to /boot. - script.Comment("Stage 1/3") - _WriteRecoveryImageToBoot(script, output_zip) - - script.AppendExtra(""" -set_stage("%(bcb_dev)s", "2/3"); -reboot_now("%(bcb_dev)s", ""); -endif; -endif; -""" % bcb_dev) - - script.SetProgress(1) - script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) - metadata["ota-required-cache"] = str(script.required_cache) - - # We haven't written the metadata entry, which will be done in - # FinalizeMetadata. - common.ZipClose(output_zip) - - needed_property_files = ( - NonAbOtaPropertyFiles(), - ) - FinalizeMetadata(metadata, staging_file, output_file, needed_property_files) - - -def WriteMetadata(metadata, output): - """Writes the metadata to the zip archive or a file. - - Args: - metadata: The metadata dict for the package. - output: A ZipFile object or a string of the output file path. - """ - - value = "".join(["%s=%s\n" % kv for kv in sorted(metadata.items())]) - if isinstance(output, zipfile.ZipFile): - common.ZipWriteStr(output, METADATA_NAME, value, - compress_type=zipfile.ZIP_STORED) - return - - with open(output, 'w') as f: - f.write(value) - - -def HandleDowngradeMetadata(metadata, target_info, source_info): - # Only incremental OTAs are allowed to reach here. - assert OPTIONS.incremental_source is not None - - post_timestamp = target_info.GetBuildProp("ro.build.date.utc") - pre_timestamp = source_info.GetBuildProp("ro.build.date.utc") - is_downgrade = int(post_timestamp) < int(pre_timestamp) - - if OPTIONS.downgrade: - if not is_downgrade: - raise RuntimeError( - "--downgrade or --override_timestamp specified but no downgrade " - "detected: pre: %s, post: %s" % (pre_timestamp, post_timestamp)) - metadata["ota-downgrade"] = "yes" - else: - if is_downgrade: - raise RuntimeError( - "Downgrade detected based on timestamp check: pre: %s, post: %s. " - "Need to specify --override_timestamp OR --downgrade to allow " - "building the incremental." % (pre_timestamp, post_timestamp)) - - -def GetPackageMetadata(target_info, source_info=None): - """Generates and returns the metadata dict. - - It generates a dict() that contains the info to be written into an OTA - package (META-INF/com/android/metadata). It also handles the detection of - downgrade / data wipe based on the global options. - - Args: - target_info: The BuildInfo instance that holds the target build info. - source_info: The BuildInfo instance that holds the source build info, or - None if generating full OTA. - - Returns: - A dict to be written into package metadata entry. - """ - assert isinstance(target_info, common.BuildInfo) - assert source_info is None or isinstance(source_info, common.BuildInfo) - - separator = '|' - - boot_variable_values = {} - if OPTIONS.boot_variable_file: - d = common.LoadDictionaryFromFile(OPTIONS.boot_variable_file) - for key, values in d.items(): - boot_variable_values[key] = [val.strip() for val in values.split(',')] - - post_build_devices, post_build_fingerprints = \ - CalculateRuntimeDevicesAndFingerprints(target_info, boot_variable_values) - metadata = { - 'post-build': separator.join(sorted(post_build_fingerprints)), - 'post-build-incremental': target_info.GetBuildProp( - 'ro.build.version.incremental'), - 'post-sdk-level': target_info.GetBuildProp( - 'ro.build.version.sdk'), - 'post-security-patch-level': target_info.GetBuildProp( - 'ro.build.version.security_patch'), - } - - if target_info.is_ab and not OPTIONS.force_non_ab: - metadata['ota-type'] = 'AB' - metadata['ota-required-cache'] = '0' - else: - metadata['ota-type'] = 'BLOCK' - - if OPTIONS.wipe_user_data: - metadata['ota-wipe'] = 'yes' - - if OPTIONS.retrofit_dynamic_partitions: - metadata['ota-retrofit-dynamic-partitions'] = 'yes' - - is_incremental = source_info is not None - if is_incremental: - pre_build_devices, pre_build_fingerprints = \ - CalculateRuntimeDevicesAndFingerprints(source_info, - boot_variable_values) - metadata['pre-build'] = separator.join(sorted(pre_build_fingerprints)) - metadata['pre-build-incremental'] = source_info.GetBuildProp( - 'ro.build.version.incremental') - metadata['pre-device'] = separator.join(sorted(pre_build_devices)) - else: - metadata['pre-device'] = separator.join(sorted(post_build_devices)) - - # Use the actual post-timestamp, even for a downgrade case. - metadata['post-timestamp'] = target_info.GetBuildProp('ro.build.date.utc') - - # Detect downgrades and set up downgrade flags accordingly. - if is_incremental: - HandleDowngradeMetadata(metadata, target_info, source_info) - - return metadata - - -class PropertyFiles(object): - """A class that computes the property-files string for an OTA package. - - A property-files string is a comma-separated string that contains the - offset/size info for an OTA package. The entries, which must be ZIP_STORED, - can be fetched directly with the package URL along with the offset/size info. - These strings can be used for streaming A/B OTAs, or allowing an updater to - download package metadata entry directly, without paying the cost of - downloading entire package. - - Computing the final property-files string requires two passes. Because doing - the whole package signing (with signapk.jar) will possibly reorder the ZIP - entries, which may in turn invalidate earlier computed ZIP entry offset/size - values. - - This class provides functions to be called for each pass. The general flow is - as follows. - - property_files = PropertyFiles() - # The first pass, which writes placeholders before doing initial signing. - property_files.Compute() - SignOutput() - - # The second pass, by replacing the placeholders with actual data. - property_files.Finalize() - SignOutput() - - And the caller can additionally verify the final result. - - property_files.Verify() - """ - - def __init__(self): - self.name = None - self.required = () - self.optional = () - - def Compute(self, input_zip): - """Computes and returns a property-files string with placeholders. - - We reserve extra space for the offset and size of the metadata entry itself, - although we don't know the final values until the package gets signed. - - Args: - input_zip: The input ZIP file. - - Returns: - A string with placeholders for the metadata offset/size info, e.g. - "payload.bin:679:343,payload_properties.txt:378:45,metadata: ". - """ - return self.GetPropertyFilesString(input_zip, reserve_space=True) - - class InsufficientSpaceException(Exception): - pass - - def Finalize(self, input_zip, reserved_length): - """Finalizes a property-files string with actual METADATA offset/size info. - - The input ZIP file has been signed, with the ZIP entries in the desired - place (signapk.jar will possibly reorder the ZIP entries). Now we compute - the ZIP entry offsets and construct the property-files string with actual - data. Note that during this process, we must pad the property-files string - to the reserved length, so that the METADATA entry size remains the same. - Otherwise the entries' offsets and sizes may change again. - - Args: - input_zip: The input ZIP file. - reserved_length: The reserved length of the property-files string during - the call to Compute(). The final string must be no more than this - size. - - Returns: - A property-files string including the metadata offset/size info, e.g. - "payload.bin:679:343,payload_properties.txt:378:45,metadata:69:379 ". - - Raises: - InsufficientSpaceException: If the reserved length is insufficient to hold - the final string. - """ - result = self.GetPropertyFilesString(input_zip, reserve_space=False) - if len(result) > reserved_length: - raise self.InsufficientSpaceException( - 'Insufficient reserved space: reserved={}, actual={}'.format( - reserved_length, len(result))) - - result += ' ' * (reserved_length - len(result)) - return result - - def Verify(self, input_zip, expected): - """Verifies the input ZIP file contains the expected property-files string. - - Args: - input_zip: The input ZIP file. - expected: The property-files string that's computed from Finalize(). - - Raises: - AssertionError: On finding a mismatch. - """ - actual = self.GetPropertyFilesString(input_zip) - assert actual == expected, \ - "Mismatching streaming metadata: {} vs {}.".format(actual, expected) - - def GetPropertyFilesString(self, zip_file, reserve_space=False): - """ - Constructs the property-files string per request. - - Args: - zip_file: The input ZIP file. - reserved_length: The reserved length of the property-files string. - - Returns: - A property-files string including the metadata offset/size info, e.g. - "payload.bin:679:343,payload_properties.txt:378:45,metadata: ". - """ - - def ComputeEntryOffsetSize(name): - """Computes the zip entry offset and size.""" - info = zip_file.getinfo(name) - offset = info.header_offset - offset += zipfile.sizeFileHeader - offset += len(info.extra) + len(info.filename) - size = info.file_size - return '%s:%d:%d' % (os.path.basename(name), offset, size) - - tokens = [] - tokens.extend(self._GetPrecomputed(zip_file)) - for entry in self.required: - tokens.append(ComputeEntryOffsetSize(entry)) - for entry in self.optional: - if entry in zip_file.namelist(): - tokens.append(ComputeEntryOffsetSize(entry)) - - # 'META-INF/com/android/metadata' is required. We don't know its actual - # offset and length (as well as the values for other entries). So we reserve - # 15-byte as a placeholder ('offset:length'), which is sufficient to cover - # the space for metadata entry. Because 'offset' allows a max of 10-digit - # (i.e. ~9 GiB), with a max of 4-digit for the length. Note that all the - # reserved space serves the metadata entry only. - if reserve_space: - tokens.append('metadata:' + ' ' * 15) - else: - tokens.append(ComputeEntryOffsetSize(METADATA_NAME)) - - return ','.join(tokens) - - def _GetPrecomputed(self, input_zip): - """Computes the additional tokens to be included into the property-files. - - This applies to tokens without actual ZIP entries, such as - payload_metadadata.bin. We want to expose the offset/size to updaters, so - that they can download the payload metadata directly with the info. - - Args: - input_zip: The input zip file. - - Returns: - A list of strings (tokens) to be added to the property-files string. - """ - # pylint: disable=no-self-use - # pylint: disable=unused-argument - return [] - - class StreamingPropertyFiles(PropertyFiles): """A subclass for computing the property-files for streaming A/B OTAs.""" @@ -1260,362 +593,6 @@ class AbOtaPropertyFiles(StreamingPropertyFiles): return (payload_offset, metadata_total) -class NonAbOtaPropertyFiles(PropertyFiles): - """The property-files for non-A/B OTA. - - For non-A/B OTA, the property-files string contains the info for METADATA - entry, with which a system updater can be fetched the package metadata prior - to downloading the entire package. - """ - - def __init__(self): - super(NonAbOtaPropertyFiles, self).__init__() - self.name = 'ota-property-files' - - -def FinalizeMetadata(metadata, input_file, output_file, needed_property_files): - """Finalizes the metadata and signs an A/B OTA package. - - In order to stream an A/B OTA package, we need 'ota-streaming-property-files' - that contains the offsets and sizes for the ZIP entries. An example - property-files string is as follows. - - "payload.bin:679:343,payload_properties.txt:378:45,metadata:69:379" - - OTA server can pass down this string, in addition to the package URL, to the - system update client. System update client can then fetch individual ZIP - entries (ZIP_STORED) directly at the given offset of the URL. - - Args: - metadata: The metadata dict for the package. - input_file: The input ZIP filename that doesn't contain the package METADATA - entry yet. - output_file: The final output ZIP filename. - needed_property_files: The list of PropertyFiles' to be generated. - """ - - def ComputeAllPropertyFiles(input_file, needed_property_files): - # Write the current metadata entry with placeholders. - with zipfile.ZipFile(input_file) as input_zip: - for property_files in needed_property_files: - metadata[property_files.name] = property_files.Compute(input_zip) - namelist = input_zip.namelist() - - if METADATA_NAME in namelist: - common.ZipDelete(input_file, METADATA_NAME) - output_zip = zipfile.ZipFile(input_file, 'a') - WriteMetadata(metadata, output_zip) - common.ZipClose(output_zip) - - if OPTIONS.no_signing: - return input_file - - prelim_signing = common.MakeTempFile(suffix='.zip') - SignOutput(input_file, prelim_signing) - return prelim_signing - - def FinalizeAllPropertyFiles(prelim_signing, needed_property_files): - with zipfile.ZipFile(prelim_signing) as prelim_signing_zip: - for property_files in needed_property_files: - metadata[property_files.name] = property_files.Finalize( - prelim_signing_zip, len(metadata[property_files.name])) - - # SignOutput(), which in turn calls signapk.jar, will possibly reorder the ZIP - # entries, as well as padding the entry headers. We do a preliminary signing - # (with an incomplete metadata entry) to allow that to happen. Then compute - # the ZIP entry offsets, write back the final metadata and do the final - # signing. - prelim_signing = ComputeAllPropertyFiles(input_file, needed_property_files) - try: - FinalizeAllPropertyFiles(prelim_signing, needed_property_files) - except PropertyFiles.InsufficientSpaceException: - # Even with the preliminary signing, the entry orders may change - # dramatically, which leads to insufficiently reserved space during the - # first call to ComputeAllPropertyFiles(). In that case, we redo all the - # preliminary signing works, based on the already ordered ZIP entries, to - # address the issue. - prelim_signing = ComputeAllPropertyFiles( - prelim_signing, needed_property_files) - FinalizeAllPropertyFiles(prelim_signing, needed_property_files) - - # Replace the METADATA entry. - common.ZipDelete(prelim_signing, METADATA_NAME) - output_zip = zipfile.ZipFile(prelim_signing, 'a') - WriteMetadata(metadata, output_zip) - common.ZipClose(output_zip) - - # Re-sign the package after updating the metadata entry. - if OPTIONS.no_signing: - output_file = prelim_signing - else: - SignOutput(prelim_signing, output_file) - - # Reopen the final signed zip to double check the streaming metadata. - with zipfile.ZipFile(output_file) as output_zip: - for property_files in needed_property_files: - property_files.Verify(output_zip, metadata[property_files.name].strip()) - - # If requested, dump the metadata to a separate file. - output_metadata_path = OPTIONS.output_metadata_path - if output_metadata_path: - WriteMetadata(metadata, output_metadata_path) - - -def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file): - target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts) - source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts) - - target_api_version = target_info["recovery_api_version"] - source_api_version = source_info["recovery_api_version"] - if source_api_version == 0: - logger.warning( - "Generating edify script for a source that can't install it.") - - script = edify_generator.EdifyGenerator( - source_api_version, target_info, fstab=source_info["fstab"]) - - if target_info.oem_props or source_info.oem_props: - if not OPTIONS.oem_no_mount: - source_info.WriteMountOemScript(script) - - metadata = GetPackageMetadata(target_info, source_info) - - if not OPTIONS.no_signing: - staging_file = common.MakeTempFile(suffix='.zip') - else: - staging_file = output_file - - output_zip = zipfile.ZipFile( - staging_file, "w", compression=zipfile.ZIP_DEFLATED) - - device_specific = common.DeviceSpecificParams( - source_zip=source_zip, - source_version=source_api_version, - source_tmp=OPTIONS.source_tmp, - target_zip=target_zip, - target_version=target_api_version, - target_tmp=OPTIONS.target_tmp, - output_zip=output_zip, - script=script, - metadata=metadata, - info_dict=source_info) - - source_boot = common.GetBootableImage( - "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", source_info) - target_boot = common.GetBootableImage( - "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT", target_info) - updating_boot = (not OPTIONS.two_step and - (source_boot.data != target_boot.data)) - - target_recovery = common.GetBootableImage( - "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") - - block_diff_dict = GetBlockDifferences(target_zip=target_zip, - source_zip=source_zip, - target_info=target_info, - source_info=source_info, - device_specific=device_specific) - - CheckVintfIfTrebleEnabled(OPTIONS.target_tmp, target_info) - - # Assertions (e.g. device properties check). - target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount) - device_specific.IncrementalOTA_Assertions() - - # Two-step incremental package strategy (in chronological order, - # which is *not* the order in which the generated script has - # things): - # - # if stage is not "2/3" or "3/3": - # do verification on current system - # write recovery image to boot partition - # set stage to "2/3" - # reboot to boot partition and restart recovery - # else if stage is "2/3": - # write recovery image to recovery partition - # set stage to "3/3" - # reboot to recovery partition and restart recovery - # else: - # (stage must be "3/3") - # perform update: - # patch system files, etc. - # force full install of new boot image - # set up system to update recovery partition on first boot - # complete script normally - # (allow recovery to mark itself finished and reboot) - - if OPTIONS.two_step: - if not source_info.get("multistage_support"): - assert False, "two-step packages not supported by this build" - fs = source_info["fstab"]["/misc"] - assert fs.fs_type.upper() == "EMMC", \ - "two-step packages only supported on devices with EMMC /misc partitions" - bcb_dev = {"bcb_dev" : fs.device} - common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data) - script.AppendExtra(""" -if get_stage("%(bcb_dev)s") == "2/3" then -""" % bcb_dev) - - # Stage 2/3: Write recovery image to /recovery (currently running /boot). - script.Comment("Stage 2/3") - script.AppendExtra("sleep(20);\n") - script.WriteRawImage("/recovery", "recovery.img") - script.AppendExtra(""" -set_stage("%(bcb_dev)s", "3/3"); -reboot_now("%(bcb_dev)s", "recovery"); -else if get_stage("%(bcb_dev)s") != "3/3" then -""" % bcb_dev) - - # Stage 1/3: (a) Verify the current system. - script.Comment("Stage 1/3") - - # Dump fingerprints - script.Print("Source: {}".format(source_info.fingerprint)) - script.Print("Target: {}".format(target_info.fingerprint)) - - script.Print("Verifying current system...") - - device_specific.IncrementalOTA_VerifyBegin() - - WriteFingerprintAssertion(script, target_info, source_info) - - # Check the required cache size (i.e. stashed blocks). - required_cache_sizes = [diff.required_cache for diff in - block_diff_dict.values()] - if updating_boot: - boot_type, boot_device_expr = common.GetTypeAndDeviceExpr("/boot", - source_info) - d = common.Difference(target_boot, source_boot) - _, _, d = d.ComputePatch() - if d is None: - include_full_boot = True - common.ZipWriteStr(output_zip, "boot.img", target_boot.data) - else: - include_full_boot = False - - logger.info( - "boot target: %d source: %d diff: %d", target_boot.size, - source_boot.size, len(d)) - - common.ZipWriteStr(output_zip, "boot.img.p", d) - - target_expr = 'concat("{}:",{},":{}:{}")'.format( - boot_type, boot_device_expr, target_boot.size, target_boot.sha1) - source_expr = 'concat("{}:",{},":{}:{}")'.format( - boot_type, boot_device_expr, source_boot.size, source_boot.sha1) - script.PatchPartitionExprCheck(target_expr, source_expr) - - required_cache_sizes.append(target_boot.size) - - if required_cache_sizes: - script.CacheFreeSpaceCheck(max(required_cache_sizes)) - - # Verify the existing partitions. - for diff in block_diff_dict.values(): - diff.WriteVerifyScript(script, touched_blocks_only=True) - - device_specific.IncrementalOTA_VerifyEnd() - - if OPTIONS.two_step: - # Stage 1/3: (b) Write recovery image to /boot. - _WriteRecoveryImageToBoot(script, output_zip) - - script.AppendExtra(""" -set_stage("%(bcb_dev)s", "2/3"); -reboot_now("%(bcb_dev)s", ""); -else -""" % bcb_dev) - - # Stage 3/3: Make changes. - script.Comment("Stage 3/3") - - script.Comment("---- start making changes here ----") - - device_specific.IncrementalOTA_InstallBegin() - - progress_dict = {partition: 0.1 for partition in block_diff_dict} - progress_dict["system"] = 1 - len(block_diff_dict) * 0.1 - - if OPTIONS.source_info_dict.get("use_dynamic_partitions") == "true": - if OPTIONS.target_info_dict.get("use_dynamic_partitions") != "true": - raise RuntimeError( - "can't generate incremental that disables dynamic partitions") - dynamic_partitions_diff = common.DynamicPartitionsDifference( - info_dict=OPTIONS.target_info_dict, - source_info_dict=OPTIONS.source_info_dict, - block_diffs=block_diff_dict.values(), - progress_dict=progress_dict) - dynamic_partitions_diff.WriteScript( - script, output_zip, write_verify_script=OPTIONS.verify) - else: - for block_diff in block_diff_dict.values(): - block_diff.WriteScript(script, output_zip, - progress=progress_dict.get(block_diff.partition), - write_verify_script=OPTIONS.verify) - - if OPTIONS.two_step: - common.ZipWriteStr(output_zip, "boot.img", target_boot.data) - script.WriteRawImage("/boot", "boot.img") - logger.info("writing full boot image (forced by two-step mode)") - - if not OPTIONS.two_step: - if updating_boot: - if include_full_boot: - logger.info("boot image changed; including full.") - script.Print("Installing boot image...") - script.WriteRawImage("/boot", "boot.img") - else: - # Produce the boot image by applying a patch to the current - # contents of the boot partition, and write it back to the - # partition. - logger.info("boot image changed; including patch.") - script.Print("Patching boot image...") - script.ShowProgress(0.1, 10) - target_expr = 'concat("{}:",{},":{}:{}")'.format( - boot_type, boot_device_expr, target_boot.size, target_boot.sha1) - source_expr = 'concat("{}:",{},":{}:{}")'.format( - boot_type, boot_device_expr, source_boot.size, source_boot.sha1) - script.PatchPartitionExpr(target_expr, source_expr, '"boot.img.p"') - else: - logger.info("boot image unchanged; skipping.") - - # Do device-specific installation (eg, write radio image). - device_specific.IncrementalOTA_InstallEnd() - - if OPTIONS.extra_script is not None: - script.AppendExtra(OPTIONS.extra_script) - - if OPTIONS.wipe_user_data: - script.Print("Erasing user data...") - script.FormatPartition("/data") - - if OPTIONS.two_step: - script.AppendExtra(""" -set_stage("%(bcb_dev)s", ""); -endif; -endif; -""" % bcb_dev) - - script.SetProgress(1) - # For downgrade OTAs, we prefer to use the update-binary in the source - # build that is actually newer than the one in the target build. - if OPTIONS.downgrade: - script.AddToZip(source_zip, output_zip, input_path=OPTIONS.updater_binary) - else: - script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) - metadata["ota-required-cache"] = str(script.required_cache) - - # We haven't written the metadata entry yet, which will be handled in - # FinalizeMetadata(). - common.ZipClose(output_zip) - - # Sign the generated zip package unless no_signing is specified. - needed_property_files = ( - NonAbOtaPropertyFiles(), - ) - FinalizeMetadata(metadata, staging_file, output_file, needed_property_files) - - def GetTargetFilesZipForSecondaryImages(input_file, skip_postinstall=False): """Returns a target-files.zip file for generating secondary payload. @@ -1668,7 +645,7 @@ def GetTargetFilesZipForSecondaryImages(input_file, skip_postinstall=False): partitions = [partition for partition in partitions if partition not in SECONDARY_PAYLOAD_SKIPPED_IMAGES] output_list.append('{}={}'.format(key, ' '.join(partitions))) - elif key == 'virtual_ab' or key == "virtual_ab_retrofit": + elif key in ['virtual_ab', "virtual_ab_retrofit"]: # Remove virtual_ab flag from secondary payload so that OTA client # don't use snapshots for secondary update pass @@ -1712,7 +689,8 @@ def GetTargetFilesZipForSecondaryImages(input_file, skip_postinstall=False): partition_list = f.read().splitlines() partition_list = [partition for partition in partition_list if partition and partition not in SECONDARY_PAYLOAD_SKIPPED_IMAGES] - common.ZipWriteStr(target_zip, info.filename, '\n'.join(partition_list)) + common.ZipWriteStr(target_zip, info.filename, + '\n'.join(partition_list)) # Remove the unnecessary partitions from the dynamic partitions list. elif (info.filename == 'META/misc_info.txt' or info.filename == DYNAMIC_PARTITION_INFO): @@ -1795,11 +773,12 @@ def GetTargetFilesZipForRetrofitDynamicPartitions(input_file, "{} is in super_block_devices but not in {}".format( super_device_not_updated, AB_PARTITIONS) # ab_partitions -= (dynamic_partition_list - super_block_devices) - new_ab_partitions = common.MakeTempFile(prefix="ab_partitions", suffix=".txt") + new_ab_partitions = common.MakeTempFile( + prefix="ab_partitions", suffix=".txt") with open(new_ab_partitions, 'w') as f: for partition in ab_partitions: if (partition in dynamic_partition_list and - partition not in super_block_devices): + partition not in super_block_devices): logger.info("Dropping %s from ab_partitions.txt", partition) continue f.write(partition + "\n") @@ -1846,31 +825,49 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None): compression=zipfile.ZIP_DEFLATED) if source_file is not None: + assert "ab_partitions" in OPTIONS.source_info_dict, \ + "META/ab_partitions.txt is required for ab_update." + assert "ab_partitions" in OPTIONS.target_info_dict, \ + "META/ab_partitions.txt is required for ab_update." target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts) source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts) else: + assert "ab_partitions" in OPTIONS.info_dict, \ + "META/ab_partitions.txt is required for ab_update." target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts) source_info = None - # Metadata to comply with Android OTA package format. - metadata = GetPackageMetadata(target_info, source_info) - if OPTIONS.retrofit_dynamic_partitions: target_file = GetTargetFilesZipForRetrofitDynamicPartitions( target_file, target_info.get("super_block_devices").strip().split(), target_info.get("dynamic_partition_list").strip().split()) elif OPTIONS.skip_postinstall: target_file = GetTargetFilesZipWithoutPostinstallConfig(target_file) + # Target_file may have been modified, reparse ab_partitions + with zipfile.ZipFile(target_file, allowZip64=True) as zfp: + target_info.info_dict['ab_partitions'] = zfp.read( + AB_PARTITIONS).strip().split("\n") + # Metadata to comply with Android OTA package format. + metadata = GetPackageMetadata(target_info, source_info) # Generate payload. payload = Payload() + partition_timestamps = [] # Enforce a max timestamp this payload can be applied on top of. if OPTIONS.downgrade: max_timestamp = source_info.GetBuildProp("ro.build.date.utc") else: - max_timestamp = metadata["post-timestamp"] + max_timestamp = str(metadata.postcondition.timestamp) + partition_timestamps = [ + part.partition_name + ":" + part.version + for part in metadata.postcondition.partition_state] additional_args = ["--max_timestamp", max_timestamp] + if partition_timestamps: + additional_args.extend( + ["--partition_timestamps", ",".join( + partition_timestamps)] + ) payload.Generate(target_file, source_file, additional_args) @@ -1898,7 +895,7 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None): # into A/B OTA package. target_zip = zipfile.ZipFile(target_file, "r") if (target_info.get("verity") == "true" or - target_info.get("avb_enable") == "true"): + target_info.get("avb_enable") == "true"): care_map_list = [x for x in ["care_map.pb", "care_map.txt"] if "META/" + x in target_zip.namelist()] @@ -1932,104 +929,6 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None): FinalizeMetadata(metadata, staging_file, output_file, needed_property_files) -def GenerateNonAbOtaPackage(target_file, output_file, source_file=None): - """Generates a non-A/B OTA package.""" - # Sanity check the loaded info dicts first. - if OPTIONS.info_dict.get("no_recovery") == "true": - raise common.ExternalError( - "--- target build has specified no recovery ---") - - # Non-A/B OTAs rely on /cache partition to store temporary files. - cache_size = OPTIONS.info_dict.get("cache_size") - if cache_size is None: - logger.warning("--- can't determine the cache partition size ---") - OPTIONS.cache_size = cache_size - - if OPTIONS.extra_script is not None: - with open(OPTIONS.extra_script) as fp: - OPTIONS.extra_script = fp.read() - - if OPTIONS.extracted_input is not None: - OPTIONS.input_tmp = OPTIONS.extracted_input - else: - logger.info("unzipping target target-files...") - OPTIONS.input_tmp = common.UnzipTemp(target_file, UNZIP_PATTERN) - OPTIONS.target_tmp = OPTIONS.input_tmp - - # If the caller explicitly specified the device-specific extensions path via - # -s / --device_specific, use that. Otherwise, use META/releasetools.py if it - # is present in the target target_files. Otherwise, take the path of the file - # from 'tool_extensions' in the info dict and look for that in the local - # filesystem, relative to the current directory. - if OPTIONS.device_specific is None: - from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py") - if os.path.exists(from_input): - logger.info("(using device-specific extensions from target_files)") - OPTIONS.device_specific = from_input - else: - OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions") - - if OPTIONS.device_specific is not None: - OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific) - - # Generate a full OTA. - if source_file is None: - with zipfile.ZipFile(target_file) as input_zip: - WriteFullOTAPackage( - input_zip, - output_file) - - # Generate an incremental OTA. - else: - logger.info("unzipping source target-files...") - OPTIONS.source_tmp = common.UnzipTemp( - OPTIONS.incremental_source, UNZIP_PATTERN) - with zipfile.ZipFile(target_file) as input_zip, \ - zipfile.ZipFile(source_file) as source_zip: - WriteBlockIncrementalOTAPackage( - input_zip, - source_zip, - output_file) - - -def CalculateRuntimeDevicesAndFingerprints(build_info, boot_variable_values): - """Returns a tuple of sets for runtime devices and fingerprints""" - - device_names = {build_info.device} - fingerprints = {build_info.fingerprint} - - if not boot_variable_values: - return device_names, fingerprints - - # Calculate all possible combinations of the values for the boot variables. - keys = boot_variable_values.keys() - value_list = boot_variable_values.values() - combinations = [dict(zip(keys, values)) - for values in itertools.product(*value_list)] - for placeholder_values in combinations: - # Reload the info_dict as some build properties may change their values - # based on the value of ro.boot* properties. - info_dict = copy.deepcopy(build_info.info_dict) - for partition in common.PARTITIONS_WITH_CARE_MAP: - partition_prop_key = "{}.build.prop".format(partition) - input_file = info_dict[partition_prop_key].input_file - if isinstance(input_file, zipfile.ZipFile): - with zipfile.ZipFile(input_file.filename) as input_zip: - info_dict[partition_prop_key] = \ - common.PartitionBuildProps.FromInputFile(input_zip, partition, - placeholder_values) - else: - info_dict[partition_prop_key] = \ - common.PartitionBuildProps.FromInputFile(input_file, partition, - placeholder_values) - info_dict["build.prop"] = info_dict["system.build.prop"] - - new_build_info = common.BuildInfo(info_dict, build_info.oem_dicts) - device_names.add(new_build_info.device) - fingerprints.add(new_build_info.fingerprint) - return device_names, fingerprints - - def main(argv): def option_handler(o, a): @@ -2192,7 +1091,7 @@ def main(argv): # use_dynamic_partitions but target build does. if (OPTIONS.source_info_dict and OPTIONS.source_info_dict.get("use_dynamic_partitions") != "true" and - OPTIONS.target_info_dict.get("use_dynamic_partitions") == "true"): + OPTIONS.target_info_dict.get("use_dynamic_partitions") == "true"): if OPTIONS.target_info_dict.get("dynamic_partition_retrofit") != "true": raise common.ExternalError( "Expect to generate incremental OTA for retrofitting dynamic " @@ -2245,7 +1144,6 @@ def main(argv): OPTIONS.incremental_source, TARGET_DIFFING_UNZIP_PATTERN) with open(OPTIONS.log_diff, 'w') as out_file: - import target_files_diff target_files_diff.recursiveDiff( '', source_dir, target_dir, out_file) diff --git a/tools/releasetools/ota_metadata.proto b/tools/releasetools/ota_metadata.proto new file mode 100644 index 0000000000..20d3091570 --- /dev/null +++ b/tools/releasetools/ota_metadata.proto @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// If you change this file, +// Please update ota_metadata_pb2.py by executing +// protoc ota_metadata.proto --python_out $ANDROID_BUILD_TOP/build/tools/releasetools + + +syntax = "proto3"; + +package build.tools.releasetools; +option optimize_for = LITE_RUNTIME; + +// The build information of a particular partition on the device. +message PartitionState { + string partition_name = 1; + repeated string device = 2; + repeated string build = 3; + // The version string of the partition. It's usually timestamp if present. + // One known exception is the boot image, who uses the kmi version, e.g. + // 5.4.42-android12-0 + string version = 4; + + // TODO(xunchang), revisit other necessary fields, e.g. security_patch_level. +} + +// The build information on the device. The bytes of the running images are thus +// inferred from the device state. For more information of the meaning of each +// subfield, check +// https://source.android.com/compatibility/android-cdd#3_2_2_build_parameters +message DeviceState { + // device name. i.e. ro.product.device; if the field has multiple values, it + // means the ota package supports multiple devices. This usually happens when + // we use the same image to support multiple skus. + repeated string device = 1; + // device fingerprint. Up to R build, the value reads from + // ro.build.fingerprint. + repeated string build = 2; + // A value that specify a version of the android build. + string build_incremental = 3; + // The timestamp when the build is generated. + int64 timestamp = 4; + // The version of the currently-executing Android system. + string sdk_level = 5; + // A value indicating the security patch level of a build. + string security_patch_level = 6; + + // The detailed state of each partition. For partial updates or devices with + // mixed build of partitions, some of the above fields may left empty. And the + // client will rely on the information of specific partitions to target the + // update. + repeated PartitionState partition_state = 7; +} + +// The metadata of an OTA package. It contains the information of the package +// and prerequisite to install the update correctly. +message OtaMetadata { + enum OtaType { + UNKNOWN = 0; + AB = 1; + BLOCK = 2; + BRICK = 3; + }; + OtaType type = 1; + // True if we need to wipe after the update. + bool wipe = 2; + // True if the timestamp of the post build is older than the pre build. + bool downgrade = 3; + // A map of name:content of property files, e.g. ota-property-files. + map<string, string> property_files = 4; + + // The required device state in order to install the package. + DeviceState precondition = 5; + // The expected device state after the update. + DeviceState postcondition = 6; + + // True if the ota that updates a device to support dynamic partitions, where + // the source build doesn't support it. + bool retrofit_dynamic_partitions = 7; + // The required size of the cache partition, only valid for non-A/B update. + int64 required_cache = 8; +} diff --git a/tools/releasetools/ota_metadata_pb2.py b/tools/releasetools/ota_metadata_pb2.py new file mode 100644 index 0000000000..ff2b2c5706 --- /dev/null +++ b/tools/releasetools/ota_metadata_pb2.py @@ -0,0 +1,343 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ota_metadata.proto + +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='ota_metadata.proto', + package='build.tools.releasetools', + syntax='proto3', + serialized_options=b'H\003', + serialized_pb=b'\n\x12ota_metadata.proto\x12\x18\x62uild.tools.releasetools\"X\n\x0ePartitionState\x12\x16\n\x0epartition_name\x18\x01 \x01(\t\x12\x0e\n\x06\x64\x65vice\x18\x02 \x03(\t\x12\r\n\x05\x62uild\x18\x03 \x03(\t\x12\x0f\n\x07version\x18\x04 \x01(\t\"\xce\x01\n\x0b\x44\x65viceState\x12\x0e\n\x06\x64\x65vice\x18\x01 \x03(\t\x12\r\n\x05\x62uild\x18\x02 \x03(\t\x12\x19\n\x11\x62uild_incremental\x18\x03 \x01(\t\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x11\n\tsdk_level\x18\x05 \x01(\t\x12\x1c\n\x14security_patch_level\x18\x06 \x01(\t\x12\x41\n\x0fpartition_state\x18\x07 \x03(\x0b\x32(.build.tools.releasetools.PartitionState\"\xe1\x03\n\x0bOtaMetadata\x12;\n\x04type\x18\x01 \x01(\x0e\x32-.build.tools.releasetools.OtaMetadata.OtaType\x12\x0c\n\x04wipe\x18\x02 \x01(\x08\x12\x11\n\tdowngrade\x18\x03 \x01(\x08\x12P\n\x0eproperty_files\x18\x04 \x03(\x0b\x32\x38.build.tools.releasetools.OtaMetadata.PropertyFilesEntry\x12;\n\x0cprecondition\x18\x05 \x01(\x0b\x32%.build.tools.releasetools.DeviceState\x12<\n\rpostcondition\x18\x06 \x01(\x0b\x32%.build.tools.releasetools.DeviceState\x12#\n\x1bretrofit_dynamic_partitions\x18\x07 \x01(\x08\x12\x16\n\x0erequired_cache\x18\x08 \x01(\x03\x1a\x34\n\x12PropertyFilesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"4\n\x07OtaType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x06\n\x02\x41\x42\x10\x01\x12\t\n\x05\x42LOCK\x10\x02\x12\t\n\x05\x42RICK\x10\x03\x42\x02H\x03\x62\x06proto3' +) + + + +_OTAMETADATA_OTATYPE = _descriptor.EnumDescriptor( + name='OtaType', + full_name='build.tools.releasetools.OtaMetadata.OtaType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='AB', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BLOCK', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BRICK', index=3, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=777, + serialized_end=829, +) +_sym_db.RegisterEnumDescriptor(_OTAMETADATA_OTATYPE) + + +_PARTITIONSTATE = _descriptor.Descriptor( + name='PartitionState', + full_name='build.tools.releasetools.PartitionState', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='partition_name', full_name='build.tools.releasetools.PartitionState.partition_name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='device', full_name='build.tools.releasetools.PartitionState.device', index=1, + number=2, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='build', full_name='build.tools.releasetools.PartitionState.build', index=2, + number=3, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='version', full_name='build.tools.releasetools.PartitionState.version', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=48, + serialized_end=136, +) + + +_DEVICESTATE = _descriptor.Descriptor( + name='DeviceState', + full_name='build.tools.releasetools.DeviceState', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='device', full_name='build.tools.releasetools.DeviceState.device', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='build', full_name='build.tools.releasetools.DeviceState.build', index=1, + number=2, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='build_incremental', full_name='build.tools.releasetools.DeviceState.build_incremental', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='timestamp', full_name='build.tools.releasetools.DeviceState.timestamp', index=3, + number=4, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sdk_level', full_name='build.tools.releasetools.DeviceState.sdk_level', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='security_patch_level', full_name='build.tools.releasetools.DeviceState.security_patch_level', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='partition_state', full_name='build.tools.releasetools.DeviceState.partition_state', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=139, + serialized_end=345, +) + + +_OTAMETADATA_PROPERTYFILESENTRY = _descriptor.Descriptor( + name='PropertyFilesEntry', + full_name='build.tools.releasetools.OtaMetadata.PropertyFilesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='build.tools.releasetools.OtaMetadata.PropertyFilesEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='build.tools.releasetools.OtaMetadata.PropertyFilesEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=723, + serialized_end=775, +) + +_OTAMETADATA = _descriptor.Descriptor( + name='OtaMetadata', + full_name='build.tools.releasetools.OtaMetadata', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='type', full_name='build.tools.releasetools.OtaMetadata.type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='wipe', full_name='build.tools.releasetools.OtaMetadata.wipe', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='downgrade', full_name='build.tools.releasetools.OtaMetadata.downgrade', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='property_files', full_name='build.tools.releasetools.OtaMetadata.property_files', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='precondition', full_name='build.tools.releasetools.OtaMetadata.precondition', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='postcondition', full_name='build.tools.releasetools.OtaMetadata.postcondition', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='retrofit_dynamic_partitions', full_name='build.tools.releasetools.OtaMetadata.retrofit_dynamic_partitions', index=6, + number=7, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='required_cache', full_name='build.tools.releasetools.OtaMetadata.required_cache', index=7, + number=8, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_OTAMETADATA_PROPERTYFILESENTRY, ], + enum_types=[ + _OTAMETADATA_OTATYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=348, + serialized_end=829, +) + +_DEVICESTATE.fields_by_name['partition_state'].message_type = _PARTITIONSTATE +_OTAMETADATA_PROPERTYFILESENTRY.containing_type = _OTAMETADATA +_OTAMETADATA.fields_by_name['type'].enum_type = _OTAMETADATA_OTATYPE +_OTAMETADATA.fields_by_name['property_files'].message_type = _OTAMETADATA_PROPERTYFILESENTRY +_OTAMETADATA.fields_by_name['precondition'].message_type = _DEVICESTATE +_OTAMETADATA.fields_by_name['postcondition'].message_type = _DEVICESTATE +_OTAMETADATA_OTATYPE.containing_type = _OTAMETADATA +DESCRIPTOR.message_types_by_name['PartitionState'] = _PARTITIONSTATE +DESCRIPTOR.message_types_by_name['DeviceState'] = _DEVICESTATE +DESCRIPTOR.message_types_by_name['OtaMetadata'] = _OTAMETADATA +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +PartitionState = _reflection.GeneratedProtocolMessageType('PartitionState', (_message.Message,), { + 'DESCRIPTOR' : _PARTITIONSTATE, + '__module__' : 'ota_metadata_pb2' + # @@protoc_insertion_point(class_scope:build.tools.releasetools.PartitionState) + }) +_sym_db.RegisterMessage(PartitionState) + +DeviceState = _reflection.GeneratedProtocolMessageType('DeviceState', (_message.Message,), { + 'DESCRIPTOR' : _DEVICESTATE, + '__module__' : 'ota_metadata_pb2' + # @@protoc_insertion_point(class_scope:build.tools.releasetools.DeviceState) + }) +_sym_db.RegisterMessage(DeviceState) + +OtaMetadata = _reflection.GeneratedProtocolMessageType('OtaMetadata', (_message.Message,), { + + 'PropertyFilesEntry' : _reflection.GeneratedProtocolMessageType('PropertyFilesEntry', (_message.Message,), { + 'DESCRIPTOR' : _OTAMETADATA_PROPERTYFILESENTRY, + '__module__' : 'ota_metadata_pb2' + # @@protoc_insertion_point(class_scope:build.tools.releasetools.OtaMetadata.PropertyFilesEntry) + }) + , + 'DESCRIPTOR' : _OTAMETADATA, + '__module__' : 'ota_metadata_pb2' + # @@protoc_insertion_point(class_scope:build.tools.releasetools.OtaMetadata) + }) +_sym_db.RegisterMessage(OtaMetadata) +_sym_db.RegisterMessage(OtaMetadata.PropertyFilesEntry) + + +DESCRIPTOR._options = None +_OTAMETADATA_PROPERTYFILESENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py new file mode 100644 index 0000000000..d444d41f83 --- /dev/null +++ b/tools/releasetools/ota_utils.py @@ -0,0 +1,563 @@ +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +import itertools +import os +import zipfile + +import ota_metadata_pb2 +from common import (ZipDelete, ZipClose, OPTIONS, MakeTempFile, + ZipWriteStr, BuildInfo, LoadDictionaryFromFile, + SignFile, PARTITIONS_WITH_CARE_MAP, PartitionBuildProps) + + +OPTIONS.no_signing = False +OPTIONS.force_non_ab = False +OPTIONS.wipe_user_data = False +OPTIONS.downgrade = False +OPTIONS.key_passwords = {} +OPTIONS.package_key = None +OPTIONS.incremental_source = None +OPTIONS.retrofit_dynamic_partitions = False +OPTIONS.output_metadata_path = None +OPTIONS.boot_variable_file = None + +METADATA_NAME = 'META-INF/com/android/metadata' +METADATA_PROTO_NAME = 'META-INF/com/android/metadata.pb' +UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'OTA/*', 'RADIO/*'] + + +def FinalizeMetadata(metadata, input_file, output_file, needed_property_files): + """Finalizes the metadata and signs an A/B OTA package. + + In order to stream an A/B OTA package, we need 'ota-streaming-property-files' + that contains the offsets and sizes for the ZIP entries. An example + property-files string is as follows. + + "payload.bin:679:343,payload_properties.txt:378:45,metadata:69:379" + + OTA server can pass down this string, in addition to the package URL, to the + system update client. System update client can then fetch individual ZIP + entries (ZIP_STORED) directly at the given offset of the URL. + + Args: + metadata: The metadata dict for the package. + input_file: The input ZIP filename that doesn't contain the package METADATA + entry yet. + output_file: The final output ZIP filename. + needed_property_files: The list of PropertyFiles' to be generated. + """ + + def ComputeAllPropertyFiles(input_file, needed_property_files): + # Write the current metadata entry with placeholders. + with zipfile.ZipFile(input_file) as input_zip: + for property_files in needed_property_files: + metadata.property_files[property_files.name] = property_files.Compute( + input_zip) + namelist = input_zip.namelist() + + if METADATA_NAME in namelist or METADATA_PROTO_NAME in namelist: + ZipDelete(input_file, [METADATA_NAME, METADATA_PROTO_NAME]) + output_zip = zipfile.ZipFile(input_file, 'a') + WriteMetadata(metadata, output_zip) + ZipClose(output_zip) + + if OPTIONS.no_signing: + return input_file + + prelim_signing = MakeTempFile(suffix='.zip') + SignOutput(input_file, prelim_signing) + return prelim_signing + + def FinalizeAllPropertyFiles(prelim_signing, needed_property_files): + with zipfile.ZipFile(prelim_signing) as prelim_signing_zip: + for property_files in needed_property_files: + metadata.property_files[property_files.name] = property_files.Finalize( + prelim_signing_zip, + len(metadata.property_files[property_files.name])) + + # SignOutput(), which in turn calls signapk.jar, will possibly reorder the ZIP + # entries, as well as padding the entry headers. We do a preliminary signing + # (with an incomplete metadata entry) to allow that to happen. Then compute + # the ZIP entry offsets, write back the final metadata and do the final + # signing. + prelim_signing = ComputeAllPropertyFiles(input_file, needed_property_files) + try: + FinalizeAllPropertyFiles(prelim_signing, needed_property_files) + except PropertyFiles.InsufficientSpaceException: + # Even with the preliminary signing, the entry orders may change + # dramatically, which leads to insufficiently reserved space during the + # first call to ComputeAllPropertyFiles(). In that case, we redo all the + # preliminary signing works, based on the already ordered ZIP entries, to + # address the issue. + prelim_signing = ComputeAllPropertyFiles( + prelim_signing, needed_property_files) + FinalizeAllPropertyFiles(prelim_signing, needed_property_files) + + # Replace the METADATA entry. + ZipDelete(prelim_signing, [METADATA_NAME, METADATA_PROTO_NAME]) + output_zip = zipfile.ZipFile(prelim_signing, 'a') + WriteMetadata(metadata, output_zip) + ZipClose(output_zip) + + # Re-sign the package after updating the metadata entry. + if OPTIONS.no_signing: + output_file = prelim_signing + else: + SignOutput(prelim_signing, output_file) + + # Reopen the final signed zip to double check the streaming metadata. + with zipfile.ZipFile(output_file) as output_zip: + for property_files in needed_property_files: + property_files.Verify( + output_zip, metadata.property_files[property_files.name].strip()) + + # If requested, dump the metadata to a separate file. + output_metadata_path = OPTIONS.output_metadata_path + if output_metadata_path: + WriteMetadata(metadata, output_metadata_path) + + +def WriteMetadata(metadata_proto, output): + """Writes the metadata to the zip archive or a file. + + Args: + metadata_proto: The metadata protobuf for the package. + output: A ZipFile object or a string of the output file path. If a string + path is given, the metadata in the protobuf format will be written to + {output}.pb, e.g. ota_metadata.pb + """ + + metadata_dict = BuildLegacyOtaMetadata(metadata_proto) + legacy_metadata = "".join(["%s=%s\n" % kv for kv in + sorted(metadata_dict.items())]) + if isinstance(output, zipfile.ZipFile): + ZipWriteStr(output, METADATA_PROTO_NAME, metadata_proto.SerializeToString(), + compress_type=zipfile.ZIP_STORED) + ZipWriteStr(output, METADATA_NAME, legacy_metadata, + compress_type=zipfile.ZIP_STORED) + return + + with open('{}.pb'.format(output), 'w') as f: + f.write(metadata_proto.SerializeToString()) + with open(output, 'w') as f: + f.write(legacy_metadata) + + +def UpdateDeviceState(device_state, build_info, boot_variable_values, + is_post_build): + """Update the fields of the DeviceState proto with build info.""" + + def UpdatePartitionStates(partition_states): + """Update the per-partition state according to its build.prop""" + if not build_info.is_ab: + return + build_info_set = ComputeRuntimeBuildInfos(build_info, + boot_variable_values) + assert "ab_partitions" in build_info.info_dict,\ + "ab_partitions property required for ab update." + ab_partitions = set(build_info.info_dict.get("ab_partitions")) + + # delta_generator will error out on unused timestamps, + # so only generate timestamps for dynamic partitions + # used in OTA update. + for partition in sorted(set(PARTITIONS_WITH_CARE_MAP) & ab_partitions): + partition_prop = build_info.info_dict.get( + '{}.build.prop'.format(partition)) + # Skip if the partition is missing, or it doesn't have a build.prop + if not partition_prop or not partition_prop.build_props: + continue + + partition_state = partition_states.add() + partition_state.partition_name = partition + # Update the partition's runtime device names and fingerprints + partition_devices = set() + partition_fingerprints = set() + for runtime_build_info in build_info_set: + partition_devices.add( + runtime_build_info.GetPartitionBuildProp('ro.product.device', + partition)) + partition_fingerprints.add( + runtime_build_info.GetPartitionFingerprint(partition)) + + partition_state.device.extend(sorted(partition_devices)) + partition_state.build.extend(sorted(partition_fingerprints)) + + # TODO(xunchang) set the boot image's version with kmi. Note the boot + # image doesn't have a file map. + partition_state.version = build_info.GetPartitionBuildProp( + 'ro.build.date.utc', partition) + + # TODO(xunchang), we can save a call to ComputeRuntimeBuildInfos. + build_devices, build_fingerprints = \ + CalculateRuntimeDevicesAndFingerprints(build_info, boot_variable_values) + device_state.device.extend(sorted(build_devices)) + device_state.build.extend(sorted(build_fingerprints)) + device_state.build_incremental = build_info.GetBuildProp( + 'ro.build.version.incremental') + + UpdatePartitionStates(device_state.partition_state) + + if is_post_build: + device_state.sdk_level = build_info.GetBuildProp( + 'ro.build.version.sdk') + device_state.security_patch_level = build_info.GetBuildProp( + 'ro.build.version.security_patch') + # Use the actual post-timestamp, even for a downgrade case. + device_state.timestamp = int(build_info.GetBuildProp('ro.build.date.utc')) + + +def GetPackageMetadata(target_info, source_info=None): + """Generates and returns the metadata proto. + + It generates a ota_metadata protobuf that contains the info to be written + into an OTA package (META-INF/com/android/metadata.pb). It also handles the + detection of downgrade / data wipe based on the global options. + + Args: + target_info: The BuildInfo instance that holds the target build info. + source_info: The BuildInfo instance that holds the source build info, or + None if generating full OTA. + + Returns: + A protobuf to be written into package metadata entry. + """ + assert isinstance(target_info, BuildInfo) + assert source_info is None or isinstance(source_info, BuildInfo) + + boot_variable_values = {} + if OPTIONS.boot_variable_file: + d = LoadDictionaryFromFile(OPTIONS.boot_variable_file) + for key, values in d.items(): + boot_variable_values[key] = [val.strip() for val in values.split(',')] + + metadata_proto = ota_metadata_pb2.OtaMetadata() + # TODO(xunchang) some fields, e.g. post-device isn't necessary. We can + # consider skipping them if they aren't used by clients. + UpdateDeviceState(metadata_proto.postcondition, target_info, + boot_variable_values, True) + + if target_info.is_ab and not OPTIONS.force_non_ab: + metadata_proto.type = ota_metadata_pb2.OtaMetadata.AB + metadata_proto.required_cache = 0 + else: + metadata_proto.type = ota_metadata_pb2.OtaMetadata.BLOCK + # cache requirement will be updated by the non-A/B codes. + + if OPTIONS.wipe_user_data: + metadata_proto.wipe = True + + if OPTIONS.retrofit_dynamic_partitions: + metadata_proto.retrofit_dynamic_partitions = True + + is_incremental = source_info is not None + if is_incremental: + UpdateDeviceState(metadata_proto.precondition, source_info, + boot_variable_values, False) + else: + metadata_proto.precondition.device.extend( + metadata_proto.postcondition.device) + + # Detect downgrades and set up downgrade flags accordingly. + if is_incremental: + HandleDowngradeMetadata(metadata_proto, target_info, source_info) + + return metadata_proto + + +def BuildLegacyOtaMetadata(metadata_proto): + """Converts the metadata proto to a legacy metadata dict. + + This metadata dict is used to build the legacy metadata text file for + backward compatibility. We won't add new keys to the legacy metadata format. + If new information is needed, we should add it as a new field in OtaMetadata + proto definition. + """ + + separator = '|' + + metadata_dict = {} + if metadata_proto.type == ota_metadata_pb2.OtaMetadata.AB: + metadata_dict['ota-type'] = 'AB' + elif metadata_proto.type == ota_metadata_pb2.OtaMetadata.BLOCK: + metadata_dict['ota-type'] = 'BLOCK' + if metadata_proto.wipe: + metadata_dict['ota-wipe'] = 'yes' + if metadata_proto.retrofit_dynamic_partitions: + metadata_dict['ota-retrofit-dynamic-partitions'] = 'yes' + if metadata_proto.downgrade: + metadata_dict['ota-downgrade'] = 'yes' + + metadata_dict['ota-required-cache'] = str(metadata_proto.required_cache) + + post_build = metadata_proto.postcondition + metadata_dict['post-build'] = separator.join(post_build.build) + metadata_dict['post-build-incremental'] = post_build.build_incremental + metadata_dict['post-sdk-level'] = post_build.sdk_level + metadata_dict['post-security-patch-level'] = post_build.security_patch_level + metadata_dict['post-timestamp'] = str(post_build.timestamp) + + pre_build = metadata_proto.precondition + metadata_dict['pre-device'] = separator.join(pre_build.device) + # incremental updates + if len(pre_build.build) != 0: + metadata_dict['pre-build'] = separator.join(pre_build.build) + metadata_dict['pre-build-incremental'] = pre_build.build_incremental + + metadata_dict.update(metadata_proto.property_files) + + return metadata_dict + + +def HandleDowngradeMetadata(metadata_proto, target_info, source_info): + # Only incremental OTAs are allowed to reach here. + assert OPTIONS.incremental_source is not None + + post_timestamp = target_info.GetBuildProp("ro.build.date.utc") + pre_timestamp = source_info.GetBuildProp("ro.build.date.utc") + is_downgrade = int(post_timestamp) < int(pre_timestamp) + + if OPTIONS.downgrade: + if not is_downgrade: + raise RuntimeError( + "--downgrade or --override_timestamp specified but no downgrade " + "detected: pre: %s, post: %s" % (pre_timestamp, post_timestamp)) + metadata_proto.downgrade = True + else: + if is_downgrade: + raise RuntimeError( + "Downgrade detected based on timestamp check: pre: %s, post: %s. " + "Need to specify --override_timestamp OR --downgrade to allow " + "building the incremental." % (pre_timestamp, post_timestamp)) + + +def ComputeRuntimeBuildInfos(default_build_info, boot_variable_values): + """Returns a set of build info objects that may exist during runtime.""" + + build_info_set = {default_build_info} + if not boot_variable_values: + return build_info_set + + # Calculate all possible combinations of the values for the boot variables. + keys = boot_variable_values.keys() + value_list = boot_variable_values.values() + combinations = [dict(zip(keys, values)) + for values in itertools.product(*value_list)] + for placeholder_values in combinations: + # Reload the info_dict as some build properties may change their values + # based on the value of ro.boot* properties. + info_dict = copy.deepcopy(default_build_info.info_dict) + for partition in PARTITIONS_WITH_CARE_MAP: + partition_prop_key = "{}.build.prop".format(partition) + input_file = info_dict[partition_prop_key].input_file + if isinstance(input_file, zipfile.ZipFile): + with zipfile.ZipFile(input_file.filename) as input_zip: + info_dict[partition_prop_key] = \ + PartitionBuildProps.FromInputFile(input_zip, partition, + placeholder_values) + else: + info_dict[partition_prop_key] = \ + PartitionBuildProps.FromInputFile(input_file, partition, + placeholder_values) + info_dict["build.prop"] = info_dict["system.build.prop"] + build_info_set.add(BuildInfo(info_dict, default_build_info.oem_dicts)) + + return build_info_set + + +def CalculateRuntimeDevicesAndFingerprints(default_build_info, + boot_variable_values): + """Returns a tuple of sets for runtime devices and fingerprints""" + + device_names = set() + fingerprints = set() + build_info_set = ComputeRuntimeBuildInfos(default_build_info, + boot_variable_values) + for runtime_build_info in build_info_set: + device_names.add(runtime_build_info.device) + fingerprints.add(runtime_build_info.fingerprint) + return device_names, fingerprints + + +class PropertyFiles(object): + """A class that computes the property-files string for an OTA package. + + A property-files string is a comma-separated string that contains the + offset/size info for an OTA package. The entries, which must be ZIP_STORED, + can be fetched directly with the package URL along with the offset/size info. + These strings can be used for streaming A/B OTAs, or allowing an updater to + download package metadata entry directly, without paying the cost of + downloading entire package. + + Computing the final property-files string requires two passes. Because doing + the whole package signing (with signapk.jar) will possibly reorder the ZIP + entries, which may in turn invalidate earlier computed ZIP entry offset/size + values. + + This class provides functions to be called for each pass. The general flow is + as follows. + + property_files = PropertyFiles() + # The first pass, which writes placeholders before doing initial signing. + property_files.Compute() + SignOutput() + + # The second pass, by replacing the placeholders with actual data. + property_files.Finalize() + SignOutput() + + And the caller can additionally verify the final result. + + property_files.Verify() + """ + + def __init__(self): + self.name = None + self.required = () + self.optional = () + + def Compute(self, input_zip): + """Computes and returns a property-files string with placeholders. + + We reserve extra space for the offset and size of the metadata entry itself, + although we don't know the final values until the package gets signed. + + Args: + input_zip: The input ZIP file. + + Returns: + A string with placeholders for the metadata offset/size info, e.g. + "payload.bin:679:343,payload_properties.txt:378:45,metadata: ". + """ + return self.GetPropertyFilesString(input_zip, reserve_space=True) + + class InsufficientSpaceException(Exception): + pass + + def Finalize(self, input_zip, reserved_length): + """Finalizes a property-files string with actual METADATA offset/size info. + + The input ZIP file has been signed, with the ZIP entries in the desired + place (signapk.jar will possibly reorder the ZIP entries). Now we compute + the ZIP entry offsets and construct the property-files string with actual + data. Note that during this process, we must pad the property-files string + to the reserved length, so that the METADATA entry size remains the same. + Otherwise the entries' offsets and sizes may change again. + + Args: + input_zip: The input ZIP file. + reserved_length: The reserved length of the property-files string during + the call to Compute(). The final string must be no more than this + size. + + Returns: + A property-files string including the metadata offset/size info, e.g. + "payload.bin:679:343,payload_properties.txt:378:45,metadata:69:379 ". + + Raises: + InsufficientSpaceException: If the reserved length is insufficient to hold + the final string. + """ + result = self.GetPropertyFilesString(input_zip, reserve_space=False) + if len(result) > reserved_length: + raise self.InsufficientSpaceException( + 'Insufficient reserved space: reserved={}, actual={}'.format( + reserved_length, len(result))) + + result += ' ' * (reserved_length - len(result)) + return result + + def Verify(self, input_zip, expected): + """Verifies the input ZIP file contains the expected property-files string. + + Args: + input_zip: The input ZIP file. + expected: The property-files string that's computed from Finalize(). + + Raises: + AssertionError: On finding a mismatch. + """ + actual = self.GetPropertyFilesString(input_zip) + assert actual == expected, \ + "Mismatching streaming metadata: {} vs {}.".format(actual, expected) + + def GetPropertyFilesString(self, zip_file, reserve_space=False): + """ + Constructs the property-files string per request. + + Args: + zip_file: The input ZIP file. + reserved_length: The reserved length of the property-files string. + + Returns: + A property-files string including the metadata offset/size info, e.g. + "payload.bin:679:343,payload_properties.txt:378:45,metadata: ". + """ + + def ComputeEntryOffsetSize(name): + """Computes the zip entry offset and size.""" + info = zip_file.getinfo(name) + offset = info.header_offset + offset += zipfile.sizeFileHeader + offset += len(info.extra) + len(info.filename) + size = info.file_size + return '%s:%d:%d' % (os.path.basename(name), offset, size) + + tokens = [] + tokens.extend(self._GetPrecomputed(zip_file)) + for entry in self.required: + tokens.append(ComputeEntryOffsetSize(entry)) + for entry in self.optional: + if entry in zip_file.namelist(): + tokens.append(ComputeEntryOffsetSize(entry)) + + # 'META-INF/com/android/metadata' is required. We don't know its actual + # offset and length (as well as the values for other entries). So we reserve + # 15-byte as a placeholder ('offset:length'), which is sufficient to cover + # the space for metadata entry. Because 'offset' allows a max of 10-digit + # (i.e. ~9 GiB), with a max of 4-digit for the length. Note that all the + # reserved space serves the metadata entry only. + if reserve_space: + tokens.append('metadata:' + ' ' * 15) + tokens.append('metadata.pb:' + ' ' * 15) + else: + tokens.append(ComputeEntryOffsetSize(METADATA_NAME)) + tokens.append(ComputeEntryOffsetSize(METADATA_PROTO_NAME)) + + return ','.join(tokens) + + def _GetPrecomputed(self, input_zip): + """Computes the additional tokens to be included into the property-files. + + This applies to tokens without actual ZIP entries, such as + payload_metadata.bin. We want to expose the offset/size to updaters, so + that they can download the payload metadata directly with the info. + + Args: + input_zip: The input zip file. + + Returns: + A list of strings (tokens) to be added to the property-files string. + """ + # pylint: disable=no-self-use + # pylint: disable=unused-argument + return [] + + +def SignOutput(temp_zip_name, output_zip_name): + pw = OPTIONS.key_passwords[OPTIONS.package_key] + + SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw, + whole_file=True) diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py index 47360c9464..b4646b7c75 100755 --- a/tools/releasetools/sign_target_files_apks.py +++ b/tools/releasetools/sign_target_files_apks.py @@ -383,8 +383,8 @@ def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys, def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map, - is_compressed): - unsigned = tempfile.NamedTemporaryFile() + is_compressed, apk_name): + unsigned = tempfile.NamedTemporaryFile(suffix='_' + apk_name) unsigned.write(data) unsigned.flush() @@ -402,7 +402,7 @@ def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map, unsigned.close() unsigned = uncompressed - signed = tempfile.NamedTemporaryFile() + signed = tempfile.NamedTemporaryFile(suffix='_' + apk_name) # For pre-N builds, don't upgrade to SHA-256 JAR signatures based on the APK's # minSdkVersion to avoid increasing incremental OTA update sizes. If an APK @@ -488,7 +488,7 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info, if key not in common.SPECIAL_CERT_STRINGS: print(" signing: %-*s (%s)" % (maxsize, name, key)) signed_data = SignApk(data, key, key_passwords[key], platform_api_level, - codename_to_api_level_map, is_compressed) + codename_to_api_level_map, is_compressed, name) common.ZipWriteStr(output_tf_zip, out_info, signed_data) else: # an APK we're not supposed to sign. @@ -608,22 +608,22 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info, elif (OPTIONS.remove_avb_public_keys and (filename.startswith("BOOT/RAMDISK/avb/") or filename.startswith("BOOT/RAMDISK/first_stage_ramdisk/avb/"))): - matched_removal = False - for key_to_remove in OPTIONS.remove_avb_public_keys: - if filename.endswith(key_to_remove): - matched_removal = True - print("Removing AVB public key from ramdisk: %s" % filename) - break - if not matched_removal: - # Copy it verbatim if we don't want to remove it. - common.ZipWriteStr(output_tf_zip, out_info, data) + matched_removal = False + for key_to_remove in OPTIONS.remove_avb_public_keys: + if filename.endswith(key_to_remove): + matched_removal = True + print("Removing AVB public key from ramdisk: %s" % filename) + break + if not matched_removal: + # Copy it verbatim if we don't want to remove it. + common.ZipWriteStr(output_tf_zip, out_info, data) # Skip verity keyid (for system_root_image use) if we will replace it. elif OPTIONS.replace_verity_keyid and filename == "BOOT/cmdline": pass # Skip the care_map as we will regenerate the system/vendor images. - elif filename == "META/care_map.pb" or filename == "META/care_map.txt": + elif filename in ["META/care_map.pb", "META/care_map.txt"]: pass # Updates system_other.avbpubkey in /product/etc/. @@ -967,11 +967,10 @@ def ReplaceAvbSigningKeys(misc_info): if extra_args: print('Setting extra AVB signing args for %s to "%s"' % ( partition, extra_args)) - if partition in AVB_FOOTER_ARGS_BY_PARTITION: - args_key = AVB_FOOTER_ARGS_BY_PARTITION[partition] - else: - # custom partition - args_key = "avb_{}_add_hashtree_footer_args".format(partition) + args_key = AVB_FOOTER_ARGS_BY_PARTITION.get( + partition, + # custom partition + "avb_{}_add_hashtree_footer_args".format(partition)) misc_info[args_key] = (misc_info.get(args_key, '') + ' ' + extra_args) for partition in AVB_FOOTER_ARGS_BY_PARTITION: @@ -1117,7 +1116,7 @@ def ReadApexKeysInfo(tf_zip): privkey.endswith(privkey_suffix) and pubkey[:-pubkey_suffix_len] == privkey[:-privkey_suffix_len]) - # Sanity check on the container key names, as we'll carry them without the + # Check the container key names, as we'll carry them without the # extensions. This doesn't apply to payload keys though, which we will use # full names only. container_cert = matches.group("CONTAINER_CERT") @@ -1150,7 +1149,7 @@ def main(argv): apex_name, key = a.split("=") OPTIONS.extra_apex_payload_keys[apex_name] = key elif o == "--skip_apks_with_path_prefix": - # Sanity check the prefix, which must be in all upper case. + # Check the prefix, which must be in all upper case. prefix = a.split('/')[0] if not prefix or prefix != prefix.upper(): raise ValueError("Invalid path prefix '%s'" % (a,)) diff --git a/tools/releasetools/test_add_img_to_target_files.py b/tools/releasetools/test_add_img_to_target_files.py index c82a40bee4..efa60b67f3 100644 --- a/tools/releasetools/test_add_img_to_target_files.py +++ b/tools/releasetools/test_add_img_to_target_files.py @@ -370,7 +370,7 @@ class AddImagesToTargetFilesTest(test_utils.ReleaseToolsTestCase): with zipfile.ZipFile(output_file, 'w') as output_zip: # Create an existing META/care_map.pb entry. common.ZipWriteStr(output_zip, 'META/care_map.pb', - 'dummy care_map.pb') + 'fake care_map.pb') # Request to add META/care_map.pb again. AddCareMapForAbOta(output_zip, ['system', 'vendor'], image_paths) diff --git a/tools/releasetools/test_apex_utils.py b/tools/releasetools/test_apex_utils.py index 7b4a4b0c71..339ddc73df 100644 --- a/tools/releasetools/test_apex_utils.py +++ b/tools/releasetools/test_apex_utils.py @@ -160,7 +160,7 @@ class ApexUtilsTest(test_utils.ReleaseToolsTestCase): self.payload_key = os.path.join(self.testdata_dir, 'testkey_RSA4096.key') apex_file = signer.ProcessApexFile(apk_keys, self.payload_key) - package_name_extract_cmd = ['aapt', 'dump', 'badging', apex_file] + package_name_extract_cmd = ['aapt2', 'dump', 'badging', apex_file] output = common.RunAndCheckOutput(package_name_extract_cmd) for line in output.splitlines(): # Sample output from aapt: "package: name='com.google.android.wifi' diff --git a/tools/releasetools/test_check_target_files_vintf.py b/tools/releasetools/test_check_target_files_vintf.py index 79f9018774..8725dd6922 100644 --- a/tools/releasetools/test_check_target_files_vintf.py +++ b/tools/releasetools/test_check_target_files_vintf.py @@ -35,20 +35,20 @@ SKELETON_TARGET_FILE_STRUCTURE = { 'SYSTEM_EXT/etc/build.prop': '', # Non-empty files - 'SYSTEM/compatibility_matrix.xml':""" - <compatibility-matrix version="1.0" type="framework"> + 'SYSTEM/etc/vintf/compatibility_matrix.1.xml':""" + <compatibility-matrix version="1.0" level="1" type="framework"> <sepolicy> <sepolicy-version>0.0</sepolicy-version> <kernel-sepolicy-version>0</kernel-sepolicy-version> </sepolicy> </compatibility-matrix>""", 'SYSTEM/manifest.xml': - '<manifest version="1.0" type="framework" />', + '<manifest version="1.0" type="framework"/>', 'VENDOR/build.prop': 'ro.product.first_api_level=29\n', 'VENDOR/compatibility_matrix.xml': '<compatibility-matrix version="1.0" type="device" />', - 'VENDOR/manifest.xml': - '<manifest version="1.0" type="device"/>', + 'VENDOR/etc/vintf/manifest.xml': + '<manifest version="1.0" target-level="1" type="device"/>', 'META/misc_info.txt': 'recovery_api_version=3\nfstab_version=2\nvintf_enforce=true\n', } @@ -87,8 +87,8 @@ class CheckTargetFilesVintfTest(test_utils.ReleaseToolsTestCase): return test_dir @test_utils.SkipIfExternalToolsUnavailable() - def test_CheckVintf_sanity(self): - msg = 'Sanity check with skeleton target files failed.' + def test_CheckVintf_skeleton(self): + msg = 'vintf check with skeleton target files failed.' test_dir = self.prepare_test_dir('does-not-exist') self.assertTrue(CheckVintf(test_dir), msg=msg) @@ -140,6 +140,6 @@ class CheckTargetFilesVintfTest(test_utils.ReleaseToolsTestCase): def test_CheckVintf_bad_xml(self): test_dir = self.prepare_test_dir('does-not-exist') write_string_to_file('not an XML', - os.path.join(test_dir, 'VENDOR/manifest.xml')) + os.path.join(test_dir, 'VENDOR/etc/vintf/manifest.xml')) # Should raise an error because a file has invalid format. self.assertRaises(common.ExternalError, CheckVintf, test_dir) diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py index e4f0812372..81ee53d555 100644 --- a/tools/releasetools/test_common.py +++ b/tools/releasetools/test_common.py @@ -19,6 +19,7 @@ import os import subprocess import tempfile import time +import unittest import zipfile from hashlib import sha1 @@ -1527,6 +1528,88 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase): self.assertEqual('3', chained_partition_args[1]) self.assertTrue(os.path.exists(chained_partition_args[2])) + def test_BuildVBMeta_appendAftlCommandSyntax(self): + testdata_dir = test_utils.get_testdata_dir() + common.OPTIONS.info_dict = { + 'ab_update': 'true', + 'avb_avbtool': 'avbtool', + 'build.prop': common.PartitionBuildProps.FromDictionary( + 'system', { + 'ro.build.version.incremental': '6285659', + 'ro.product.device': 'coral', + 'ro.build.fingerprint': + 'google/coral/coral:R/RP1A.200311.002/' + '6285659:userdebug/dev-keys'} + ), + } + common.OPTIONS.aftl_tool_path = 'aftltool' + common.OPTIONS.aftl_server = 'log.endpoints.aftl-dev.cloud.goog:9000' + common.OPTIONS.aftl_key_path = os.path.join(testdata_dir, + 'test_transparency_key.pub') + common.OPTIONS.aftl_manufacturer_key_path = os.path.join( + testdata_dir, 'test_aftl_rsa4096.pem') + + vbmeta_image = tempfile.NamedTemporaryFile(delete=False) + cmd = common.ConstructAftlMakeImageCommands(vbmeta_image.name) + expected_cmd = [ + 'aftltool', 'make_icp_from_vbmeta', + '--vbmeta_image_path', 'place_holder', + '--output', vbmeta_image.name, + '--version_incremental', '6285659', + '--transparency_log_servers', + 'log.endpoints.aftl-dev.cloud.goog:9000,{}'.format( + common.OPTIONS.aftl_key_path), + '--manufacturer_key', common.OPTIONS.aftl_manufacturer_key_path, + '--algorithm', 'SHA256_RSA4096', + '--padding', '4096'] + + # ignore the place holder, i.e. path to a temp file + self.assertEqual(cmd[:3], expected_cmd[:3]) + self.assertEqual(cmd[4:], expected_cmd[4:]) + + @unittest.skip("enable after we have a server for public") + def test_BuildVBMeta_appendAftlContactServer(self): + testdata_dir = test_utils.get_testdata_dir() + common.OPTIONS.info_dict = { + 'ab_update': 'true', + 'avb_avbtool': 'avbtool', + 'build.prop': common.PartitionBuildProps.FromDictionary( + 'system', { + 'ro.build.version.incremental': '6285659', + 'ro.product.device': 'coral', + 'ro.build.fingerprint': + 'google/coral/coral:R/RP1A.200311.002/' + '6285659:userdebug/dev-keys'} + ) + } + common.OPTIONS.aftl_tool_path = "aftltool" + common.OPTIONS.aftl_server = "log.endpoints.aftl-dev.cloud.goog:9000" + common.OPTIONS.aftl_key_path = os.path.join(testdata_dir, + 'test_transparency_key.pub') + common.OPTIONS.aftl_manufacturer_key_path = os.path.join( + testdata_dir, 'test_aftl_rsa4096.pem') + + input_dir = common.MakeTempDir() + system_image = common.MakeTempFile() + build_image_cmd = ['mkuserimg_mke2fs', input_dir, system_image, 'ext4', + '/system', str(4096 * 100), '-j', '0', '-s'] + common.RunAndCheckOutput(build_image_cmd) + + add_footer_cmd = ['avbtool', 'add_hashtree_footer', + '--partition_size', str(4096 * 150), + '--partition_name', 'system', + '--image', system_image] + common.RunAndCheckOutput(add_footer_cmd) + + vbmeta_image = common.MakeTempFile() + common.BuildVBMeta(vbmeta_image, {'system': system_image}, 'vbmeta', + ['system']) + + verify_cmd = ['aftltool', 'verify_image_icp', '--vbmeta_image_path', + vbmeta_image, '--transparency_log_pub_keys', + common.OPTIONS.aftl_key_path] + common.RunAndCheckOutput(verify_cmd) + class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase): """Checks the format of install-recovery.sh. @@ -1536,12 +1619,12 @@ class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase): def setUp(self): self._tempdir = common.MakeTempDir() - # Create a dummy dict that contains the fstab info for boot&recovery. + # Create a fake dict that contains the fstab info for boot&recovery. self._info = {"fstab" : {}} - dummy_fstab = [ + fake_fstab = [ "/dev/soc.0/by-name/boot /boot emmc defaults defaults", "/dev/soc.0/by-name/recovery /recovery emmc defaults defaults"] - self._info["fstab"] = common.LoadRecoveryFSTab("\n".join, 2, dummy_fstab) + self._info["fstab"] = common.LoadRecoveryFSTab("\n".join, 2, fake_fstab) # Construct the gzipped recovery.img and boot.img self.recovery_data = bytearray([ 0x1f, 0x8b, 0x08, 0x00, 0x81, 0x11, 0x02, 0x5a, 0x00, 0x03, 0x2b, 0x4a, diff --git a/tools/releasetools/test_non_ab_ota.py b/tools/releasetools/test_non_ab_ota.py new file mode 100644 index 0000000000..5207e2fc72 --- /dev/null +++ b/tools/releasetools/test_non_ab_ota.py @@ -0,0 +1,172 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import copy +import zipfile + +import common +import test_utils + +from non_ab_ota import NonAbOtaPropertyFiles, WriteFingerprintAssertion +from test_utils import PropertyFilesTestCase + + +class NonAbOtaPropertyFilesTest(PropertyFilesTestCase): + """Additional validity checks specialized for NonAbOtaPropertyFiles.""" + def setUp(self): + common.OPTIONS.no_signing = False + def test_init(self): + property_files = NonAbOtaPropertyFiles() + self.assertEqual('ota-property-files', property_files.name) + self.assertEqual((), property_files.required) + self.assertEqual((), property_files.optional) + + def test_Compute(self): + entries = () + zip_file = self.construct_zip_package(entries) + property_files = NonAbOtaPropertyFiles() + with zipfile.ZipFile(zip_file) as zip_fp: + property_files_string = property_files.Compute(zip_fp) + + tokens = self._parse_property_files_string(property_files_string) + self.assertEqual(2, len(tokens)) + self._verify_entries(zip_file, tokens, entries) + + def test_Finalize(self): + entries = [ + 'META-INF/com/android/metadata', + 'META-INF/com/android/metadata.pb', + ] + zip_file = self.construct_zip_package(entries) + property_files = NonAbOtaPropertyFiles() + with zipfile.ZipFile(zip_file) as zip_fp: + raw_metadata = property_files.GetPropertyFilesString( + zip_fp, reserve_space=False) + property_files_string = property_files.Finalize(zip_fp, len(raw_metadata)) + tokens = self._parse_property_files_string(property_files_string) + + self.assertEqual(2, len(tokens)) + # 'META-INF/com/android/metadata' will be key'd as 'metadata'. + entries[0] = 'metadata' + entries[1] = 'metadata.pb' + self._verify_entries(zip_file, tokens, entries) + + def test_Verify(self): + entries = ( + 'META-INF/com/android/metadata', + 'META-INF/com/android/metadata.pb', + ) + zip_file = self.construct_zip_package(entries) + property_files = NonAbOtaPropertyFiles() + with zipfile.ZipFile(zip_file) as zip_fp: + raw_metadata = property_files.GetPropertyFilesString( + zip_fp, reserve_space=False) + + property_files.Verify(zip_fp, raw_metadata) + +class NonAbOTATest(test_utils.ReleaseToolsTestCase): + TEST_TARGET_INFO_DICT = { + 'build.prop': common.PartitionBuildProps.FromDictionary( + 'system', { + 'ro.product.device': 'product-device', + 'ro.build.fingerprint': 'build-fingerprint-target', + 'ro.build.version.incremental': 'build-version-incremental-target', + 'ro.build.version.sdk': '27', + 'ro.build.version.security_patch': '2017-12-01', + 'ro.build.date.utc': '1500000000'} + ) + } + TEST_INFO_DICT_USES_OEM_PROPS = { + 'build.prop': common.PartitionBuildProps.FromDictionary( + 'system', { + 'ro.product.name': 'product-name', + 'ro.build.thumbprint': 'build-thumbprint', + 'ro.build.bar': 'build-bar'} + ), + 'vendor.build.prop': common.PartitionBuildProps.FromDictionary( + 'vendor', { + 'ro.vendor.build.fingerprint': 'vendor-build-fingerprint'} + ), + 'property1': 'value1', + 'property2': 4096, + 'oem_fingerprint_properties': 'ro.product.device ro.product.brand', + } + TEST_OEM_DICTS = [ + { + 'ro.product.brand': 'brand1', + 'ro.product.device': 'device1', + }, + { + 'ro.product.brand': 'brand2', + 'ro.product.device': 'device2', + }, + { + 'ro.product.brand': 'brand3', + 'ro.product.device': 'device3', + }, + ] + def test_WriteFingerprintAssertion_without_oem_props(self): + target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) + source_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT) + source_info_dict['build.prop'].build_props['ro.build.fingerprint'] = ( + 'source-build-fingerprint') + source_info = common.BuildInfo(source_info_dict, None) + + script_writer = test_utils.MockScriptWriter() + WriteFingerprintAssertion(script_writer, target_info, source_info) + self.assertEqual( + [('AssertSomeFingerprint', 'source-build-fingerprint', + 'build-fingerprint-target')], + script_writer.lines) + + def test_WriteFingerprintAssertion_with_source_oem_props(self): + target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) + source_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, + self.TEST_OEM_DICTS) + + script_writer = test_utils.MockScriptWriter() + WriteFingerprintAssertion(script_writer, target_info, source_info) + self.assertEqual( + [('AssertFingerprintOrThumbprint', 'build-fingerprint-target', + 'build-thumbprint')], + script_writer.lines) + + def test_WriteFingerprintAssertion_with_target_oem_props(self): + target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, + self.TEST_OEM_DICTS) + source_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) + + script_writer = test_utils.MockScriptWriter() + WriteFingerprintAssertion(script_writer, target_info, source_info) + self.assertEqual( + [('AssertFingerprintOrThumbprint', 'build-fingerprint-target', + 'build-thumbprint')], + script_writer.lines) + + def test_WriteFingerprintAssertion_with_both_oem_props(self): + target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, + self.TEST_OEM_DICTS) + source_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS) + source_info_dict['build.prop'].build_props['ro.build.thumbprint'] = ( + 'source-build-thumbprint') + source_info = common.BuildInfo(source_info_dict, self.TEST_OEM_DICTS) + + script_writer = test_utils.MockScriptWriter() + WriteFingerprintAssertion(script_writer, target_info, source_info) + self.assertEqual( + [('AssertSomeThumbprint', 'build-thumbprint', + 'source-build-thumbprint')], + script_writer.lines) diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py index 7783f963b7..84cd4c809a 100644 --- a/tools/releasetools/test_ota_from_target_files.py +++ b/tools/releasetools/test_ota_from_target_files.py @@ -20,14 +20,18 @@ import os.path import zipfile import common +import ota_metadata_pb2 import test_utils +from ota_utils import ( + BuildLegacyOtaMetadata, CalculateRuntimeDevicesAndFingerprints, + FinalizeMetadata, GetPackageMetadata, PropertyFiles) from ota_from_target_files import ( - _LoadOemDicts, AbOtaPropertyFiles, FinalizeMetadata, - GetPackageMetadata, GetTargetFilesZipForSecondaryImages, - GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles, - Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles, - StreamingPropertyFiles, WriteFingerprintAssertion, - CalculateRuntimeDevicesAndFingerprints) + _LoadOemDicts, AbOtaPropertyFiles, + GetTargetFilesZipForSecondaryImages, + GetTargetFilesZipWithoutPostinstallConfig, + Payload, PayloadSigner, POSTINSTALL_CONFIG, + StreamingPropertyFiles, AB_PARTITIONS) +from test_utils import PropertyFilesTestCase def construct_target_files(secondary=False): @@ -61,7 +65,7 @@ def construct_target_files(secondary=False): 'META/ab_partitions.txt', '\n'.join([partition[1] for partition in ab_partitions])) - # Create dummy images for each of them. + # Create fake images for each of them. for path, partition in ab_partitions: target_files_zip.writestr( '{}/{}.img'.format(path, partition), @@ -142,28 +146,13 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): ), 'vendor.build.prop': common.PartitionBuildProps.FromDictionary( 'vendor', { - 'ro.vendor.build.fingerprint': 'vendor-build-fingerprint'} + 'ro.vendor.build.fingerprint': 'vendor-build-fingerprint'} ), 'property1': 'value1', 'property2': 4096, 'oem_fingerprint_properties': 'ro.product.device ro.product.brand', } - TEST_OEM_DICTS = [ - { - 'ro.product.brand': 'brand1', - 'ro.product.device': 'device1', - }, - { - 'ro.product.brand': 'brand2', - 'ro.product.device': 'device2', - }, - { - 'ro.product.brand': 'brand3', - 'ro.product.device': 'device3', - }, - ] - def setUp(self): self.testdata_dir = test_utils.get_testdata_dir() self.assertTrue(os.path.exists(self.testdata_dir)) @@ -177,63 +166,71 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.no_signing = False common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : None, + common.OPTIONS.package_key: None, } common.OPTIONS.search_path = test_utils.get_search_path() + @staticmethod + def GetLegacyOtaMetadata(target_info, source_info=None): + metadata_proto = GetPackageMetadata(target_info, source_info) + return BuildLegacyOtaMetadata(metadata_proto) + def test_GetPackageMetadata_abOta_full(self): target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT) target_info_dict['ab_update'] = 'true' + target_info_dict['ab_partitions'] = [] target_info = common.BuildInfo(target_info_dict, None) - metadata = GetPackageMetadata(target_info) + metadata = self.GetLegacyOtaMetadata(target_info) self.assertDictEqual( { - 'ota-type' : 'AB', - 'ota-required-cache' : '0', - 'post-build' : 'build-fingerprint-target', - 'post-build-incremental' : 'build-version-incremental-target', - 'post-sdk-level' : '27', - 'post-security-patch-level' : '2017-12-01', - 'post-timestamp' : '1500000000', - 'pre-device' : 'product-device', + 'ota-type': 'AB', + 'ota-required-cache': '0', + 'post-build': 'build-fingerprint-target', + 'post-build-incremental': 'build-version-incremental-target', + 'post-sdk-level': '27', + 'post-security-patch-level': '2017-12-01', + 'post-timestamp': '1500000000', + 'pre-device': 'product-device', }, metadata) def test_GetPackageMetadata_abOta_incremental(self): target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT) target_info_dict['ab_update'] = 'true' + target_info_dict['ab_partitions'] = [] target_info = common.BuildInfo(target_info_dict, None) source_info = common.BuildInfo(self.TEST_SOURCE_INFO_DICT, None) common.OPTIONS.incremental_source = '' - metadata = GetPackageMetadata(target_info, source_info) + metadata = self.GetLegacyOtaMetadata(target_info, source_info) self.assertDictEqual( { - 'ota-type' : 'AB', - 'ota-required-cache' : '0', - 'post-build' : 'build-fingerprint-target', - 'post-build-incremental' : 'build-version-incremental-target', - 'post-sdk-level' : '27', - 'post-security-patch-level' : '2017-12-01', - 'post-timestamp' : '1500000000', - 'pre-device' : 'product-device', - 'pre-build' : 'build-fingerprint-source', - 'pre-build-incremental' : 'build-version-incremental-source', + 'ota-type': 'AB', + 'ota-required-cache': '0', + 'post-build': 'build-fingerprint-target', + 'post-build-incremental': 'build-version-incremental-target', + 'post-sdk-level': '27', + 'post-security-patch-level': '2017-12-01', + 'post-timestamp': '1500000000', + 'pre-device': 'product-device', + 'pre-build': 'build-fingerprint-source', + 'pre-build-incremental': 'build-version-incremental-source', }, metadata) def test_GetPackageMetadata_nonAbOta_full(self): target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) - metadata = GetPackageMetadata(target_info) + metadata = self.GetLegacyOtaMetadata(target_info) self.assertDictEqual( { - 'ota-type' : 'BLOCK', - 'post-build' : 'build-fingerprint-target', - 'post-build-incremental' : 'build-version-incremental-target', - 'post-sdk-level' : '27', - 'post-security-patch-level' : '2017-12-01', - 'post-timestamp' : '1500000000', - 'pre-device' : 'product-device', + 'ota-type': 'BLOCK', + 'ota-required-cache': '0', + 'post-build': 'build-fingerprint-target', + 'post-build-incremental': 'build-version-incremental-target', + 'post-sdk-level': '27', + 'post-security-patch-level': '2017-12-01', + 'post-timestamp': '1500000000', + 'pre-device': 'product-device', }, metadata) @@ -241,52 +238,55 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) source_info = common.BuildInfo(self.TEST_SOURCE_INFO_DICT, None) common.OPTIONS.incremental_source = '' - metadata = GetPackageMetadata(target_info, source_info) + metadata = self.GetLegacyOtaMetadata(target_info, source_info) self.assertDictEqual( { - 'ota-type' : 'BLOCK', - 'post-build' : 'build-fingerprint-target', - 'post-build-incremental' : 'build-version-incremental-target', - 'post-sdk-level' : '27', - 'post-security-patch-level' : '2017-12-01', - 'post-timestamp' : '1500000000', - 'pre-device' : 'product-device', - 'pre-build' : 'build-fingerprint-source', - 'pre-build-incremental' : 'build-version-incremental-source', + 'ota-type': 'BLOCK', + 'ota-required-cache': '0', + 'post-build': 'build-fingerprint-target', + 'post-build-incremental': 'build-version-incremental-target', + 'post-sdk-level': '27', + 'post-security-patch-level': '2017-12-01', + 'post-timestamp': '1500000000', + 'pre-device': 'product-device', + 'pre-build': 'build-fingerprint-source', + 'pre-build-incremental': 'build-version-incremental-source', }, metadata) def test_GetPackageMetadata_wipe(self): target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) common.OPTIONS.wipe_user_data = True - metadata = GetPackageMetadata(target_info) + metadata = self.GetLegacyOtaMetadata(target_info) self.assertDictEqual( { - 'ota-type' : 'BLOCK', - 'ota-wipe' : 'yes', - 'post-build' : 'build-fingerprint-target', - 'post-build-incremental' : 'build-version-incremental-target', - 'post-sdk-level' : '27', - 'post-security-patch-level' : '2017-12-01', - 'post-timestamp' : '1500000000', - 'pre-device' : 'product-device', + 'ota-type': 'BLOCK', + 'ota-required-cache': '0', + 'ota-wipe': 'yes', + 'post-build': 'build-fingerprint-target', + 'post-build-incremental': 'build-version-incremental-target', + 'post-sdk-level': '27', + 'post-security-patch-level': '2017-12-01', + 'post-timestamp': '1500000000', + 'pre-device': 'product-device', }, metadata) def test_GetPackageMetadata_retrofitDynamicPartitions(self): target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) common.OPTIONS.retrofit_dynamic_partitions = True - metadata = GetPackageMetadata(target_info) + metadata = self.GetLegacyOtaMetadata(target_info) self.assertDictEqual( { - 'ota-retrofit-dynamic-partitions' : 'yes', - 'ota-type' : 'BLOCK', - 'post-build' : 'build-fingerprint-target', - 'post-build-incremental' : 'build-version-incremental-target', - 'post-sdk-level' : '27', - 'post-security-patch-level' : '2017-12-01', - 'post-timestamp' : '1500000000', - 'pre-device' : 'product-device', + 'ota-retrofit-dynamic-partitions': 'yes', + 'ota-type': 'BLOCK', + 'ota-required-cache': '0', + 'post-build': 'build-fingerprint-target', + 'post-build-incremental': 'build-version-incremental-target', + 'post-sdk-level': '27', + 'post-security-patch-level': '2017-12-01', + 'post-timestamp': '1500000000', + 'pre-device': 'product-device', }, metadata) @@ -306,7 +306,7 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): target_info = common.BuildInfo(target_info_dict, None) source_info = common.BuildInfo(source_info_dict, None) common.OPTIONS.incremental_source = '' - self.assertRaises(RuntimeError, GetPackageMetadata, target_info, + self.assertRaises(RuntimeError, self.GetLegacyOtaMetadata, target_info, source_info) def test_GetPackageMetadata_downgrade(self): @@ -320,20 +320,22 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.incremental_source = '' common.OPTIONS.downgrade = True common.OPTIONS.wipe_user_data = True - metadata = GetPackageMetadata(target_info, source_info) + metadata = self.GetLegacyOtaMetadata(target_info, source_info) + self.assertDictEqual( { - 'ota-downgrade' : 'yes', - 'ota-type' : 'BLOCK', - 'ota-wipe' : 'yes', - 'post-build' : 'build-fingerprint-target', - 'post-build-incremental' : 'build-version-incremental-target', - 'post-sdk-level' : '27', - 'post-security-patch-level' : '2017-12-01', - 'post-timestamp' : '1400000000', - 'pre-device' : 'product-device', - 'pre-build' : 'build-fingerprint-source', - 'pre-build-incremental' : 'build-version-incremental-source', + 'ota-downgrade': 'yes', + 'ota-type': 'BLOCK', + 'ota-required-cache': '0', + 'ota-wipe': 'yes', + 'post-build': 'build-fingerprint-target', + 'post-build-incremental': 'build-version-incremental-target', + 'post-sdk-level': '27', + 'post-security-patch-level': '2017-12-01', + 'post-timestamp': '1400000000', + 'pre-device': 'product-device', + 'pre-build': 'build-fingerprint-source', + 'pre-build-incremental': 'build-version-incremental-source', }, metadata) @@ -477,13 +479,13 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): 'A' * 1024 * 1024 * 1024, zipfile.ZIP_STORED) - metadata = {} + metadata = ota_metadata_pb2.OtaMetadata() output_file = common.MakeTempFile(suffix='.zip') needed_property_files = ( TestPropertyFiles(), ) FinalizeMetadata(metadata, zip_file, output_file, needed_property_files) - self.assertIn('ota-test-property-files', metadata) + self.assertIn('ota-test-property-files', metadata.property_files) @test_utils.SkipIfExternalToolsUnavailable() def test_FinalizeMetadata(self): @@ -521,66 +523,13 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): 'A' * 1024 * 1024, zipfile.ZIP_STORED) - metadata = {} + metadata = ota_metadata_pb2.OtaMetadata() needed_property_files = ( TestPropertyFiles(), ) output_file = common.MakeTempFile(suffix='.zip') FinalizeMetadata(metadata, zip_file, output_file, needed_property_files) - self.assertIn('ota-test-property-files', metadata) - - def test_WriteFingerprintAssertion_without_oem_props(self): - target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) - source_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT) - source_info_dict['build.prop'].build_props['ro.build.fingerprint'] = ( - 'source-build-fingerprint') - source_info = common.BuildInfo(source_info_dict, None) - - script_writer = test_utils.MockScriptWriter() - WriteFingerprintAssertion(script_writer, target_info, source_info) - self.assertEqual( - [('AssertSomeFingerprint', 'source-build-fingerprint', - 'build-fingerprint-target')], - script_writer.lines) - - def test_WriteFingerprintAssertion_with_source_oem_props(self): - target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) - source_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, - self.TEST_OEM_DICTS) - - script_writer = test_utils.MockScriptWriter() - WriteFingerprintAssertion(script_writer, target_info, source_info) - self.assertEqual( - [('AssertFingerprintOrThumbprint', 'build-fingerprint-target', - 'build-thumbprint')], - script_writer.lines) - - def test_WriteFingerprintAssertion_with_target_oem_props(self): - target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, - self.TEST_OEM_DICTS) - source_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None) - - script_writer = test_utils.MockScriptWriter() - WriteFingerprintAssertion(script_writer, target_info, source_info) - self.assertEqual( - [('AssertFingerprintOrThumbprint', 'build-fingerprint-target', - 'build-thumbprint')], - script_writer.lines) - - def test_WriteFingerprintAssertion_with_both_oem_props(self): - target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, - self.TEST_OEM_DICTS) - source_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS) - source_info_dict['build.prop'].build_props['ro.build.thumbprint'] = ( - 'source-build-thumbprint') - source_info = common.BuildInfo(source_info_dict, self.TEST_OEM_DICTS) - - script_writer = test_utils.MockScriptWriter() - WriteFingerprintAssertion(script_writer, target_info, source_info) - self.assertEqual( - [('AssertSomeThumbprint', 'build-thumbprint', - 'source-build-thumbprint')], - script_writer.lines) + self.assertIn('ota-test-property-files', metadata.property_files) class TestPropertyFiles(PropertyFiles): @@ -599,40 +548,7 @@ class TestPropertyFiles(PropertyFiles): ) -class PropertyFilesTest(test_utils.ReleaseToolsTestCase): - - def setUp(self): - common.OPTIONS.no_signing = False - - @staticmethod - def construct_zip_package(entries): - zip_file = common.MakeTempFile(suffix='.zip') - with zipfile.ZipFile(zip_file, 'w') as zip_fp: - for entry in entries: - zip_fp.writestr( - entry, - entry.replace('.', '-').upper(), - zipfile.ZIP_STORED) - return zip_file - - @staticmethod - def _parse_property_files_string(data): - result = {} - for token in data.split(','): - name, info = token.split(':', 1) - result[name] = info - return result - - def _verify_entries(self, input_file, tokens, entries): - for entry in entries: - offset, size = map(int, tokens[entry].split(':')) - with open(input_file, 'rb') as input_fp: - input_fp.seek(offset) - if entry == 'metadata': - expected = b'META-INF/COM/ANDROID/METADATA' - else: - expected = entry.replace('.', '-').upper().encode() - self.assertEqual(expected, input_fp.read(size)) +class PropertyFilesTest(PropertyFilesTestCase): @test_utils.SkipIfExternalToolsUnavailable() def test_Compute(self): @@ -646,7 +562,7 @@ class PropertyFilesTest(test_utils.ReleaseToolsTestCase): property_files_string = property_files.Compute(zip_fp) tokens = self._parse_property_files_string(property_files_string) - self.assertEqual(3, len(tokens)) + self.assertEqual(4, len(tokens)) self._verify_entries(zip_file, tokens, entries) def test_Compute_withOptionalEntries(self): @@ -662,7 +578,7 @@ class PropertyFilesTest(test_utils.ReleaseToolsTestCase): property_files_string = property_files.Compute(zip_fp) tokens = self._parse_property_files_string(property_files_string) - self.assertEqual(5, len(tokens)) + self.assertEqual(6, len(tokens)) self._verify_entries(zip_file, tokens, entries) def test_Compute_missingRequiredEntry(self): @@ -680,6 +596,7 @@ class PropertyFilesTest(test_utils.ReleaseToolsTestCase): 'required-entry1', 'required-entry2', 'META-INF/com/android/metadata', + 'META-INF/com/android/metadata.pb', ] zip_file = self.construct_zip_package(entries) property_files = TestPropertyFiles() @@ -689,10 +606,11 @@ class PropertyFilesTest(test_utils.ReleaseToolsTestCase): streaming_metadata = property_files.Finalize(zip_fp, len(raw_metadata)) tokens = self._parse_property_files_string(streaming_metadata) - self.assertEqual(3, len(tokens)) + self.assertEqual(4, len(tokens)) # 'META-INF/com/android/metadata' will be key'd as 'metadata' in the # streaming metadata. entries[2] = 'metadata' + entries[3] = 'metadata.pb' self._verify_entries(zip_file, tokens, entries) @test_utils.SkipIfExternalToolsUnavailable() @@ -703,6 +621,7 @@ class PropertyFilesTest(test_utils.ReleaseToolsTestCase): 'optional-entry1', 'optional-entry2', 'META-INF/com/android/metadata', + 'META-INF/com/android/metadata.pb', ) zip_file = self.construct_zip_package(entries) property_files = TestPropertyFiles() @@ -737,6 +656,7 @@ class PropertyFilesTest(test_utils.ReleaseToolsTestCase): 'optional-entry1', 'optional-entry2', 'META-INF/com/android/metadata', + 'META-INF/com/android/metadata.pb', ) zip_file = self.construct_zip_package(entries) property_files = TestPropertyFiles() @@ -753,8 +673,8 @@ class PropertyFilesTest(test_utils.ReleaseToolsTestCase): AssertionError, property_files.Verify, zip_fp, raw_metadata + 'x') -class StreamingPropertyFilesTest(PropertyFilesTest): - """Additional sanity checks specialized for StreamingPropertyFiles.""" +class StreamingPropertyFilesTest(PropertyFilesTestCase): + """Additional validity checks specialized for StreamingPropertyFiles.""" def test_init(self): property_files = StreamingPropertyFiles() @@ -786,7 +706,7 @@ class StreamingPropertyFilesTest(PropertyFilesTest): property_files_string = property_files.Compute(zip_fp) tokens = self._parse_property_files_string(property_files_string) - self.assertEqual(5, len(tokens)) + self.assertEqual(6, len(tokens)) self._verify_entries(zip_file, tokens, entries) def test_Finalize(self): @@ -796,6 +716,7 @@ class StreamingPropertyFilesTest(PropertyFilesTest): 'care_map.txt', 'compatibility.zip', 'META-INF/com/android/metadata', + 'META-INF/com/android/metadata.pb', ] zip_file = self.construct_zip_package(entries) property_files = StreamingPropertyFiles() @@ -805,10 +726,11 @@ class StreamingPropertyFilesTest(PropertyFilesTest): streaming_metadata = property_files.Finalize(zip_fp, len(raw_metadata)) tokens = self._parse_property_files_string(streaming_metadata) - self.assertEqual(5, len(tokens)) + self.assertEqual(6, len(tokens)) # 'META-INF/com/android/metadata' will be key'd as 'metadata' in the # streaming metadata. entries[4] = 'metadata' + entries[5] = 'metadata.pb' self._verify_entries(zip_file, tokens, entries) def test_Verify(self): @@ -818,6 +740,7 @@ class StreamingPropertyFilesTest(PropertyFilesTest): 'care_map.txt', 'compatibility.zip', 'META-INF/com/android/metadata', + 'META-INF/com/android/metadata.pb', ) zip_file = self.construct_zip_package(entries) property_files = StreamingPropertyFiles() @@ -834,8 +757,8 @@ class StreamingPropertyFilesTest(PropertyFilesTest): AssertionError, property_files.Verify, zip_fp, raw_metadata + 'x') -class AbOtaPropertyFilesTest(PropertyFilesTest): - """Additional sanity checks specialized for AbOtaPropertyFiles.""" +class AbOtaPropertyFilesTest(PropertyFilesTestCase): + """Additional validity checks specialized for AbOtaPropertyFiles.""" # The size for payload and metadata signature size. SIGNATURE_SIZE = 256 @@ -849,7 +772,7 @@ class AbOtaPropertyFilesTest(PropertyFilesTest): common.OPTIONS.payload_signer_args = None common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : None, + common.OPTIONS.package_key: None, } def test_init(self): @@ -954,6 +877,7 @@ class AbOtaPropertyFilesTest(PropertyFilesTest): # Put META-INF/com/android/metadata if needed. if with_metadata: entries.append('META-INF/com/android/metadata') + entries.append('META-INF/com/android/metadata.pb') for entry in entries: zip_fp.writestr( @@ -969,9 +893,9 @@ class AbOtaPropertyFilesTest(PropertyFilesTest): property_files_string = property_files.Compute(zip_fp) tokens = self._parse_property_files_string(property_files_string) - # "6" indcludes the four entries above, one metadata entry, and one entry + # "7" indcludes the four entries above, two metadata entries, and one entry # for payload-metadata.bin. - self.assertEqual(6, len(tokens)) + self.assertEqual(7, len(tokens)) self._verify_entries( zip_file, tokens, ('care_map.txt', 'compatibility.zip')) @@ -982,12 +906,13 @@ class AbOtaPropertyFilesTest(PropertyFilesTest): with zipfile.ZipFile(zip_file, 'r') as zip_fp: raw_metadata = property_files.GetPropertyFilesString( zip_fp, reserve_space=False) - property_files_string = property_files.Finalize(zip_fp, len(raw_metadata)) + property_files_string = property_files.Finalize( + zip_fp, len(raw_metadata)) tokens = self._parse_property_files_string(property_files_string) - # "6" indcludes the four entries above, one metadata entry, and one entry + # "7" includes the four entries above, two metadata entries, and one entry # for payload-metadata.bin. - self.assertEqual(6, len(tokens)) + self.assertEqual(7, len(tokens)) self._verify_entries( zip_file, tokens, ('care_map.txt', 'compatibility.zip')) @@ -1002,56 +927,6 @@ class AbOtaPropertyFilesTest(PropertyFilesTest): property_files.Verify(zip_fp, raw_metadata) -class NonAbOtaPropertyFilesTest(PropertyFilesTest): - """Additional sanity checks specialized for NonAbOtaPropertyFiles.""" - - def test_init(self): - property_files = NonAbOtaPropertyFiles() - self.assertEqual('ota-property-files', property_files.name) - self.assertEqual((), property_files.required) - self.assertEqual((), property_files.optional) - - def test_Compute(self): - entries = () - zip_file = self.construct_zip_package(entries) - property_files = NonAbOtaPropertyFiles() - with zipfile.ZipFile(zip_file) as zip_fp: - property_files_string = property_files.Compute(zip_fp) - - tokens = self._parse_property_files_string(property_files_string) - self.assertEqual(1, len(tokens)) - self._verify_entries(zip_file, tokens, entries) - - def test_Finalize(self): - entries = [ - 'META-INF/com/android/metadata', - ] - zip_file = self.construct_zip_package(entries) - property_files = NonAbOtaPropertyFiles() - with zipfile.ZipFile(zip_file) as zip_fp: - raw_metadata = property_files.GetPropertyFilesString( - zip_fp, reserve_space=False) - property_files_string = property_files.Finalize(zip_fp, len(raw_metadata)) - tokens = self._parse_property_files_string(property_files_string) - - self.assertEqual(1, len(tokens)) - # 'META-INF/com/android/metadata' will be key'd as 'metadata'. - entries[0] = 'metadata' - self._verify_entries(zip_file, tokens, entries) - - def test_Verify(self): - entries = ( - 'META-INF/com/android/metadata', - ) - zip_file = self.construct_zip_package(entries) - property_files = NonAbOtaPropertyFiles() - with zipfile.ZipFile(zip_file) as zip_fp: - raw_metadata = property_files.GetPropertyFilesString( - zip_fp, reserve_space=False) - - property_files.Verify(zip_fp, raw_metadata) - - class PayloadSignerTest(test_utils.ReleaseToolsTestCase): SIGFILE = 'sigfile.bin' @@ -1065,7 +940,7 @@ class PayloadSignerTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.payload_signer_args = [] common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : None, + common.OPTIONS.package_key: None, } def _assertFilesEqual(self, file1, file2): @@ -1083,7 +958,7 @@ class PayloadSignerTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.package_key = os.path.join( self.testdata_dir, 'testkey_with_passwd') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : 'foo', + common.OPTIONS.package_key: 'foo', } payload_signer = PayloadSigner() self.assertEqual('openssl', payload_signer.signer) @@ -1160,7 +1035,7 @@ class PayloadTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.payload_signer_args = None common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : None, + common.OPTIONS.package_key: None, } @staticmethod @@ -1315,8 +1190,8 @@ class PayloadTest(test_utils.ReleaseToolsTestCase): # Then assert these entries are stored. for entry_info in verify_zip.infolist(): if entry_info.filename not in ( - Payload.SECONDARY_PAYLOAD_BIN, - Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT): + Payload.SECONDARY_PAYLOAD_BIN, + Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT): continue self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type) @@ -1326,6 +1201,7 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): 'recovery_api_version=3', 'fstab_version=2', 'recovery_as_boot=true', + 'ab_update=true', ] BUILD_PROP = [ @@ -1336,10 +1212,29 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): 'ro.build.tags=build-tags', 'ro.build.version.sdk=30', 'ro.build.version.security_patch=2020', - 'ro.build.date.utc=12345678' + 'ro.build.date.utc=12345678', + 'ro.system.build.version.release=version-release', + 'ro.system.build.id=build-id', + 'ro.system.build.version.incremental=version-incremental', + 'ro.system.build.type=build-type', + 'ro.system.build.tags=build-tags', + 'ro.system.build.version.sdk=30', + 'ro.system.build.version.security_patch=2020', + 'ro.system.build.date.utc=12345678', + 'ro.product.system.brand=generic', + 'ro.product.system.name=generic', + 'ro.product.system.device=generic', ] VENDOR_BUILD_PROP = [ + 'ro.vendor.build.version.release=version-release', + 'ro.vendor.build.id=build-id', + 'ro.vendor.build.version.incremental=version-incremental', + 'ro.vendor.build.type=build-type', + 'ro.vendor.build.tags=build-tags', + 'ro.vendor.build.version.sdk=30', + 'ro.vendor.build.version.security_patch=2020', + 'ro.vendor.build.date.utc=12345678', 'ro.product.vendor.brand=vendor-product-brand', 'ro.product.vendor.name=vendor-product-name', 'ro.product.vendor.device=vendor-product-device' @@ -1468,6 +1363,7 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): 'ro.product.vendor.name=vendor-product-std', 'VENDOR/etc/build_pro.prop': 'ro.product.vendor.name=vendor-product-pro', + AB_PARTITIONS: '\n'.join(['system', 'vendor']), }, self.test_dir) common.OPTIONS.boot_variable_file = common.MakeTempFile() @@ -1475,8 +1371,8 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): f.write('ro.boot.sku_name=std,pro') build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir)) - metadata = GetPackageMetadata(build_info) - self.assertEqual('vendor-product-device', metadata['pre-device']) + metadata_dict = BuildLegacyOtaMetadata(GetPackageMetadata(build_info)) + self.assertEqual('vendor-product-device', metadata_dict['pre-device']) fingerprints = [ self.constructFingerprint( 'vendor-product-brand/vendor-product-name/vendor-product-device'), @@ -1485,7 +1381,33 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): self.constructFingerprint( 'vendor-product-brand/vendor-product-std/vendor-product-device'), ] - self.assertEqual('|'.join(fingerprints), metadata['post-build']) + self.assertEqual('|'.join(fingerprints), metadata_dict['post-build']) + + def CheckMetadataEqual(self, metadata_dict, metadata_proto): + post_build = metadata_proto.postcondition + self.assertEqual('|'.join(post_build.build), + metadata_dict['post-build']) + self.assertEqual(post_build.build_incremental, + metadata_dict['post-build-incremental']) + self.assertEqual(post_build.sdk_level, + metadata_dict['post-sdk-level']) + self.assertEqual(post_build.security_patch_level, + metadata_dict['post-security-patch-level']) + + if metadata_proto.type == ota_metadata_pb2.OtaMetadata.AB: + ota_type = 'AB' + elif metadata_proto.type == ota_metadata_pb2.OtaMetadata.BLOCK: + ota_type = 'BLOCK' + else: + ota_type = '' + self.assertEqual(ota_type, metadata_dict['ota-type']) + self.assertEqual(metadata_proto.wipe, + metadata_dict.get('ota-wipe') == 'yes') + self.assertEqual(metadata_proto.required_cache, + int(metadata_dict.get('ota-required-cache', 0))) + self.assertEqual(metadata_proto.retrofit_dynamic_partitions, + metadata_dict.get( + 'ota-retrofit-dynamic-partitions') == 'yes') def test_GetPackageMetadata_incremental_package(self): vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP) @@ -1493,6 +1415,8 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): 'import /vendor/etc/build_${ro.boot.sku_name}.prop', ]) self.writeFiles({ + 'META/misc_info.txt': '\n'.join(self.MISC_INFO), + 'META/ab_partitions.txt': '\n'.join(['system', 'vendor', 'product']), 'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP), 'VENDOR/build.prop': '\n'.join(vendor_build_prop), 'VENDOR/etc/build_std.prop': @@ -1514,10 +1438,22 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): 'ro.build.tags=build-tags', 'ro.build.version.sdk=29', 'ro.build.version.security_patch=2020', - 'ro.build.date.utc=12340000' + 'ro.build.date.utc=12340000', + 'ro.system.build.version.release=source-version-release', + 'ro.system.build.id=source-build-id', + 'ro.system.build.version.incremental=source-version-incremental', + 'ro.system.build.type=build-type', + 'ro.system.build.tags=build-tags', + 'ro.system.build.version.sdk=29', + 'ro.system.build.version.security_patch=2020', + 'ro.system.build.date.utc=12340000', + 'ro.product.system.brand=generic', + 'ro.product.system.name=generic', + 'ro.product.system.device=generic', ] self.writeFiles({ 'META/misc_info.txt': '\n'.join(self.MISC_INFO), + 'META/ab_partitions.txt': '\n'.join(['system', 'vendor', 'product']), 'SYSTEM/build.prop': '\n'.join(source_build_prop), 'VENDOR/build.prop': '\n'.join(vendor_build_prop), 'VENDOR/etc/build_std.prop': @@ -1530,21 +1466,22 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): target_info = common.BuildInfo(common.LoadInfoDict(self.test_dir)) source_info = common.BuildInfo(common.LoadInfoDict(source_dir)) - metadata = GetPackageMetadata(target_info, source_info) + metadata_proto = GetPackageMetadata(target_info, source_info) + metadata_dict = BuildLegacyOtaMetadata(metadata_proto) self.assertEqual( 'vendor-device-pro|vendor-device-std|vendor-product-device', - metadata['pre-device']) - suffix = ':source-version-release/source-build-id/' \ - 'source-version-incremental:build-type/build-tags' + metadata_dict['pre-device']) + source_suffix = ':source-version-release/source-build-id/' \ + 'source-version-incremental:build-type/build-tags' pre_fingerprints = [ 'vendor-product-brand/vendor-product-name/vendor-device-pro' - '{}'.format(suffix), + '{}'.format(source_suffix), 'vendor-product-brand/vendor-product-name/vendor-device-std' - '{}'.format(suffix), + '{}'.format(source_suffix), 'vendor-product-brand/vendor-product-name/vendor-product-device' - '{}'.format(suffix), + '{}'.format(source_suffix), ] - self.assertEqual('|'.join(pre_fingerprints), metadata['pre-build']) + self.assertEqual('|'.join(pre_fingerprints), metadata_dict['pre-build']) post_fingerprints = [ self.constructFingerprint( @@ -1554,4 +1491,31 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): self.constructFingerprint( 'vendor-product-brand/vendor-product-name/vendor-product-device'), ] - self.assertEqual('|'.join(post_fingerprints), metadata['post-build']) + self.assertEqual('|'.join(post_fingerprints), metadata_dict['post-build']) + + self.CheckMetadataEqual(metadata_dict, metadata_proto) + + pre_partition_states = metadata_proto.precondition.partition_state + self.assertEqual(2, len(pre_partition_states)) + self.assertEqual('system', pre_partition_states[0].partition_name) + self.assertEqual(['generic'], pre_partition_states[0].device) + self.assertEqual(['generic/generic/generic{}'.format(source_suffix)], + pre_partition_states[0].build) + + self.assertEqual('vendor', pre_partition_states[1].partition_name) + self.assertEqual(['vendor-device-pro', 'vendor-device-std', + 'vendor-product-device'], pre_partition_states[1].device) + vendor_fingerprints = post_fingerprints + self.assertEqual(vendor_fingerprints, pre_partition_states[1].build) + + post_partition_states = metadata_proto.postcondition.partition_state + self.assertEqual(2, len(post_partition_states)) + self.assertEqual('system', post_partition_states[0].partition_name) + self.assertEqual(['generic'], post_partition_states[0].device) + self.assertEqual([self.constructFingerprint('generic/generic/generic')], + post_partition_states[0].build) + + self.assertEqual('vendor', post_partition_states[1].partition_name) + self.assertEqual(['vendor-device-pro', 'vendor-device-std', + 'vendor-product-device'], post_partition_states[1].device) + self.assertEqual(vendor_fingerprints, post_partition_states[1].build) diff --git a/tools/releasetools/test_utils.py b/tools/releasetools/test_utils.py index e99975765b..7b7f22a9c7 100755 --- a/tools/releasetools/test_utils.py +++ b/tools/releasetools/test_utils.py @@ -22,9 +22,11 @@ Utils for running unittests. import logging import os import os.path +import re import struct import sys import unittest +import zipfile import common @@ -192,9 +194,57 @@ class ReleaseToolsTestCase(unittest.TestCase): def tearDown(self): common.Cleanup() +class PropertyFilesTestCase(ReleaseToolsTestCase): + + @staticmethod + def construct_zip_package(entries): + zip_file = common.MakeTempFile(suffix='.zip') + with zipfile.ZipFile(zip_file, 'w') as zip_fp: + for entry in entries: + zip_fp.writestr( + entry, + entry.replace('.', '-').upper(), + zipfile.ZIP_STORED) + return zip_file + + @staticmethod + def _parse_property_files_string(data): + result = {} + for token in data.split(','): + name, info = token.split(':', 1) + result[name] = info + return result + + def setUp(self): + common.OPTIONS.no_signing = False + + def _verify_entries(self, input_file, tokens, entries): + for entry in entries: + offset, size = map(int, tokens[entry].split(':')) + with open(input_file, 'rb') as input_fp: + input_fp.seek(offset) + if entry == 'metadata': + expected = b'META-INF/COM/ANDROID/METADATA' + elif entry == 'metadata.pb': + expected = b'META-INF/COM/ANDROID/METADATA-PB' + else: + expected = entry.replace('.', '-').upper().encode() + self.assertEqual(expected, input_fp.read(size)) + if __name__ == '__main__': - testsuite = unittest.TestLoader().discover( - os.path.dirname(os.path.realpath(__file__))) + # We only want to run tests from the top level directory. Unfortunately the + # pattern option of unittest.discover, internally using fnmatch, doesn't + # provide a good API to filter the test files based on directory. So we do an + # os walk and load them manually. + test_modules = [] + base_path = os.path.dirname(os.path.realpath(__file__)) + for dirpath, _, files in os.walk(base_path): + for fn in files: + if dirpath == base_path and re.match('test_.*\\.py$', fn): + test_modules.append(fn[:-3]) + + test_suite = unittest.TestLoader().loadTestsFromNames(test_modules) + # atest needs a verbosity level of >= 2 to correctly parse the result. - unittest.TextTestRunner(verbosity=2).run(testsuite) + unittest.TextTestRunner(verbosity=2).run(test_suite) diff --git a/tools/releasetools/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py index 65045150a3..ca70ca8fd5 100644 --- a/tools/releasetools/test_validate_target_files.py +++ b/tools/releasetools/test_validate_target_files.py @@ -25,10 +25,9 @@ import common import test_utils from rangelib import RangeSet from validate_target_files import (ValidateVerifiedBootImages, - ValidateFileConsistency) + ValidateFileConsistency, CheckBuildPropDuplicity) from verity_utils import CreateVerityImageBuilder - class ValidateTargetFilesTest(test_utils.ReleaseToolsTestCase): def setUp(self): @@ -329,3 +328,38 @@ class ValidateTargetFilesTest(test_utils.ReleaseToolsTestCase): with zipfile.ZipFile(input_file) as input_zip: info_dict = {'extfs_sparse_flag': '-s'} ValidateFileConsistency(input_zip, input_tmp, info_dict) + + @staticmethod + def make_build_prop(build_prop): + input_tmp = common.MakeTempDir() + system_dir = os.path.join(input_tmp, 'SYSTEM') + os.makedirs(system_dir) + prop_file = os.path.join(system_dir, 'build.prop') + with open(prop_file, 'w') as output_file: + output_file.write("\n".join(build_prop)) + return input_tmp + + def test_checkDuplicateProps_noDuplicate(self): + build_prop = [ + 'ro.odm.build.date.utc=1578430045', + 'ro.odm.build.fingerprint=' + 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys', + 'ro.product.odm.device=coral', + ] + input_tmp = ValidateTargetFilesTest.make_build_prop(build_prop) + CheckBuildPropDuplicity(input_tmp) + + def test_checkDuplicateProps_withDuplicate(self): + build_prop = [ + 'ro.odm.build.date.utc=1578430045', + 'ro.odm.build.date.utc=1578430049', + 'ro.odm.build.fingerprint=' + 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys', + 'ro.product.odm.device=coral', + ] + input_tmp = ValidateTargetFilesTest.make_build_prop({ + 'ODM/etc/build.prop': '\n'.join(build_prop), + }) + + self.assertRaises(ValueError, CheckBuildPropDuplicity, + input_tmp) diff --git a/tools/releasetools/test_verity_utils.py b/tools/releasetools/test_verity_utils.py index d02bc7f98b..a850390b8e 100644 --- a/tools/releasetools/test_verity_utils.py +++ b/tools/releasetools/test_verity_utils.py @@ -233,8 +233,8 @@ class VerifiedBootVersion1VerityImageBuilderTest(ReleaseToolsTestCase): os.path.join(get_testdata_dir(), 'testkey_mincrypt')) @SkipIfExternalToolsUnavailable() - def test_Build_SanityCheck(self): - # A sanity check for the test itself: the image shouldn't be verifiable + def test_Build_ValidationCheck(self): + # A validity check for the test itself: the image shouldn't be verifiable # with wrong key. self.assertRaises( common.ExternalError, diff --git a/tools/releasetools/testdata/apexkeys_framework.txt b/tools/releasetools/testdata/apexkeys_framework.txt index b9caf9e271..a827f2293b 100644 --- a/tools/releasetools/testdata/apexkeys_framework.txt +++ b/tools/releasetools/testdata/apexkeys_framework.txt @@ -1,5 +1,5 @@ name="com.android.conscrypt.apex" public_key="external/conscrypt/apex/com.android.conscrypt.avbpubkey" private_key="external/conscrypt/apex/com.android.conscrypt.pem" container_certificate="external/conscrypt/apex/com.android.conscrypt.x509.pem" container_private_key="external/conscrypt/apex/com.android.conscrypt.pk8" partition="system" -name="com.android.dummy_product.apex" public_key="selected" private_key="selected" container_certificate="selected" container_private_key="selected" partition="product" +name="com.android.fake_product.apex" public_key="selected" private_key="selected" container_certificate="selected" container_private_key="selected" partition="product" name="com.android.runtime.apex" public_key="bionic/apex/com.android.runtime.avbpubkey" private_key="bionic/apex/com.android.runtime.pem" container_certificate="bionic/apex/com.android.runtime.x509.pem" container_private_key="bionic/apex/com.android.runtime.pk8" partition="system" name="com.android.vndk.current.on_vendor.apex" public_key="not_selected" private_key="not_selected" container_certificate="not_selected" container_private_key="not_selected" partition="vendor" name="com.android.vndk.v27.apex" public_key="packages/modules/vndk/apex/com.android.vndk.v27.pubkey" private_key="packages/modules/vndk/apex/com.android.vndk.v27.pem" container_certificate="packages/modules/vndk/apex/com.android.vndk.v27.x509.pem" container_private_key="packages/modules/vndk/apex/com.android.vndk.v27.pk8" partition="system_ext" diff --git a/tools/releasetools/testdata/apexkeys_merge.txt b/tools/releasetools/testdata/apexkeys_merge.txt index a9355d770d..5b1b544428 100644 --- a/tools/releasetools/testdata/apexkeys_merge.txt +++ b/tools/releasetools/testdata/apexkeys_merge.txt @@ -1,5 +1,5 @@ name="com.android.conscrypt.apex" public_key="external/conscrypt/apex/com.android.conscrypt.avbpubkey" private_key="external/conscrypt/apex/com.android.conscrypt.pem" container_certificate="external/conscrypt/apex/com.android.conscrypt.x509.pem" container_private_key="external/conscrypt/apex/com.android.conscrypt.pk8" partition="system" -name="com.android.dummy_product.apex" public_key="selected" private_key="selected" container_certificate="selected" container_private_key="selected" partition="product" +name="com.android.fake_product.apex" public_key="selected" private_key="selected" container_certificate="selected" container_private_key="selected" partition="product" name="com.android.runtime.apex" public_key="bionic/apex/com.android.runtime.avbpubkey" private_key="bionic/apex/com.android.runtime.pem" container_certificate="bionic/apex/com.android.runtime.x509.pem" container_private_key="bionic/apex/com.android.runtime.pk8" partition="system" name="com.android.vndk.current.on_vendor.apex" public_key="packages/modules/vndk/apex/com.android.vndk.current.pubkey" private_key="packages/modules/vndk/apex/com.android.vndk.current.pem" container_certificate="packages/modules/vndk/apex/com.android.vndk.current.x509.pem" container_private_key="packages/modules/vndk/apex/com.android.vndk.current.pk8" partition="vendor" name="com.android.vndk.v27.apex" public_key="packages/modules/vndk/apex/com.android.vndk.v27.pubkey" private_key="packages/modules/vndk/apex/com.android.vndk.v27.pem" container_certificate="packages/modules/vndk/apex/com.android.vndk.v27.x509.pem" container_private_key="packages/modules/vndk/apex/com.android.vndk.v27.pk8" partition="system_ext" diff --git a/tools/releasetools/testdata/apexkeys_vendor.txt b/tools/releasetools/testdata/apexkeys_vendor.txt index 7dd3964bca..c6a9771076 100644 --- a/tools/releasetools/testdata/apexkeys_vendor.txt +++ b/tools/releasetools/testdata/apexkeys_vendor.txt @@ -1,5 +1,5 @@ name="com.android.conscrypt.apex" public_key="not_selected" private_key="not_selected" container_certificate="not_selected" container_private_key="not_selected" partition="system" -name="com.android.dummy_product.apex" public_key="not_selected" private_key="not_selected" container_certificate="not_selected" container_private_key="not_selected" partition="product" +name="com.android.fake_product.apex" public_key="not_selected" private_key="not_selected" container_certificate="not_selected" container_private_key="not_selected" partition="product" name="com.android.runtime.apex" public_key="not_selected" private_key="not_selected" container_certificate="not_selected" container_private_key="not_selected" partition="system" name="com.android.vndk.current.on_vendor.apex" public_key="packages/modules/vndk/apex/com.android.vndk.current.pubkey" private_key="packages/modules/vndk/apex/com.android.vndk.current.pem" container_certificate="packages/modules/vndk/apex/com.android.vndk.current.x509.pem" container_private_key="packages/modules/vndk/apex/com.android.vndk.current.pk8" partition="vendor" name="com.android.vndk.v27.apex" public_key="not_selected" private_key="not_selected" container_certificate="not_selected" container_private_key="not_selected" partition="system_ext" diff --git a/tools/releasetools/testdata/test_aftl_rsa4096.pem b/tools/releasetools/testdata/test_aftl_rsa4096.pem new file mode 100644 index 0000000000..89f1ef3e59 --- /dev/null +++ b/tools/releasetools/testdata/test_aftl_rsa4096.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDDlhUPUgtWL6LB +Wybp6wsEJeioV1aRLPGSA2/xIpTiJUK46cb/MD5eBTWjKENoIgX23eL/ePy2I68e ++WvcZ5ITGOTRQqNVZIdc5qvr03wkV0BsJQMHSMAHacePpB/4xM5MzN/6Ku1wA8Dw +uK+v/Cw4hqq8H/gP0oPVQ1bwcIePzRPX4YkkyXusoyzTIm5DJ9reVtyFucKqANCN +aFmGxcaEc2nADtARQWJpO95joFsMvr68+JBxpCt8aWbxuSz/rLJ9Y8Z46V/++XG+ +E4QEob/WVY5pUD/RyogLrfhIf+zO7R3wJklXElSFacIX9+RzR9dgkQVbqxLfBKIP +XWLCsF4I4EnvqUtaVjIMl8UpZpoq8pDLRqZ71Os5xZYq06x9E02M6DnvFbZEdaOX +MCz2mmNX3g5FahvJayBhCuNhyTkd79MFR71Wp48TvWxKz3S7q0T0cWHNhtPkHSCa +KwD93AQnqtLKYDGkHIZBzJPcs+QxbzdHyGzhXZb+qh5KmQvNA9HRBQY1RkMmzIbI +8pzYTwpOkbCEhVoCWcRaaF1Pgl+zcpgJOMbBBUabx/dConFIhMDW/I5fHgKgwGqm +tWUibrMPdnfS6W5MXi8jC0eDuZl0VwmdE+4dLujiOofUYnb7D+GXojf3PrSLcTw1 +PmG0f7l5xDKN9a0N+IXqvD2oAANTsQIDAQABAoICAQCW5HXw8OogHvYg2HMIKrbA +B4McRO1baWIhtRcq4PQeGIMGaA2HmS+0l65O5uRCNWWGlJ7pW+0TlCop6mHFk/4F +T8JQk2mxmrI4ARqIAQwYeVwRUuioOP81eO1mK0gjQ6qpY7I0reOq9KpozQN18UYo +gfS82Kkng9EDukUbkKV1UtFJTw3gXLVWdjlB1qFcnCXmPPs7DBpbz+8V+XiAWpsS +WnwumP77IQeMiozDLdaw2YQMBHRjyDVocWTjfmpyAkleJZjcdagC7W1MKIBElomL +EUyigTALaYZWBGy1ekQ3TIY5XUBdtZ2RpAsDNNOCAN3v+VI565zOhCOHWRO1gh24 +vyhBFR0HYqBRoLbLAqo8bM5iLPz1EWGyaTnfxt38J8Va0TD7KihcBnphiA+dkhEF +oc0yIp/8S2o3CfkNok7Ju8Amb7M4JJuKhuP8wxn86fAHpjjd3Y4SlZp0NrTrd7T2 +msLIneb1OUZZxFxyJG1XQGEZplLPalnGadIF4p3q/3nd1rVb491qCNl/A5QwhI9r +ZV62O90M9fu3+cAynBLbMT09IZecNwP1gXmunlY6YH+ymM+3NFqC8q2tnzomiz8/ +Fee0ftZ2C/jK62fET0Y8LPWGkVQGHtvZH0FPg4suA0GMmYAe0tQl93A+jFltfKKZ +RgCDrYs6Wv76E9gnWVnEdQKCAQEA8L76LjZUTKOg83Bra+hP+cXnwGsgwOwJfGBp +OM++5HzlpYjtbD38esBZVJtwb/8xJGdsHtP2n7ZgbSDuAnRj5S50QHIApvRkz1Y+ +1hL8tAdgVP2JkYjpyG3bPk4QVKyXkKvBcp2BCidXs75+HzfOxqkazumaYOYo2guh +azHdka2xSqxcZqo4yyORc/oue25RU4skmuNDOlP0+OTxU/uXnl7QZmlaOfT5TqO4 +s7uER4BXt/87j44mnOBdXmtqrsL49+R9bzVskx76aeuaBbwf7jnpR058E71OZwSd +F1P3fx6hl0yLOZF/5Jnq+14rEna6jH50XtzlhB6deSZFTOw2gwKCAQEAz/qXRzwH +I0YWISgkUG2zBJseHmfHqV4CDzb5+tTJ3B2I8cXE0m2sQJXi2s7oMhWSc1cQOHCX +txpgWaD59uBz2lcwnGRNp27TRXv8Wo+X0+O+lGWU2cO+j8AB2Vtb7F7rCySp0+Uu +z+dBfoQ2zhKEQlkX0YldVILGzCL3QBHVvPC4iDlwkMRbcejDoh9NsBtHL8lG+MAw +ZXbwJjhaJkhTXJFpJpejq70naS8VVlLt8Os80iuBXe5JK/ecAHtsNcJlXO02sMNZ +Fbcy8WosGyvRKQ/tHtTjAlxZ7Ey8usWE8BvWBdUgiIBkIcjLtE2GrA8eOGNb3v1I +HRt8NsV8yaLWuwKCAQAR7SaT6le8nTKO7gARuOq7npDzMwbtVqYeLM+o+08rlGFF +QjzronH6cfg05J4quMXgABN8+CuVGO91MM6IQEJv/lWJtvN1ex1GkxV6u0812JbD +vV1RCPDfi86XhRiSNYfTrfZponDJYMSXDcg2auFqyYzFe3+TV5ATLGqIoN3uyxA4 +jz0SJ/qypaNfD3IGnuBPaD0Bi4ql/TpwjhuqNUHE+SprdczSI/usb2SBfaUL7fKa +MNcuiVc2tz48maMIAFypmMn+TewXyGa9HF4Lr0ZxZr6IIL/8eEwuP5my8v2q6Yz+ +xyRW1Q7A5vUoYoqyhUS+0Wu45JnyjJUNQFxIrg4hAoIBAF1uBIGSvN4iwRQ6FT4w +WahrCre8BVzXh3NQTjJZXylL91YtcwLZE/Wbn+KN6o99U2IPLZE9O1qdNcVt5Hz8 +Te87FfJbuOrLhYuEbFQ+h4U/nUDK9XhyT+wB5JLBUOU5qrtByC0Rmtr411o/iONA +PDwWC/YskEnDygywdIRKvsr3FN7VdvUB0Na2KxRsnZjMWElmUUS0Ccm7CZ0R2aWy +/gfqpuMYYgVnnwnIhfxWmt+MvbDorGAHCMYAoQsyZuUrpB9/zP7RcvanavI6sP+v +ynF43xvnpOdNl3Po8SuyScsXpijOmqPXkaP/sUsZPLOUww2vzPi6raetzjpIs4td +ZLsCggEAe42Zj3FEbruJZeDgmd9lSc0j8UF90mNw8KH44IbuA6R9fGv3WkrNHEVd +XZOwjWqAxhOj6pFoJk8n6h5d8iS/yXFZ0AfBMc21XMecu9mnfx9E9LFAIWmv7Wut +vy3h2BqY+crglpg5RAw+3J97HAGMYCvp+hH2il+9zzjpmCtTD21LRMkw34szY7RR +CDy9G5FTmKVlxw5eegvyj164olQRLurEdUIfSr5UnBjrWftJHy9JW8KWCeFDSmm9 +xCl3nGDyQuZmOTngxPtrOYAhb5LoKR9BeGcy6jlom7V4nYYqm3t1IDBgMqjYGT9c +vqQgxO2OFsQOJQ/4PRYEKd1neTlZrw== +-----END PRIVATE KEY----- diff --git a/tools/releasetools/testdata/test_transparency_key.pub b/tools/releasetools/testdata/test_transparency_key.pub new file mode 100644 index 0000000000..8bfd81619d --- /dev/null +++ b/tools/releasetools/testdata/test_transparency_key.pub @@ -0,0 +1,15 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4ilqCNsenNA013iCdwgD +YPxZ853nbHG9lMBp9boXiwRcqT/8bUKHIL7YX5z7s+QoRYVY3rkMKppRabclXzyx +H59YnPMaU4uv7NqwWzjgaZo7E+vo7IF+KBjV3cJulId5Av0yIYUCsrwd7MpGtWdC +Q3S+7Vd4zwzCKEhcvliNIhnNlp1U3wNkPCxOyCAsMEn6k8O5ar12ke5TvxDv15db +rPDeHh8G2OYWoCkWL+lSN35L2kOJqKqVbLKWrrOd96RCYrrtbPCi580OADJRcUlG +lgcjwmNwmypBWvQMZ6ITj0P0ksHnl1zZz1DE2rXe1goLI1doghb5KxLaezlR8c2C +E3w/uo9KJgNmNgUVzzqZZ6FE0moyIDNOpP7KtZAL0DvEZj6jqLbB0ccPQElrg52m +Dv2/A3nYSr0mYBKeskT4+Bg7PGgoC8p7WyLSxMyzJEDYdtrj9OFx6eZaA23oqTQx +k3Qq5H8RfNBeeSUEeKF7pKH/7gyqZ2bNzBFMA2EBZgBozwRfaeN/HCv3qbaCnwvu +6caacmAsK+RxiYxSL1QsJqyhCWWGxVyenmxdc1KG/u5ypi7OIioztyzR3t2tAzD3 +Nb+2t8lgHBRxbV24yiPlnvPmB1ZYEctXnlRR9Evpl1o9xA9NnybPHKr9rozN39CZ +V/USB8K6ao1y5xPZxa8CZksCAwEAAQ== +-----END PUBLIC KEY----- + diff --git a/tools/releasetools/testdata/vintf/kernel/SYSTEM/compatibility_matrix.xml b/tools/releasetools/testdata/vintf/kernel/SYSTEM/etc/vintf/compatibility_matrix.1.xml index ed46b6b761..a92dd6e667 100644 --- a/tools/releasetools/testdata/vintf/kernel/SYSTEM/compatibility_matrix.xml +++ b/tools/releasetools/testdata/vintf/kernel/SYSTEM/etc/vintf/compatibility_matrix.1.xml @@ -1,4 +1,4 @@ -<compatibility-matrix version="1.0" type="framework"> +<compatibility-matrix version="1.0" level="1" type="framework"> <kernel version="4.14.1" /> <sepolicy> <sepolicy-version>0.0</sepolicy-version> diff --git a/tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/compatibility_matrix.xml b/tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/etc/vintf/compatibility_matrix.1.xml index 5d891fa4a1..1700e214e9 100644 --- a/tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/compatibility_matrix.xml +++ b/tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/etc/vintf/compatibility_matrix.1.xml @@ -1,4 +1,4 @@ -<compatibility-matrix version="1.0" type="framework"> +<compatibility-matrix version="1.0" level="1" type="framework"> <sepolicy> <sepolicy-version>1.0</sepolicy-version> <kernel-sepolicy-version>0</kernel-sepolicy-version> diff --git a/tools/releasetools/testdata/vintf/sku_compat/SYSTEM/compatibility_matrix.xml b/tools/releasetools/testdata/vintf/sku_compat/SYSTEM/etc/vintf/compatibility_matrix.1.xml index 19a9b6a0d4..22272fd30e 100644 --- a/tools/releasetools/testdata/vintf/sku_compat/SYSTEM/compatibility_matrix.xml +++ b/tools/releasetools/testdata/vintf/sku_compat/SYSTEM/etc/vintf/compatibility_matrix.1.xml @@ -1,4 +1,4 @@ -<compatibility-matrix version="1.0" type="framework"> +<compatibility-matrix version="1.0" level="1" type="framework"> <hal format="hidl" optional="false"> <name>foo</name> <version>1.0</version> diff --git a/tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/compatibility_matrix.xml b/tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/etc/vintf/compatibility_matrix.1.xml index e0e0d6c20a..1a3fc43f5a 100644 --- a/tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/compatibility_matrix.xml +++ b/tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/etc/vintf/compatibility_matrix.1.xml @@ -1,4 +1,4 @@ -<compatibility-matrix version="1.0" type="framework"> +<compatibility-matrix version="1.0" level="1" type="framework"> <hal format="hidl" optional="false"> <name>foo</name> <version>1.1</version> diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py index ac469eb685..2e3aa74de6 100755 --- a/tools/releasetools/validate_target_files.py +++ b/tools/releasetools/validate_target_files.py @@ -236,6 +236,15 @@ def ValidateInstallRecoveryScript(input_tmp, info_dict): logging.info('Done checking %s', script_path) +# Symlink files in `src` to `dst`, if the files do not +# already exists in `dst` directory. +def symlinkIfNotExists(src, dst): + if not os.path.isdir(src): + return + for filename in os.listdir(src): + if os.path.exists(os.path.join(dst, filename)): + continue + os.symlink(os.path.join(src, filename), os.path.join(dst, filename)) def ValidateVerifiedBootImages(input_tmp, info_dict, options): """Validates the Verified Boot related images. @@ -257,6 +266,12 @@ def ValidateVerifiedBootImages(input_tmp, info_dict, options): Raises: AssertionError: On any verification failure. """ + # See bug 159299583 + # After commit 5277d1015, some images (e.g. acpio.img and tos.img) are no + # longer copied from RADIO to the IMAGES folder. But avbtool assumes that + # images are in IMAGES folder. So we symlink them. + symlinkIfNotExists(os.path.join(input_tmp, "RADIO"), + os.path.join(input_tmp, "IMAGES")) # Verified boot 1.0 (images signed with boot_signer and verity_signer). if info_dict.get('boot_signer') == 'true': logging.info('Verifying Verified Boot images...') @@ -408,6 +423,34 @@ def ValidateVerifiedBootImages(input_tmp, info_dict, options): 'Verified %s with avbtool (key: %s):\n%s', image, key, stdoutdata.rstrip()) +def CheckDataDuplicity(lines): + build_prop = {} + for line in lines: + if line.startswith("import") or line.startswith("#"): + continue + key, value = line.split("=", 1) + if key in build_prop: + return key + build_prop[key] = value + +def CheckBuildPropDuplicity(input_tmp): + """Check all buld.prop files inside directory input_tmp, raise error + if they contain duplicates""" + + if not os.path.isdir(input_tmp): + raise ValueError("Expect {} to be a directory".format(input_tmp)) + for name in os.listdir(input_tmp): + if not name.isupper(): + continue + for prop_file in ['build.prop', 'etc/build.prop']: + path = os.path.join(input_tmp, name, prop_file) + if not os.path.exists(path): + continue + logging.info("Checking {}".format(path)) + with open(path, 'r') as fp: + dupKey = CheckDataDuplicity(fp.readlines()) + if dupKey: + raise ValueError("{} contains duplicate keys for {}", path, dupKey) def main(): parser = argparse.ArgumentParser( @@ -447,6 +490,8 @@ def main(): with zipfile.ZipFile(args.target_files, 'r') as input_zip: ValidateFileConsistency(input_zip, input_tmp, info_dict) + CheckBuildPropDuplicity(input_tmp) + ValidateInstallRecoveryScript(input_tmp, info_dict) ValidateVerifiedBootImages(input_tmp, info_dict, options) diff --git a/tools/soong_to_convert.py b/tools/soong_to_convert.py index 083f6f78da..949131b1c6 100755 --- a/tools/soong_to_convert.py +++ b/tools/soong_to_convert.py @@ -78,7 +78,7 @@ def process(reader): reverse_deps = dict() module_types = dict() - for (module, module_type, problem, dependencies) in reader: + for (module, module_type, problem, dependencies, makefiles, installed) in reader: module_types[module] = module_type problems[module] = problem deps[module] = [d for d in dependencies.strip().split(' ') if d != ""] diff --git a/tools/test_post_process_props.py b/tools/test_post_process_props.py new file mode 100644 index 0000000000..12d52e566d --- /dev/null +++ b/tools/test_post_process_props.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import contextlib +import io +import unittest + +from unittest.mock import * +from post_process_props import * + +class PropTestCase(unittest.TestCase): + def test_createFromLine(self): + p = Prop.from_line("# this is comment") + self.assertTrue(p.is_comment()) + self.assertEqual("", p.name) + self.assertEqual("", p.value) + self.assertFalse(p.is_optional()) + self.assertEqual("# this is comment", str(p)) + + for line in ["a=b", "a = b", "a= b", "a =b", " a=b "]: + p = Prop.from_line(line) + self.assertFalse(p.is_comment()) + self.assertEqual("a", p.name) + self.assertEqual("b", p.value) + self.assertFalse(p.is_optional()) + self.assertEqual("a=b", str(p)) + + for line in ["a?=b", "a ?= b", "a?= b", "a ?=b", " a?=b "]: + p = Prop.from_line(line) + self.assertFalse(p.is_comment()) + self.assertEqual("a", p.name) + self.assertEqual("b", p.value) + self.assertTrue(p.is_optional()) + self.assertEqual("a?=b", str(p)) + + def test_makeAsComment(self): + p = Prop.from_line("a=b") + p.comments.append("# a comment") + self.assertFalse(p.is_comment()) + + p.make_as_comment() + self.assertTrue(p.is_comment()) + self.assertTrue("# a comment\n#a=b", str(p)) + +class PropListTestcase(unittest.TestCase): + def setUp(self): + content = """ + # comment + foo=true + bar=false + qux?=1 + # another comment + foo?=false + """ + self.patcher = patch("post_process_props.open", mock_open(read_data=content)) + self.mock_open = self.patcher.start() + self.props = PropList("file") + + def tearDown(self): + self.patcher.stop() + self.props = None + + def test_readFromFile(self): + self.assertEqual(4, len(self.props.get_all_props())) + expected = [ + ("foo", "true", False), + ("bar", "false", False), + ("qux", "1", True), + ("foo", "false", True) + ] + for i,p in enumerate(self.props.get_all_props()): + self.assertEqual(expected[i][0], p.name) + self.assertEqual(expected[i][1], p.value) + self.assertEqual(expected[i][2], p.is_optional()) + self.assertFalse(p.is_comment()) + + self.assertEqual(set(["foo", "bar", "qux"]), self.props.get_all_names()) + + self.assertEqual("true", self.props.get_value("foo")) + self.assertEqual("false", self.props.get_value("bar")) + self.assertEqual("1", self.props.get_value("qux")) + + # there are two assignments for 'foo' + self.assertEqual(2, len(self.props.get_props("foo"))) + + def test_putNewProp(self): + self.props.put("new", "30") + + self.assertEqual(5, len(self.props.get_all_props())) + last_prop = self.props.get_all_props()[-1] + self.assertEqual("new", last_prop.name) + self.assertEqual("30", last_prop.value) + self.assertFalse(last_prop.is_optional()) + + def test_putExistingNonOptionalProp(self): + self.props.put("foo", "NewValue") + + self.assertEqual(4, len(self.props.get_all_props())) + foo_prop = self.props.get_props("foo")[0] + self.assertEqual("foo", foo_prop.name) + self.assertEqual("NewValue", foo_prop.value) + self.assertFalse(foo_prop.is_optional()) + self.assertEqual("# Value overridden by post_process_props.py. " + + "Original value: true\nfoo=NewValue", str(foo_prop)) + + def test_putExistingOptionalProp(self): + self.props.put("qux", "2") + + self.assertEqual(5, len(self.props.get_all_props())) + last_prop = self.props.get_all_props()[-1] + self.assertEqual("qux", last_prop.name) + self.assertEqual("2", last_prop.value) + self.assertFalse(last_prop.is_optional()) + self.assertEqual("# Auto-added by post_process_props.py\nqux=2", + str(last_prop)) + + def test_deleteNonOptionalProp(self): + props_to_delete = self.props.get_props("foo")[0] + props_to_delete.delete(reason="testing") + + self.assertEqual(3, len(self.props.get_all_props())) + self.assertEqual("# Removed by post_process_props.py because testing\n" + + "#foo=true", str(props_to_delete)) + + def test_deleteOptionalProp(self): + props_to_delete = self.props.get_props("qux")[0] + props_to_delete.delete(reason="testing") + + self.assertEqual(3, len(self.props.get_all_props())) + self.assertEqual("# Removed by post_process_props.py because testing\n" + + "#qux?=1", str(props_to_delete)) + + def test_overridingNonOptional(self): + props_to_be_overridden = self.props.get_props("foo")[1] + self.assertTrue("true", props_to_be_overridden.value) + + self.assertTrue(override_optional_props(self.props)) + + # size reduced to 3 because foo?=false was overridden by foo=true + self.assertEqual(3, len(self.props.get_all_props())) + + self.assertEqual(1, len(self.props.get_props("foo"))) + self.assertEqual("true", self.props.get_props("foo")[0].value) + + self.assertEqual("# Removed by post_process_props.py because " + + "overridden by foo=true\n#foo?=false", + str(props_to_be_overridden)) + + def test_overridingOptional(self): + content = """ + # comment + qux?=2 + foo=true + bar=false + qux?=1 + # another comment + foo?=false + """ + with patch('post_process_props.open', mock_open(read_data=content)) as m: + props = PropList("hello") + + props_to_be_overridden = props.get_props("qux")[0] + self.assertEqual("2", props_to_be_overridden.value) + + self.assertTrue(override_optional_props(props)) + + self.assertEqual(1, len(props.get_props("qux"))) + self.assertEqual("1", props.get_props("qux")[0].value) + # the only left optional assignment becomes non-optional + self.assertFalse(props.get_props("qux")[0].is_optional()) + + self.assertEqual("# Removed by post_process_props.py because " + + "overridden by qux?=1\n#qux?=2", + str(props_to_be_overridden)) + + def test_overridingDuplicated(self): + content = """ + # comment + foo=true + bar=false + qux?=1 + foo=false + # another comment + foo?=false + """ + with patch("post_process_props.open", mock_open(read_data=content)) as m: + stderr_redirect = io.StringIO() + with contextlib.redirect_stderr(stderr_redirect): + props = PropList("hello") + + # fails due to duplicated foo=true and foo=false + self.assertFalse(override_optional_props(props)) + + self.assertEqual("error: found duplicate sysprop assignments:\n" + + "foo=true\nfoo=false\n", stderr_redirect.getvalue()) + + def test_overridingDuplicatedWithSameValue(self): + content = """ + # comment + foo=true + bar=false + qux?=1 + foo=true + # another comment + foo?=false + """ + with patch("post_process_props.open", mock_open(read_data=content)) as m: + stderr_redirect = io.StringIO() + with contextlib.redirect_stderr(stderr_redirect): + props = PropList("hello") + optional_prop = props.get_props("foo")[2] # the last foo?=false one + + # we have duplicated foo=true and foo=true, but that's allowed + # since they have the same value + self.assertTrue(override_optional_props(props)) + + # foo?=false should be commented out + self.assertEqual("# Removed by post_process_props.py because " + + "overridden by foo=true\n#foo?=false", + str(optional_prop)) + + def test_allowDuplicates(self): + content = """ + # comment + foo=true + bar=false + qux?=1 + foo=false + # another comment + foo?=false + """ + with patch("post_process_props.open", mock_open(read_data=content)) as m: + stderr_redirect = io.StringIO() + with contextlib.redirect_stderr(stderr_redirect): + props = PropList("hello") + + # we have duplicated foo=true and foo=false, but that's allowed + # because it's explicitly allowed + self.assertTrue(override_optional_props(props, allow_dup=True)) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/tools/warn/chrome_project_list.py b/tools/warn/chrome_project_list.py new file mode 100644 index 0000000000..609652267b --- /dev/null +++ b/tools/warn/chrome_project_list.py @@ -0,0 +1,686 @@ +# python3 +"""Clang_Tidy_Warn Project List data for Chrome. + +This file stores the Chrome project_list used in warn.py and +its dependencies. It has been put into this file for easier navigation and +unification of the Chrome and Android warn.py. +""" + + +def create_pattern(pattern): + return [pattern, '(^|.*/)' + pattern + '/.*: warning:'] + + +# A list of [project_name, file_path_pattern]. +project_list = [ + create_pattern('android_webview'), + create_pattern('apps'), + create_pattern('ash/app_list'), + create_pattern('ash/public'), + create_pattern('ash/assistant'), + create_pattern('ash/display'), + create_pattern('ash/resources'), + create_pattern('ash/login'), + create_pattern('ash/system'), + create_pattern('ash/wm'), + create_pattern('ash/shelf'), + create_pattern('ash'), + create_pattern('base/trace_event'), + create_pattern('base/debug'), + create_pattern('base/third_party'), + create_pattern('base/files'), + create_pattern('base/test'), + create_pattern('base/util'), + create_pattern('base/task'), + create_pattern('base/metrics'), + create_pattern('base/strings'), + create_pattern('base/memory'), + create_pattern('base'), + create_pattern('build'), + create_pattern('build_overrides'), + create_pattern('buildtools'), + create_pattern('cc'), + create_pattern('chrome/services'), + create_pattern('chrome/app'), + create_pattern('chrome/renderer'), + create_pattern('chrome/test'), + create_pattern('chrome/common/safe_browsing'), + create_pattern('chrome/common/importer'), + create_pattern('chrome/common/media_router'), + create_pattern('chrome/common/extensions'), + create_pattern('chrome/common'), + create_pattern('chrome/browser/sync_file_system'), + create_pattern('chrome/browser/safe_browsing'), + create_pattern('chrome/browser/download'), + create_pattern('chrome/browser/ui'), + create_pattern('chrome/browser/supervised_user'), + create_pattern('chrome/browser/search'), + create_pattern('chrome/browser/browsing_data'), + create_pattern('chrome/browser/predictors'), + create_pattern('chrome/browser/net'), + create_pattern('chrome/browser/devtools'), + create_pattern('chrome/browser/resource_coordinator'), + create_pattern('chrome/browser/page_load_metrics'), + create_pattern('chrome/browser/extensions'), + create_pattern('chrome/browser/ssl'), + create_pattern('chrome/browser/printing'), + create_pattern('chrome/browser/profiles'), + create_pattern('chrome/browser/chromeos'), + create_pattern('chrome/browser/performance_manager'), + create_pattern('chrome/browser/metrics'), + create_pattern('chrome/browser/component_updater'), + create_pattern('chrome/browser/media'), + create_pattern('chrome/browser/notifications'), + create_pattern('chrome/browser/web_applications'), + create_pattern('chrome/browser/media_galleries'), + create_pattern('chrome/browser'), + create_pattern('chrome'), + create_pattern('chromecast'), + create_pattern('chromeos/services'), + create_pattern('chromeos/dbus'), + create_pattern('chromeos/assistant'), + create_pattern('chromeos/components'), + create_pattern('chromeos/settings'), + create_pattern('chromeos/constants'), + create_pattern('chromeos/network'), + create_pattern('chromeos'), + create_pattern('cloud_print'), + create_pattern('components/crash'), + create_pattern('components/subresource_filter'), + create_pattern('components/invalidation'), + create_pattern('components/autofill'), + create_pattern('components/onc'), + create_pattern('components/arc'), + create_pattern('components/safe_browsing'), + create_pattern('components/services'), + create_pattern('components/cast_channel'), + create_pattern('components/download'), + create_pattern('components/feed'), + create_pattern('components/offline_pages'), + create_pattern('components/bookmarks'), + create_pattern('components/cloud_devices'), + create_pattern('components/mirroring'), + create_pattern('components/spellcheck'), + create_pattern('components/viz'), + create_pattern('components/gcm_driver'), + create_pattern('components/ntp_snippets'), + create_pattern('components/translate'), + create_pattern('components/search_engines'), + create_pattern('components/background_task_scheduler'), + create_pattern('components/signin'), + create_pattern('components/chromeos_camera'), + create_pattern('components/reading_list'), + create_pattern('components/assist_ranker'), + create_pattern('components/payments'), + create_pattern('components/feedback'), + create_pattern('components/ui_devtools'), + create_pattern('components/password_manager'), + create_pattern('components/omnibox'), + create_pattern('components/content_settings'), + create_pattern('components/dom_distiller'), + create_pattern('components/nacl'), + create_pattern('components/metrics'), + create_pattern('components/policy'), + create_pattern('components/optimization_guide'), + create_pattern('components/exo'), + create_pattern('components/update_client'), + create_pattern('components/data_reduction_proxy'), + create_pattern('components/sync'), + create_pattern('components/drive'), + create_pattern('components/variations'), + create_pattern('components/history'), + create_pattern('components/webcrypto'), + create_pattern('components'), + create_pattern('content/public'), + create_pattern('content/renderer'), + create_pattern('content/test'), + create_pattern('content/common'), + create_pattern('content/browser'), + create_pattern('content/zygote'), + create_pattern('content'), + create_pattern('courgette'), + create_pattern('crypto'), + create_pattern('dbus'), + create_pattern('device/base'), + create_pattern('device/vr'), + create_pattern('device/gamepad'), + create_pattern('device/test'), + create_pattern('device/fido'), + create_pattern('device/bluetooth'), + create_pattern('device'), + create_pattern('docs'), + create_pattern('extensions/docs'), + create_pattern('extensions/components'), + create_pattern('extensions/buildflags'), + create_pattern('extensions/renderer'), + create_pattern('extensions/test'), + create_pattern('extensions/common'), + create_pattern('extensions/shell'), + create_pattern('extensions/browser'), + create_pattern('extensions/strings'), + create_pattern('extensions'), + create_pattern('fuchsia'), + create_pattern('gin'), + create_pattern('google_apis'), + create_pattern('google_update'), + create_pattern('gpu/perftests'), + create_pattern('gpu/GLES2'), + create_pattern('gpu/command_buffer'), + create_pattern('gpu/tools'), + create_pattern('gpu/gles2_conform_support'), + create_pattern('gpu/ipc'), + create_pattern('gpu/khronos_glcts_support'), + create_pattern('gpu'), + create_pattern('headless'), + create_pattern('infra'), + create_pattern('ipc'), + create_pattern('jingle'), + create_pattern('media'), + create_pattern('mojo'), + create_pattern('native_client'), + create_pattern('ative_client_sdk'), + create_pattern('net'), + create_pattern('out'), + create_pattern('pdf'), + create_pattern('ppapi'), + create_pattern('printing'), + create_pattern('remoting'), + create_pattern('rlz'), + create_pattern('sandbox'), + create_pattern('services/audio'), + create_pattern('services/content'), + create_pattern('services/data_decoder'), + create_pattern('services/device'), + create_pattern('services/file'), + create_pattern('services/identity'), + create_pattern('services/image_annotation'), + create_pattern('services/media_session'), + create_pattern('services/metrics'), + create_pattern('services/network'), + create_pattern('services/preferences'), + create_pattern('services/proxy_resolver'), + create_pattern('services/resource_coordinator'), + create_pattern('services/service_manager'), + create_pattern('services/shape_detection'), + create_pattern('services/strings'), + create_pattern('services/test'), + create_pattern('services/tracing'), + create_pattern('services/video_capture'), + create_pattern('services/viz'), + create_pattern('services/ws'), + create_pattern('services'), + create_pattern('skia/config'), + create_pattern('skia/ext'), + create_pattern('skia/public'), + create_pattern('skia/tools'), + create_pattern('skia'), + create_pattern('sql'), + create_pattern('storage'), + create_pattern('styleguide'), + create_pattern('testing'), + create_pattern('third_party/Python-Markdown'), + create_pattern('third_party/SPIRV-Tools'), + create_pattern('third_party/abseil-cpp'), + create_pattern('third_party/accessibility-audit'), + create_pattern('third_party/accessibility_test_framework'), + create_pattern('third_party/adobe'), + create_pattern('third_party/afl'), + create_pattern('third_party/android_build_tools'), + create_pattern('third_party/android_crazy_linker'), + create_pattern('third_party/android_data_chart'), + create_pattern('third_party/android_deps'), + create_pattern('third_party/android_media'), + create_pattern('third_party/android_ndk'), + create_pattern('third_party/android_opengl'), + create_pattern('third_party/android_platform'), + create_pattern('third_party/android_protobuf'), + create_pattern('third_party/android_sdk'), + create_pattern('third_party/android_support_test_runner'), + create_pattern('third_party/android_swipe_refresh'), + create_pattern('third_party/android_system_sdk'), + create_pattern('third_party/android_tools'), + create_pattern('third_party/angle'), + create_pattern('third_party/apache-mac'), + create_pattern('third_party/apache-portable-runtime'), + create_pattern('third_party/apache-win32'), + create_pattern('third_party/apk-patch-size-estimator'), + create_pattern('third_party/apple_apsl'), + create_pattern('third_party/arcore-android-sdk'), + create_pattern('third_party/ashmem'), + create_pattern('third_party/auto'), + create_pattern('third_party/axe-core'), + create_pattern('third_party/bazel'), + create_pattern('third_party/binutils'), + create_pattern('third_party/bison'), + create_pattern('third_party/blanketjs'), + create_pattern('third_party/blink/common'), + create_pattern('third_party/blink/manual_tests'), + create_pattern('third_party/blink/perf_tests'), + create_pattern('third_party/blink/public/common'), + create_pattern('third_party/blink/public/default_100_percent'), + create_pattern('third_party/blink/public/default_200_percent'), + create_pattern('third_party/blink/public/platform'), + create_pattern('third_party/blink/public/mojom/ad_tagging'), + create_pattern('third_party/blink/public/mojom/app_banner'), + create_pattern('third_party/blink/public/mojom/appcache'), + create_pattern('third_party/blink/public/mojom/array_buffer'), + create_pattern('third_party/blink/public/mojom/associated_interfaces'), + create_pattern('third_party/blink/public/mojom/autoplay'), + create_pattern('third_party/blink/public/mojom/background_fetch'), + create_pattern('third_party/blink/public/mojom/background_sync'), + create_pattern('third_party/blink/public/mojom/badging'), + create_pattern('third_party/blink/public/mojom/blob'), + create_pattern('third_party/blink/public/mojom/bluetooth'), + create_pattern('third_party/blink/public/mojom/broadcastchannel'), + create_pattern('third_party/blink/public/mojom/cache_storage'), + create_pattern('third_party/blink/public/mojom/choosers'), + create_pattern('third_party/blink/public/mojom/clipboard'), + create_pattern('third_party/blink/public/mojom/commit_result'), + create_pattern('third_party/blink/public/mojom/contacts'), + create_pattern('third_party/blink/public/mojom/cookie_store'), + create_pattern('third_party/blink/public/mojom/crash'), + create_pattern('third_party/blink/public/mojom/credentialmanager'), + create_pattern('third_party/blink/public/mojom/csp'), + create_pattern('third_party/blink/public/mojom/devtools'), + create_pattern('third_party/blink/public/mojom/document_metadata'), + create_pattern('third_party/blink/public/mojom/dom_storage'), + create_pattern('third_party/blink/public/mojom/dwrite_font_proxy'), + create_pattern('third_party/blink/public/mojom/feature_policy'), + create_pattern('third_party/blink/public/mojom/fetch'), + create_pattern('third_party/blink/public/mojom/file'), + create_pattern('third_party/blink/public/mojom/filesystem'), + create_pattern('third_party/blink/public/mojom/font_unique_name_lookup'), + create_pattern('third_party/blink/public/mojom/frame'), + create_pattern('third_party/blink/public/mojom/frame_sinks'), + create_pattern('third_party/blink/public/mojom/geolocation'), + create_pattern('third_party/blink/public/mojom/hyphenation'), + create_pattern('third_party/blink/public/mojom/idle'), + create_pattern('third_party/blink/public/mojom/indexeddb'), + create_pattern('third_party/blink/public/mojom/input'), + create_pattern('third_party/blink/public/mojom/insecure_input'), + create_pattern('third_party/blink/public/mojom/installation'), + create_pattern('third_party/blink/public/mojom/installedapp'), + create_pattern('third_party/blink/public/mojom/keyboard_lock'), + create_pattern('third_party/blink/public/mojom/leak_detector'), + create_pattern('third_party/blink/public/mojom/loader'), + create_pattern('third_party/blink/public/mojom/locks'), + create_pattern('third_party/blink/public/mojom/manifest'), + create_pattern('third_party/blink/public/mojom/media_controls'), + create_pattern('third_party/blink/public/mojom/mediasession'), + create_pattern('third_party/blink/public/mojom/mediastream'), + create_pattern('third_party/blink/public/mojom/messaging'), + create_pattern('third_party/blink/public/mojom/mime'), + create_pattern('third_party/blink/public/mojom/native_file_system'), + create_pattern('third_party/blink/public/mojom/net'), + create_pattern('third_party/blink/public/mojom/notifications'), + create_pattern('third_party/blink/public/mojom/oom_intervention'), + create_pattern('third_party/blink/public/mojom/page'), + create_pattern('third_party/blink/public/mojom/payments'), + create_pattern('third_party/blink/public/mojom/permissions'), + create_pattern('third_party/blink/public/mojom/picture_in_picture'), + create_pattern('third_party/blink/public/mojom/plugins'), + create_pattern('third_party/blink/public/mojom/portal'), + create_pattern('third_party/blink/public/mojom/presentation'), + create_pattern('third_party/blink/public/mojom/push_messaging'), + create_pattern('third_party/blink/public/mojom/quota'), + create_pattern('third_party/blink/public/mojom/remote_objects'), + create_pattern('third_party/blink/public/mojom/reporting'), + create_pattern('third_party/blink/public/mojom/script'), + create_pattern('third_party/blink/public/mojom/selection_menu'), + create_pattern('third_party/blink/public/mojom/serial'), + create_pattern('third_party/blink/public/mojom/service_worker'), + create_pattern('third_party/blink/public/mojom/site_engagement'), + create_pattern('third_party/blink/public/mojom/sms'), + create_pattern('third_party/blink/public/mojom/speech'), + create_pattern('third_party/blink/public/mojom/ukm'), + create_pattern('third_party/blink/public/mojom/unhandled_tap_notifier'), + create_pattern('third_party/blink/public/mojom/usb'), + create_pattern('third_party/blink/public/mojom/use_counter'), + create_pattern('third_party/blink/public/mojom/user_agent'), + create_pattern('third_party/blink/public/mojom/wake_lock'), + create_pattern('third_party/blink/public/mojom/web_client_hints'), + create_pattern('third_party/blink/public/mojom/web_feature'), + create_pattern('third_party/blink/public/mojom/webaudio'), + create_pattern('third_party/blink/public/mojom/webauthn'), + create_pattern('third_party/blink/public/mojom/webdatabase'), + create_pattern('third_party/blink/public/mojom/webshare'), + create_pattern('third_party/blink/public/mojom/window_features'), + create_pattern('third_party/blink/public/mojom/worker'), + create_pattern('third_party/blink/public/web'), + create_pattern('third_party/blink/renderer/bindings'), + create_pattern('third_party/blink/renderer/build'), + create_pattern('third_party/blink/renderer/controller'), + create_pattern('third_party/blink/renderer/core/accessibility'), + create_pattern('third_party/blink/renderer/core/animation'), + create_pattern('third_party/blink/renderer/core/aom'), + create_pattern('third_party/blink/renderer/core/clipboard'), + create_pattern('third_party/blink/renderer/core/content_capture'), + create_pattern('third_party/blink/renderer/core/context_features'), + create_pattern('third_party/blink/renderer/core/css'), + create_pattern('third_party/blink/renderer/core/display_lock'), + create_pattern('third_party/blink/renderer/core/dom'), + create_pattern('third_party/blink/renderer/core/editing'), + create_pattern('third_party/blink/renderer/core/events'), + create_pattern('third_party/blink/renderer/core/execution_context'), + create_pattern('third_party/blink/renderer/core/exported'), + create_pattern('third_party/blink/renderer/core/feature_policy'), + create_pattern('third_party/blink/renderer/core/fetch'), + create_pattern('third_party/blink/renderer/core/fileapi'), + create_pattern('third_party/blink/renderer/core/frame'), + create_pattern('third_party/blink/renderer/core/fullscreen'), + create_pattern('third_party/blink/renderer/core/geometry'), + create_pattern('third_party/blink/renderer/core/html'), + create_pattern('third_party/blink/renderer/core/imagebitmap'), + create_pattern('third_party/blink/renderer/core/input'), + create_pattern('third_party/blink/renderer/core/inspector'), + create_pattern('third_party/blink/renderer/core/intersection_observer'), + create_pattern('third_party/blink/renderer/core/invisible_dom'), + create_pattern('third_party/blink/renderer/core/layout'), + create_pattern('third_party/blink/renderer/core/loader'), + create_pattern('third_party/blink/renderer/core/messaging'), + create_pattern('third_party/blink/renderer/core/mojo'), + create_pattern('third_party/blink/renderer/core/offscreencanvas'), + create_pattern('third_party/blink/renderer/core/origin_trials'), + create_pattern('third_party/blink/renderer/core/page'), + create_pattern('third_party/blink/renderer/core/paint'), + create_pattern('third_party/blink/renderer/core/probe'), + create_pattern('third_party/blink/renderer/core/resize_observer'), + create_pattern('third_party/blink/renderer/core/scheduler'), + create_pattern('third_party/blink/renderer/core/script'), + create_pattern('third_party/blink/renderer/core/scroll'), + create_pattern('third_party/blink/renderer/core/streams'), + create_pattern('third_party/blink/renderer/core/style'), + create_pattern('third_party/blink/renderer/core/svg'), + create_pattern('third_party/blink/renderer/core/testing'), + create_pattern('third_party/blink/renderer/core/timezone'), + create_pattern('third_party/blink/renderer/core/timing'), + create_pattern('third_party/blink/renderer/core/trustedtypes'), + create_pattern('third_party/blink/renderer/core/typed_arrays'), + create_pattern('third_party/blink/renderer/core/url'), + create_pattern('third_party/blink/renderer/core/win'), + create_pattern('third_party/blink/renderer/core/workers'), + create_pattern('third_party/blink/renderer/core/xml'), + create_pattern('third_party/blink/renderer/core/xmlhttprequest'), + create_pattern('third_party/blink/renderer/devtools'), + create_pattern('third_party/blink/renderer/modules'), + create_pattern('third_party/blink/renderer/platform'), + create_pattern('third_party/blink/tools'), + create_pattern('third_party/blink/web_tests'), + create_pattern('third_party/boringssl'), + create_pattern('third_party/bouncycastle'), + create_pattern('third_party/breakpad'), + create_pattern('third_party/brotli'), + create_pattern('third_party/bspatch'), + create_pattern('third_party/byte_buddy'), + create_pattern('third_party/cacheinvalidation'), + create_pattern('third_party/catapult'), + create_pattern('third_party/cct_dynamic_module'), + create_pattern('third_party/ced'), + create_pattern('third_party/chaijs'), + create_pattern('third_party/checkstyle'), + create_pattern('third_party/chromevox'), + create_pattern('third_party/chromite'), + create_pattern('third_party/cld_3'), + create_pattern('third_party/closure_compiler'), + create_pattern('third_party/colorama'), + create_pattern('third_party/crashpad'), + create_pattern('third_party/crc32c'), + create_pattern('third_party/cros_system_api'), + create_pattern('third_party/custom_tabs_client'), + create_pattern('third_party/d3'), + create_pattern('third_party/dav1d'), + create_pattern('third_party/dawn'), + create_pattern('third_party/decklink'), + create_pattern('third_party/depot_tools'), + create_pattern('third_party/devscripts'), + create_pattern('third_party/devtools-node-modules'), + create_pattern('third_party/dom_distiller_js'), + create_pattern('third_party/elfutils'), + create_pattern('third_party/emoji-segmenter'), + create_pattern('third_party/errorprone'), + create_pattern('third_party/espresso'), + create_pattern('third_party/expat'), + create_pattern('third_party/feed'), + create_pattern('third_party/ffmpeg'), + create_pattern('third_party/flac'), + create_pattern('third_party/flatbuffers'), + create_pattern('third_party/flot'), + create_pattern('third_party/fontconfig'), + create_pattern('third_party/freetype'), + create_pattern('third_party/fuchsia-sdk'), + create_pattern('third_party/gestures'), + create_pattern('third_party/gif_player'), + create_pattern('third_party/glfw'), + create_pattern('third_party/glslang'), + create_pattern('third_party/gnu_binutils'), + create_pattern('third_party/google-truth'), + create_pattern('third_party/google_android_play_core'), + create_pattern('third_party/google_appengine_cloudstorage'), + create_pattern('third_party/google_input_tools'), + create_pattern('third_party/google_toolbox_for_mac'), + create_pattern('third_party/google_trust_services'), + create_pattern('third_party/googletest'), + create_pattern('third_party/gperf'), + create_pattern('third_party/gradle_wrapper'), + create_pattern('third_party/grpc'), + create_pattern('third_party/gson'), + create_pattern('third_party/guava'), + create_pattern('third_party/gvr-android-keyboard'), + create_pattern('third_party/gvr-android-sdk'), + create_pattern('third_party/hamcrest'), + create_pattern('third_party/harfbuzz-ng'), + create_pattern('third_party/hunspell'), + create_pattern('third_party/hunspell_dictionaries'), + create_pattern('third_party/iaccessible2'), + create_pattern('third_party/iccjpeg'), + create_pattern('third_party/icu/android'), + create_pattern('third_party/icu/android_small'), + create_pattern('third_party/icu/cast'), + create_pattern('third_party/icu/chromeos'), + create_pattern('third_party/icu/common'), + create_pattern('third_party/icu/filters'), + create_pattern('third_party/icu/flutter'), + create_pattern('third_party/icu/fuzzers'), + create_pattern('third_party/icu/ios'), + create_pattern('third_party/icu/patches'), + create_pattern('third_party/icu/scripts'), + create_pattern('third_party/icu/source'), + create_pattern('third_party/icu/tzres'), + create_pattern('third_party/icu4j'), + create_pattern('third_party/ijar'), + create_pattern('third_party/ink'), + create_pattern('third_party/inspector_protocol'), + create_pattern('third_party/instrumented_libraries'), + create_pattern('third_party/intellij'), + create_pattern('third_party/isimpledom'), + create_pattern('third_party/jacoco'), + create_pattern('third_party/jinja2'), + create_pattern('third_party/jsoncpp'), + create_pattern('third_party/jsr-305'), + create_pattern('third_party/jstemplate'), + create_pattern('third_party/junit'), + create_pattern('third_party/khronos'), + create_pattern('third_party/lcov'), + create_pattern('third_party/leveldatabase'), + create_pattern('third_party/libFuzzer'), + create_pattern('third_party/libXNVCtrl'), + create_pattern('third_party/libaddressinput'), + create_pattern('third_party/libaom'), + create_pattern('third_party/libcxx-pretty-printers'), + create_pattern('third_party/libdrm'), + create_pattern('third_party/libevdev'), + create_pattern('third_party/libjingle_xmpp'), + create_pattern('third_party/libjpeg'), + create_pattern('third_party/libjpeg_turbo'), + create_pattern('third_party/liblouis'), + create_pattern('third_party/libovr'), + create_pattern('third_party/libphonenumber'), + create_pattern('third_party/libpng'), + create_pattern('third_party/libprotobuf-mutator'), + create_pattern('third_party/libsecret'), + create_pattern('third_party/libsrtp'), + create_pattern('third_party/libsync'), + create_pattern('third_party/libudev'), + create_pattern('third_party/libusb'), + create_pattern('third_party/libvpx'), + create_pattern('third_party/libwebm'), + create_pattern('third_party/libwebp'), + create_pattern('third_party/libxml'), + create_pattern('third_party/libxslt'), + create_pattern('third_party/libyuv'), + create_pattern('third_party/lighttpd'), + create_pattern('third_party/logilab'), + create_pattern('third_party/lss'), + create_pattern('third_party/lzma_sdk'), + create_pattern('third_party/mach_override'), + create_pattern('third_party/markdown'), + create_pattern('third_party/markupsafe'), + create_pattern('third_party/material_design_icons'), + create_pattern('third_party/mesa_headers'), + create_pattern('third_party/metrics_proto'), + create_pattern('third_party/microsoft_webauthn'), + create_pattern('third_party/mingw-w64'), + create_pattern('third_party/minigbm'), + create_pattern('third_party/minizip'), + create_pattern('third_party/mocha'), + create_pattern('third_party/mockito'), + create_pattern('third_party/modp_b64'), + create_pattern('third_party/motemplate'), + create_pattern('third_party/mozilla'), + create_pattern('third_party/nacl_sdk_binaries'), + create_pattern('third_party/nasm'), + create_pattern('third_party/netty-tcnative'), + create_pattern('third_party/netty4'), + create_pattern('third_party/node'), + create_pattern('third_party/nvml'), + create_pattern('third_party/objenesis'), + create_pattern('third_party/ocmock'), + create_pattern('third_party/openh264'), + create_pattern('third_party/openscreen'), + create_pattern('third_party/openvr'), + create_pattern('third_party/opus'), + create_pattern('third_party/ots'), + create_pattern('third_party/ow2_asm'), + create_pattern('third_party/pdfium'), + create_pattern('third_party/pefile'), + create_pattern('third_party/perfetto'), + create_pattern('third_party/perl'), + create_pattern('third_party/pexpect'), + create_pattern('third_party/pffft'), + create_pattern('third_party/ply'), + create_pattern('third_party/polymer'), + create_pattern('third_party/proguard'), + create_pattern('third_party/protobuf'), + create_pattern('third_party/protoc_javalite'), + create_pattern('third_party/pycoverage'), + create_pattern('third_party/pyelftools'), + create_pattern('third_party/pyjson5'), + create_pattern('third_party/pylint'), + create_pattern('third_party/pymock'), + create_pattern('third_party/pystache'), + create_pattern('third_party/pywebsocket'), + create_pattern('third_party/qcms'), + create_pattern('third_party/quic_trace'), + create_pattern('third_party/qunit'), + create_pattern('third_party/r8'), + create_pattern('third_party/re2'), + create_pattern('third_party/requests'), + create_pattern('third_party/rnnoise'), + create_pattern('third_party/robolectric'), + create_pattern('third_party/s2cellid'), + create_pattern('third_party/sfntly'), + create_pattern('third_party/shaderc'), + create_pattern('third_party/simplejson'), + create_pattern('third_party/sinonjs'), + create_pattern('third_party/skia'), + create_pattern('third_party/smhasher'), + create_pattern('third_party/snappy'), + create_pattern('third_party/speech-dispatcher'), + create_pattern('third_party/spirv-cross'), + create_pattern('third_party/spirv-headers'), + create_pattern('third_party/sqlite'), + create_pattern('third_party/sqlite4java'), + create_pattern('third_party/sudden_motion_sensor'), + create_pattern('third_party/swiftshader'), + create_pattern('third_party/tcmalloc'), + create_pattern('third_party/test_fonts'), + create_pattern('third_party/tlslite'), + create_pattern('third_party/ub-uiautomator'), + create_pattern('third_party/unrar'), + create_pattern('third_party/usb_ids'), + create_pattern('third_party/usrsctp'), + create_pattern('third_party/v4l-utils'), + create_pattern('third_party/vulkan'), + create_pattern('third_party/wayland'), + create_pattern('third_party/wayland-protocols'), + create_pattern('third_party/wds'), + create_pattern('third_party/web-animations-js'), + create_pattern('third_party/webdriver'), + create_pattern('third_party/webgl'), + create_pattern('third_party/webrtc'), + create_pattern('third_party/webrtc_overrides'), + create_pattern('third_party/webxr_test_pages'), + create_pattern('third_party/widevine'), + create_pattern('third_party/win_build_output'), + create_pattern('third_party/woff2'), + create_pattern('third_party/wtl'), + create_pattern('third_party/xdg-utils'), + create_pattern('third_party/xstream'), + create_pattern('third_party/yasm'), + create_pattern('third_party/zlib'), + create_pattern('tools'), + create_pattern('ui/accelerated_widget_mac'), + create_pattern('ui/accessibility'), + create_pattern('ui/android'), + create_pattern('ui/aura'), + create_pattern('ui/aura_extra'), + create_pattern('ui/base'), + create_pattern('ui/chromeos'), + create_pattern('ui/compositor'), + create_pattern('ui/compositor_extra'), + create_pattern('ui/content_accelerators'), + create_pattern('ui/display'), + create_pattern('ui/events'), + create_pattern('ui/file_manager'), + create_pattern('ui/gfx'), + create_pattern('ui/gl'), + create_pattern('ui/latency'), + create_pattern('ui/login'), + create_pattern('ui/message_center'), + create_pattern('ui/native_theme'), + create_pattern('ui/ozone'), + create_pattern('ui/platform_window'), + create_pattern('ui/resources'), + create_pattern('ui/shell_dialogs'), + create_pattern('ui/snapshot'), + create_pattern('ui/strings'), + create_pattern('ui/surface'), + create_pattern('ui/touch_selection'), + create_pattern('ui/views'), + create_pattern('ui/views_bridge_mac'), + create_pattern('ui/views_content_client'), + create_pattern('ui/web_dialogs'), + create_pattern('ui/webui'), + create_pattern('ui/wm'), + create_pattern('url'), + create_pattern('v8/benchmarks'), + create_pattern('v8/build_overrides'), + create_pattern('v8/custom_deps'), + create_pattern('v8/docs'), + create_pattern('v8/gni'), + create_pattern('v8/include'), + create_pattern('v8/infra'), + create_pattern('v8/samples'), + create_pattern('v8/src'), + create_pattern('v8/test'), + create_pattern('v8/testing'), + create_pattern('v8/third_party'), + create_pattern('v8/tools'), + + # keep out/obj and other patterns at the end. + [ + 'out/obj', '.*/(gen|obj[^/]*)/(include|EXECUTABLES|SHARED_LIBRARIES|' + 'STATIC_LIBRARIES|NATIVE_TESTS)/.*: warning:' + ], + ['other', '.*'] # all other unrecognized patterns +] diff --git a/tools/warn/html_writer.py b/tools/warn/html_writer.py new file mode 100644 index 0000000000..b8d3fe6f5d --- /dev/null +++ b/tools/warn/html_writer.py @@ -0,0 +1,673 @@ +# Lint as: python3 +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Emit warning messages to html or csv files.""" + +# To emit html page of warning messages: +# flags: --byproject, --url, --separator +# Old stuff for static html components: +# html_script_style: static html scripts and styles +# htmlbig: +# dump_stats, dump_html_prologue, dump_html_epilogue: +# emit_buttons: +# dump_fixed +# sort_warnings: +# emit_stats_by_project: +# all_patterns, +# findproject, classify_warning +# dump_html +# +# New dynamic HTML page's static JavaScript data: +# Some data are copied from Python to JavaScript, to generate HTML elements. +# FlagPlatform flags.platform +# FlagURL flags.url, used by 'android' +# FlagSeparator flags.separator, used by 'android' +# SeverityColors: list of colors for all severity levels +# SeverityHeaders: list of headers for all severity levels +# SeverityColumnHeaders: list of column_headers for all severity levels +# ProjectNames: project_names, or project_list[*][0] +# WarnPatternsSeverity: warn_patterns[*]['severity'] +# WarnPatternsDescription: warn_patterns[*]['description'] +# WarningMessages: warning_messages +# Warnings: warning_records +# StatsHeader: warning count table header row +# StatsRows: array of warning count table rows +# +# New dynamic HTML page's dynamic JavaScript data: +# +# New dynamic HTML related function to emit data: +# escape_string, strip_escape_string, emit_warning_arrays +# emit_js_data(): + +from __future__ import print_function +import cgi +import csv +import sys + +# pylint:disable=relative-beyond-top-level +# pylint:disable=g-importing-member +from .severity import Severity + + +html_head_scripts = """\ + <script type="text/javascript"> + function expand(id) { + var e = document.getElementById(id); + var f = document.getElementById(id + "_mark"); + if (e.style.display == 'block') { + e.style.display = 'none'; + f.innerHTML = '⊕'; + } + else { + e.style.display = 'block'; + f.innerHTML = '⊖'; + } + }; + function expandCollapse(show) { + for (var id = 1; ; id++) { + var e = document.getElementById(id + ""); + var f = document.getElementById(id + "_mark"); + if (!e || !f) break; + e.style.display = (show ? 'block' : 'none'); + f.innerHTML = (show ? '⊖' : '⊕'); + } + }; + </script> + <style type="text/css"> + th,td{border-collapse:collapse; border:1px solid black;} + .button{color:blue;font-size:110%;font-weight:bolder;} + .bt{color:black;background-color:transparent;border:none;outline:none; + font-size:140%;font-weight:bolder;} + .c0{background-color:#e0e0e0;} + .c1{background-color:#d0d0d0;} + .t1{border-collapse:collapse; width:100%; border:1px solid black;} + </style> + <script src="https://www.gstatic.com/charts/loader.js"></script> +""" + + +def make_writer(output_stream): + + def writer(text): + return output_stream.write(text + '\n') + + return writer + + +def html_big(param): + return '<font size="+2">' + param + '</font>' + + +def dump_html_prologue(title, writer, warn_patterns, project_names): + writer('<html>\n<head>') + writer('<title>' + title + '</title>') + writer(html_head_scripts) + emit_stats_by_project(writer, warn_patterns, project_names) + writer('</head>\n<body>') + writer(html_big(title)) + writer('<p>') + + +def dump_html_epilogue(writer): + writer('</body>\n</head>\n</html>') + + +def sort_warnings(warn_patterns): + for i in warn_patterns: + i['members'] = sorted(set(i['members'])) + + +def create_warnings(warn_patterns, project_names): + """Creates warnings s.t. + + warnings[p][s] is as specified in above docs. + + Args: + warn_patterns: list of warning patterns for specified platform + project_names: list of project names + + Returns: + 2D warnings array where warnings[p][s] is # of warnings in project name p of + severity level s + """ + # pylint:disable=g-complex-comprehension + warnings = {p: {s.value: 0 for s in Severity.levels} for p in project_names} + for i in warn_patterns: + s = i['severity'].value + for p in i['projects']: + warnings[p][s] += i['projects'][p] + return warnings + + +def get_total_by_project(warnings, project_names): + """Returns dict, project as key and # warnings for that project as value.""" + # pylint:disable=g-complex-comprehension + return { + p: sum(warnings[p][s.value] for s in Severity.levels) + for p in project_names + } + + +def get_total_by_severity(warnings, project_names): + """Returns dict, severity as key and # warnings of that severity as value.""" + # pylint:disable=g-complex-comprehension + return { + s.value: sum(warnings[p][s.value] for p in project_names) + for s in Severity.levels + } + + +def emit_table_header(total_by_severity): + """Returns list of HTML-formatted content for severity stats.""" + + stats_header = ['Project'] + for s in Severity.levels: + if total_by_severity[s.value]: + stats_header.append( + '<span style=\'background-color:{}\'>{}</span>'.format( + s.color, s.column_header)) + stats_header.append('TOTAL') + return stats_header + + +def emit_row_counts_per_project(warnings, total_by_project, total_by_severity, + project_names): + """Returns total project warnings and row of stats for each project. + + Args: + warnings: output of create_warnings(warn_patterns, project_names) + total_by_project: output of get_total_by_project(project_names) + total_by_severity: output of get_total_by_severity(project_names) + project_names: list of project names + + Returns: + total_all_projects, the total number of warnings over all projects + stats_rows, a 2d list where each row is [Project Name, <severity counts>, + total # warnings for this project] + """ + + total_all_projects = 0 + stats_rows = [] + for p in project_names: + if total_by_project[p]: + one_row = [p] + for s in Severity.levels: + if total_by_severity[s.value]: + one_row.append(warnings[p][s.value]) + one_row.append(total_by_project[p]) + stats_rows.append(one_row) + total_all_projects += total_by_project[p] + return total_all_projects, stats_rows + + +def emit_row_counts_per_severity(total_by_severity, stats_header, stats_rows, + total_all_projects, writer): + """Emits stats_header and stats_rows as specified above. + + Args: + total_by_severity: output of get_total_by_severity() + stats_header: output of emit_table_header() + stats_rows: output of emit_row_counts_per_project() + total_all_projects: output of emit_row_counts_per_project() + writer: writer returned by make_writer(output_stream) + """ + + total_all_severities = 0 + one_row = ['<b>TOTAL</b>'] + for s in Severity.levels: + if total_by_severity[s.value]: + one_row.append(total_by_severity[s.value]) + total_all_severities += total_by_severity[s.value] + one_row.append(total_all_projects) + stats_rows.append(one_row) + writer('<script>') + emit_const_string_array('StatsHeader', stats_header, writer) + emit_const_object_array('StatsRows', stats_rows, writer) + writer(draw_table_javascript) + writer('</script>') + + +def emit_stats_by_project(writer, warn_patterns, project_names): + """Dump a google chart table of warnings per project and severity.""" + + warnings = create_warnings(warn_patterns, project_names) + total_by_project = get_total_by_project(warnings, project_names) + total_by_severity = get_total_by_severity(warnings, project_names) + stats_header = emit_table_header(total_by_severity) + total_all_projects, stats_rows = \ + emit_row_counts_per_project(warnings, total_by_project, total_by_severity, project_names) + emit_row_counts_per_severity(total_by_severity, stats_header, stats_rows, + total_all_projects, writer) + + +def dump_stats(writer, warn_patterns): + """Dump some stats about total number of warnings and such.""" + + known = 0 + skipped = 0 + unknown = 0 + sort_warnings(warn_patterns) + for i in warn_patterns: + if i['severity'] == Severity.UNMATCHED: + unknown += len(i['members']) + elif i['severity'] == Severity.SKIP: + skipped += len(i['members']) + else: + known += len(i['members']) + writer('Number of classified warnings: <b>' + str(known) + '</b><br>') + writer('Number of skipped warnings: <b>' + str(skipped) + '</b><br>') + writer('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>') + total = unknown + known + skipped + extra_msg = '' + if total < 1000: + extra_msg = ' (low count may indicate incremental build)' + writer('Total number of warnings: <b>' + str(total) + '</b>' + extra_msg) + + +# New base table of warnings, [severity, warn_id, project, warning_message] +# Need buttons to show warnings in different grouping options. +# (1) Current, group by severity, id for each warning pattern +# sort by severity, warn_id, warning_message +# (2) Current --byproject, group by severity, +# id for each warning pattern + project name +# sort by severity, warn_id, project, warning_message +# (3) New, group by project + severity, +# id for each warning pattern +# sort by project, severity, warn_id, warning_message +def emit_buttons(writer): + writer('<button class="button" onclick="expandCollapse(1);">' + 'Expand all warnings</button>\n' + '<button class="button" onclick="expandCollapse(0);">' + 'Collapse all warnings</button>\n' + '<button class="button" onclick="groupBySeverity();">' + 'Group warnings by severity</button>\n' + '<button class="button" onclick="groupByProject();">' + 'Group warnings by project</button><br>') + + +def all_patterns(category): + patterns = '' + for i in category['patterns']: + patterns += i + patterns += ' / ' + return patterns + + +def dump_fixed(writer, warn_patterns): + """Show which warnings no longer occur.""" + anchor = 'fixed_warnings' + mark = anchor + '_mark' + writer('\n<br><p style="background-color:lightblue"><b>' + '<button id="' + mark + '" ' + 'class="bt" onclick="expand(\'' + anchor + '\');">' + '⊕</button> Fixed warnings. ' + 'No more occurrences. Please consider turning these into ' + 'errors if possible, before they are reintroduced in to the build' + ':</b></p>') + writer('<blockquote>') + fixed_patterns = [] + for i in warn_patterns: + if not i['members']: + fixed_patterns.append(i['description'] + ' (' + all_patterns(i) + ')') + fixed_patterns = sorted(fixed_patterns) + writer('<div id="' + anchor + '" style="display:none;"><table>') + cur_row_class = 0 + for text in fixed_patterns: + cur_row_class = 1 - cur_row_class + # remove last '\n' + t = text[:-1] if text[-1] == '\n' else text + writer('<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>') + writer('</table></div>') + writer('</blockquote>') + + +def write_severity(csvwriter, sev, kind, warn_patterns): + """Count warnings of given severity and write CSV entries to writer.""" + total = 0 + for pattern in warn_patterns: + if pattern['severity'] == sev and pattern['members']: + n = len(pattern['members']) + total += n + warning = kind + ': ' + (pattern['description'] or '?') + csvwriter.writerow([n, '', warning]) + # print number of warnings for each project, ordered by project name + projects = sorted(pattern['projects'].keys()) + for project in projects: + csvwriter.writerow([pattern['projects'][project], project, warning]) + csvwriter.writerow([total, '', kind + ' warnings']) + return total + + +def dump_csv(csvwriter, warn_patterns): + """Dump number of warnings in CSV format to writer.""" + sort_warnings(warn_patterns) + total = 0 + for s in Severity.levels: + total += write_severity(csvwriter, s, s.column_header, warn_patterns) + csvwriter.writerow([total, '', 'All warnings']) + + +# Return s with escaped backslash and quotation characters. +def escape_string(s): + return s.replace('\\', '\\\\').replace('"', '\\"') + + +# Return s without trailing '\n' and escape the quotation characters. +def strip_escape_string(s): + if not s: + return s + s = s[:-1] if s[-1] == '\n' else s + return escape_string(s) + + +def emit_warning_array(name, writer, warn_patterns): + writer('var warning_{} = ['.format(name)) + for w in warn_patterns: + if name == 'severity': + writer('{},'.format(w[name].value)) + else: + writer('{},'.format(w[name])) + writer('];') + + +def emit_warning_arrays(writer, warn_patterns): + emit_warning_array('severity', writer, warn_patterns) + writer('var warning_description = [') + for w in warn_patterns: + if w['members']: + writer('"{}",'.format(escape_string(w['description']))) + else: + writer('"",') # no such warning + writer('];') + + +scripts_for_warning_groups = """ + function compareMessages(x1, x2) { // of the same warning type + return (WarningMessages[x1[2]] <= WarningMessages[x2[2]]) ? -1 : 1; + } + function byMessageCount(x1, x2) { + return x2[2] - x1[2]; // reversed order + } + function bySeverityMessageCount(x1, x2) { + // orer by severity first + if (x1[1] != x2[1]) + return x1[1] - x2[1]; + return byMessageCount(x1, x2); + } + const ParseLinePattern = /^([^ :]+):(\\d+):(.+)/; + function addURL(line) { // used by Android + if (FlagURL == "") return line; + if (FlagSeparator == "") { + return line.replace(ParseLinePattern, + "<a target='_blank' href='" + FlagURL + "/$1'>$1</a>:$2:$3"); + } + return line.replace(ParseLinePattern, + "<a target='_blank' href='" + FlagURL + "/$1" + FlagSeparator + + "$2'>$1:$2</a>:$3"); + } + function addURLToLine(line, link) { // used by Chrome + let line_split = line.split(":"); + let path = line_split.slice(0,3).join(":"); + let msg = line_split.slice(3).join(":"); + let html_link = `<a target="_blank" href="${link}">${path}</a>${msg}`; + return html_link; + } + function createArrayOfDictionaries(n) { + var result = []; + for (var i=0; i<n; i++) result.push({}); + return result; + } + function groupWarningsBySeverity() { + // groups is an array of dictionaries, + // each dictionary maps from warning type to array of warning messages. + var groups = createArrayOfDictionaries(SeverityColors.length); + for (var i=0; i<Warnings.length; i++) { + var w = Warnings[i][0]; + var s = WarnPatternsSeverity[w]; + var k = w.toString(); + if (!(k in groups[s])) + groups[s][k] = []; + groups[s][k].push(Warnings[i]); + } + return groups; + } + function groupWarningsByProject() { + var groups = createArrayOfDictionaries(ProjectNames.length); + for (var i=0; i<Warnings.length; i++) { + var w = Warnings[i][0]; + var p = Warnings[i][1]; + var k = w.toString(); + if (!(k in groups[p])) + groups[p][k] = []; + groups[p][k].push(Warnings[i]); + } + return groups; + } + var GlobalAnchor = 0; + function createWarningSection(header, color, group) { + var result = ""; + var groupKeys = []; + var totalMessages = 0; + for (var k in group) { + totalMessages += group[k].length; + groupKeys.push([k, WarnPatternsSeverity[parseInt(k)], group[k].length]); + } + groupKeys.sort(bySeverityMessageCount); + for (var idx=0; idx<groupKeys.length; idx++) { + var k = groupKeys[idx][0]; + var messages = group[k]; + var w = parseInt(k); + var wcolor = SeverityColors[WarnPatternsSeverity[w]]; + var description = WarnPatternsDescription[w]; + if (description.length == 0) + description = "???"; + GlobalAnchor += 1; + result += "<table class='t1'><tr bgcolor='" + wcolor + "'><td>" + + "<button class='bt' id='" + GlobalAnchor + "_mark" + + "' onclick='expand(\\"" + GlobalAnchor + "\\");'>" + + "⊕</button> " + + description + " (" + messages.length + ")</td></tr></table>"; + result += "<div id='" + GlobalAnchor + + "' style='display:none;'><table class='t1'>"; + var c = 0; + messages.sort(compareMessages); + if (FlagPlatform == "chrome") { + for (var i=0; i<messages.length; i++) { + result += "<tr><td class='c" + c + "'>" + + addURLToLine(WarningMessages[messages[i][2]], WarningLinks[messages[i][3]]) + "</td></tr>"; + c = 1 - c; + } + } else { + for (var i=0; i<messages.length; i++) { + result += "<tr><td class='c" + c + "'>" + + addURL(WarningMessages[messages[i][2]]) + "</td></tr>"; + c = 1 - c; + } + } + result += "</table></div>"; + } + if (result.length > 0) { + return "<br><span style='background-color:" + color + "'><b>" + + header + ": " + totalMessages + + "</b></span><blockquote><table class='t1'>" + + result + "</table></blockquote>"; + + } + return ""; // empty section + } + function generateSectionsBySeverity() { + var result = ""; + var groups = groupWarningsBySeverity(); + for (s=0; s<SeverityColors.length; s++) { + result += createWarningSection(SeverityHeaders[s], SeverityColors[s], + groups[s]); + } + return result; + } + function generateSectionsByProject() { + var result = ""; + var groups = groupWarningsByProject(); + for (i=0; i<groups.length; i++) { + result += createWarningSection(ProjectNames[i], 'lightgrey', groups[i]); + } + return result; + } + function groupWarnings(generator) { + GlobalAnchor = 0; + var e = document.getElementById("warning_groups"); + e.innerHTML = generator(); + } + function groupBySeverity() { + groupWarnings(generateSectionsBySeverity); + } + function groupByProject() { + groupWarnings(generateSectionsByProject); + } +""" + + +# Emit a JavaScript const string +def emit_const_string(name, value, writer): + writer('const ' + name + ' = "' + escape_string(value) + '";') + + +# Emit a JavaScript const integer array. +def emit_const_int_array(name, array, writer): + writer('const ' + name + ' = [') + for n in array: + writer(str(n) + ',') + writer('];') + + +# Emit a JavaScript const string array. +def emit_const_string_array(name, array, writer): + writer('const ' + name + ' = [') + for s in array: + writer('"' + strip_escape_string(s) + '",') + writer('];') + + +# Emit a JavaScript const string array for HTML. +def emit_const_html_string_array(name, array, writer): + writer('const ' + name + ' = [') + for s in array: + # Not using html.escape yet, to work for both python 2 and 3, + # until all users switch to python 3. + # pylint:disable=deprecated-method + writer('"' + cgi.escape(strip_escape_string(s)) + '",') + writer('];') + + +# Emit a JavaScript const object array. +def emit_const_object_array(name, array, writer): + writer('const ' + name + ' = [') + for x in array: + writer(str(x) + ',') + writer('];') + + +def emit_js_data(writer, flags, warning_messages, warning_links, + warning_records, warn_patterns, project_names): + """Dump dynamic HTML page's static JavaScript data.""" + emit_const_string('FlagPlatform', flags.platform, writer) + emit_const_string('FlagURL', flags.url, writer) + emit_const_string('FlagSeparator', flags.separator, writer) + emit_const_string_array('SeverityColors', [s.color for s in Severity.levels], + writer) + emit_const_string_array('SeverityHeaders', + [s.header for s in Severity.levels], writer) + emit_const_string_array('SeverityColumnHeaders', + [s.column_header for s in Severity.levels], writer) + emit_const_string_array('ProjectNames', project_names, writer) + # pytype: disable=attribute-error + emit_const_int_array('WarnPatternsSeverity', + [w['severity'].value for w in warn_patterns], writer) + # pytype: enable=attribute-error + emit_const_html_string_array('WarnPatternsDescription', + [w['description'] for w in warn_patterns], + writer) + emit_const_html_string_array('WarningMessages', warning_messages, writer) + emit_const_object_array('Warnings', warning_records, writer) + if flags.platform == 'chrome': + emit_const_html_string_array('WarningLinks', warning_links, writer) + + +draw_table_javascript = """ +google.charts.load('current', {'packages':['table']}); +google.charts.setOnLoadCallback(drawTable); +function drawTable() { + var data = new google.visualization.DataTable(); + data.addColumn('string', StatsHeader[0]); + for (var i=1; i<StatsHeader.length; i++) { + data.addColumn('number', StatsHeader[i]); + } + data.addRows(StatsRows); + for (var i=0; i<StatsRows.length; i++) { + for (var j=0; j<StatsHeader.length; j++) { + data.setProperty(i, j, 'style', 'border:1px solid black;'); + } + } + var table = new google.visualization.Table( + document.getElementById('stats_table')); + table.draw(data, {allowHtml: true, alternatingRowStyle: true}); +} +""" + + +def dump_html(flags, output_stream, warning_messages, warning_links, + warning_records, header_str, warn_patterns, project_names): + """Dump the flags output to output_stream.""" + writer = make_writer(output_stream) + dump_html_prologue('Warnings for ' + header_str, writer, warn_patterns, + project_names) + dump_stats(writer, warn_patterns) + writer('<br><div id="stats_table"></div><br>') + writer('\n<script>') + emit_js_data(writer, flags, warning_messages, warning_links, warning_records, + warn_patterns, project_names) + writer(scripts_for_warning_groups) + writer('</script>') + emit_buttons(writer) + # Warning messages are grouped by severities or project names. + writer('<br><div id="warning_groups"></div>') + if flags.byproject: + writer('<script>groupByProject();</script>') + else: + writer('<script>groupBySeverity();</script>') + dump_fixed(writer, warn_patterns) + dump_html_epilogue(writer) + + +def write_html(flags, project_names, warn_patterns, html_path, warning_messages, + warning_links, warning_records, header_str): + """Write warnings html file.""" + if html_path: + with open(html_path, 'w') as f: + dump_html(flags, f, warning_messages, warning_links, warning_records, + header_str, warn_patterns, project_names) + + +def write_out_csv(flags, warn_patterns, warning_messages, warning_links, + warning_records, header_str, project_names): + """Write warnings csv file.""" + if flags.csvpath: + with open(flags.csvpath, 'w') as f: + dump_csv(csv.writer(f, lineterminator='\n'), warn_patterns) + + if flags.gencsv: + dump_csv(csv.writer(sys.stdout, lineterminator='\n'), warn_patterns) + else: + dump_html(flags, sys.stdout, warning_messages, warning_links, + warning_records, header_str, warn_patterns, project_names) diff --git a/tools/warn/java_warn_patterns.py b/tools/warn/java_warn_patterns.py index 80e2e1d5cf..17e3864daf 100644 --- a/tools/warn/java_warn_patterns.py +++ b/tools/warn/java_warn_patterns.py @@ -16,8 +16,8 @@ """Warning patterns for Java compiler tools.""" # pylint:disable=relative-beyond-top-level -from .cpp_warn_patterns import compile_patterns # pylint:disable=g-importing-member +from .cpp_warn_patterns import compile_patterns from .severity import Severity @@ -485,16 +485,24 @@ warn_patterns = [ java_medium('Static method should be qualified', [r'.*\.java:.*: warning: \[static\] static method should be qualified']), medium('AbstractInner'), + medium('BothPackageInfoAndHtml'), medium('CallbackName'), medium('ExecutorRegistration'), + medium('HiddenTypeParameter'), medium('JavaApiUsedByMainlineModule'), medium('ListenerLast'), + medium('MinMaxConstant'), medium('MissingBuildMethod'), medium('NoByteOrShort'), medium('OverlappingConstants'), medium('SetterReturnsThis'), + medium('StreamFiles'), medium('Typo'), medium('UseIcu'), + medium('fallthrough'), + medium('overrides'), + medium('serial'), + medium('try'), high('AndroidInjectionBeforeSuper', 'AndroidInjection.inject() should always be invoked before calling super.lifecycleMethod()'), high('AndroidJdkLibsChecker', @@ -783,6 +791,8 @@ warn_patterns = [ # Other javac tool warnings java_medium('addNdkApiCoverage failed to getPackage', [r".*: warning: addNdkApiCoverage failed to getPackage"]), + java_medium('bad path element', + [r".*: warning: \[path\] bad path element .*\.jar"]), java_medium('Supported version from annotation processor', [r".*: warning: Supported source version .+ from annotation processor"]), ] diff --git a/tools/warn/make_warn_patterns.py b/tools/warn/make_warn_patterns.py index dd6a1b0419..4b20493ba1 100644 --- a/tools/warn/make_warn_patterns.py +++ b/tools/warn/make_warn_patterns.py @@ -16,8 +16,8 @@ """Warning patterns for build make tools.""" # pylint:disable=relative-beyond-top-level -from .cpp_warn_patterns import compile_patterns # pylint:disable=g-importing-member +from .cpp_warn_patterns import compile_patterns from .severity import Severity warn_patterns = [ diff --git a/tools/warn/other_warn_patterns.py b/tools/warn/other_warn_patterns.py index 1350936cf1..318c3d47f5 100644 --- a/tools/warn/other_warn_patterns.py +++ b/tools/warn/other_warn_patterns.py @@ -16,8 +16,8 @@ """Warning patterns from other tools.""" # pylint:disable=relative-beyond-top-level -from .cpp_warn_patterns import compile_patterns # pylint:disable=g-importing-member +from .cpp_warn_patterns import compile_patterns from .severity import Severity @@ -42,14 +42,20 @@ def asm(description, pattern_list): return warn('asm', Severity.MEDIUM, description, pattern_list) -def kotlin(description, pattern_list): - return warn('Kotlin', Severity.MEDIUM, description, pattern_list) +def kotlin(description, pattern): + return warn('Kotlin', Severity.MEDIUM, description, + [r'.*\.kt:.*: warning: ' + pattern]) def yacc(description, pattern_list): return warn('yacc', Severity.MEDIUM, description, pattern_list) +def rust(severity, description, pattern): + return warn('Rust', severity, description, + [r'.*\.rs:.*: warning: ' + pattern]) + + warn_patterns = [ # pylint:disable=line-too-long,g-inconsistent-quotes # aapt warnings @@ -109,26 +115,31 @@ warn_patterns = [ 'description': 'Proto: Import not used', 'patterns': [r".*: warning: Import .*/.*\.proto but not used.$"]}, # Kotlin warnings - kotlin('never used parameter or variable', - [r".*\.kt:.*: warning: (parameter|variable) '.*' is never used$", - r".*\.kt:.*: warning: (parameter|variable) '.*' is never used, could be renamed to _$"]), - kotlin('initializer is redundant', - [r".*\.kt:.*: warning: .* initializer is redundant$"]), + kotlin('never used parameter or variable', '.+ \'.*\' is never used'), + kotlin('multiple labels', '.+ more than one label .+ in this scope'), + kotlin('type mismatch', 'type mismatch: '), + kotlin('is always true', '.+ is always \'true\''), + kotlin('no effect', '.+ annotation has no effect for '), + kotlin('no cast needed', 'no cast needed'), + kotlin('accessor not generated', 'an accessor will not be generated '), + kotlin('initializer is redundant', '.* initializer is redundant$'), kotlin('elvis operator always returns ...', - [r".*\.kt:.*: warning: elvis operator \(\?:\) always returns .+"]), - kotlin('shadowed name', - [r".*\.kt:.*: warning: name shadowed: .+"]), - kotlin('unchecked cast', - [r".*\.kt:.*: warning: unchecked cast: .* to .*$"]), + 'elvis operator (?:) always returns .+'), + kotlin('shadowed name', 'name shadowed: .+'), + kotlin('unchecked cast', 'unchecked cast: .* to .*$'), + kotlin('unreachable code', 'unreachable code'), + kotlin('unnecessary assertion', 'unnecessary .+ assertion .+'), kotlin('unnecessary safe call on a non-null receiver', - [r".*\.kt:.*: warning: unnecessary safe call on a non-null receiver"]), + 'unnecessary safe call on a non-null receiver'), kotlin('Deprecated in Java', - [r".*\.kt:.*: warning: '.*' is deprecated. Deprecated in Java"]), + '\'.*\' is deprecated. Deprecated in Java'), kotlin('Replacing Handler for Executor', - [r".*\.kt:.*: warning: .+ Replacing Handler for Executor in "]), + '.+ Replacing Handler for Executor in '), kotlin('library has Kotlin runtime', - [r".*: warning: library has Kotlin runtime bundled into it", - r".*: warning: some JAR files .* have the Kotlin Runtime library"]), + '.+ has Kotlin runtime (bundled|library)'), + warn('Kotlin', Severity.MEDIUM, 'bundled Kotlin runtime', + ['.*warning: .+ (has|have the) Kotlin (runtime|Runtime library) bundled']), + kotlin('other warnings', '.+'), # catch all other Kotlin warnings # Yacc warnings yacc('deprecate directive', [r".*\.yy?:.*: warning: deprecated directive: "]), @@ -138,15 +149,20 @@ warn_patterns = [ 'description': 'yacc: fix-its can be applied', 'patterns': [r".*\.yy?: warning: fix-its can be applied."]}, # Rust warnings - {'category': 'Rust', 'severity': Severity.HIGH, - 'description': 'Rust: Does not derive Copy', - 'patterns': [r".*: warning: .+ does not derive Copy"]}, - {'category': 'Rust', 'severity': Severity.MEDIUM, - 'description': 'Rust: Deprecated range pattern', - 'patterns': [r".*: warning: .+ range patterns are deprecated"]}, - {'category': 'Rust', 'severity': Severity.MEDIUM, - 'description': 'Rust: Deprecated missing explicit \'dyn\'', - 'patterns': [r".*: warning: .+ without an explicit `dyn` are deprecated"]}, + rust(Severity.HIGH, 'Does not derive Copy', '.+ does not derive Copy'), + rust(Severity.MEDIUM, '... are deprecated', + ('(.+ are deprecated$|' + + 'use of deprecated item .* (use .* instead|is now preferred))')), + rust(Severity.MEDIUM, 'never used', '.* is never used:'), + rust(Severity.MEDIUM, 'unused import', 'unused import: '), + rust(Severity.MEDIUM, 'unnecessary attribute', + '.+ no longer requires an attribute'), + rust(Severity.MEDIUM, 'unnecessary parentheses', + 'unnecessary parentheses around'), + # Catch all RenderScript warnings + {'category': 'RenderScript', 'severity': Severity.LOW, + 'description': 'RenderScript warnings', + 'patterns': [r'.*\.rscript:.*: warning: ']}, # Broken/partial warning messages will be skipped. {'category': 'Misc', 'severity': Severity.SKIP, 'description': 'skip, ,', diff --git a/tools/warn/severity.py b/tools/warn/severity.py index b1c38e4a37..b4c03c9efe 100644 --- a/tools/warn/severity.py +++ b/tools/warn/severity.py @@ -20,24 +20,26 @@ This file stores definition for class Severity that is used in warn_patterns. # pylint:disable=old-style-class -class Severity: - """Class of Severity levels where each level is a SeverityInfo.""" +class SeverityInfo: + + def __init__(self, value, color, column_header, header): + self.value = value + self.color = color + self.column_header = column_header + self.header = header - class SeverityInfo: - def __init__(self, value, color, column_header, header): - self.value = value - self.color = color - self.column_header = column_header - self.header = header +# pylint:disable=old-style-class +class Severity: + """Class of Severity levels where each level is a SeverityInfo.""" # SEVERITY_UNKNOWN should never occur since every warn_pattern listed has # a specified severity. It exists for protobuf, the other values must # map to non-zero values (since 0 is reserved for a default UNKNOWN), but # logic in clang_tidy_warn.py assumes severity level values are consecutive # ints starting with 0. - SEVERITY_UNKNOWN = SeverityInfo(0, 'blueviolet', 'Errors of unknown severity', - 'Unknown severity (should not occur)') + SEVERITY_UNKNOWN = SeverityInfo(0, 'blueviolet', 'Unknown', + 'Unknown-severity warnings)') FIXMENOW = SeverityInfo(1, 'fuschia', 'FixNow', 'Critical warnings, fix me now') HIGH = SeverityInfo(2, 'red', 'High', 'High severity warnings') diff --git a/tools/warn/tidy_warn_patterns.py b/tools/warn/tidy_warn_patterns.py index 2c5ab79bd4..5416cb23d7 100644 --- a/tools/warn/tidy_warn_patterns.py +++ b/tools/warn/tidy_warn_patterns.py @@ -16,8 +16,8 @@ """Warning patterns for clang-tidy.""" # pylint:disable=relative-beyond-top-level -from .cpp_warn_patterns import compile_patterns # pylint:disable=g-importing-member +from .cpp_warn_patterns import compile_patterns from .severity import Severity @@ -78,6 +78,7 @@ warn_patterns = [ group_tidy_warn_pattern('android'), simple_tidy_warn_pattern('abseil-string-find-startswith'), simple_tidy_warn_pattern('bugprone-argument-comment'), + simple_tidy_warn_pattern('bugprone-branch-clone'), simple_tidy_warn_pattern('bugprone-copy-constructor-init'), simple_tidy_warn_pattern('bugprone-fold-init-type'), simple_tidy_warn_pattern('bugprone-forward-declaration-namespace'), @@ -89,6 +90,9 @@ warn_patterns = [ simple_tidy_warn_pattern('bugprone-macro-parentheses'), simple_tidy_warn_pattern('bugprone-misplaced-widening-cast'), simple_tidy_warn_pattern('bugprone-move-forwarding-reference'), + simple_tidy_warn_pattern('bugprone-parent-virtual-call'), + simple_tidy_warn_pattern('bugprone-posix-return'), + simple_tidy_warn_pattern('bugprone-sizeof-container'), simple_tidy_warn_pattern('bugprone-sizeof-expression'), simple_tidy_warn_pattern('bugprone-string-constructor'), simple_tidy_warn_pattern('bugprone-string-integer-assignment'), @@ -96,10 +100,25 @@ warn_patterns = [ simple_tidy_warn_pattern('bugprone-suspicious-missing-comma'), simple_tidy_warn_pattern('bugprone-suspicious-string-compare'), simple_tidy_warn_pattern('bugprone-suspicious-semicolon'), + simple_tidy_warn_pattern('bugprone-terminating-continue'), + simple_tidy_warn_pattern('bugprone-too-small-loop-variable'), simple_tidy_warn_pattern('bugprone-undefined-memory-manipulation'), + simple_tidy_warn_pattern('bugprone-unhandled-self-assignment'), simple_tidy_warn_pattern('bugprone-unused-raii'), + simple_tidy_warn_pattern('bugprone-unused-return-value'), simple_tidy_warn_pattern('bugprone-use-after-move'), group_tidy_warn_pattern('bugprone'), + simple_tidy_warn_pattern('cert-dcl16-c'), + simple_tidy_warn_pattern('cert-dcl21-cpp'), + simple_tidy_warn_pattern('cert-dcl50-cpp'), + simple_tidy_warn_pattern('cert-dcl54-cpp'), + simple_tidy_warn_pattern('cert-dcl59-cpp'), + simple_tidy_warn_pattern('cert-env33-c'), + simple_tidy_warn_pattern('cert-err34-c'), + simple_tidy_warn_pattern('cert-err52-cpp'), + simple_tidy_warn_pattern('cert-msc30-c'), + simple_tidy_warn_pattern('cert-msc50-cpp'), + simple_tidy_warn_pattern('cert-oop54-cpp'), group_tidy_warn_pattern('cert'), group_tidy_warn_pattern('clang-diagnostic'), group_tidy_warn_pattern('cppcoreguidelines'), diff --git a/tools/warn/warn.py b/tools/warn/warn.py index bdfd489847..56e8787d99 100755 --- a/tools/warn/warn.py +++ b/tools/warn/warn.py @@ -17,21 +17,51 @@ """Simple wrapper to run warn_common with Python standard Pool.""" import multiprocessing +import signal +import sys # pylint:disable=relative-beyond-top-level -# pylint:disable=g-importing-member -from .warn_common import common_main +from . import warn_common as common -# This parallel_process could be changed depending on platform -# and availability of multi-process library functions. -def parallel_process(num_cpu, classify_warnings, groups): +def classify_warnings(args): + """Classify a list of warning lines. + + Args: + args: dictionary { + 'group': list of (warning, link), + 'project_patterns': re.compile(project_list[p][1]), + 'warn_patterns': list of warn_pattern, + 'num_processes': number of processes being used for multiprocessing } + Returns: + results: a list of the classified warnings. + """ + results = [] + for line, link in args['group']: + common.classify_one_warning(line, link, results, args['project_patterns'], + args['warn_patterns']) + + # After the main work, ignore all other signals to a child process, + # to avoid bad warning/error messages from the exit clean-up process. + if args['num_processes'] > 1: + signal.signal(signal.SIGTERM, lambda *args: sys.exit(-signal.SIGTERM)) + return results + + +def create_and_launch_subprocesses(num_cpu, classify_warnings_fn, arg_groups, + group_results): pool = multiprocessing.Pool(num_cpu) - return pool.map(classify_warnings, groups) + for cpu in range(num_cpu): + proc_result = pool.map(classify_warnings_fn, arg_groups[cpu]) + if proc_result is not None: + group_results.append(proc_result) + return group_results def main(): - common_main(parallel_process) + use_google3 = False + common.common_main(use_google3, create_and_launch_subprocesses, + classify_warnings) if __name__ == '__main__': diff --git a/tools/warn/warn_common.py b/tools/warn/warn_common.py index 0c9d9efbbd..68ed995c00 100755 --- a/tools/warn/warn_common.py +++ b/tools/warn/warn_common.py @@ -18,6 +18,8 @@ Default is to output warnings in HTML tables grouped by warning severity. Use option --byproject to output tables grouped by source file projects. Use option --gencsv to output warning counts in CSV format. + +Default input file is build.log, which can be changed with the --log flag. """ # List of important data structures and functions in this script. @@ -36,431 +38,203 @@ Use option --gencsv to output warning counts in CSV format. # project_patterns[p] re.compile(project_list[p][1]) # project_names[p] project_list[p][0] # warning_messages array of each warning message, without source url +# warning_links array of each warning code search link; for 'chrome' # warning_records array of [idx to warn_patterns, # idx to project_names, -# idx to warning_messages] -# android_root -# platform_version -# target_product -# target_variant +# idx to warning_messages, +# idx to warning_links] # parse_input_file # -# To emit html page of warning messages: -# flags: --byproject, --url, --separator -# Old stuff for static html components: -# html_script_style: static html scripts and styles -# htmlbig: -# dump_stats, dump_html_prologue, dump_html_epilogue: -# emit_buttons: -# dump_fixed -# sort_warnings: -# emit_stats_by_project: -# all_patterns, -# findproject, classify_warning -# dump_html -# -# New dynamic HTML page's static JavaScript data: -# Some data are copied from Python to JavaScript, to generate HTML elements. -# FlagURL args.url -# FlagSeparator args.separator -# SeverityColors: list of colors for all severity levels -# SeverityHeaders: list of headers for all severity levels -# SeverityColumnHeaders: list of column_headers for all severity levels -# ProjectNames: project_names, or project_list[*][0] -# WarnPatternsSeverity: warn_patterns[*]['severity'] -# WarnPatternsDescription: warn_patterns[*]['description'] -# WarningMessages: warning_messages -# Warnings: warning_records -# StatsHeader: warning count table header row -# StatsRows: array of warning count table rows -# -# New dynamic HTML page's dynamic JavaScript data: -# -# New dynamic HTML related function to emit data: -# escape_string, strip_escape_string, emit_warning_arrays -# emit_js_data(): - -from __future__ import print_function import argparse -import cgi -import csv import io import multiprocessing import os import re -import signal import sys # pylint:disable=relative-beyond-top-level -from . import cpp_warn_patterns -from . import java_warn_patterns -from . import make_warn_patterns -from . import other_warn_patterns -from . import tidy_warn_patterns # pylint:disable=g-importing-member -from .android_project_list import project_list -from .severity import Severity - -parser = argparse.ArgumentParser(description='Convert a build log into HTML') -parser.add_argument('--csvpath', - help='Save CSV warning file to the passed absolute path', - default=None) -parser.add_argument('--gencsv', - help='Generate a CSV file with number of various warnings', - action='store_true', - default=False) -parser.add_argument('--byproject', - help='Separate warnings in HTML output by project names', - action='store_true', - default=False) -parser.add_argument('--url', - help='Root URL of an Android source code tree prefixed ' - 'before files in warnings') -parser.add_argument('--separator', - help='Separator between the end of a URL and the line ' - 'number argument. e.g. #') -parser.add_argument('--processes', - type=int, - default=multiprocessing.cpu_count(), - help='Number of parallel processes to process warnings') -parser.add_argument(dest='buildlog', metavar='build.log', - help='Path to build.log file') -args = parser.parse_args() - -warn_patterns = make_warn_patterns.warn_patterns -warn_patterns.extend(cpp_warn_patterns.warn_patterns) -warn_patterns.extend(java_warn_patterns.warn_patterns) -warn_patterns.extend(tidy_warn_patterns.warn_patterns) -warn_patterns.extend(other_warn_patterns.warn_patterns) - -project_patterns = [] -project_names = [] -warning_messages = [] -warning_records = [] - - -def initialize_arrays(): - """Complete global arrays before they are used.""" - global project_names, project_patterns - project_names = [p[0] for p in project_list] - project_patterns = [re.compile(p[1]) for p in project_list] - for w in warn_patterns: - w['members'] = [] - # Each warning pattern has a 'projects' dictionary, that - # maps a project name to number of warnings in that project. - w['projects'] = {} - - -initialize_arrays() - - -android_root = '' -platform_version = 'unknown' -target_product = 'unknown' -target_variant = 'unknown' - - -##### Data and functions to dump html file. ################################## - -html_head_scripts = """\ - <script type="text/javascript"> - function expand(id) { - var e = document.getElementById(id); - var f = document.getElementById(id + "_mark"); - if (e.style.display == 'block') { - e.style.display = 'none'; - f.innerHTML = '⊕'; - } - else { - e.style.display = 'block'; - f.innerHTML = '⊖'; - } - }; - function expandCollapse(show) { - for (var id = 1; ; id++) { - var e = document.getElementById(id + ""); - var f = document.getElementById(id + "_mark"); - if (!e || !f) break; - e.style.display = (show ? 'block' : 'none'); - f.innerHTML = (show ? '⊖' : '⊕'); - } - }; - </script> - <style type="text/css"> - th,td{border-collapse:collapse; border:1px solid black;} - .button{color:blue;font-size:110%;font-weight:bolder;} - .bt{color:black;background-color:transparent;border:none;outline:none; - font-size:140%;font-weight:bolder;} - .c0{background-color:#e0e0e0;} - .c1{background-color:#d0d0d0;} - .t1{border-collapse:collapse; width:100%; border:1px solid black;} - </style> - <script src="https://www.gstatic.com/charts/loader.js"></script> -""" - - -def make_writer(output_stream): - - def writer(text): - return output_stream.write(text + '\n') - - return writer - - -def html_big(param): - return '<font size="+2">' + param + '</font>' - - -def dump_html_prologue(title, writer): - writer('<html>\n<head>') - writer('<title>' + title + '</title>') - writer(html_head_scripts) - emit_stats_by_project(writer) - writer('</head>\n<body>') - writer(html_big(title)) - writer('<p>') - - -def dump_html_epilogue(writer): - writer('</body>\n</head>\n</html>') - - -def sort_warnings(): - for i in warn_patterns: - i['members'] = sorted(set(i['members'])) - - -def emit_stats_by_project(writer): - """Dump a google chart table of warnings per project and severity.""" - # warnings[p][s] is number of warnings in project p of severity s. - # pylint:disable=g-complex-comprehension - warnings = {p: {s.value: 0 for s in Severity.levels} for p in project_names} - for i in warn_patterns: - # pytype: disable=attribute-error - s = i['severity'].value - # pytype: enable=attribute-error - for p in i['projects']: - warnings[p][s] += i['projects'][p] - - # total_by_project[p] is number of warnings in project p. - total_by_project = { - p: sum(warnings[p][s.value] for s in Severity.levels) - for p in project_names - } - - # total_by_severity[s] is number of warnings of severity s. - total_by_severity = { - s.value: sum(warnings[p][s.value] for p in project_names) - for s in Severity.levels - } - - # emit table header - stats_header = ['Project'] - for s in Severity.levels: - if total_by_severity[s.value]: - stats_header.append( - '<span style=\'background-color:{}\'>{}</span>'.format( - s.color, s.column_header)) - stats_header.append('TOTAL') - - # emit a row of warning counts per project, skip no-warning projects - total_all_projects = 0 - stats_rows = [] - for p in project_names: - if total_by_project[p]: - one_row = [p] - for s in Severity.levels: - if total_by_severity[s.value]: - one_row.append(warnings[p][s.value]) - one_row.append(total_by_project[p]) - stats_rows.append(one_row) - total_all_projects += total_by_project[p] - - # emit a row of warning counts per severity - total_all_severities = 0 - one_row = ['<b>TOTAL</b>'] - for s in Severity.levels: - if total_by_severity[s.value]: - one_row.append(total_by_severity[s.value]) - total_all_severities += total_by_severity[s.value] - one_row.append(total_all_projects) - stats_rows.append(one_row) - writer('<script>') - emit_const_string_array('StatsHeader', stats_header, writer) - emit_const_object_array('StatsRows', stats_rows, writer) - writer(draw_table_javascript) - writer('</script>') - - -def dump_stats(writer): - """Dump some stats about total number of warnings and such.""" - known = 0 - skipped = 0 - unknown = 0 - sort_warnings() - for i in warn_patterns: - if i['severity'] == Severity.UNMATCHED: - unknown += len(i['members']) - elif i['severity'] == Severity.SKIP: - skipped += len(i['members']) - else: - known += len(i['members']) - writer('Number of classified warnings: <b>' + str(known) + '</b><br>') - writer('Number of skipped warnings: <b>' + str(skipped) + '</b><br>') - writer('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>') - total = unknown + known + skipped - extra_msg = '' - if total < 1000: - extra_msg = ' (low count may indicate incremental build)' - writer('Total number of warnings: <b>' + str(total) + '</b>' + extra_msg) - - -# New base table of warnings, [severity, warn_id, project, warning_message] -# Need buttons to show warnings in different grouping options. -# (1) Current, group by severity, id for each warning pattern -# sort by severity, warn_id, warning_message -# (2) Current --byproject, group by severity, -# id for each warning pattern + project name -# sort by severity, warn_id, project, warning_message -# (3) New, group by project + severity, -# id for each warning pattern -# sort by project, severity, warn_id, warning_message -def emit_buttons(writer): - writer('<button class="button" onclick="expandCollapse(1);">' - 'Expand all warnings</button>\n' - '<button class="button" onclick="expandCollapse(0);">' - 'Collapse all warnings</button>\n' - '<button class="button" onclick="groupBySeverity();">' - 'Group warnings by severity</button>\n' - '<button class="button" onclick="groupByProject();">' - 'Group warnings by project</button><br>') - - -def all_patterns(category): - patterns = '' - for i in category['patterns']: - patterns += i - patterns += ' / ' - return patterns - - -def dump_fixed(writer): - """Show which warnings no longer occur.""" - anchor = 'fixed_warnings' - mark = anchor + '_mark' - writer('\n<br><p style="background-color:lightblue"><b>' - '<button id="' + mark + '" ' - 'class="bt" onclick="expand(\'' + anchor + '\');">' - '⊕</button> Fixed warnings. ' - 'No more occurrences. Please consider turning these into ' - 'errors if possible, before they are reintroduced in to the build' - ':</b></p>') - writer('<blockquote>') - fixed_patterns = [] - for i in warn_patterns: - if not i['members']: - fixed_patterns.append(i['description'] + ' (' + all_patterns(i) + ')') - fixed_patterns = sorted(fixed_patterns) - writer('<div id="' + anchor + '" style="display:none;"><table>') - cur_row_class = 0 - for text in fixed_patterns: - cur_row_class = 1 - cur_row_class - # remove last '\n' - t = text[:-1] if text[-1] == '\n' else text - writer('<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>') - writer('</table></div>') - writer('</blockquote>') - - -def find_project_index(line): - for p in range(len(project_patterns)): - if project_patterns[p].match(line): - return p +from . import android_project_list +from . import chrome_project_list +from . import cpp_warn_patterns as cpp_patterns +from . import html_writer +from . import java_warn_patterns as java_patterns +from . import make_warn_patterns as make_patterns +from . import other_warn_patterns as other_patterns +from . import tidy_warn_patterns as tidy_patterns + + +def parse_args(use_google3): + """Define and parse the args. Return the parse_args() result.""" + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('--capacitor_path', default='', + help='Save capacitor warning file to the passed absolute' + ' path') + # csvpath has a different naming than the above path because historically the + # original Android script used csvpath, so other scripts rely on it + parser.add_argument('--csvpath', default='', + help='Save CSV warning file to the passed path') + parser.add_argument('--gencsv', action='store_true', + help='Generate CSV file with number of various warnings') + parser.add_argument('--byproject', action='store_true', + help='Separate warnings in HTML output by project names') + parser.add_argument('--url', default='', + help='Root URL of an Android source code tree prefixed ' + 'before files in warnings') + parser.add_argument('--separator', default='?l=', + help='Separator between the end of a URL and the line ' + 'number argument. e.g. #') + parser.add_argument('--processes', default=multiprocessing.cpu_count(), + type=int, + help='Number of parallel processes to process warnings') + # Old Android build scripts call warn.py without --platform, + # so the default platform is set to 'android'. + parser.add_argument('--platform', default='android', + choices=['chrome', 'android'], + help='Platform of the build log') + # Old Android build scripts call warn.py with only a build.log file path. + parser.add_argument('--log', help='Path to build log file') + parser.add_argument(dest='buildlog', metavar='build.log', + default='build.log', nargs='?', + help='Path to build.log file') + flags = parser.parse_args() + if not flags.log: + flags.log = flags.buildlog + if not use_google3 and not os.path.exists(flags.log): + sys.exit('Cannot find log file: ' + flags.log) + return flags + + +def get_project_names(project_list): + """Get project_names from project_list.""" + return [p[0] for p in project_list] + + +def find_project_index(line, project_patterns): + for i, p in enumerate(project_patterns): + if p.match(line): + return i return -1 -def classify_one_warning(line, results): +def classify_one_warning(warning, link, results, project_patterns, + warn_patterns): """Classify one warning line.""" - for i in range(len(warn_patterns)): - w = warn_patterns[i] + for i, w in enumerate(warn_patterns): for cpat in w['compiled_patterns']: - # pytype: disable=attribute-error - if cpat.match(line): - p = find_project_index(line) - results.append([line, i, p]) + if cpat.match(warning): + p = find_project_index(warning, project_patterns) + results.append([warning, link, i, p]) return else: # If we end up here, there was a problem parsing the log # probably caused by 'make -j' mixing the output from # 2 or more concurrent compiles pass - # pytype: enable=attribute-error - -def classify_warnings(lines): - results = [] - for line in lines: - classify_one_warning(line, results) - # After the main work, ignore all other signals to a child process, - # to avoid bad warning/error messages from the exit clean-up process. - if args.processes > 1: - signal.signal(signal.SIGTERM, lambda *args: sys.exit(-signal.SIGTERM)) - return results - -def parallel_classify_warnings(warning_lines, parallel_process): - """Classify all warning lines with num_cpu parallel processes.""" - num_cpu = args.processes - if num_cpu > 1: - groups = [[] for x in range(num_cpu)] - i = 0 - for x in warning_lines: - groups[i].append(x) - i = (i + 1) % num_cpu - group_results = parallel_process(num_cpu, classify_warnings, groups) - else: - group_results = [classify_warnings(warning_lines)] - - for result in group_results: - for line, pattern_idx, project_idx in result: - pattern = warn_patterns[pattern_idx] - pattern['members'].append(line) - message_idx = len(warning_messages) - warning_messages.append(line) - warning_records.append([pattern_idx, project_idx, message_idx]) - pname = '???' if project_idx < 0 else project_names[project_idx] - # Count warnings by project. - if pname in pattern['projects']: - pattern['projects'][pname] += 1 - else: - pattern['projects'][pname] = 1 +def remove_prefix(s, sub): + """Remove everything before last occurrence of substring sub in string s.""" + if sub in s: + inc_sub = s.rfind(sub) + return s[inc_sub:] + return s + + +# TODO(emmavukelj): Don't have any generate_*_cs_link functions call +# normalize_path a second time (the first time being in parse_input_file) +def generate_cs_link(warning_line, flags, android_root=None): + if flags.platform == 'chrome': + return generate_chrome_cs_link(warning_line, flags) + if flags.platform == 'android': + return generate_android_cs_link(warning_line, flags, android_root) + return 'https://cs.corp.google.com/' + + +def generate_android_cs_link(warning_line, flags, android_root): + """Generate the code search link for a warning line in Android.""" + # max_splits=2 -> only 3 items + raw_path, line_number_str, _ = warning_line.split(':', 2) + normalized_path = normalize_path(raw_path, flags, android_root) + if not flags.url: + return normalized_path + link_path = flags.url + '/' + normalized_path + if line_number_str.isdigit(): + link_path += flags.separator + line_number_str + return link_path + + +def generate_chrome_cs_link(warning_line, flags): + """Generate the code search link for a warning line in Chrome.""" + split_line = warning_line.split(':') + raw_path = split_line[0] + normalized_path = normalize_path(raw_path, flags) + link_base = 'https://cs.chromium.org/' + link_add = 'chromium' + link_path = None + + # Basically just going through a few specific directory cases and specifying + # the proper behavior for that case. This list of cases was accumulated + # through trial and error manually going through the warnings. + # + # This code pattern of using case-specific "if"s instead of "elif"s looks + # possibly accidental and mistaken but it is intentional because some paths + # fall under several cases (e.g. third_party/lib/nghttp2_frame.c) and for + # those we want the most specific case to be applied. If there is reliable + # knowledge of exactly where these occur, this could be changed to "elif"s + # but there is no reliable set of paths falling under multiple cases at the + # moment. + if '/src/third_party' in raw_path: + link_path = remove_prefix(raw_path, '/src/third_party/') + if '/chrome_root/src_internal/' in raw_path: + link_path = remove_prefix(raw_path, '/chrome_root/src_internal/') + link_path = link_path[len('/chrome_root'):] # remove chrome_root + if '/chrome_root/src/' in raw_path: + link_path = remove_prefix(raw_path, '/chrome_root/src/') + link_path = link_path[len('/chrome_root'):] # remove chrome_root + if '/libassistant/' in raw_path: + link_add = 'eureka_internal/chromium/src' + link_base = 'https://cs.corp.google.com/' # internal data + link_path = remove_prefix(normalized_path, '/libassistant/') + if raw_path.startswith('gen/'): + link_path = '/src/out/Debug/gen/' + normalized_path + if '/gen/' in raw_path: + return '%s?q=file:%s' % (link_base, remove_prefix(normalized_path, '/gen/')) + + if not link_path and (raw_path.startswith('src/') or + raw_path.startswith('src_internal/')): + link_path = '/%s' % raw_path + + if not link_path: # can't find specific link, send a query + return '%s?q=file:%s' % (link_base, normalized_path) + + line_number = int(split_line[1]) + link = '%s%s%s?l=%d' % (link_base, link_add, link_path, line_number) + return link def find_warn_py_and_android_root(path): - """Set and return android_root path if it is found.""" - global android_root + """Return android source root path if warn.py is found.""" parts = path.split('/') for idx in reversed(range(2, len(parts))): root_path = '/'.join(parts[:idx]) # Android root directory should contain this script. if os.path.exists(root_path + '/build/make/tools/warn.py'): - android_root = root_path - return True - return False + return root_path + return '' -def find_android_root(): - """Guess android_root from common prefix of file paths.""" +def find_android_root(buildlog): + """Guess android source root from common prefix of file paths.""" # Use the longest common prefix of the absolute file paths # of the first 10000 warning messages as the android_root. - global android_root - warning_lines = set() + warning_lines = [] warning_pattern = re.compile('^/[^ ]*/[^ ]*: warning: .*') count = 0 - infile = io.open(args.buildlog, mode='r', encoding='utf-8') - for line in infile: + for line in buildlog: if warning_pattern.match(line): - warning_lines.add(line) + warning_lines.append(line) count += 1 if count > 9999: break @@ -468,56 +242,110 @@ def find_android_root(): # the source tree root. if count < 100: path = os.path.normpath(re.sub(':.*$', '', line)) - if find_warn_py_and_android_root(path): - return + android_root = find_warn_py_and_android_root(path) + if android_root: + return android_root # Do not use common prefix of a small number of paths. if count > 10: # pytype: disable=wrong-arg-types root_path = os.path.commonprefix(warning_lines) # pytype: enable=wrong-arg-types if len(root_path) > 2 and root_path[len(root_path) - 1] == '/': - android_root = root_path[:-1] + return root_path[:-1] + return '' -def remove_android_root_prefix(path): +def remove_android_root_prefix(path, android_root): """Remove android_root prefix from path if it is found.""" if path.startswith(android_root): return path[1 + len(android_root):] - else: - return path + return path -def normalize_path(path): - """Normalize file path relative to android_root.""" - # If path is not an absolute path, just normalize it. +def normalize_path(path, flags, android_root=None): + """Normalize file path relative to src/ or src-internal/ directory.""" path = os.path.normpath(path) + + if flags.platform == 'android': + if android_root: + return remove_android_root_prefix(path, android_root) + return path + # Remove known prefix of root path and normalize the suffix. - if path[0] == '/' and android_root: - return remove_android_root_prefix(path) - return path + idx = path.find('chrome_root/') + if idx >= 0: + # remove chrome_root/, we want path relative to that + return path[idx + len('chrome_root/'):] + else: + return path -def normalize_warning_line(line): - """Normalize file path relative to android_root in a warning line.""" - # replace fancy quotes with plain ol' quotes +def normalize_warning_line(line, flags, android_root=None): + """Normalize file path relative to src directory in a warning line.""" line = re.sub(u'[\u2018\u2019]', '\'', line) # replace non-ASCII chars to spaces line = re.sub(u'[^\x00-\x7f]', ' ', line) line = line.strip() first_column = line.find(':') - if first_column > 0: - return normalize_path(line[:first_column]) + line[first_column:] - else: - return line + return normalize_path(line[:first_column], flags, + android_root) + line[first_column:] -def parse_input_file(infile): - """Parse input file, collect parameters and warning lines.""" - global android_root - global platform_version - global target_product - global target_variant - line_counter = 0 +def parse_input_file_chrome(infile, flags): + """Parse Chrome input file, collect parameters and warning lines.""" + platform_version = 'unknown' + board_name = 'unknown' + architecture = 'unknown' + + # only handle warning lines of format 'file_path:line_no:col_no: warning: ...' + chrome_warning_pattern = r'^[^ ]*/[^ ]*:[0-9]+:[0-9]+: warning: .*' + + warning_pattern = re.compile(chrome_warning_pattern) + + # Collect all unique warning lines + # Remove the duplicated warnings save ~8% of time when parsing + # one typical build log than before + unique_warnings = dict() + for line in infile: + if warning_pattern.match(line): + normalized_line = normalize_warning_line(line, flags) + if normalized_line not in unique_warnings: + unique_warnings[normalized_line] = generate_cs_link(line, flags) + elif (platform_version == 'unknown' or board_name == 'unknown' or + architecture == 'unknown'): + m = re.match(r'.+Package:.+chromeos-base/chromeos-chrome-', line) + if m is not None: + platform_version = 'R' + line.split('chrome-')[1].split('_')[0] + continue + m = re.match(r'.+Source\sunpacked\sin\s(.+)', line) + if m is not None: + board_name = m.group(1).split('/')[2] + continue + m = re.match(r'.+USE:\s*([^\s]*).*', line) + if m is not None: + architecture = m.group(1) + continue + + header_str = '%s - %s - %s' % (platform_version, board_name, architecture) + return unique_warnings, header_str + + +def add_normalized_line_to_warnings(line, flags, android_root, unique_warnings): + """Parse/normalize path, updating warning line and add to warnings dict.""" + normalized_line = normalize_warning_line(line, flags, android_root) + if normalized_line not in unique_warnings: + unique_warnings[normalized_line] = generate_cs_link(line, flags, + android_root) + return unique_warnings + + +def parse_input_file_android(infile, flags): + """Parse Android input file, collect parameters and warning lines.""" + platform_version = 'unknown' + target_product = 'unknown' + target_variant = 'unknown' + android_root = find_android_root(infile) + infile.seek(0) # rustc warning messages have two lines that should be combined: # warning: description @@ -532,20 +360,25 @@ def parse_input_file(infile): warning_without_file = re.compile('^warning: .*') rustc_file_position = re.compile('^[ ]+--> [^ ]*/[^ ]*:[0-9]+:[0-9]+') - # Collect all warnings into the warning_lines set. - warning_lines = set() + # Collect all unique warning lines + # Remove the duplicated warnings save ~8% of time when parsing + # one typical build log than before + unique_warnings = dict() + line_counter = 0 prev_warning = '' for line in infile: if prev_warning: if rustc_file_position.match(line): # must be a rustc warning, combine 2 lines into one warning line = line.strip().replace('--> ', '') + ': ' + prev_warning - warning_lines.add(normalize_warning_line(line)) + unique_warnings = add_normalized_line_to_warnings( + line, flags, android_root, unique_warnings) prev_warning = '' continue # add prev_warning, and then process the current line prev_warning = 'unknown_source_file: ' + prev_warning - warning_lines.add(normalize_warning_line(prev_warning)) + unique_warnings = add_normalized_line_to_warnings( + prev_warning, flags, android_root, unique_warnings) prev_warning = '' if warning_pattern.match(line): @@ -553,7 +386,8 @@ def parse_input_file(infile): # save this line and combine it with the next line prev_warning = line else: - warning_lines.add(normalize_warning_line(line)) + unique_warnings = add_normalized_line_to_warnings( + line, flags, android_root, unique_warnings) continue if line_counter < 100: @@ -568,336 +402,182 @@ def parse_input_file(infile): m = re.search('(?<=^TARGET_BUILD_VARIANT=).*', line) if m is not None: target_variant = m.group(0) - m = re.search('.* TOP=([^ ]*) .*', line) + m = re.search('(?<=^TOP=).*', line) if m is not None: android_root = m.group(1) - return warning_lines - - -# Return s with escaped backslash and quotation characters. -def escape_string(s): - # pytype: disable=attribute-error - return s.replace('\\', '\\\\').replace('"', '\\"') - # pytype: enable=attribute-error - - -# Return s without trailing '\n' and escape the quotation characters. -def strip_escape_string(s): - if not s: - return s - s = s[:-1] if s[-1] == '\n' else s - return escape_string(s) - - -def emit_warning_array(name, writer): - writer('var warning_{} = ['.format(name)) - for i in range(len(warn_patterns)): - writer('{},'.format(warn_patterns[i][name])) - writer('];') - - -def emit_warning_arrays(writer): - emit_warning_array('severity', writer) - writer('var warning_description = [') - for i in range(len(warn_patterns)): - if warn_patterns[i]['members']: - writer('"{}",'.format(escape_string(warn_patterns[i]['description']))) - else: - writer('"",') # no such warning - writer('];') - - -scripts_for_warning_groups = """ - function compareMessages(x1, x2) { // of the same warning type - return (WarningMessages[x1[2]] <= WarningMessages[x2[2]]) ? -1 : 1; - } - function byMessageCount(x1, x2) { - return x2[2] - x1[2]; // reversed order - } - function bySeverityMessageCount(x1, x2) { - // orer by severity first - if (x1[1] != x2[1]) - return x1[1] - x2[1]; - return byMessageCount(x1, x2); - } - const ParseLinePattern = /^([^ :]+):(\\d+):(.+)/; - function addURL(line) { - if (FlagURL == "") return line; - if (FlagSeparator == "") { - return line.replace(ParseLinePattern, - "<a target='_blank' href='" + FlagURL + "/$1'>$1</a>:$2:$3"); - } - return line.replace(ParseLinePattern, - "<a target='_blank' href='" + FlagURL + "/$1" + FlagSeparator + - "$2'>$1:$2</a>:$3"); - } - function createArrayOfDictionaries(n) { - var result = []; - for (var i=0; i<n; i++) result.push({}); - return result; - } - function groupWarningsBySeverity() { - // groups is an array of dictionaries, - // each dictionary maps from warning type to array of warning messages. - var groups = createArrayOfDictionaries(SeverityColors.length); - for (var i=0; i<Warnings.length; i++) { - var w = Warnings[i][0]; - var s = WarnPatternsSeverity[w]; - var k = w.toString(); - if (!(k in groups[s])) - groups[s][k] = []; - groups[s][k].push(Warnings[i]); - } - return groups; - } - function groupWarningsByProject() { - var groups = createArrayOfDictionaries(ProjectNames.length); - for (var i=0; i<Warnings.length; i++) { - var w = Warnings[i][0]; - var p = Warnings[i][1]; - var k = w.toString(); - if (!(k in groups[p])) - groups[p][k] = []; - groups[p][k].push(Warnings[i]); - } - return groups; - } - var GlobalAnchor = 0; - function createWarningSection(header, color, group) { - var result = ""; - var groupKeys = []; - var totalMessages = 0; - for (var k in group) { - totalMessages += group[k].length; - groupKeys.push([k, WarnPatternsSeverity[parseInt(k)], group[k].length]); - } - groupKeys.sort(bySeverityMessageCount); - for (var idx=0; idx<groupKeys.length; idx++) { - var k = groupKeys[idx][0]; - var messages = group[k]; - var w = parseInt(k); - var wcolor = SeverityColors[WarnPatternsSeverity[w]]; - var description = WarnPatternsDescription[w]; - if (description.length == 0) - description = "???"; - GlobalAnchor += 1; - result += "<table class='t1'><tr bgcolor='" + wcolor + "'><td>" + - "<button class='bt' id='" + GlobalAnchor + "_mark" + - "' onclick='expand(\\"" + GlobalAnchor + "\\");'>" + - "⊕</button> " + - description + " (" + messages.length + ")</td></tr></table>"; - result += "<div id='" + GlobalAnchor + - "' style='display:none;'><table class='t1'>"; - var c = 0; - messages.sort(compareMessages); - for (var i=0; i<messages.length; i++) { - result += "<tr><td class='c" + c + "'>" + - addURL(WarningMessages[messages[i][2]]) + "</td></tr>"; - c = 1 - c; - } - result += "</table></div>"; - } - if (result.length > 0) { - return "<br><span style='background-color:" + color + "'><b>" + - header + ": " + totalMessages + - "</b></span><blockquote><table class='t1'>" + - result + "</table></blockquote>"; - - } - return ""; // empty section - } - function generateSectionsBySeverity() { - var result = ""; - var groups = groupWarningsBySeverity(); - for (s=0; s<SeverityColors.length; s++) { - result += createWarningSection(SeverityHeaders[s], SeverityColors[s], - groups[s]); - } - return result; - } - function generateSectionsByProject() { - var result = ""; - var groups = groupWarningsByProject(); - for (i=0; i<groups.length; i++) { - result += createWarningSection(ProjectNames[i], 'lightgrey', groups[i]); - } - return result; - } - function groupWarnings(generator) { - GlobalAnchor = 0; - var e = document.getElementById("warning_groups"); - e.innerHTML = generator(); - } - function groupBySeverity() { - groupWarnings(generateSectionsBySeverity); - } - function groupByProject() { - groupWarnings(generateSectionsByProject); - } -""" + + if android_root: + new_unique_warnings = dict() + for warning_line in unique_warnings: + normalized_line = normalize_warning_line(warning_line, flags, + android_root) + new_unique_warnings[normalized_line] = generate_android_cs_link( + warning_line, flags, android_root) + unique_warnings = new_unique_warnings + + header_str = '%s - %s - %s' % (platform_version, target_product, + target_variant) + return unique_warnings, header_str + + +def parse_input_file(infile, flags): + if flags.platform == 'chrome': + return parse_input_file_chrome(infile, flags) + if flags.platform == 'android': + return parse_input_file_android(infile, flags) + raise RuntimeError('parse_input_file not defined for platform %s' % + flags.platform) + + +def parse_compiler_output(compiler_output): + """Parse compiler output for relevant info.""" + split_output = compiler_output.split(':', 3) # 3 = max splits + file_path = split_output[0] + line_number = int(split_output[1]) + col_number = int(split_output[2].split(' ')[0]) + warning_message = split_output[3] + return file_path, line_number, col_number, warning_message + + +def get_warn_patterns(platform): + """Get and initialize warn_patterns.""" + warn_patterns = [] + if platform == 'chrome': + warn_patterns = cpp_patterns.warn_patterns + elif platform == 'android': + warn_patterns = make_patterns.warn_patterns + cpp_patterns.warn_patterns + java_patterns.warn_patterns + tidy_patterns.warn_patterns + other_patterns.warn_patterns + else: + raise Exception('platform name %s is not valid' % platform) + for w in warn_patterns: + w['members'] = [] + # Each warning pattern has a 'projects' dictionary, that + # maps a project name to number of warnings in that project. + w['projects'] = {} + return warn_patterns -# Emit a JavaScript const string -def emit_const_string(name, value, writer): - writer('const ' + name + ' = "' + escape_string(value) + '";') - - -# Emit a JavaScript const integer array. -def emit_const_int_array(name, array, writer): - writer('const ' + name + ' = [') - for n in array: - writer(str(n) + ',') - writer('];') - - -# Emit a JavaScript const string array. -def emit_const_string_array(name, array, writer): - writer('const ' + name + ' = [') - for s in array: - writer('"' + strip_escape_string(s) + '",') - writer('];') - - -# Emit a JavaScript const string array for HTML. -def emit_const_html_string_array(name, array, writer): - writer('const ' + name + ' = [') - for s in array: - # Not using html.escape yet, to work for both python 2 and 3, - # until all users switch to python 3. - # pylint:disable=deprecated-method - writer('"' + cgi.escape(strip_escape_string(s)) + '",') - writer('];') - - -# Emit a JavaScript const object array. -def emit_const_object_array(name, array, writer): - writer('const ' + name + ' = [') - for x in array: - writer(str(x) + ',') - writer('];') - - -def emit_js_data(writer): - """Dump dynamic HTML page's static JavaScript data.""" - emit_const_string('FlagURL', - args.url if args.url else '', writer) - emit_const_string('FlagSeparator', - args.separator if args.separator else '', writer) - emit_const_string_array('SeverityColors', - [s.color for s in Severity.levels], writer) - emit_const_string_array('SeverityHeaders', - [s.header for s in Severity.levels], writer) - emit_const_string_array('SeverityColumnHeaders', - [s.column_header for s in Severity.levels], writer) - emit_const_string_array('ProjectNames', project_names, writer) - # pytype: disable=attribute-error - emit_const_int_array('WarnPatternsSeverity', - [w['severity'].value for w in warn_patterns], writer) - # pytype: enable=attribute-error - emit_const_html_string_array('WarnPatternsDescription', - [w['description'] for w in warn_patterns], - writer) - emit_const_html_string_array('WarningMessages', warning_messages, writer) - emit_const_object_array('Warnings', warning_records, writer) - -draw_table_javascript = """ -google.charts.load('current', {'packages':['table']}); -google.charts.setOnLoadCallback(drawTable); -function drawTable() { - var data = new google.visualization.DataTable(); - data.addColumn('string', StatsHeader[0]); - for (var i=1; i<StatsHeader.length; i++) { - data.addColumn('number', StatsHeader[i]); - } - data.addRows(StatsRows); - for (var i=0; i<StatsRows.length; i++) { - for (var j=0; j<StatsHeader.length; j++) { - data.setProperty(i, j, 'style', 'border:1px solid black;'); - } - } - var table = new google.visualization.Table( - document.getElementById('stats_table')); - table.draw(data, {allowHtml: true, alternatingRowStyle: true}); -} -""" +def get_project_list(platform): + """Return project list for appropriate platform.""" + if platform == 'chrome': + return chrome_project_list.project_list + if platform == 'android': + return android_project_list.project_list + raise Exception('platform name %s is not valid' % platform) -def dump_html(output_stream): - """Dump the html output to output_stream.""" - writer = make_writer(output_stream) - dump_html_prologue('Warnings for ' + platform_version + ' - ' + - target_product + ' - ' + target_variant, writer) - dump_stats(writer) - writer('<br><div id="stats_table"></div><br>') - writer('\n<script>') - emit_js_data(writer) - writer(scripts_for_warning_groups) - writer('</script>') - emit_buttons(writer) - # Warning messages are grouped by severities or project names. - writer('<br><div id="warning_groups"></div>') - if args.byproject: - writer('<script>groupByProject();</script>') +def parallel_classify_warnings(warning_data, args, project_names, + project_patterns, warn_patterns, + use_google3, create_launch_subprocs_fn, + classify_warnings_fn): + """Classify all warning lines with num_cpu parallel processes.""" + num_cpu = args.processes + group_results = [] + + if num_cpu > 1: + # set up parallel processing for this... + warning_groups = [[] for _ in range(num_cpu)] + i = 0 + for warning, link in warning_data.items(): + warning_groups[i].append((warning, link)) + i = (i + 1) % num_cpu + arg_groups = [[] for _ in range(num_cpu)] + for i, group in enumerate(warning_groups): + arg_groups[i] = [{ + 'group': group, + 'project_patterns': project_patterns, + 'warn_patterns': warn_patterns, + 'num_processes': num_cpu + }] + + group_results = create_launch_subprocs_fn(num_cpu, + classify_warnings_fn, + arg_groups, + group_results) else: - writer('<script>groupBySeverity();</script>') - dump_fixed(writer) - dump_html_epilogue(writer) - - -##### Functions to count warnings and dump csv file. ######################### - - -def description_for_csv(category): - if not category['description']: - return '?' - return category['description'] - - -def count_severity(writer, sev, kind): - """Count warnings of given severity.""" - total = 0 - for i in warn_patterns: - if i['severity'] == sev and i['members']: - n = len(i['members']) - total += n - warning = kind + ': ' + description_for_csv(i) - writer.writerow([n, '', warning]) - # print number of warnings for each project, ordered by project name. - # pytype: disable=attribute-error - projects = sorted(i['projects'].keys()) - # pytype: enable=attribute-error - for p in projects: - writer.writerow([i['projects'][p], p, warning]) - writer.writerow([total, '', kind + ' warnings']) - - return total - - -# dump number of warnings in csv format to stdout -def dump_csv(writer): - """Dump number of warnings in csv format to stdout.""" - sort_warnings() - total = 0 - for s in Severity.levels: - if s != Severity.SEVERITY_UNKNOWN: - total += count_severity(writer, s, s.column_header) - writer.writerow([total, '', 'All warnings']) - - -def common_main(parallel_process): - """Real main function to classify warnings and generate .html file.""" - find_android_root() - # We must use 'utf-8' codec to parse some non-ASCII code in warnings. - warning_lines = parse_input_file( - io.open(args.buildlog, mode='r', encoding='utf-8')) - parallel_classify_warnings(warning_lines, parallel_process) - # If a user pases a csv path, save the fileoutput to the path - # If the user also passed gencsv write the output to stdout - # If the user did not pass gencsv flag dump the html report to stdout. - if args.csvpath: - with open(args.csvpath, 'w') as f: - dump_csv(csv.writer(f, lineterminator='\n')) - if args.gencsv: - dump_csv(csv.writer(sys.stdout, lineterminator='\n')) + group_results = [] + for warning, link in warning_data.items(): + classify_one_warning(warning, link, group_results, + project_patterns, warn_patterns) + group_results = [group_results] + + warning_messages = [] + warning_links = [] + warning_records = [] + if use_google3: + group_results = [group_results] + for group_result in group_results: + for result in group_result: + for line, link, pattern_idx, project_idx in result: + pattern = warn_patterns[pattern_idx] + pattern['members'].append(line) + message_idx = len(warning_messages) + warning_messages.append(line) + link_idx = len(warning_links) + warning_links.append(link) + warning_records.append([pattern_idx, project_idx, message_idx, + link_idx]) + pname = '???' if project_idx < 0 else project_names[project_idx] + # Count warnings by project. + if pname in pattern['projects']: + pattern['projects'][pname] += 1 + else: + pattern['projects'][pname] = 1 + return warning_messages, warning_links, warning_records + + +def process_log(logfile, flags, project_names, project_patterns, warn_patterns, + html_path, use_google3, create_launch_subprocs_fn, + classify_warnings_fn, logfile_object): + # pylint: disable=g-doc-args + # pylint: disable=g-doc-return-or-yield + """Function that handles processing of a log. + + This is isolated into its own function (rather than just taking place in main) + so that it can be used by both warn.py and the borg job process_gs_logs.py, to + avoid duplication of code. + Note that if the arguments to this function change, process_gs_logs.py must + be updated accordingly. + """ + if logfile_object is None: + with io.open(logfile, encoding='utf-8') as log: + warning_lines_and_links, header_str = parse_input_file(log, flags) else: - dump_html(sys.stdout) + warning_lines_and_links, header_str = parse_input_file( + logfile_object, flags) + warning_messages, warning_links, warning_records = parallel_classify_warnings( + warning_lines_and_links, flags, project_names, project_patterns, + warn_patterns, use_google3, create_launch_subprocs_fn, + classify_warnings_fn) + + html_writer.write_html(flags, project_names, warn_patterns, html_path, + warning_messages, warning_links, warning_records, + header_str) + + return warning_messages, warning_links, warning_records, header_str + + +def common_main(use_google3, create_launch_subprocs_fn, classify_warnings_fn, + logfile_object=None): + """Shared main function for Google3 and non-Google3 versions of warn.py.""" + flags = parse_args(use_google3) + warn_patterns = get_warn_patterns(flags.platform) + project_list = get_project_list(flags.platform) + + project_names = get_project_names(project_list) + project_patterns = [re.compile(p[1]) for p in project_list] + + # html_path=None because we output html below if not outputting CSV + warning_messages, warning_links, warning_records, header_str = process_log( + logfile=flags.log, flags=flags, project_names=project_names, + project_patterns=project_patterns, warn_patterns=warn_patterns, + html_path=None, use_google3=use_google3, + create_launch_subprocs_fn=create_launch_subprocs_fn, + classify_warnings_fn=classify_warnings_fn, + logfile_object=logfile_object) + + html_writer.write_out_csv(flags, warn_patterns, warning_messages, + warning_links, warning_records, header_str, + project_names) + + # Return these values, so that caller can use them, if desired. + return flags, warning_messages, warning_records, warn_patterns diff --git a/tools/zipalign/ZipFile.cpp b/tools/zipalign/ZipFile.cpp index 63fb962767..88505b7508 100644 --- a/tools/zipalign/ZipFile.cpp +++ b/tools/zipalign/ZipFile.cpp @@ -1221,7 +1221,7 @@ class FileReader : public zip_archive::Reader { FileReader(FILE* fp) : Reader(), fp_(fp), current_offset_(0) { } - bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const { + bool ReadAtOffset(uint8_t* buf, size_t len, off64_t offset) const { // Data is usually requested sequentially, so this helps avoid pointless // fseeks every time we perform a read. There's an impedence mismatch // here because the original API was designed around pread and pwrite. @@ -1244,7 +1244,7 @@ class FileReader : public zip_archive::Reader { private: FILE* fp_; - mutable uint32_t current_offset_; + mutable off64_t current_offset_; }; // free the memory when you're done |