Merge RQ1A.210105.003 to aosp-master - DO NOT MERGE
Merged-In: Ic0390b8c19cbe4b38042939647e316901bb4bd17
Change-Id: I4f5adfb48b892311c1bd2dd2a50b670547eb2fb5
diff --git a/Changes.md b/Changes.md
index 2720a0f..84c8d95 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 3fc7cbc..41defb2 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -748,6 +748,13 @@
$(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)
+
+# Workaround for Soong not being able to rebuild the host binary if its
+# JNI dependencies change: b/170389375
+$(call add-clean-step, rm -rf $(OUT_DIR)/soong/host/*/lib*/libconscrypt_openjdk_jni.so)
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/Deprecation.md b/Deprecation.md
index 2f936e3..74b54fa 100644
--- a/Deprecation.md
+++ b/Deprecation.md
@@ -14,21 +14,21 @@
| 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/OWNERS b/OWNERS
index 05f8b3d..4cac0f5 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,11 +1 @@
-# Core build team (MTV)
-ccross@android.com
-dwillemsen@google.com
-asmundak@google.com
-jungjw@google.com
-
-# To expedite LON reviews
-hansson@google.com
-
-# For version updates
-per-file version_defaults.mk = aseaton@google.com,elisapascual@google.com,lubomir@google.com,pscovanner@google.com
+include platform/build/soong:/OWNERS
diff --git a/common/math.mk b/common/math.mk
index 83f2218..ec15f88 100644
--- a/common/math.mk
+++ b/common/math.mk
@@ -181,6 +181,22 @@
$(call math-expect,(call numbers_less_than,4,0 2 1 3),0 2 1 3)
$(call math-expect,(call numbers_less_than,3,0 2 1 3 2),0 2 1 2)
+# Returns the words in $2 that are numbers and are greater or equal to $1
+define numbers_greater_or_equal_to
+$(strip \
+ $(foreach n,$2, \
+ $(if $(call math_is_number,$(n)), \
+ $(if $(call math_gt_or_eq,$(n),$(1)), \
+ $(n)))))
+endef
+
+$(call math-expect,(call numbers_greater_or_equal_to,4,0 1 2 3),)
+$(call math-expect,(call numbers_greater_or_equal_to,3,0 2 1 3),3)
+$(call math-expect,(call numbers_greater_or_equal_to,2,0 2 1 3),2 3)
+$(call math-expect,(call numbers_greater_or_equal_to,1,0 2 1 3),2 1 3)
+$(call math-expect,(call numbers_greater_or_equal_to,0,0 2 1 3),0 2 1 3)
+$(call math-expect,(call numbers_greater_or_equal_to,1,0 2 1 3 2),2 1 3 2)
+
_INT_LIMIT_WORDS := $(foreach a,x x,$(foreach b,x x x x x x x x x x x x x x x x,\
$(foreach c,x x x x x x x x x x x x x x x x,x x x x x x x x x x x x x x x x)))
diff --git a/common/strings.mk b/common/strings.mk
index ba20e27..e560bf0 100644
--- a/common/strings.mk
+++ b/common/strings.mk
@@ -28,7 +28,7 @@
###########################################################
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 45ad60f..40e9274 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -39,6 +39,18 @@
use ODM_MANIFEST_FILES / vintf_fragments instead!)) \
)
endef
+
+# Phony target to check PRODUCT_COPY_FILES copy pairs don't contain ELF files
+.PHONY: check-elf-prebuilt-product-copy-files
+check-elf-prebuilt-product-copy-files:
+
+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 +71,10 @@
$(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 +134,7 @@
# -----------------------------------------------------------------
# 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,540 +165,22 @@
$(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 :=
+# Build recovery image if
+# BUILDING_RECOVERY_IMAGE && !BOARD_USES_RECOVERY_AS_BOOT && !BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT.
+# If BOARD_USES_RECOVERY_AS_BOOT is true, leave empty because INSTALLED_BOOTIMAGE_TARGET is built
+# with recovery resources.
+# If BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT is true, leave empty to build recovery resources
+# but not the final recovery image.
ifdef BUILDING_RECOVERY_IMAGE
ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+ifneq ($(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT),true)
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
# ----------------------------------------------------------------
@@ -855,6 +352,15 @@
$(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.
@@ -884,13 +390,35 @@
VENDOR_RAMDISK_STRIPPED_MODULE_STAGING_DIR :=
endif
+# Create the "kernel module directory" to "vendor ramdisk fragment" inverse mapping.
+$(foreach vendor_ramdisk_fragment,$(BOARD_VENDOR_RAMDISK_FRAGMENTS), \
+ $(if $(and $(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).KERNEL_MODULE_DIRS), \
+ $(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).PREBUILT)), \
+ $(error Must not specify KERNEL_MODULE_DIRS for prebuilt vendor ramdisk fragment "$(vendor_ramdisk_fragment)": $(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).KERNEL_MODULE_DIRS))) \
+ $(eval VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).STAGING_DIR := $(call intermediates-dir-for,PACKAGING,vendor_ramdisk_fragment-dlkm-$(vendor_ramdisk_fragment))) \
+ $(eval VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).FILES :=) \
+ $(foreach dir,$(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).KERNEL_MODULE_DIRS), \
+ $(eval kmd_vrf := KERNEL_MODULE_DIR_VENDOR_RAMDISK_FRAGMENT_$(dir)) \
+ $(if $($(kmd_vrf)),$(error Kernel module directory "$(dir)" belongs to multiple vendor ramdisk fragments: "$($(kmd_vrf))" "$(vendor_ramdisk_fragment)", each kernel module directory should belong to exactly one or none vendor ramdisk fragment)) \
+ $(eval $(kmd_vrf) := $(vendor_ramdisk_fragment)) \
+ ) \
+)
+
BOARD_KERNEL_MODULE_DIRS += top
$(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 vendor_ramdisk_fragment := $(KERNEL_MODULE_DIR_VENDOR_RAMDISK_FRAGMENT_$(dir))) \
+ $(if $(vendor_ramdisk_fragment), \
+ $(eval output_dir := $(VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).STAGING_DIR)) \
+ $(eval result_var := VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).FILES) \
+ $(eval ### else ###), \
+ $(eval output_dir := $(TARGET_VENDOR_RAMDISK_OUT)) \
+ $(eval result_var := ALL_DEFAULT_INSTALLED_MODULES)) \
+ $(eval $(result_var) += $(call build-image-kernel-modules-dir,VENDOR_RAMDISK,$(output_dir),,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)))))
@@ -942,7 +470,7 @@
$(if $(PACKAGES.$(p).APKCERTS_FILE),\
$(call _apkcerts_merge,$(PACKAGES.$(p).APKCERTS_FILE), $@),\
$(if $(PACKAGES.$(p).EXTERNAL_KEY),\
- $(call _apkcerts_write_line,$(PACKAGES.$(p).STEM),"EXTERNAL","",$(PACKAGES.$(p).COMPRESSED),$(PACKAGES.$(p).PARTITION),$@),\
+ $(call _apkcerts_write_line,$(PACKAGES.$(p).STEM),EXTERNAL,,$(PACKAGES.$(p).COMPRESSED),$(PACKAGES.$(p).PARTITION),$@),\
$(call _apkcerts_write_line,$(PACKAGES.$(p).STEM),$(PACKAGES.$(p).CERTIFICATE),$(PACKAGES.$(p).PRIVATE_KEY),$(PACKAGES.$(p).COMPRESSED),$(PACKAGES.$(p).PARTITION),$@))))
# In case value of PACKAGES is empty.
$(hide) touch $@
@@ -981,7 +509,7 @@
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 +518,30 @@
$(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
@@ -1016,6 +568,12 @@
$(call dist-for-goals,droidcore,$(PGO_PROFILE_MISSING))
+CERTIFICATE_VIOLATION_MODULES_FILENAME := $(PRODUCT_OUT)/certificate_violation_modules.txt
+$(CERTIFICATE_VIOLATION_MODULES_FILENAME):
+ rm -f $@
+ $(foreach m,$(sort $(CERTIFICATE_VIOLATION_MODULES)), echo $(m) >> $@;)
+$(call dist-for-goals,droidcore,$(CERTIFICATE_VIOLATION_MODULES_FILENAME))
+
# -----------------------------------------------------------------
# The dev key is used to sign this package, and as the key required
# for future OTA packages installed by this system. Actual product
@@ -1045,12 +603,8 @@
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 +613,14 @@
# 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 +634,10 @@
# #################################################################
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 +742,34 @@
BUILT_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
endif
+INTERNAL_PREBUILT_BOOTIMAGE :=
+
+my_installed_prebuilt_gki_apex := $(strip $(foreach package,$(PRODUCT_PACKAGES),$(if $(ALL_MODULES.$(package).EXTRACTED_BOOT_IMAGE),$(package))))
+ifdef my_installed_prebuilt_gki_apex
+ ifneq (1,$(words $(my_installed_prebuilt_gki_apex))) # len(my_installed_prebuilt_gki_apex) > 1
+ $(error More than one prebuilt GKI APEXes are installed: $(my_installed_prebuilt_gki_apex))
+ endif # len(my_installed_prebuilt_gki_apex) > 1
+
+ ifdef BOARD_PREBUILT_BOOTIMAGE
+ $(error Must not define BOARD_PREBUILT_BOOTIMAGE because a prebuilt GKI APEX is installed: $(my_installed_prebuilt_gki_apex))
+ endif # BOARD_PREBUILT_BOOTIMAGE defined
+
+ my_apex_extracted_boot_image := $(ALL_MODULES.$(my_installed_prebuilt_gki_apex).EXTRACTED_BOOT_IMAGE)
+ INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
+ $(eval $(call copy-one-file,$(my_apex_extracted_boot_image),$(INSTALLED_BOOTIMAGE_TARGET)))
+
+ INTERNAL_PREBUILT_BOOTIMAGE := $(my_apex_extracted_boot_image)
+
+else # my_installed_prebuilt_gki_apex not defined
+
+# $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 +782,7 @@
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)
@@ -1220,22 +805,27 @@
INTERNAL_KERNEL_CMDLINE := $(strip $(INTERNAL_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
-ifndef BUILDING_VENDOR_BOOT_IMAGE
-ifdef BOARD_KERNEL_BASE
- INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
-endif
-ifdef BOARD_KERNEL_PAGESIZE
- INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
-endif
-ifdef INTERNAL_KERNEL_CMDLINE
- INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
-endif
-else
-# building vendor boot image, dtb/base/pagesize go there
-ifdef GENERIC_KERNEL_CMDLINE
- INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(GENERIC_KERNEL_CMDLINE)"
-endif
-endif
+# kernel cmdline/base/pagesize in boot.
+# - If using GKI, use GENERIC_KERNEL_CMDLINE. Remove kernel base and pagesize because they are
+# device-specific.
+# - If not using GKI:
+# - If building vendor_boot, INTERNAL_KERNEL_CMDLINE, base and pagesize goes in vendor_boot.
+# - Otherwise, put them in boot.
+ifeq (true,$(BOARD_USES_GENERIC_KERNEL_IMAGE))
+ ifdef GENERIC_KERNEL_CMDLINE
+ INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(GENERIC_KERNEL_CMDLINE)"
+ endif
+else ifndef BUILDING_VENDOR_BOOT_IMAGE # && BOARD_USES_GENERIC_KERNEL_IMAGE != true
+ ifdef INTERNAL_KERNEL_CMDLINE
+ INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
+ endif
+ ifdef BOARD_KERNEL_BASE
+ INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
+ endif
+ ifdef BOARD_KERNEL_PAGESIZE
+ INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
+ endif
+endif # BUILDING_VENDOR_BOOT_IMAGE == "" && BOARD_USES_GENERIC_KERNEL_IMAGE != true
INTERNAL_MKBOOTIMG_VERSION_ARGS := \
--os_version $(PLATFORM_VERSION_LAST_STABLE) \
@@ -1247,74 +837,86 @@
ifeq ($(TARGET_BOOTIMAGE_USE_EXT2),true)
$(error TARGET_BOOTIMAGE_USE_EXT2 is not supported anymore)
+endif # TARGET_BOOTIMAGE_USE_EXT2
-else ifeq (true,$(BOARD_AVB_ENABLE)) # TARGET_BOOTIMAGE_USE_EXT2 != true
+$(foreach b,$(INSTALLED_BOOTIMAGE_TARGET), $(eval $(call add-dependency,$(b),$(call bootimage-to-kernel,$(b)))))
+
+ifeq (true,$(BOARD_AVB_ENABLE))
+
+# $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,$(call get-bootimage-partition-size,$(1),boot)))
+ $(AVBTOOL) add_hash_footer \
+ --image $(1) \
+ --partition_size $(call get-bootimage-partition-size,$(1),boot) \
+ --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 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
+# $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),$(call get-bootimage-partition-size,$(1),boot))
+endef
+
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER)
$(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
+# $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),$(call get-bootimage-partition-size,$(1),boot))
+endef
+
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(VBOOT_SIGNER) $(FUTILITY)
$(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
+# $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,$(call get-bootimage-partition-size,$(1),boot))
+endef
+
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES)
$(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 # BOARD_AVB_ENABLE
endif # BUILDING_BOOT_IMAGE
else # TARGET_NO_KERNEL == "true"
@@ -1323,12 +925,23 @@
# Remove when b/63676296 is resolved.
$(error Prebuilt bootimage is only supported for AB targets)
endif
+INTERNAL_PREBUILT_BOOTIMAGE := $(BOARD_PREBUILT_BOOTIMAGE)
INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
-$(eval $(call copy-one-file,$(BOARD_PREBUILT_BOOTIMAGE),$(INSTALLED_BOOTIMAGE_TARGET)))
+$(eval $(call copy-one-file,$(INTERNAL_PREBUILT_BOOTIMAGE),$(INSTALLED_BOOTIMAGE_TARGET)))
else # BOARD_PREBUILT_BOOTIMAGE not defined
INSTALLED_BOOTIMAGE_TARGET :=
endif # BOARD_PREBUILT_BOOTIMAGE
endif # TARGET_NO_KERNEL
+endif # my_installed_prebuilt_gki_apex not defined
+
+my_apex_extracted_boot_image :=
+my_installed_prebuilt_gki_apex :=
+
+# -----------------------------------------------------------------
+# declare recovery ramdisk files
+ifeq ($(BUILDING_RECOVERY_IMAGE),true)
+INTERNAL_RECOVERY_RAMDISK_FILES_TIMESTAMP := $(call intermediates-dir-for,PACKAGING,recovery)/ramdisk_files-timestamp
+endif
# -----------------------------------------------------------------
# vendor boot image
@@ -1342,9 +955,26 @@
$(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)
+
+ifeq (true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT))
+$(INTERNAL_VENDOR_RAMDISK_TARGET): $(INTERNAL_RECOVERY_RAMDISK_FILES_TIMESTAMP)
+$(INTERNAL_VENDOR_RAMDISK_TARGET): PRIVATE_ADDITIONAL_DIR := $(TARGET_RECOVERY_ROOT_OUT)
+endif
+
$(INTERNAL_VENDOR_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_RAMDISK_FILES) | $(COMPRESSION_COMMAND_DEPS)
- $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_RAMDISK_OUT) | $(COMPRESSION_COMMAND) > $@
+ $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_RAMDISK_OUT) $(PRIVATE_ADDITIONAL_DIR) | $(COMPRESSION_COMMAND) > $@
+
+INSTALLED_FILES_FILE_VENDOR_RAMDISK := $(PRODUCT_OUT)/installed-files-vendor-ramdisk.txt
+INSTALLED_FILES_JSON_VENDOR_RAMDISK := $(INSTALLED_FILES_FILE_VENDOR_RAMDISK:.txt=.json)
+$(INSTALLED_FILES_FILE_VENDOR_RAMDISK): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_VENDOR_RAMDISK)
+$(INSTALLED_FILES_FILE_VENDOR_RAMDISK): $(INTERNAL_VENDOR_RAMDISK_TARGET)
+$(INSTALLED_FILES_FILE_VENDOR_RAMDISK): $(INTERNAL_VENDOR_RAMDISK_FILES) $(FILESLIST) $(FILESLIST_UTIL)
+ echo Installed file list: $@
+ mkdir -p $(dir $@)
+ rm -f $@
+ $(hide) $(FILESLIST) $(TARGET_VENDOR_RAMDISK_OUT) > $(@:.txt=.json)
+ $(hide) $(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
INTERNAL_VENDOR_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
@@ -1359,12 +989,55 @@
INTERNAL_VENDOR_BOOTIMAGE_ARGS += --vendor_cmdline "$(INTERNAL_KERNEL_CMDLINE)"
endif
+# $(1): Build target name
+# $(2): Staging dir to be compressed
+# $(3): Build dependencies
+define build-vendor-ramdisk-fragment-target
+$(1): $(3) $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)
+ $(MKBOOTFS) -d $(TARGET_OUT) $(2) | $(COMPRESSION_COMMAND) > $$@
+endef
+
+# $(1): Ramdisk name
+define build-vendor-ramdisk-fragment
+$(strip \
+ $(eval build_target := $(call intermediates-dir-for,PACKAGING,vendor_ramdisk_fragments)/$(1).cpio$(RAMDISK_EXT)) \
+ $(eval $(call build-vendor-ramdisk-fragment-target,$(build_target),$(VENDOR_RAMDISK_FRAGMENT.$(1).STAGING_DIR),$(VENDOR_RAMDISK_FRAGMENT.$(1).FILES))) \
+ $(build_target) \
+)
+endef
+
+# $(1): Ramdisk name
+# $(2): Prebuilt file path
+define build-prebuilt-vendor-ramdisk-fragment
+$(strip \
+ $(eval build_target := $(call intermediates-dir-for,PACKAGING,prebuilt_vendor_ramdisk_fragments)/$(1)) \
+ $(eval $(call copy-one-file,$(2),$(build_target))) \
+ $(build_target) \
+)
+endef
+
+INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS :=
+INTERNAL_VENDOR_RAMDISK_FRAGMENT_ARGS :=
+
+$(foreach vendor_ramdisk_fragment,$(BOARD_VENDOR_RAMDISK_FRAGMENTS), \
+ $(eval prebuilt_vendor_ramdisk_fragment_file := $(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).PREBUILT)) \
+ $(if $(prebuilt_vendor_ramdisk_fragment_file), \
+ $(eval vendor_ramdisk_fragment_target := $(call build-prebuilt-vendor-ramdisk-fragment,$(vendor_ramdisk_fragment),$(prebuilt_vendor_ramdisk_fragment_file))) \
+ $(eval ### else ###), \
+ $(eval vendor_ramdisk_fragment_target := $(call build-vendor-ramdisk-fragment,$(vendor_ramdisk_fragment))) \
+ $(if $(filter --ramdisk_type,$(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).MKBOOTIMG_ARGS)),, \
+ $(eval BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).MKBOOTIMG_ARGS += --ramdisk_type DLKM))) \
+ $(eval INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS += $(vendor_ramdisk_fragment_target)) \
+ $(eval INTERNAL_VENDOR_RAMDISK_FRAGMENT_ARGS += $(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).MKBOOTIMG_ARGS) --vendor_ramdisk_fragment $(vendor_ramdisk_fragment_target)) \
+)
+
INSTALLED_VENDOR_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/vendor_boot.img
$(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_VENDOR_RAMDISK_TARGET) $(INSTALLED_DTBIMAGE_TARGET)
+$(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS)
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) $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_ARGS) --vendor_boot $@
$(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
$(AVBTOOL) add_hash_footer \
--image $@ \
@@ -1374,7 +1047,7 @@
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) $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_ARGS) --vendor_boot $@
$(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
endif
endif # BUILDING_VENDOR_BOOT_IMAGE
@@ -1394,14 +1067,17 @@
.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,18 +1091,20 @@
# 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) \
+ $(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 +1120,11 @@
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 +1136,8 @@
$(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 +1167,27 @@
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 +1195,53 @@
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 +1251,50 @@
$(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 +1306,10 @@
$(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 +1320,18 @@
$(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 +1342,8 @@
"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
@@ -1624,6 +1382,9 @@
ifneq (true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED))
INTERNAL_USERIMAGES_SPARSE_EXT_FLAG := -s
endif
+ifneq (true,$(TARGET_USERIMAGES_SPARSE_EROFS_DISABLED))
+ INTERNAL_USERIMAGES_SPARSE_EROFS_FLAG := -s
+endif
ifneq (true,$(TARGET_USERIMAGES_SPARSE_SQUASHFS_DISABLED))
INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG := -s
endif
@@ -1640,7 +1401,27 @@
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) \
+ ,erofs),)
+INTERNAL_USERIMAGES_DEPS += $(MKEROFSUSERIMG)
+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) \
+ $(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE) \
+ $(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE) \
+ ,squashfs),)
INTERNAL_USERIMAGES_DEPS += $(MKSQUASHFSUSERIMG)
endif
@@ -1658,7 +1439,13 @@
# Get a colon-separated list of search paths.
INTERNAL_USERIMAGES_BINARY_PATHS := $(subst $(space),:,$(sort $(dir $(INTERNAL_USERIMAGES_DEPS))))
+# Collects file_contexts files from modules to be installed
+$(call merge-fc-files, \
+ $(sort $(foreach m,$(product_MODULES),$(ALL_MODULES.$(m).FILE_CONTEXTS))),\
+ $(call intermediates-dir-for,ETC,file_contexts.bin)/file_contexts.modules.tmp)
+
SELINUX_FC := $(call intermediates-dir-for,ETC,file_contexts.bin)/file_contexts.bin
+
INTERNAL_USERIMAGES_DEPS += $(SELINUX_FC)
ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
@@ -1670,13 +1457,15 @@
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),\
$(if $(BOARD_SYSTEMIMAGE_PARTITION_SIZE),$(hide) echo "system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(INTERNAL_SYSTEM_OTHER_PARTITION_SIZE),$(hide) echo "system_other_size=$(INTERNAL_SYSTEM_OTHER_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_fs_type=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
+ $(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_COMPRESS),$(hide) echo "system_fs_compress=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_COMPRESS)" >> $(1))
+ $(if $(BOARD_SYSTEMIMAGE_F2FS_SLOAD_COMPRESS_FLAGS),$(hide) echo "system_f2fs_sldc_flags=$(BOARD_SYSTEMIMAGE_F2FS_SLOAD_COMPRESS_FLAGS)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "system_extfs_inode_count=$(BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_EXTFS_RSV_PCT),$(hide) echo "system_extfs_rsv_pct=$(BOARD_SYSTEMIMAGE_EXTFS_RSV_PCT)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_JOURNAL_SIZE),$(hide) echo "system_journal_size=$(BOARD_SYSTEMIMAGE_JOURNAL_SIZE)" >> $(1))
@@ -1688,18 +1477,25 @@
$(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))
$(if $(BOARD_USERDATAIMAGE_PARTITION_SIZE),$(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(PRODUCT_FS_CASEFOLD),$(hide) echo "needs_casefold=$(PRODUCT_FS_CASEFOLD)" >> $(1))
$(if $(PRODUCT_QUOTA_PROJID),$(hide) echo "needs_projid=$(PRODUCT_QUOTA_PROJID)" >> $(1))
+ $(if $(PRODUCT_FS_COMPRESSION),$(hide) echo "needs_compress=$(PRODUCT_FS_COMPRESSION)" >> $(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 +1510,7 @@
$(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 +1525,7 @@
$(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 +1539,7 @@
$(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 +1554,35 @@
$(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))
@@ -1767,6 +1595,7 @@
$(if $(INTERNAL_USERIMAGES_EXT_VARIANT),$(hide) echo "fs_type=$(INTERNAL_USERIMAGES_EXT_VARIANT)" >> $(1))
$(if $(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG),$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(1))
+$(if $(INTERNAL_USERIMAGES_SPARSE_EROFS_FLAG),$(hide) echo "erofs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EROFS_FLAG)" >> $(1))
$(if $(INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG),$(hide) echo "squashfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG)" >> $(1))
$(if $(INTERNAL_USERIMAGES_SPARSE_F2FS_FLAG),$(hide) echo "f2fs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_F2FS_FLAG)" >> $(1))
$(if $(BOARD_EXT4_SHARE_DUP_BLOCKS),$(hide) echo "ext4_share_dup_blocks=$(BOARD_EXT4_SHARE_DUP_BLOCKS)" >> $(1))
@@ -1782,6 +1611,8 @@
$(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 +1661,22 @@
$(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 +1696,9 @@
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 +1714,12 @@
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
@@ -1886,16 +1742,15 @@
INSTALLED_FILES_FILE_RECOVERY := $(PRODUCT_OUT)/installed-files-recovery.txt
INSTALLED_FILES_JSON_RECOVERY := $(INSTALLED_FILES_FILE_RECOVERY:.txt=.json)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+INSTALLED_BOOTIMAGE_TARGET := $(BUILT_BOOTIMAGE_TARGET)
+endif
+
# TODO(b/30414428): Can't depend on INTERNAL_RECOVERYIMAGE_FILES alone like other
# INSTALLED_FILES_FILE_* rules. Because currently there're cp/rsync/rm commands in
# build-recoveryimage-target, which would touch the files under TARGET_RECOVERY_OUT and race with
# the call to FILELIST.
-ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
-INSTALLED_BOOTIMAGE_TARGET := $(BUILT_BOOTIMAGE_TARGET)
-$(INSTALLED_FILES_FILE_RECOVERY): $(INSTALLED_BOOTIMAGE_TARGET)
-else
-$(INSTALLED_FILES_FILE_RECOVERY): $(INSTALLED_RECOVERYIMAGE_TARGET)
-endif
+$(INSTALLED_FILES_FILE_RECOVERY): $(INTERNAL_RECOVERY_RAMDISK_FILES_TIMESTAMP)
$(INSTALLED_FILES_FILE_RECOVERY): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_RECOVERY)
$(INSTALLED_FILES_FILE_RECOVERY): $(INTERNAL_RECOVERYIMAGE_FILES) $(FILESLIST) $(FILESLIST_UTIL)
@@ -1922,9 +1777,11 @@
# 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 +1809,9 @@
# 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 +1835,7 @@
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 +1859,12 @@
$(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 +1882,7 @@
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)
@@ -2091,9 +1949,13 @@
# e) We include the recovery ACPIO image within recovery - not needing the resource file as we
# do bsdiff because boot and recovery will contain different number of entries
# (BOARD_INCLUDE_RECOVERY_ACPIO = true).
+# f) We build a single image that contains vendor_boot and recovery both - no recovery image to
+# install
+# (BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT = true).
ifeq (,$(filter true, $(BOARD_USES_FULL_RECOVERY_IMAGE) $(BOARD_USES_RECOVERY_AS_BOOT) \
- $(BOARD_BUILD_SYSTEM_ROOT_IMAGE) $(BOARD_INCLUDE_RECOVERY_DTBO) $(BOARD_INCLUDE_RECOVERY_ACPIO)))
+ $(BOARD_BUILD_SYSTEM_ROOT_IMAGE) $(BOARD_INCLUDE_RECOVERY_DTBO) $(BOARD_INCLUDE_RECOVERY_ACPIO) \
+ $(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT)))
# Named '.dat' so we don't attempt to use imgdiff for patching it.
RECOVERY_RESOURCE_ZIP := $(TARGET_OUT_VENDOR)/etc/recovery-resource.dat
ALL_DEFAULT_INSTALLED_MODULES += $(RECOVERY_RESOURCE_ZIP)
@@ -2131,9 +1993,7 @@
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,28 +2001,32 @@
@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) >> $@
$(hide) cat $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET) >> $@
$(call append-recovery-ui-properties,$(PRIVATE_RECOVERY_UI_PROPERTIES),$@)
-ifeq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(AB_OTA_UPDATER)))
- INTERNAL_RECOVERYIMAGE_ARGS := --ramdisk $(recovery_ramdisk)
-ifdef GENERIC_KERNEL_CMDLINE
- INTERNAL_RECOVERYIMAGE_ARGS += --cmdline "$(GENERIC_KERNEL_CMDLINE)"
+# Only install boot/etc/build.prop to recovery image on recovery_as_boot.
+# On device with dedicated recovery partition, the file should come from the boot
+# ramdisk.
+ifeq (true,$(BOARD_USES_RECOVERY_AS_BOOT))
+INSTALLED_RECOVERY_RAMDISK_BUILD_PROP_TARGET := $(TARGET_RECOVERY_ROOT_OUT)/$(RAMDISK_BUILD_PROP_REL_PATH)
+$(INSTALLED_RECOVERY_RAMDISK_BUILD_PROP_TARGET): $(INSTALLED_RAMDISK_BUILD_PROP_TARGET)
+ $(copy-file-to-target)
endif
-else # not (BUILDING_VENDOR_BOOT_IMAGE and AB_OTA_UPDATER)
- INTERNAL_RECOVERYIMAGE_ARGS := \
- $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
- --ramdisk $(recovery_ramdisk)
+
+INTERNAL_RECOVERYIMAGE_ARGS := --ramdisk $(recovery_ramdisk)
+
+ifneq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(BOARD_USES_RECOVERY_AS_BOOT)))
+INTERNAL_RECOVERYIMAGE_ARGS += $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET))
# Assumes this has already been stripped
+ifneq (true,$(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE))
ifdef INTERNAL_KERNEL_CMDLINE
INTERNAL_RECOVERYIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
-endif
+endif # INTERNAL_KERNEL_CMDLINE != ""
+endif # BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE != true
ifdef BOARD_KERNEL_BASE
INTERNAL_RECOVERYIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
endif
@@ -2182,18 +2046,19 @@
ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
INTERNAL_RECOVERYIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
endif
-endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET not defined
+endif # (BUILDING_VENDOR_BOOT_IMAGE and BOARD_USES_RECOVERY_AS_BOOT)
ifndef BOARD_RECOVERY_MKBOOTIMG_ARGS
BOARD_RECOVERY_MKBOOTIMG_ARGS := $(BOARD_MKBOOTIMG_ARGS)
endif
-$(recovery_ramdisk): $(MKBOOTFS) $(COMPRESSION_COMMAND_DEPS) \
+$(INTERNAL_RECOVERY_RAMDISK_FILES_TIMESTAMP): $(MKBOOTFS) $(COMPRESSION_COMMAND_DEPS) \
$(INTERNAL_ROOT_FILES) \
$(INSTALLED_RAMDISK_TARGET) \
$(INTERNAL_RECOVERYIMAGE_FILES) \
$(recovery_sepolicy) \
$(INSTALLED_2NDBOOTLOADER_TARGET) \
$(INSTALLED_RECOVERY_BUILD_PROP_TARGET) \
+ $(INSTALLED_RECOVERY_RAMDISK_BUILD_PROP_TARGET) \
$(recovery_resource_deps) \
$(recovery_fstab)
# Making recovery image
@@ -2222,16 +2087,19 @@
cp -f $(recovery_wipe) $(TARGET_RECOVERY_ROOT_OUT)/system/etc/recovery.wipe)
ln -sf prop.default $(TARGET_RECOVERY_ROOT_OUT)/default.prop
$(BOARD_RECOVERY_IMAGE_PREPARE)
+ $(hide) touch $@
+
+$(recovery_ramdisk): $(INTERNAL_RECOVERY_RAMDISK_FILES_TIMESTAMP)
$(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RECOVERY_ROOT_OUT) | $(COMPRESSION_COMMAND) > $(recovery_ramdisk)
# $(1): output file
-# $(2): kernel file
+# $(2): optional kernel file
define build-recoveryimage-target
$(if $(filter true,$(PRODUCT_SUPPORTS_VBOOT)), \
- $(MKBOOTIMG) --kernel $(2) $(INTERNAL_RECOVERYIMAGE_ARGS) \
+ $(MKBOOTIMG) $(if $(strip $(2)),--kernel $(strip $(2))) $(INTERNAL_RECOVERYIMAGE_ARGS) \
$(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_RECOVERY_MKBOOTIMG_ARGS) \
--output $(1).unsigned, \
- $(MKBOOTIMG) --kernel $(2) $(INTERNAL_RECOVERYIMAGE_ARGS) \
+ $(MKBOOTIMG) $(if $(strip $(2)),--kernel $(strip $(2))) $(INTERNAL_RECOVERYIMAGE_ARGS) \
$(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_RECOVERY_MKBOOTIMG_ARGS) \
--output $(1))
$(if $(filter true,$(PRODUCT_SUPPORTS_BOOT_SIGNER)),\
@@ -2276,13 +2144,15 @@
endif
ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+$(foreach b,$(INSTALLED_BOOTIMAGE_TARGET), $(eval $(call add-dependency,$(b),$(call bootimage-to-kernel,$(b)))))
$(INSTALLED_BOOTIMAGE_TARGET): $(recoveryimage-deps)
$(call pretty,"Target boot image from recovery: $@")
$(call build-recoveryimage-target, $@, $(PRODUCT_OUT)/$(subst .img,,$(subst boot,kernel,$(notdir $@))))
endif # BOARD_USES_RECOVERY_AS_BOOT
$(INSTALLED_RECOVERYIMAGE_TARGET): $(recoveryimage-deps)
- $(call build-recoveryimage-target, $@, $(recovery_kernel))
+ $(call build-recoveryimage-target, $@, \
+ $(if $(filter true, $(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE)),, $(recovery_kernel)))
ifdef RECOVERY_RESOURCE_ZIP
$(RECOVERY_RESOURCE_ZIP): $(INSTALLED_RECOVERYIMAGE_TARGET) | $(ZIPTIME)
@@ -2294,7 +2164,8 @@
.PHONY: recoveryimage-nodeps
recoveryimage-nodeps:
@echo "make $@: ignoring dependencies"
- $(call build-recoveryimage-target, $(INSTALLED_RECOVERYIMAGE_TARGET))
+ $(call build-recoveryimage-target, $(INSTALLED_RECOVERYIMAGE_TARGET), \
+ $(if $(filter true, $(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE)),, $(recovery_kernel)))
else # BUILDING_RECOVERY_IMAGE
RECOVERY_RESOURCE_ZIP :=
@@ -2392,6 +2263,7 @@
#
# Note: it's intentional to skip signing for boot-debug.img, because it
# can only be used if the device is unlocked with verification error.
+ifneq ($(INSTALLED_BOOTIMAGE_TARGET),)
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
ifneq ($(strip $(BOARD_KERNEL_BINARIES)),)
INSTALLED_DEBUG_BOOTIMAGE_TARGET := $(foreach k,$(subst kernel,boot-debug,$(BOARD_KERNEL_BINARIES)), \
@@ -2446,6 +2318,7 @@
$(foreach b,$(INSTALLED_DEBUG_BOOTIMAGE_TARGET),$(call build-debug-bootimage-target,$b))
endif # TARGET_NO_KERNEL
+endif # INSTALLED_BOOTIMAGE_TARGET
ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
ifeq ($(BUILDING_RAMDISK_IMAGE),true)
@@ -2514,8 +2387,9 @@
# 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)
+$(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET): $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS)
$(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) $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_ARGS) --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 +2485,48 @@
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: .KATI_SYMLINK_OUTPUTS := $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)
@@ -2640,6 +2543,15 @@
# -----------------------------------------------------------------
ifdef BUILDING_SYSTEM_IMAGE
+# Install system linker configuration
+# Collect all available stub libraries installed in system and install with predefined linker configuration
+SYSTEM_LINKER_CONFIG := $(TARGET_OUT)/etc/linker.config.pb
+$(SYSTEM_LINKER_CONFIG) : $(INTERNAL_SYSTEMIMAGE_FILES) $(LINKER_CONFIG_PATH_system_linker_config) | conv_linker_config
+ $(HOST_OUT_EXECUTABLES)/conv_linker_config systemprovide --source $(LINKER_CONFIG_PATH_system_linker_config)\
+ --output $@ --value "$(STUB_LIBRARIES)" --system "$(TARGET_OUT)"
+
+FULL_SYSTEMIMAGE_DEPS += $(SYSTEM_LINKER_CONFIG)
+
# installed file list
# Depending on anything that $(BUILT_SYSTEMIMAGE) depends on.
# We put installed-files.txt ahead of image itself in the dependency graph
@@ -2664,57 +2576,9 @@
$(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 +2621,11 @@
$(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 +2645,8 @@
@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 +2655,14 @@
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 +2796,7 @@
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 +2859,31 @@
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 +2895,12 @@
$(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 +2935,7 @@
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 +2986,7 @@
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 +3039,25 @@
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 +3104,109 @@
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
@@ -3348,6 +3226,26 @@
endif # BOARD_PREBUILT_DTBOIMAGE
+# -----------------------------------------------------------------
+# Protected VM firmware image
+ifdef BOARD_PREBUILT_PVMFWIMAGE
+INSTALLED_PVMFWIMAGE_TARGET := $(PRODUCT_OUT)/pvmfw.img
+
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(INSTALLED_PVMFWIMAGE_TARGET): $(BOARD_PREBUILT_PVMFWIMAGE) $(AVBTOOL) $(BOARD_AVB_PVMFW_KEY_PATH)
+ cp $(BOARD_PREBUILT_PVMFWIMAGE) $@
+ $(AVBTOOL) add_hash_footer \
+ --image $@ \
+ --partition_size $(BOARD_PVMFWIMG_PARTITION_SIZE) \
+ --partition_name pvmfw $(INTERNAL_AVB_PVMFW_SIGNING_ARGS) \
+ $(BOARD_AVB_PVMFW_ADD_HASH_FOOTER_ARGS)
+else
+$(INSTALLED_PVMFWIMAGE_TARGET): $(BOARD_PREBUILT_PVMFWIMAGE)
+ cp $(BOARD_PREBUILT_PVMFWIMAGE) $@
+endif
+
+endif # BOARD_PREBUILT_PVMFWIMAGE
+
# Returns a list of image targets corresponding to the given list of partitions. For example, it
# returns "$(INSTALLED_PRODUCTIMAGE_TARGET)" for "product", or "$(INSTALLED_SYSTEMIMAGE_TARGET)
# $(INSTALLED_VENDORIMAGE_TARGET)" for "system vendor".
@@ -3484,9 +3382,20 @@
--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)
+BOARD_AVB_PVMFW_ADD_HASH_FOOTER_ARGS += \
+ --prop com.android.build.pvmfw.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
+
# The following vendor- and odm-specific images needs explicit SPL set per board.
ifdef BOOT_SECURITY_PATCH
BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
@@ -3503,15 +3412,33 @@
--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
+
+ifdef PVMFW_SECURITY_PATCH
+BOARD_AVB_PVMFW_ADD_HASH_FOOTER_ARGS += \
+ --prop com.android.build.pvmfw.security_patch:$(PVMFW_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
+PVMFW_FOOTER_ARGS := BOARD_AVB_PVMFW_ADD_HASH_FOOTER_ARGS
SYSTEM_FOOTER_ARGS := BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS
VENDOR_FOOTER_ARGS := BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS
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,10 +3533,22 @@
$(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
+ifdef INSTALLED_PVMFWIMAGE_TARGET
+$(eval $(call check-and-set-avb-args,pvmfw))
+endif
+
ifdef INSTALLED_RECOVERYIMAGE_TARGET
$(eval $(call check-and-set-avb-args,recovery))
endif
@@ -3686,9 +3625,18 @@
$(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)
+ $(if $(BOARD_AVB_PVMFW_KEY_PATH),\
+ $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_PVMFW_KEY_PATH) \
+ --output $(1)/pvmfw.avbpubkey)
$(if $(BOARD_AVB_RECOVERY_KEY_PATH),\
$(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_RECOVERY_KEY_PATH) \
--output $(1)/recovery.avbpubkey)
@@ -3768,7 +3716,10 @@
$(INSTALLED_PRODUCTIMAGE_TARGET) \
$(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
$(INSTALLED_ODMIMAGE_TARGET) \
+ $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) \
+ $(INSTALLED_ODM_DLKMIMAGE_TARGET) \
$(INSTALLED_DTBOIMAGE_TARGET) \
+ $(INSTALLED_PVMFWIMAGE_TARGET) \
$(INSTALLED_CUSTOMIMAGES_TARGET) \
$(INSTALLED_RECOVERYIMAGE_TARGET) \
$(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET) \
@@ -3790,7 +3741,9 @@
# -----------------------------------------------------------------
# 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 :=
@@ -3826,11 +3779,19 @@
check_vintf_system_deps := $(filter $(TARGET_OUT)/etc/vintf/%, $(check_vintf_common_srcs))
ifneq ($(check_vintf_system_deps),)
check_vintf_has_system := true
+
check_vintf_system_log := $(intermediates)/check_vintf_system_log
check_vintf_all_deps += $(check_vintf_system_log)
$(check_vintf_system_log): $(HOST_OUT_EXECUTABLES)/checkvintf $(check_vintf_system_deps)
@( $< --check-one --dirmap /system:$(TARGET_OUT) > $@ 2>&1 ) || ( cat $@ && exit 1 )
check_vintf_system_log :=
+
+vintffm_log := $(intermediates)/vintffm_log
+check_vintf_all_deps += $(vintffm_log)
+$(vintffm_log): $(HOST_OUT_EXECUTABLES)/vintffm $(check_vintf_system_deps)
+ @( $< --check --dirmap /system:$(TARGET_OUT) \
+ $(VINTF_FRAMEWORK_MANIFEST_FROZEN_DIR) > $@ 2>&1 ) || ( cat $@ && exit 1 )
+
endif # check_vintf_system_deps
check_vintf_system_deps :=
@@ -3915,10 +3876,10 @@
$(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)
+ --output-release $(BUILT_KERNEL_VERSION_FILE)
my_decompress_tools :=
@@ -3927,7 +3888,7 @@
endif # INSTALLED_KERNEL_TARGET
-check_vintf_compatible_args += --kernel $$(cat $(BUILT_KERNEL_VERSION_FILE)):$(BUILT_KERNEL_CONFIGS_FILE)
+check_vintf_compatible_args += --kernel $(BUILT_KERNEL_VERSION_FILE):$(BUILT_KERNEL_CONFIGS_FILE)
check_vintf_compatible_deps += $(BUILT_KERNEL_CONFIGS_FILE) $(BUILT_KERNEL_VERSION_FILE)
endif # PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
@@ -3996,13 +3957,12 @@
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 +3998,7 @@
endif # PRODUCT_BUILD_SUPER_PARTITION
-endif # TARGET_BUILD_APPS
+endif # !TARGET_BUILD_UNBUNDLED
# -----------------------------------------------------------------
# bring in the installer image generation defines if necessary
@@ -4064,9 +4024,6 @@
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 +4048,7 @@
INTERNAL_OTATOOLS_MODULES := \
aapt2 \
add_img_to_target_files \
+ aftltool \
apksigner \
append2simg \
avbtool \
@@ -4115,6 +4073,7 @@
fec \
fs_config \
generate_verity_key \
+ host_init_verifier \
img2simg \
img_from_target_files \
imgdiff \
@@ -4123,6 +4082,7 @@
lpunpack \
lz4 \
make_f2fs \
+ make_f2fs_casefold \
merge_target_files \
minigzip \
mk_combined_img \
@@ -4130,6 +4090,8 @@
mkbootimg \
mke2fs \
mke2fs.conf \
+ mkfs.erofs \
+ mkerofsimage.sh \
mkf2fsuserimg.sh \
mksquashfs \
mksquashfsimage.sh \
@@ -4143,6 +4105,7 @@
signapk \
simg2img \
sload_f2fs \
+ toybox \
tune2fs \
unpack_bootimg \
update_host_simulator \
@@ -4311,6 +4274,9 @@
$(hide) echo "board_uses_vendorimage=true" >> $@
endif
ifeq ($(BOARD_AVB_ENABLE),true)
+ifeq ($(BUILDING_VBMETA_IMAGE),true)
+ $(hide) echo "avb_building_vbmeta_image=true" >> $@
+endif # BUILDING_VBMETA_IMAGE
$(hide) echo "avb_enable=true" >> $@
$(hide) echo "avb_vbmeta_key_path=$(BOARD_AVB_KEY_PATH)" >> $@
$(hide) echo "avb_vbmeta_algorithm=$(BOARD_AVB_ALGORITHM)" >> $@
@@ -4387,6 +4353,18 @@
endif # BOARD_AVB_DTBO_KEY_PATH
endif # BOARD_AVB_ENABLE
endif # BOARD_PREBUILT_DTBOIMAGE
+ifdef BOARD_PREBUILT_PVMFWIMAGE
+ $(hide) echo "has_pvmfw=true" >> $@
+ifeq ($(BOARD_AVB_ENABLE),true)
+ $(hide) echo "pvmfw_size=$(BOARD_PVMFWIMG_PARTITION_SIZE)" >> $@
+ $(hide) echo "avb_pvmfw_add_hash_footer_args=$(BOARD_AVB_PVMFW_ADD_HASH_FOOTER_ARGS)" >> $@
+ifdef BOARD_AVB_PVMFW_KEY_PATH
+ $(hide) echo "avb_pvmfw_key_path=$(BOARD_AVB_PVMFW_KEY_PATH)" >> $@
+ $(hide) echo "avb_pvmfw_algorithm=$(BOARD_AVB_PVMFW_ALGORITHM)" >> $@
+ $(hide) echo "avb_pvmfw_rollback_index_location=$(BOARD_AVB_PVMFW_ROLLBACK_INDEX_LOCATION)" >> $@
+endif # BOARD_AVB_PVMFW_KEY_PATH
+endif # BOARD_AVB_ENABLE
+endif # BOARD_PREBUILT_PVMFWIMAGE
$(call dump-dynamic-partitions-info,$@)
@# VINTF checks
ifeq ($(PRODUCT_ENFORCE_VINTF_MANIFEST),true)
@@ -4404,6 +4382,15 @@
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
+ifeq ($(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE),true)
+ $(hide) echo "exclude_kernel_from_recovery_image=true" >> $@
+endif
+ifneq ($(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST),)
+ $(hide) echo "partial_ota_update_partitions_list=$(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST)" >> $@
+endif
.PHONY: misc_info
misc_info: $(INSTALLED_MISC_INFO_TARGET)
@@ -4442,7 +4429,7 @@
# 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)
@@ -4462,8 +4449,11 @@
$(BUILT_TARGET_FILES_PACKAGE): $(updater_dep)
# If we are using recovery as boot, output recovery files to BOOT/.
+# If we are moving recovery resources to vendor_boot, output recovery files to VENDOR_BOOT/.
ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_OUT := BOOT
+else ifeq ($(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT),true)
+$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_OUT := VENDOR_BOOT
else
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_OUT := RECOVERY
endif
@@ -4521,13 +4511,13 @@
$(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,34 +4542,104 @@
# 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)
+ $(BUILT_TARGET_FILES_PACKAGE): $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS)
+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)
+endif
+ifneq (,$(INTERNAL_PREBUILT_BOOTIMAGE) $(filter true,$(BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES)))
+ $(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_PVMFWIMAGE_TARGET) \
$(INSTALLED_CUSTOMIMAGES_TARGET) \
- $(INTERNAL_SYSTEMOTHERIMAGE_FILES) \
$(INSTALLED_ANDROID_INFO_TXT_TARGET) \
$(INSTALLED_KERNEL_TARGET) \
+ $(INSTALLED_RAMDISK_TARGET) \
$(INSTALLED_DTBIMAGE_TARGET) \
$(INSTALLED_2NDBOOTLOADER_TARGET) \
$(BOARD_PREBUILT_DTBOIMAGE) \
@@ -4590,6 +4650,8 @@
$(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,23 +4665,21 @@
$(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)))
+ifneq (,$(INSTALLED_RECOVERYIMAGE_TARGET)$(filter true,$(BOARD_USES_RECOVERY_AS_BOOT))$(filter true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT)))
@# Components of the recovery image
$(hide) mkdir -p $(zip_root)/$(PRIVATE_RECOVERY_OUT)
$(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 ifneq (true,$(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE))
+ cp $(firstword $(INSTALLED_KERNEL_TARGET)) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/kernel
endif
-ifeq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(AB_OTA_UPDATER)))
- echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
-else # not (BUILDING_VENDOR_BOOT_IMAGE and AB_OTA_UPDATER)
+endif
+ifneq (truetrue,$(strip $(BUILDING_VENDOR_BOOT_IMAGE))$(strip $(BOARD_USES_RECOVERY_AS_BOOT)))
ifdef INSTALLED_2NDBOOTLOADER_TARGET
cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/second
endif
@@ -4636,16 +4696,18 @@
ifdef INSTALLED_DTBIMAGE_TARGET
cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/dtb
endif
+ifneq (true,$(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE))
ifdef INTERNAL_KERNEL_CMDLINE
echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
-endif
+endif # INTERNAL_KERNEL_CMDLINE != ""
+endif # BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE != true
ifdef BOARD_KERNEL_BASE
echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/base
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 BOARD_USES_RECOVERY_AS_BOOT)
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,25 +4721,25 @@
$(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
+ifeq (true,$(BOARD_USES_GENERIC_KERNEL_IMAGE))
+ echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
+else ifndef INSTALLED_VENDOR_BOOTIMAGE_TARGET # && BOARD_USES_GENERIC_KERNEL_IMAGE != true
+ echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
ifdef INSTALLED_2NDBOOTLOADER_TARGET
cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/BOOT/second
endif
ifdef INSTALLED_DTBIMAGE_TARGET
cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/BOOT/dtb
endif
- echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
ifdef BOARD_KERNEL_BASE
echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/BOOT/base
endif
ifdef BOARD_KERNEL_PAGESIZE
echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/BOOT/pagesize
endif
-else # INSTALLED_VENDOR_BOOTIMAGE_TARGET defined
- echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
-endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET defined
+endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET == "" && BOARD_USES_GENERIC_KERNEL_IMAGE != true
endif # BOARD_USES_RECOVERY_AS_BOOT not true
$(hide) $(foreach t,$(INSTALLED_RADIOIMAGE_TARGET),\
mkdir -p $(zip_root)/RADIO; \
@@ -4696,6 +4758,19 @@
echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/VENDOR_BOOT/pagesize
endif
echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/VENDOR_BOOT/vendor_cmdline
+ifdef BOARD_VENDOR_RAMDISK_FRAGMENTS
+ echo "$(BOARD_VENDOR_RAMDISK_FRAGMENTS)" > "$(zip_root)/VENDOR_BOOT/vendor_ramdisk_fragments"
+ $(foreach vendor_ramdisk_fragment,$(BOARD_VENDOR_RAMDISK_FRAGMENTS), \
+ mkdir -p $(zip_root)/VENDOR_BOOT/RAMDISK_FRAGMENTS/$(vendor_ramdisk_fragment); \
+ echo "$(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).MKBOOTIMG_ARGS)" > "$(zip_root)/VENDOR_BOOT/RAMDISK_FRAGMENTS/$(vendor_ramdisk_fragment)/mkbootimg_args"; \
+ $(eval prebuilt_ramdisk := $(BOARD_VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).PREBUILT)) \
+ $(if $(prebuilt_ramdisk), \
+ cp "$(prebuilt_ramdisk)" "$(zip_root)/VENDOR_BOOT/RAMDISK_FRAGMENTS/$(vendor_ramdisk_fragment)/prebuilt_ramdisk";, \
+ $(call package_files-copy-root, \
+ $(VENDOR_RAMDISK_FRAGMENT.$(vendor_ramdisk_fragment).STAGING_DIR), \
+ $(zip_root)/VENDOR_BOOT/RAMDISK_FRAGMENTS/$(vendor_ramdisk_fragment)/RAMDISK); \
+ ))
+endif # BOARD_VENDOR_RAMDISK_FRAGMENTS != ""
endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET
ifdef BUILDING_SYSTEM_IMAGE
@# Contents of the system image
@@ -4727,6 +4802,16 @@
$(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, \
@@ -4735,6 +4820,13 @@
@# Extra contents of the OTA package
$(hide) mkdir -p $(zip_root)/OTA
$(hide) cp $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/
+ifdef BUILDING_RAMDISK_IMAGE
+ifeq (true,$(BOARD_IMG_USE_RAMDISK))
+ @# Contents of the ramdisk image
+ $(hide) mkdir -p $(zip_root)/IMAGES
+ $(hide) cp $(INSTALLED_RAMDISK_TARGET) $(zip_root)/IMAGES/
+endif
+endif
ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(built_ota_tools),)
$(hide) mkdir -p $(zip_root)/OTA/bin
@@ -4772,6 +4864,14 @@
$(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) \
@@ -4809,18 +4909,36 @@
$(hide) mkdir -p $(zip_root)/IMAGES
$(hide) cp $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) $(zip_root)/IMAGES/
endif
-ifdef BOARD_PREBUILT_BOOTIMAGE
+ifneq (,$(INTERNAL_PREBUILT_BOOTIMAGE) $(filter true,$(BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES)))
+ifdef INSTALLED_BOOTIMAGE_TARGET
$(hide) mkdir -p $(zip_root)/IMAGES
$(hide) cp $(INSTALLED_BOOTIMAGE_TARGET) $(zip_root)/IMAGES/
-endif
+endif # INSTALLED_BOOTIMAGE_TARGET
+endif # INTERNAL_PREBUILT_BOOTIMAGE != "" || BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES == true
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_PVMFWIMAGE
+ $(hide) mkdir -p $(zip_root)/PREBUILT_IMAGES
+ $(hide) cp $(INSTALLED_PVMFWIMAGE_TARGET) $(zip_root)/PREBUILT_IMAGES/
+endif # BOARD_PREBUILT_PVMFWIMAGE
+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 +4966,12 @@
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 +5017,7 @@
.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
@@ -4913,7 +5035,7 @@
# $(1): output file
# $(2): additional args
define build-ota-package-target
-PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
+PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$(dir $(ZIP2ZIP)):$$PATH \
$(OTA_FROM_TARGET_FILES) \
--verbose \
--extracted_input_target_files $(patsubst %.zip,%,$(BUILT_TARGET_FILES_PACKAGE)) \
@@ -4923,18 +5045,18 @@
$(BUILT_TARGET_FILES_PACKAGE) $(1)
endef
-name := $(TARGET_PRODUCT)
+product_name := $(TARGET_PRODUCT)
ifeq ($(TARGET_BUILD_TYPE),debug)
- name := $(name)_debug
+ product_name := $(product_name)_debug
endif
-name := $(name)-ota-$(FILE_NAME_TAG)
+name := $(product_name)-ota-$(FILE_NAME_TAG)
INTERNAL_OTA_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
INTERNAL_OTA_METADATA := $(PRODUCT_OUT)/ota_metadata
$(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
$(INTERNAL_OTA_PACKAGE_TARGET): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_OTA_METADATA)
-$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(OTA_FROM_TARGET_FILES)
+$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(OTA_FROM_TARGET_FILES) $(INTERNAL_OTATOOLS_FILES)
@echo "Package OTA: $@"
$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR) --output_metadata_path $(INTERNAL_OTA_METADATA))
@@ -4942,17 +5064,14 @@
otapackage: $(INTERNAL_OTA_PACKAGE_TARGET)
ifeq ($(BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE),true)
-name := $(TARGET_PRODUCT)
-ifeq ($(TARGET_BUILD_TYPE),debug)
- name := $(name)_debug
-endif
-name := $(name)-ota-retrofit-$(FILE_NAME_TAG)
+name := $(product_name)-ota-retrofit-$(FILE_NAME_TAG)
INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
$(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
$(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET): \
$(BUILT_TARGET_FILES_PACKAGE) \
- $(OTA_FROM_TARGET_FILES)
+ $(OTA_FROM_TARGET_FILES) \
+ $(INTERNAL_OTATOOLS_FILES)
@echo "Package OTA (retrofit dynamic partitions): $@"
$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR) --retrofit_dynamic_partitions)
@@ -4962,20 +5081,33 @@
endif # BOARD_BUILD_RETROFIT_DYNAMIC_PARTITIONS_OTA_PACKAGE
+ifneq ($(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST),)
+name := $(product_name)-partial-ota-$(FILE_NAME_TAG)
+
+INTERNAL_OTA_PARTIAL_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
+$(INTERNAL_OTA_PARTIAL_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
+$(INTERNAL_OTA_PARTIAL_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(OTA_FROM_TARGET_FILES) $(INTERNAL_OTATOOLS_FILES)
+ @echo "Package partial OTA: $@"
+ $(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR) --partial "$(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST)")
+
+.PHONY: partialotapackage
+partialotapackage: $(INTERNAL_OTA_PARTIAL_PACKAGE_TARGET)
+
+endif # BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST
+
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 +5129,16 @@
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 +5156,16 @@
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 +5199,7 @@
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 $@)
@@ -5087,7 +5221,7 @@
JACOCO_REPORT_CLASSES_ALL := $(PRODUCT_OUT)/jacoco-report-classes-all.jar
$(JACOCO_REPORT_CLASSES_ALL) :
@echo "Collecting uninstrumented classes"
- find $(TARGET_COMMON_OUT_ROOT) $(HOST_COMMON_OUT_ROOT) -name "jacoco-report-classes.jar" 2>/dev/null | sort > $@.list
+ find $(TARGET_COMMON_OUT_ROOT) $(HOST_COMMON_OUT_ROOT) -name "jacoco-report-classes.jar" -o -name "proguard_usage.zip" 2>/dev/null | sort > $@.list
$(SOONG_ZIP) -o $@ -L 0 -C $(OUT_DIR) -P out -l $@.list
endif # EMMA_INSTRUMENT=true
@@ -5098,16 +5232,17 @@
#
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): \
- $(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) \
+ $(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
@@ -5118,6 +5253,31 @@
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) \
+ $(INSTALLED_USERDATAIMAGE_TARGET) \
+ $(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_PRODUCTIMAGE_TARGET) \
+ $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
+ $(INSTALLED_ODMIMAGE_TARGET) \
+ $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) \
+ $(INSTALLED_ODM_DLKMIMAGE_TARGET) \
+ $(updater_dep)
+endif
+$(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_usage.zip > $(PRIVATE_LIST_FILE)
+ $(MERGE_ZIPS) $@ @$(PRIVATE_LIST_FILE)
ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
@@ -5346,6 +5506,26 @@
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 +5556,6 @@
$(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
# -----------------------------------------------------------------
@@ -5593,7 +5766,3 @@
.PHONY: haiku
haiku: $(SOONG_FUZZ_PACKAGING_ARCH_MODULES) $(ALL_FUZZ_TARGETS)
$(call dist-for-goals,haiku,$(SOONG_FUZZ_PACKAGING_ARCH_MODULES))
-
-# -----------------------------------------------------------------
-# The makefile for haiku line coverage.
-include $(BUILD_SYSTEM)/line_coverage.mk
diff --git a/core/OWNERS b/core/OWNERS
index 750f1fa..5456d4f 100644
--- a/core/OWNERS
+++ b/core/OWNERS
@@ -1,3 +1,6 @@
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
+
+# For version updates
+per-file version_defaults.mk = aseaton@google.com,elisapascual@google.com,lubomir@google.com,pscovanner@google.com
+
diff --git a/core/android_manifest.mk b/core/android_manifest.mk
index 8fab9c6..254e09b 100644
--- a/core/android_manifest.mk
+++ b/core/android_manifest.mk
@@ -45,7 +45,7 @@
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 0000000..883f92d
--- /dev/null
+++ b/core/android_soong_config_vars.mk
@@ -0,0 +1,36 @@
+# 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)
+
+# TODO(b/172480615): Remove when platform uses ART Module prebuilts by default.
+ifeq (,$(filter art_module,$(SOONG_CONFIG_NAMESPACES)))
+ $(call add_soong_config_namespace,art_module)
+ SOONG_CONFIG_art_module += source_build
+endif
+SOONG_CONFIG_art_module_source_build ?= true
diff --git a/core/app_prebuilt_internal.mk b/core/app_prebuilt_internal.mk
index ab574b3..5767996 100644
--- a/core/app_prebuilt_internal.mk
+++ b/core/app_prebuilt_internal.mk
@@ -45,7 +45,7 @@
# 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/artifact_path_requirements.mk b/core/artifact_path_requirements.mk
new file mode 100644
index 0000000..ceaefa2
--- /dev/null
+++ b/core/artifact_path_requirements.mk
@@ -0,0 +1,60 @@
+# This file contains logic to enforce artifact path requirements
+# defined in product makefiles.
+
+# Fakes don't get installed, and NDK stubs aren't installed to device.
+static_allowed_patterns := $(TARGET_OUT_FAKE)/% $(SOONG_OUT_DIR)/ndk/%
+# RROs become REQUIRED by the source module, but are always placed on the vendor partition.
+static_allowed_patterns += %__auto_generated_rro_product.apk
+static_allowed_patterns += %__auto_generated_rro_vendor.apk
+# Auto-included targets are not considered
+static_allowed_patterns += $(call product-installed-files,)
+# $(PRODUCT_OUT)/apex is where shared libraries in APEXes get installed.
+# The path can be considered as a fake path, as the shared libraries
+# are installed there just to have symbols files for them under
+# $(PRODUCT_OUT)/symbols/apex for debugging purpose. The /apex directory
+# is never compiled into a filesystem image.
+static_allowed_patterns += $(PRODUCT_OUT)/apex/%
+ifeq (true,$(BOARD_USES_SYSTEM_OTHER_ODEX))
+ # Allow system_other odex space optimization.
+ static_allowed_patterns += \
+ $(TARGET_OUT_SYSTEM_OTHER)/%.odex \
+ $(TARGET_OUT_SYSTEM_OTHER)/%.vdex \
+ $(TARGET_OUT_SYSTEM_OTHER)/%.art
+endif
+
+all_offending_files :=
+$(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\
+ $(eval requirements := $(PRODUCTS.$(makefile).ARTIFACT_PATH_REQUIREMENTS)) \
+ $(eval ### Verify that the product only produces files inside its path requirements.) \
+ $(eval allowed := $(PRODUCTS.$(makefile).ARTIFACT_PATH_ALLOWED_LIST)) \
+ $(eval path_patterns := $(call resolve-product-relative-paths,$(requirements),%)) \
+ $(eval allowed_patterns := $(call resolve-product-relative-paths,$(allowed))) \
+ $(eval files := $(call product-installed-files, $(makefile))) \
+ $(eval offending_files := $(filter-out $(path_patterns) $(allowed_patterns) $(static_allowed_patterns),$(files))) \
+ $(call maybe-print-list-and-error,$(offending_files),\
+ $(makefile) produces files outside its artifact path requirement. \
+ Allowed paths are $(subst $(space),$(comma)$(space),$(addsuffix *,$(requirements)))) \
+ $(eval unused_allowed := $(filter-out $(files),$(allowed_patterns))) \
+ $(if $(PRODUCTS.$(makefile).ARTIFACT_PATH_REQUIREMENT_IS_RELAXED),, \
+ $(call maybe-print-list-and-error,$(unused_allowed),$(makefile) includes redundant allowed entries in its artifact path requirement.) \
+ ) \
+ $(eval ### Optionally verify that nothing else produces files inside this artifact path requirement.) \
+ $(eval extra_files := $(filter-out $(files) $(HOST_OUT)/%,$(product_target_FILES))) \
+ $(eval files_in_requirement := $(filter $(path_patterns),$(extra_files))) \
+ $(eval all_offending_files += $(files_in_requirement)) \
+ $(eval allowed := $(PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST)) \
+ $(eval allowed_patterns := $(call resolve-product-relative-paths,$(allowed))) \
+ $(eval offending_files := $(filter-out $(allowed_patterns),$(files_in_requirement))) \
+ $(eval enforcement := $(PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS)) \
+ $(if $(enforcement),\
+ $(call maybe-print-list-and-error,$(offending_files),\
+ $(INTERNAL_PRODUCT) produces files inside $(makefile)s artifact path requirement. \
+ $(PRODUCT_ARTIFACT_PATH_REQUIREMENT_HINT)) \
+ $(eval unused_allowed := $(if $(filter true strict,$(enforcement)),\
+ $(foreach p,$(allowed_patterns),$(if $(filter $(p),$(extra_files)),,$(p))))) \
+ $(call maybe-print-list-and-error,$(unused_allowed),$(INTERNAL_PRODUCT) includes redundant artifact path requirement allowed list entries.) \
+ ) \
+)
+$(PRODUCT_OUT)/offending_artifacts.txt:
+ rm -f $@
+ $(foreach f,$(sort $(all_offending_files)),echo $(f) >> $@;)
diff --git a/core/autogen_test_config.mk b/core/autogen_test_config.mk
index d4ca56f..137b118 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 @@
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 10d2536..0000000
--- 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 5395e61..0000000
--- 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 d88478d..0000000
--- 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 c710228..0000000
--- 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 e608ee7..dbd8930 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -34,7 +34,6 @@
$(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 @@
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 @@
$(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 @@
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 @@
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 :=
@@ -267,6 +274,12 @@
endif
endif
+ifeq ($(LOCAL_IS_UNIT_TEST),true)
+ ifeq ($(LOCAL_IS_HOST_MODULE),true)
+ LOCAL_COMPATIBILITY_SUITE += host-unit-tests
+ endif
+endif
+
ifeq ($(my_module_path),)
install_path_var := $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT$(partition_tag)_$(LOCAL_MODULE_CLASS)
ifeq (true,$(LOCAL_PRIVILEGED_MODULE))
@@ -315,12 +328,9 @@
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 +376,16 @@
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 +447,6 @@
###########################################################
$(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 +473,35 @@
# 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 +522,11 @@
$(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 +619,22 @@
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 +768,13 @@
$(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 +802,19 @@
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 +835,8 @@
$(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 +991,11 @@
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)
+ifndef LOCAL_IS_HOST_MODULE
+ALL_MODULES.$(my_register_name).FILE_CONTEXTS := $(LOCAL_FILE_CONTEXTS)
+endif
test_config :=
INSTALLABLE_FILES.$(LOCAL_INSTALLED_MODULE).MODULE := $(my_register_name)
@@ -938,7 +1003,7 @@
##########################################################
# 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 db476c0..be008e6 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -125,12 +125,8 @@
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
@@ -160,6 +156,8 @@
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)
@@ -168,19 +166,7 @@
# 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)
@@ -195,6 +181,8 @@
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.
@@ -214,17 +202,11 @@
$(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
@@ -238,11 +220,7 @@
# 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
@@ -253,9 +231,6 @@
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
@@ -364,8 +339,7 @@
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))
@@ -677,7 +651,7 @@
$(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 $@
@@ -1143,37 +1117,39 @@
endif
###################################################################
+## 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_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).
##################################################################
-define use_soong_cfi_static_libraries
- $(foreach l,$(1),$(if $(filter $(l),$(SOONG_CFI_STATIC_LIBRARIES)),\
- $(l).cfi,$(l)))
-endef
-
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
###########################################################
@@ -1432,7 +1408,7 @@
# 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)))
@@ -1582,7 +1558,7 @@
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)
@@ -1601,28 +1577,22 @@
## 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
@@ -1705,9 +1675,22 @@
####################################################
## 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), \
@@ -1843,6 +1826,10 @@
$(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 86162b6..725c0a5 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -16,77 +16,115 @@
# ###############################################################
# 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_EGL_CFG \
- BOARD_HAVE_BLUETOOTH \
- BOARD_INSTALLER_CMDLINE \
- BOARD_KERNEL_CMDLINE \
- BOARD_KERNEL_BASE \
- BOARD_USES_GENERIC_AUDIO \
- BOARD_USES_RECOVERY_AS_BOOT \
- BOARD_VENDOR_USE_AKMD \
- BOARD_WPA_SUPPLICANT_DRIVER \
- BOARD_WLAN_DEVICE \
- TARGET_ARCH \
- TARGET_ARCH_VARIANT \
- TARGET_CPU_ABI \
- TARGET_CPU_ABI2 \
- TARGET_CPU_VARIANT \
- TARGET_CPU_VARIANT_RUNTIME \
- TARGET_2ND_ARCH \
- TARGET_2ND_ARCH_VARIANT \
- TARGET_2ND_CPU_ABI \
- TARGET_2ND_CPU_ABI2 \
- TARGET_2ND_CPU_VARIANT \
- TARGET_2ND_CPU_VARIANT_RUNTIME \
- TARGET_BOARD_PLATFORM \
- TARGET_BOARD_PLATFORM_GPU \
- TARGET_BOOTLOADER_BOARD_NAME \
- TARGET_FS_CONFIG_GEN \
- TARGET_NO_BOOTLOADER \
- TARGET_NO_KERNEL \
- TARGET_NO_RECOVERY \
- TARGET_NO_RADIOIMAGE \
- TARGET_HARDWARE_3D \
- WITH_DEXPREOPT \
+_board_strip_readonly_list :=
+_board_strip_readonly_list += BOARD_BOOTLOADER_IN_UPDATE_PACKAGE
+_board_strip_readonly_list += BOARD_EGL_CFG
+_board_strip_readonly_list += BOARD_HAVE_BLUETOOTH
+_board_strip_readonly_list += BOARD_INSTALLER_CMDLINE
+_board_strip_readonly_list += BOARD_KERNEL_CMDLINE
+_board_strip_readonly_list += BOARD_KERNEL_BASE
+_board_strip_readonly_list += BOARD_USES_GENERIC_AUDIO
+_board_strip_readonly_list += BOARD_USES_RECOVERY_AS_BOOT
+_board_strip_readonly_list += BOARD_VENDOR_USE_AKMD
+_board_strip_readonly_list += BOARD_WPA_SUPPLICANT_DRIVER
+_board_strip_readonly_list += BOARD_WLAN_DEVICE
+_board_strip_readonly_list += TARGET_BOARD_PLATFORM
+_board_strip_readonly_list += TARGET_BOARD_PLATFORM_GPU
+_board_strip_readonly_list += TARGET_BOOTLOADER_BOARD_NAME
+_board_strip_readonly_list += TARGET_FS_CONFIG_GEN
+_board_strip_readonly_list += TARGET_NO_BOOTLOADER
+_board_strip_readonly_list += TARGET_NO_KERNEL
+_board_strip_readonly_list += TARGET_NO_RECOVERY
+_board_strip_readonly_list += TARGET_NO_RADIOIMAGE
+_board_strip_readonly_list += TARGET_HARDWARE_3D
+_board_strip_readonly_list += WITH_DEXPREOPT
+
+# Arch variables
+_board_strip_readonly_list += TARGET_ARCH
+_board_strip_readonly_list += TARGET_ARCH_VARIANT
+_board_strip_readonly_list += TARGET_CPU_ABI
+_board_strip_readonly_list += TARGET_CPU_ABI2
+_board_strip_readonly_list += TARGET_CPU_VARIANT
+_board_strip_readonly_list += TARGET_CPU_VARIANT_RUNTIME
+_board_strip_readonly_list += TARGET_2ND_ARCH
+_board_strip_readonly_list += TARGET_2ND_ARCH_VARIANT
+_board_strip_readonly_list += TARGET_2ND_CPU_ABI
+_board_strip_readonly_list += TARGET_2ND_CPU_ABI2
+_board_strip_readonly_list += TARGET_2ND_CPU_VARIANT
+_board_strip_readonly_list += TARGET_2ND_CPU_VARIANT_RUNTIME
+# TARGET_ARCH_SUITE is an alternative arch configuration to TARGET_ARCH (and related variables),
+# that can be used for soong-only builds to build for several architectures at once.
+# Allowed values currently are "ndk" and "mainline_sdk".
+_board_strip_readonly_list += TARGET_ARCH_SUITE
# File system variables
-_board_strip_readonly_list += \
- BOARD_FLASH_BLOCK_SIZE \
- BOARD_BOOTIMAGE_PARTITION_SIZE \
- BOARD_RECOVERYIMAGE_PARTITION_SIZE \
- BOARD_SYSTEMIMAGE_PARTITION_SIZE \
- BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE \
- BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE \
- BOARD_USERDATAIMAGE_PARTITION_SIZE \
- BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE \
- BOARD_CACHEIMAGE_PARTITION_SIZE \
- BOARD_VENDORIMAGE_PARTITION_SIZE \
- BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE \
- BOARD_PRODUCTIMAGE_PARTITION_SIZE \
- BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE \
- BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE \
- BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE \
- BOARD_ODMIMAGE_PARTITION_SIZE \
- BOARD_ODMIMAGE_FILE_SYSTEM_TYPE \
+_board_strip_readonly_list += BOARD_FLASH_BLOCK_SIZE
+_board_strip_readonly_list += BOARD_BOOTIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_RECOVERYIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_SYSTEMIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE
+_board_strip_readonly_list += BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE
+_board_strip_readonly_list += BOARD_USERDATAIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+_board_strip_readonly_list += BOARD_CACHEIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_VENDORIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+_board_strip_readonly_list += BOARD_PRODUCTIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+_board_strip_readonly_list += BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE
+_board_strip_readonly_list += BOARD_ODMIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_ODMIMAGE_FILE_SYSTEM_TYPE
+_board_strip_readonly_list += BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE
+_board_strip_readonly_list += BOARD_ODM_DLKMIMAGE_PARTITION_SIZE
+_board_strip_readonly_list += 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_PRODUCTIMAGE_PARTITION_RESERVED_SIZE \
- BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE \
- BOARD_SUPER_PARTITION_SIZE \
- BOARD_SUPER_PARTITION_GROUPS \
+_board_strip_readonly_list += BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE
+_board_strip_readonly_list += BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE
+_board_strip_readonly_list += BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE
+_board_strip_readonly_list += BOARD_VENDOR_DLKMIMAGE_PARTITION_RESERVED_SIZE
+_board_strip_readonly_list += BOARD_ODM_DLKMIMAGE_PARTITION_RESERVED_SIZE
+_board_strip_readonly_list += BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE
+_board_strip_readonly_list += BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE
+_board_strip_readonly_list += BOARD_SUPER_PARTITION_SIZE
+_board_strip_readonly_list += BOARD_SUPER_PARTITION_GROUPS
-_board_strip_readonly_list += $(_dynamic_partitions_var_list)
+# Kernel related variables
+_board_strip_readonly_list += BOARD_KERNEL_BINARIES
+_board_strip_readonly_list += BOARD_KERNEL_MODULE_INTERFACE_VERSIONS
+
+# Variables related to generic kernel image (GKI) and generic boot image
+# - BOARD_USES_GENERIC_KERNEL_IMAGE is the global variable that defines if the
+# board uses GKI and generic boot image.
+# Update mechanism of the boot image is not enforced by this variable.
+# - BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE controls whether the recovery image
+# contains a kernel or not.
+# - BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT controls whether ramdisk
+# recovery resources are built to vendor_boot.
+# - BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT controls whether GSI AVB keys are
+# built to vendor_boot.
+# - BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES controls whether boot images in $OUT are added
+# to target files package directly.
+_board_strip_readonly_list += BOARD_USES_GENERIC_KERNEL_IMAGE
+_board_strip_readonly_list += BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE
+_board_strip_readonly_list += BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT
+_board_strip_readonly_list += BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT
+_board_strip_readonly_list += BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES
+
+# Defines the list of logical vendor ramdisk names to build or include in vendor_boot.
+_board_strip_readonly_list += BOARD_VENDOR_RAMDISK_FRAGMENTS
_build_broken_var_list := \
BUILD_BROKEN_DUP_RULES \
+ BUILD_BROKEN_DUP_SYSPROP \
+ BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES \
+ BUILD_BROKEN_ENFORCE_SYSPROP_OWNER \
+ BUILD_BROKEN_MISSING_REQUIRED_MODULES \
BUILD_BROKEN_OUTSIDE_INCLUDE_DIRS \
BUILD_BROKEN_PREBUILT_ELF_FILES \
BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW \
@@ -139,10 +177,19 @@
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
.KATI_READONLY := TARGET_DEVICE_DIR
endif
+
include $(board_config_mk)
-ifeq ($(TARGET_ARCH),)
- $(error TARGET_ARCH not defined by board config: $(board_config_mk))
+
+ifneq (,$(and $(TARGET_ARCH),$(TARGET_ARCH_SUITE)))
+ $(error $(board_config_mk) erroneously sets both TARGET_ARCH and TARGET_ARCH_SUITE)
endif
+ifeq ($(TARGET_ARCH)$(TARGET_ARCH_SUITE),)
+ $(error Target architectures not defined by board config: $(board_config_mk))
+endif
+ifeq ($(TARGET_CPU_ABI)$(TARGET_ARCH_SUITE),)
+ $(error TARGET_CPU_ABI not defined by board config: $(board_config_mk))
+endif
+
ifneq ($(MALLOC_IMPL),)
$(warning *** Unsupported option MALLOC_IMPL defined by board config: $(board_config_mk).)
$(error Use `MALLOC_SVELTE := true` to configure jemalloc for low-memory)
@@ -159,10 +206,12 @@
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
-combo_target := TARGET_
-combo_2nd_arch_prefix :=
-include $(BUILD_SYSTEM)/combo/select.mk
+ifdef TARGET_ARCH
+ # The combo makefiles check and set defaults for various CPU configuration
+ combo_target := TARGET_
+ combo_2nd_arch_prefix :=
+ include $(BUILD_SYSTEM)/combo/select.mk
+endif
ifdef TARGET_2ND_ARCH
combo_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
@@ -172,9 +221,7 @@
.KATI_READONLY := $(_board_strip_readonly_list)
INTERNAL_KERNEL_CMDLINE := $(BOARD_KERNEL_CMDLINE)
-ifeq ($(TARGET_CPU_ABI),)
- $(error No TARGET_CPU_ABI defined by board config: $(board_config_mk))
-endif
+
ifneq ($(filter %64,$(TARGET_ARCH)),)
TARGET_IS_64_BIT := true
endif
@@ -183,7 +230,7 @@
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 +288,8 @@
# 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 +322,8 @@
###########################################
# 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) $(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT)))
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
@@ -332,23 +375,34 @@
# Are we building a boot image
BUILDING_BOOT_IMAGE :=
-ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
- BUILDING_BOOT_IMAGE :=
-else ifeq ($(PRODUCT_BUILD_BOOT_IMAGE),)
- ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
+ifeq ($(PRODUCT_BUILD_BOOT_IMAGE),)
+ ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+ BUILDING_BOOT_IMAGE :=
+ else ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
+ BUILDING_BOOT_IMAGE := true
+ else ifneq (,$(foreach kernel,$(BOARD_KERNEL_BINARIES),$(BOARD_$(call to-upper,$(kernel))_BOOTIMAGE_PARTITION_SIZE)))
BUILDING_BOOT_IMAGE := true
endif
else ifeq ($(PRODUCT_BUILD_BOOT_IMAGE),true)
- BUILDING_BOOT_IMAGE := true
+ ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+ $(warning *** PRODUCT_BUILD_BOOT_IMAGE is true, but so is BOARD_USES_RECOVERY_AS_BOOT.)
+ $(warning *** Skipping building boot image.)
+ BUILDING_BOOT_IMAGE :=
+ else
+ BUILDING_BOOT_IMAGE := true
+ endif
endif
.KATI_READONLY := BUILDING_BOOT_IMAGE
# Are we building a recovery image
BUILDING_RECOVERY_IMAGE :=
-ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
- BUILDING_RECOVERY_IMAGE := true
-else ifeq ($(PRODUCT_BUILD_RECOVERY_IMAGE),)
- ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE
+ifeq ($(PRODUCT_BUILD_RECOVERY_IMAGE),)
+ ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+ BUILDING_RECOVERY_IMAGE := true
+ else ifeq ($(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT),true)
+ # Set to true to build recovery resources for vendor_boot
+ BUILDING_RECOVERY_IMAGE := true
+ else ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE
ifeq (,$(filter true, $(TARGET_NO_KERNEL) $(TARGET_NO_RECOVERY)))
BUILDING_RECOVERY_IMAGE := true
endif
@@ -362,7 +416,9 @@
BUILDING_VENDOR_BOOT_IMAGE :=
ifdef BOARD_BOOT_HEADER_VERSION
ifneq ($(call math_gt_or_eq,$(BOARD_BOOT_HEADER_VERSION),3),)
- ifneq ($(TARGET_NO_VENDOR_BOOT),true)
+ ifeq ($(PRODUCT_BUILD_VENDOR_BOOT_IMAGE),)
+ BUILDING_VENDOR_BOOT_IMAGE := true
+ else ifeq ($(PRODUCT_BUILD_VENDOR_BOOT_IMAGE),true)
BUILDING_VENDOR_BOOT_IMAGE := true
endif
endif
@@ -515,6 +571,40 @@
.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 +638,41 @@
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 +702,7 @@
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 +722,9 @@
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
@@ -605,6 +733,16 @@
TARGET_VENDOR_TEST_SUFFIX :=
endif
+# If PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY is set,
+# BOARD_VNDK_VERSION must be set because PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY
+# is a enforcement of inter-partition dependency, and it doesn't have any meaning
+# when BOARD_VNDK_VERSION isn't set.
+ifeq ($(PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY),true)
+ ifeq ($(BOARD_VNDK_VERSION),)
+ $(error BOARD_VNDK_VERSION must be set when PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY is true)
+ endif
+endif
+
###########################################
# APEXes are by default flattened, i.e. non-updatable.
# It can be unflattened (and updatable) by inheriting from
@@ -621,7 +759,7 @@
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
@@ -650,3 +788,39 @@
$(if $(filter true,$(BUILD_BROKEN_USES_$(m))),\
$(KATI_deprecated_var $(m),Please convert to Soong),\
$(KATI_obsolete_var $(m),Please convert to Soong)))
+
+ifndef BUILDING_RECOVERY_IMAGE
+ ifeq (true,$(BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE))
+ $(error Should not set BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE if not building recovery image)
+ endif
+endif
+
+ifndef BUILDING_VENDOR_BOOT_IMAGE
+ ifeq (true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT))
+ $(error Should not set BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT if not building vendor_boot image)
+ endif
+ ifdef BOARD_VENDOR_RAMDISK_FRAGMENTS
+ $(error Should not set BOARD_VENDOR_RAMDISK_FRAGMENTS if not building vendor_boot image)
+ endif
+endif
+
+ifneq ($(words $(BOARD_VENDOR_RAMDISK_FRAGMENTS)),$(words $(sort $(BOARD_VENDOR_RAMDISK_FRAGMENTS))))
+ $(error BOARD_VENDOR_RAMDISK_FRAGMENTS has duplicate entries: $(BOARD_VENDOR_RAMDISK_FRAGMENTS))
+endif
+
+# If BOARD_USES_GENERIC_KERNEL_IMAGE is set, BOARD_USES_RECOVERY_AS_BOOT must not be set.
+# Devices without a dedicated recovery partition uses BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT to
+# build recovery into vendor_boot.
+ifeq (true,$(BOARD_USES_GENERIC_KERNEL_IMAGE))
+ ifeq (true,$(BOARD_USES_RECOVERY_AS_BOOT))
+ $(error BOARD_USES_RECOVERY_AS_BOOT cannot be true if BOARD_USES_GENERIC_KERNEL_IMAGE is true. \
+ Use BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT instead)
+ endif
+endif
+
+ifeq (true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT))
+ ifeq (true,$(BOARD_USES_RECOVERY_AS_BOOT))
+ $(error BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT and BOARD_USES_RECOVERY_AS_BOOT cannot be \
+ both true. Recovery resources should be installed to either boot or vendor_boot, but not both)
+ endif
+endif
diff --git a/core/build-system.html b/core/build-system.html
index cc242d9..b872909c 100644
--- a/core/build-system.html
+++ b/core/build-system.html
@@ -440,6 +440,33 @@
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 @@
<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 938cdef..ba5ca42 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=RQ1A.210105.003
+BUILD_ID=AOSP.MASTER
diff --git a/core/cc_prebuilt_internal.mk b/core/cc_prebuilt_internal.mk
index 99b7d0f..e8e01d8 100644
--- a/core/cc_prebuilt_internal.mk
+++ b/core/cc_prebuilt_internal.mk
@@ -65,7 +65,7 @@
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 da4168d..b5be81f 100644
--- a/core/check_elf_file.mk
+++ b/core/check_elf_file.mk
@@ -14,12 +14,14 @@
# - my_installed_module_stem
# - my_prebuilt_src_file
# - my_check_elf_file_shared_lib_files
+# - my_system_shared_libraries
ifndef LOCAL_IS_HOST_MODULE
ifneq ($(filter $(LOCAL_MODULE_CLASS),SHARED_LIBRARIES EXECUTABLES NATIVE_TESTS),)
check_elf_files_stamp := $(intermediates)/check_elf_files.timestamp
$(check_elf_files_stamp): PRIVATE_SONAME := $(if $(filter $(LOCAL_MODULE_CLASS),SHARED_LIBRARIES),$(my_installed_module_stem))
$(check_elf_files_stamp): PRIVATE_ALLOW_UNDEFINED_SYMBOLS := $(LOCAL_ALLOW_UNDEFINED_SYMBOLS)
+$(check_elf_files_stamp): PRIVATE_SYSTEM_SHARED_LIBRARIES := $(my_system_shared_libraries)
# PRIVATE_SHARED_LIBRARY_FILES are file paths to built shared libraries.
# In addition to $(my_check_elf_file_shared_lib_files), some file paths are
# added by `resolve-shared-libs-for-elf-file-check` from `core/main.mk`.
@@ -33,11 +35,14 @@
--skip-unknown-elf-machine \
$(if $(PRIVATE_SONAME),--soname $(PRIVATE_SONAME)) \
$(foreach l,$(PRIVATE_SHARED_LIBRARY_FILES),--shared-lib $(l)) \
+ $(foreach l,$(PRIVATE_SYSTEM_SHARED_LIBRARIES),--system-shared-lib $(l)) \
$(if $(PRIVATE_ALLOW_UNDEFINED_SYMBOLS),--allow-undefined-symbols) \
--llvm-readobj=$(LLVM_READOBJ) \
$<
$(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 3e54a66..0000000
--- 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 cb6a3cd..0000000
--- 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 ebdb663..6909275 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -21,7 +21,7 @@
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:=
@@ -74,7 +74,6 @@
LOCAL_DROIDDOC_CUSTOM_ASSET_DIR:=
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=
LOCAL_DROIDDOC_DOC_ZIP :=
-LOCAL_DROIDDOC_JDIFF_DOC_ZIP :=
LOCAL_DROIDDOC_HTML_DIR:=
LOCAL_DROIDDOC_METADATA_ZIP:=
LOCAL_DROIDDOC_OPTIONS:=
@@ -98,9 +97,11 @@
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:=
+LOCAL_FILE_CONTEXTS:=
LOCAL_FINDBUGS_FLAGS:=
LOCAL_FORCE_STATIC_EXECUTABLE:=
LOCAL_FULL_CLASSES_JACOCO_JAR:=
@@ -129,6 +130,7 @@
LOCAL_IS_FUZZ_TARGET:=
LOCAL_IS_HOST_MODULE:=
LOCAL_IS_RUNTIME_RESOURCE_OVERLAY:=
+LOCAL_IS_UNIT_TEST:=
LOCAL_JACK_CLASSPATH:=
LOCAL_JACK_COVERAGE_EXCLUDE_FILTER:=
LOCAL_JACK_COVERAGE_INCLUDE_FILTER:=
@@ -258,7 +260,7 @@
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:=
@@ -275,6 +277,7 @@
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 :=
@@ -297,8 +300,8 @@
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:=
@@ -479,17 +482,6 @@
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/target/product/virtual_ab_ota_retrofit.mk b/core/combo/HOST_CROSS_linux_bionic-arm64.mk
similarity index 69%
copy from target/product/virtual_ab_ota_retrofit.mk
copy to core/combo/HOST_CROSS_linux_bionic-arm64.mk
index 3e85741..df6865f 100644
--- a/target/product/virtual_ab_ota_retrofit.mk
+++ b/core/combo/HOST_CROSS_linux_bionic-arm64.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,9 @@
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
+# Configuration for builds hosted on linux_arm-arm64
+# Included by combo/select.mk
-PRODUCT_VIRTUAL_AB_OTA_RETROFIT := true
-
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.retrofit=true
+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 cbca1fb..e45c1a6 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -39,7 +39,7 @@
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 9f14aa2..0000000
--- 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 ae17e46..0000000
--- 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/target/product/virtual_ab_ota.mk b/core/combo/arch/arm64/armv8-2a-dotprod.mk
similarity index 71%
copy from target/product/virtual_ab_ota.mk
copy to core/combo/arch/arm64/armv8-2a-dotprod.mk
index 1774de4..c775cf7 100644
--- a/target/product/virtual_ab_ota.mk
+++ b/core/combo/arch/arm64/armv8-2a-dotprod.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,6 @@
# limitations under the License.
#
-PRODUCT_VIRTUAL_AB_OTA := true
-
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.enabled=true
-
-PRODUCT_PACKAGES += e2fsck_ramdisk
+# .mk file required to support build for the new armv8-2a-dotprod Arm64 arch
+# variant. The file just needs to be present but does not require to contain
+# anything
diff --git a/core/config.mk b/core/config.mk
index 90eea5b..9c04fe0 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -22,6 +22,13 @@
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,35 @@
$(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.)
+$(KATI_deprecated_var BOARD_PLAT_PUBLIC_SEPOLICY_DIR,Use SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS instead.)
+$(KATI_deprecated_var BOARD_PLAT_PRIVATE_SEPOLICY_DIR,Use SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS instead.)
+$(KATI_obsolete_var TARGET_NO_VENDOR_BOOT,Use PRODUCT_BUILD_VENDOR_BOOT_IMAGE instead)
# Used to force goals to build. Only use for conditionally defined goals.
.PHONY: FORCE
@@ -172,8 +206,6 @@
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 +220,12 @@
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 +392,6 @@
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 +432,13 @@
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 +446,19 @@
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 +480,25 @@
.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 +518,8 @@
# ---------------------------------------------------------------
# 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
@@ -621,6 +555,7 @@
FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
MKEXTUSERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg_mke2fs
MKE2FS_CONF := system/extras/ext4_utils/mke2fs.conf
+MKEROFSUSERIMG := $(HOST_OUT_EXECUTABLES)/mkerofsimage.sh
MKSQUASHFSUSERIMG := $(HOST_OUT_EXECUTABLES)/mksquashfsimage.sh
MKF2FSUSERIMG := $(HOST_OUT_EXECUTABLES)/mkf2fsuserimg.sh
SIMG2IMG := $(HOST_OUT_EXECUTABLES)/simg2img$(HOST_EXECUTABLE_SUFFIX)
@@ -667,16 +602,12 @@
# 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
-ifneq ($(PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE),)
- PRODUCT_COMPATIBLE_PROPERTY := $(PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE)
-else ifeq ($(PRODUCT_SHIPPING_API_LEVEL),)
- #$(warning no product shipping level defined)
-else ifneq ($(call math_lt,27,$(PRODUCT_SHIPPING_API_LEVEL)),)
- PRODUCT_COMPATIBLE_PROPERTY := true
+PRODUCT_COMPATIBLE_PROPERTY := true
+ifeq ($(PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE),false)
+ $(error PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE is obsolete)
endif
.KATI_READONLY := \
@@ -747,33 +678,22 @@
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 @@
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 @@
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 @@
)
# 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 @@
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 @@
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_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 @@
# 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 @@
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 efb21e7..eaab1b5 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -134,12 +134,6 @@
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 @@
# 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 @@
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 794795a..0000000
--- 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 89c2e27..0230340 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -95,7 +95,6 @@
# Display names for various build targets
TARGET_DISPLAY := target
-AUX_DISPLAY := aux
HOST_DISPLAY := host
HOST_CROSS_DISPLAY := host cross
@@ -108,9 +107,12 @@
# All tests that should be skipped in presubmit check.
ALL_DISABLED_PRESUBMIT_TESTS :=
-# All compatibility suites mentioned in LOCAL_COMPATIBILITY_SUITES
+# All compatibility suites mentioned in LOCAL_COMPATIBILITY_SUITE
ALL_COMPATIBILITY_SUITES :=
+# All compatibility suite files to dist.
+ALL_COMPATIBILITY_DIST_FILES :=
+
# All LINK_TYPE entries
ALL_LINK_TYPES :=
@@ -522,29 +524,32 @@
$(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 @@
# $(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 @@
$(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 @@
# $(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 @@
$(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 @@
$(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_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
@@ -2482,6 +2404,7 @@
$(1) \
$(HOST_INIT_VERIFIER) \
$(call intermediates-dir-for,ETC,passwd_system)/passwd_system \
+ $(call intermediates-dir-for,ETC,passwd_system_ext)/passwd_system_ext \
$(call intermediates-dir-for,ETC,passwd_vendor)/passwd_vendor \
$(call intermediates-dir-for,ETC,passwd_odm)/passwd_odm \
$(call intermediates-dir-for,ETC,passwd_product)/passwd_product \
@@ -2492,6 +2415,7 @@
$(call intermediates-dir-for,ETC,odm_property_contexts)/odm_property_contexts
$(hide) $(HOST_INIT_VERIFIER) \
-p $(call intermediates-dir-for,ETC,passwd_system)/passwd_system \
+ -p $(call intermediates-dir-for,ETC,passwd_system_ext)/passwd_system_ext \
-p $(call intermediates-dir-for,ETC,passwd_vendor)/passwd_vendor \
-p $(call intermediates-dir-for,ETC,passwd_odm)/passwd_odm \
-p $(call intermediates-dir-for,ETC,passwd_product)/passwd_product \
@@ -2564,6 +2488,32 @@
$(_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
+$(eval check_non_elf_file_timestamp := \
+ $(call intermediates-dir-for,FAKE,check-non-elf-file-timestamps)/$(2).timestamp)
+$(check_non_elf_file_timestamp): $(1) $(LLVM_READOBJ)
+ @echo "Check non-ELF: $$<"
+ $(hide) mkdir -p "$$(dir $$@)"
+ $(hide) rm -f "$$@"
+ $(hide) \
+ if $(LLVM_READOBJ) -h "$$<" >/dev/null 2>&1; then \
+ $(call echo-error,$(2),$(3)); \
+ $(call echo-error,$(2),found ELF file: $$<); \
+ false; \
+ fi
+ $(hide) touch "$$@"
+
+$(2): $(1) $(check_non_elf_file_timestamp)
+ @echo "Copy non-ELF: $$@"
+ $$(copy-file-to-target)
+
+check-elf-prebuilt-product-copy-files: $(check_non_elf_file_timestamp)
+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 +2566,18 @@
$(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 +2590,13 @@
$(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.
@@ -2653,6 +2622,7 @@
@mkdir -p $(dir $$@)
@rm -rf $$@
$(hide) ln -sf $(2) $$@
+$(3): .KATI_SYMLINK_OUTPUTS := $(3)
endef
# Copy an apk to a target location while removing classes*.dex
@@ -2778,32 +2748,6 @@
$$(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 +2847,7 @@
# 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 +2858,13 @@
$(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 +3124,6 @@
## 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 19bd4cf..2b7a869 100644
--- a/core/deprecation.mk
+++ b/core/deprecation.mk
@@ -29,25 +29,25 @@
# 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 55eeec6..dd31999 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -18,9 +18,41 @@
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 ccf53f5..f72752c 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 @@
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,55 +68,47 @@
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)
+ifdef TARGET_ARCH
$(call add_json_map, CpuVariant)
$(call add_json_str, $(TARGET_ARCH), $(DEX2OAT_TARGET_CPU_VARIANT))
ifdef TARGET_2ND_ARCH
@@ -118,6 +122,7 @@
$(call add_json_str, $(TARGET_2ND_ARCH), $($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES))
endif
$(call end_json_map)
+endif
$(call add_json_str, DirtyImageObjects, $(DIRTY_IMAGE_OBJECTS))
$(call add_json_list, BootImageProfiles, $(PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION))
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 79d5f8c..8f0702b 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
-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))))
+# 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_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_boot_image_module :=
-my_dexpreopt_image_extra_deps := $(firstword $(my_installed))
+my_suffix := $(my_boot_image_name)_$($(my_boot_image_arch))
+my_copy_pairs := $(strip $(DEXPREOPT_IMAGE_BUILT_INSTALLED_$(my_suffix)))
-my_2nd_arch_prefix :=
-include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
+# 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))
-ifdef TARGET_2ND_ARCH
- my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
- include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
-endif
+ my_first_src := $(call word-colon,1,$(my_first_pair))
+ my_first_dest := $(my_boot_image_out)$(call word-colon,2,$(my_first_pair))
-my_2nd_arch_prefix :=
+ 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))
+ # We don't have a LOCAL_PATH for the auto-generated modules, so let it be the $(BUILD_SYSTEM).
+ LOCAL_PATH := $(BUILD_SYSTEM)
-my_vdex_copy_pairs :=
-my_installed :=
-my_built_vdex_dir :=
-my_installed_vdex_dir :=
-my_dexpreopt_image_extra_deps :=
+ 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_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 34b8526..0000000
--- 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 9dbddf6..c31d4e8 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -40,8 +40,8 @@
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,19 +189,42 @@
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.
- my_extra_dexpreopt_libs := \
- org.apache.http.legacy \
+ # compatibility libraries are added to class loader context of an app only if
+ # targetSdkVersion in the app's manifest is lower than the given SDK version
+
+ my_dexpreopt_libs_compat_28 := \
+ org.apache.http.legacy
+
+ my_dexpreopt_libs_compat_29 := \
android.hidl.base-V1.0-java \
- android.hidl.manager-V1.0-java \
+ android.hidl.manager-V1.0-java
+
+ my_dexpreopt_libs_compat_30 := \
+ android.test.base \
+ android.test.mock
+
+ my_dexpreopt_libs_compat := \
+ $(my_dexpreopt_libs_compat_28) \
+ $(my_dexpreopt_libs_compat_29) \
+ $(my_dexpreopt_libs_compat_30)
my_dexpreopt_libs := $(sort \
$(LOCAL_USES_LIBRARIES) \
$(my_filtered_optional_uses_libraries) \
- $(my_extra_dexpreopt_libs) \
)
+ # 1: SDK version
+ # 2: list of libraries
+ add_json_class_loader_context = \
+ $(call add_json_map, $(1)) \
+ $(foreach lib, $(2),\
+ $(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)
+
# Record dex-preopt config.
DEXPREOPT.$(LOCAL_MODULE).DEX_PREOPT := $(LOCAL_DEX_PREOPT)
DEXPREOPT.$(LOCAL_MODULE).MULTILIB := $(LOCAL_MULTILIB)
@@ -229,11 +252,11 @@
$(call add_json_str, ProfileClassListing, $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE)))
$(call add_json_bool, ProfileIsTextListing, $(my_profile_is_text_listing))
$(call add_json_bool, EnforceUsesLibraries, $(LOCAL_ENFORCE_USES_LIBRARIES))
- $(call add_json_list, OptionalUsesLibraries, $(my_filtered_optional_uses_libraries))
- $(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, ClassLoaderContexts)
+ $(call add_json_class_loader_context, any, $(my_dexpreopt_libs))
+ $(call add_json_class_loader_context, 28, $(my_dexpreopt_libs_compat_28))
+ $(call add_json_class_loader_context, 29, $(my_dexpreopt_libs_compat_29))
+ $(call add_json_class_loader_context, 30, $(my_dexpreopt_libs_compat_30))
$(call end_json_map)
$(call add_json_list, Archs, $(my_dexpreopt_archs))
$(call add_json_list, DexPreoptImages, $(my_dexpreopt_images))
@@ -275,7 +298,7 @@
my_dexpreopt_deps := $(my_dex_jar)
my_dexpreopt_deps += $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE))
my_dexpreopt_deps += \
- $(foreach lib, $(my_dexpreopt_libs), \
+ $(foreach lib, $(my_dexpreopt_libs) $(my_dexpreopt_libs_compat), \
$(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar)
my_dexpreopt_deps += $(my_dexpreopt_images_deps)
my_dexpreopt_deps += $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)
diff --git a/core/distdir.mk b/core/distdir.mk
index 5f40407..aad8ff3 100644
--- a/core/distdir.mk
+++ b/core/distdir.mk
@@ -28,7 +28,7 @@
# 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/dumpvar.mk b/core/dumpvar.mk
index b2ee8fd..6b5c030 100644
--- a/core/dumpvar.mk
+++ b/core/dumpvar.mk
@@ -24,9 +24,14 @@
# Input variables:
# DUMP_MANY_VARS: the list of variable names.
# DUMP_VAR_PREFIX: an optional prefix of the variable name added to the output.
+# The value is printed in parts because large variables like PRODUCT_PACKAGES
+# can exceed the maximum linux command line size
.PHONY: dump-many-vars
dump-many-vars :
@$(foreach v, $(DUMP_MANY_VARS),\
- printf "%s='%s'\n" '$(DUMP_VAR_PREFIX)$(v)' '$($(v))';)
+ printf "%s='%s" '$(DUMP_VAR_PREFIX)$(v)' '$(firstword $($(v)))'; \
+ $(foreach part, $(wordlist 2, $(words $($(v))), $($(v))),\
+ printf " %s" '$(part)'$(newline))\
+ printf "'\n";)
endif # CALLED_FROM_SETUP
diff --git a/core/envsetup.mk b/core/envsetup.mk
index f4650f9..a5571ae 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -93,15 +93,38 @@
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 @@
# 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 @@
_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_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 @@
# 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 := $(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_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_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_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_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 \
$(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 db8dcc6..9175e0a 100644
--- a/core/executable.mk
+++ b/core/executable.mk
@@ -40,14 +40,9 @@
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 @@
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 32e56dd..c6a8faf 100644
--- a/core/executable_internal.mk
+++ b/core/executable_internal.mk
@@ -56,9 +56,9 @@
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 9b9814e..fea0bef 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 @@
# 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 c265259..2b51d8b 100644
--- a/core/goma.mk
+++ b/core/goma.mk
@@ -27,7 +27,8 @@
# 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 882fe3a..da32978 100644
--- a/core/host_dalvik_java_library.mk
+++ b/core/host_dalvik_java_library.mk
@@ -79,7 +79,8 @@
$(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 @@
$(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 54c6577..0000000
--- 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 beaea2a..f9abe9b 100644
--- a/core/host_java_library.mk
+++ b/core/host_java_library.mk
@@ -70,7 +70,8 @@
$(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 @@
$(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 aa05bb3..0000000
--- 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 ed7e23a..0000000
--- 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 a9e39b1..0000000
--- 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_config.mk b/core/host_test_config.mk
deleted file mode 100644
index b9975e5..0000000
--- a/core/host_test_config.mk
+++ /dev/null
@@ -1,25 +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.
-#
-
-#
-# 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
-
-include $(BUILD_SYSTEM)/test_config_common.mk
diff --git a/core/host_test_internal.mk b/core/host_test_internal.mk
deleted file mode 100644
index dfe8cf1..0000000
--- 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 48c93de..289d16f 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -57,9 +57,9 @@
# 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 @@
$(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 @@
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/java.mk b/core/java.mk
index a041321..5fe8da5 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 @@
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 @@
# 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 @@
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 @@
$(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 @@
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 @@
$(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 f6e01d2..1798ca8 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -6,10 +6,6 @@
my_soong_problems += dotdot_srcs
endif
-ifneq (,$(LOCAL_JNI_SHARED_LIBRARIES))
-my_soong_problems += jni_libs
-endif
-
###########################################################
## Java version
###########################################################
@@ -29,7 +25,7 @@
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_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 @@
# 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 @@
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 @@
# 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 @@
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 @@
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 @@
$(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_host_unit_test_config_template.xml b/core/java_host_unit_test_config_template.xml
new file mode 100644
index 0000000..ff300da
--- /dev/null
+++ b/core/java_host_unit_test_config_template.xml
@@ -0,0 +1,26 @@
+<?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-unit-tests" />
+
+ {EXTRA_CONFIGS}
+
+ <test class="com.android.tradefed.testtype.IsolatedHostTest" >
+ <option name="jar" value="{MODULE}.jar" />
+ </test>
+</configuration>
diff --git a/core/java_prebuilt_internal.mk b/core/java_prebuilt_internal.mk
index da653b7..279b0e4 100644
--- a/core/java_prebuilt_internal.mk
+++ b/core/java_prebuilt_internal.mk
@@ -35,9 +35,9 @@
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)
@@ -173,7 +173,7 @@
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 672863b..572d6e4 100644
--- a/core/java_renderscript.mk
+++ b/core/java_renderscript.mk
@@ -50,8 +50,8 @@
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 @@
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 @@
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
deleted file mode 100644
index c89642e..0000000
--- a/core/line_coverage.mk
+++ /dev/null
@@ -1,95 +0,0 @@
-# -----------------------------------------------------------------
-# Make target for line coverage. This target generates a zip file
-# called `line_coverage_profiles.zip` that contains a large set of
-# zip files one for each fuzz target/critical component. Each zip
-# file contains a set of profile files (*.gcno) that we will use
-# to generate line coverage reports. Furthermore, target compiles
-# all fuzz targets with line coverage instrumentation enabled and
-# packs them into another zip file called `line_coverage_profiles.zip`.
-#
-# To run the make target set the coverage related envvars first:
-# NATIVE_COVERAGE=true NATIVE_COVERAGE_PATHS=* make haiku-line-coverage
-# -----------------------------------------------------------------
-
-# 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
-
-fuzz_targets := $(ALL_FUZZ_TARGETS)
-fuzz_targets := $(filter-out $(blacklisted_fuzz_targets),$(fuzz_targets))
-
-
-# Android components that considered critical.
-# Please note that adding/Removing critical components is very rare.
-critical_components_static := \
- lib-bt-packets \
- libbt-stack \
- libffi \
- libhevcdec \
- libhevcenc \
- libmpeg2dec \
- libosi \
- libpdx \
- libselinux \
- libvold \
- libyuv
-
-# Format is <module_name> or <module_name>:<apex_name>
-critical_components_shared := \
- libaudioprocessing \
- libbinder \
- libbluetooth_gd \
- libbrillo \
- libcameraservice \
- libcurl \
- libhardware \
- libinputflinger \
- libopus \
- libstagefright \
- libunwind \
- libvixl:com.android.art.debug
-
-# Use the intermediates directory to avoid installing libraries to the device.
-intermediates := $(call intermediates-dir-for,PACKAGING,haiku-line-coverage)
-
-
-# We want the profile files for all fuzz targets + critical components.
-line_coverage_profiles := $(intermediates)/line_coverage_profiles.zip
-
-critical_components_static_inputs := $(foreach lib,$(critical_components_static), \
- $(call intermediates-dir-for,STATIC_LIBRARIES,$(lib))/$(lib).a)
-
-critical_components_shared_inputs := $(foreach lib,$(critical_components_shared), \
- $(eval filename := $(call word-colon,1,$(lib))) \
- $(eval modulename := $(subst :,.,$(lib))) \
- $(call intermediates-dir-for,SHARED_LIBRARIES,$(modulename))/$(filename).so)
-
-fuzz_target_inputs := $(foreach fuzz,$(fuzz_targets), \
- $(call intermediates-dir-for,EXECUTABLES,$(fuzz))/$(fuzz))
-
-# When coverage is enabled (NATIVE_COVERAGE is set), make creates
-# a "coverage" directory and stores all profile (*.gcno) files in inside.
-# We need everything that is stored inside this directory.
-$(line_coverage_profiles): $(fuzz_target_inputs)
-$(line_coverage_profiles): $(critical_components_static_inputs)
-$(line_coverage_profiles): $(critical_components_shared_inputs)
-$(line_coverage_profiles): $(SOONG_ZIP)
- $(SOONG_ZIP) -o $@ -D $(PRODUCT_OUT)/coverage
-
-
-# Zip all fuzz targets compiled with line coverage.
-line_coverage_fuzz_targets := $(intermediates)/line_coverage_fuzz_targets.zip
-
-$(line_coverage_fuzz_targets): $(fuzz_target_inputs)
-$(line_coverage_fuzz_targets): $(SOONG_ZIP)
- $(SOONG_ZIP) -o $@ -j $(addprefix -f ,$(fuzz_target_inputs))
-
-
-.PHONY: haiku-line-coverage
-haiku-line-coverage: $(line_coverage_profiles) $(line_coverage_fuzz_targets)
-$(call dist-for-goals, haiku-line-coverage, \
- $(line_coverage_profiles):line_coverage_profiles.zip \
- $(line_coverage_fuzz_targets):line_coverage_fuzz_targets.zip)
-
-line_coverage_profiles :=
-line_coverage_fuzz_targets :=
diff --git a/core/link_type.mk b/core/link_type.mk
index e8cfd2e..48cd8f3 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 0000000..ea7da8a
--- /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 357c70d..8857b5d 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -33,6 +33,8 @@
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,43 @@
endif
endif
-#
-# -----------------------------------------------------------------
-# Validate ADDITIONAL_DEFAULT_PROPERTIES.
-ifneq ($(ADDITIONAL_DEFAULT_PROPERTIES),)
-$(error ADDITIONAL_DEFAULT_PROPERTIES must not be set before here: $(ADDITIONAL_DEFAULT_PROPERTIES))
+ifdef TARGET_ARCH_SUITE
+ # TODO(b/175577370): Enable this error.
+ # $(error TARGET_ARCH_SUITE is not supported in kati/make builds)
endif
-#
-# -----------------------------------------------------------------
-# Validate ADDITIONAL_BUILD_PROPERTIES.
-ifneq ($(ADDITIONAL_BUILD_PROPERTIES),)
-$(error ADDITIONAL_BUILD_PROPERTIES must not be set before here: $(ADDITIONAL_BUILD_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
-ADDITIONAL_BUILD_PROPERTIES :=
+$(foreach name, $(_additional_prop_var_names),\
+ $(if $($(name)),\
+ $(error $(name) must not set before here. $($(name)))\
+ ,)\
+ $(eval $(name) :=)\
+)
+_additional_prop_var_names :=
-#
-# -----------------------------------------------------------------
-# Validate ADDITIONAL_PRODUCT_PROPERTIES.
-ifneq ($(ADDITIONAL_PRODUCT_PROPERTIES),)
-$(error ADDITIONAL_PRODUCT_PROPERTIES must not be set before here: $(ADDITIONAL_PRODUCT_PROPERTIES))
-endif
-
-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 +159,6 @@
# 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 +184,12 @@
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
-
-# -----------------------------------------------------------------
-# The pdk (Platform Development Kit) build
-include build/make/core/pdk_config.mk
+# PDK builds are no longer supported, this is always platform
+TARGET_BUILD_JAVA_SUPPORT_LEVEL :=$= platform
# -----------------------------------------------------------------
-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 \
@@ -208,11 +198,7 @@
# 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
-else
-ADDITIONAL_DEFAULT_PROPERTIES += ro.actionable_compatible_property.enabled=${PRODUCT_COMPATIBLE_PROPERTY}
-endif
+ADDITIONAL_SYSTEM_PROPERTIES += ro.actionable_compatible_property.enabled=true
# Add the system server compiler filter if they are specified for the product.
ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
@@ -221,9 +207,12 @@
# 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 +220,92 @@
#
# 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 +318,12 @@
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 +343,11 @@
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 +359,40 @@
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 +422,21 @@
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 +468,16 @@
# 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 +513,6 @@
$(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 +548,13 @@
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 +575,158 @@
# 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))))
-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)))\
- )\
+# 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
-$(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)))\
- )\
+# 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 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.<*>.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-cross-select-bitness-of-required-modules)
-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
+
+_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)
@@ -604,7 +749,7 @@
$(eval r := $(call module-installed-files,$(r))) \
$(eval h_m := $(filter $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
$(eval h_r := $(filter $(HOST_OUT)/%, $(r))) \
- $(eval h_m := $(filter-out $(h_r), $(h_m))) \
+ $(eval h_r := $(filter-out $(h_m), $(h_r))) \
$(if $(h_m), $(eval $(call add-required-deps, $(h_m),$(h_r)))) \
) \
)
@@ -620,7 +765,7 @@
$(eval r := $(call module-installed-files,$(r))) \
$(eval hc_m := $(filter $(HOST_CROSS_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
$(eval hc_r := $(filter $(HOST_CROSS_OUT)/%, $(r))) \
- $(eval hc_m := $(filter-out $(hc_r), $(hc_m))) \
+ $(eval hc_r := $(filter-out $(hc_m), $(hc_r))) \
$(if $(hc_m), $(eval $(call add-required-deps, $(hc_m),$(hc_r)))) \
) \
)
@@ -636,7 +781,7 @@
$(eval r := $(call module-installed-files,$(r))) \
$(eval t_m := $(filter $(TARGET_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
$(eval t_r := $(filter $(TARGET_OUT_ROOT)/%, $(r))) \
- $(eval t_m := $(filter-out $(t_r), $(t_m))) \
+ $(eval t_r := $(filter-out $(t_m), $(t_r))) \
$(if $(t_m), $(eval $(call add-required-deps, $(t_m),$(t_r)))) \
) \
)
@@ -652,15 +797,17 @@
$(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)))\
$(eval mod_files := $(filter $(HOST_OUT)/%, $(call module-installed-files,$(m)))) \
- $(eval mod_files := $(filter-out $(req_files),$(mod_files)))\
$(if $(mod_files),\
$(eval $(call add-required-deps, $(mod_files),$(req_files))) \
)\
@@ -678,15 +825,17 @@
$(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)))\
$(eval mod_files := $(filter $(TARGET_OUT_ROOT)/%, $(call module-installed-files,$(m))))\
- $(eval mod_files := $(filter-out $(req_files),$(mod_files)))\
$(if $(mod_files),\
$(eval $(call add-required-deps, $(mod_files),$(req_files))) \
)\
@@ -745,7 +894,7 @@
# Scan all modules in general-tests, device-tests and other selected suites and
# flatten the shared library dependencies.
define update-host-shared-libs-deps-for-suites
-$(foreach suite,general-tests device-tests vts,\
+$(foreach suite,general-tests device-tests vts art-host-tests host-unit-tests,\
$(foreach m,$(COMPATIBILITY.$(suite).MODULES),\
$(eval my_deps := $(call get-all-shared-libs-deps,$(m)))\
$(foreach dep,$(my_deps),\
@@ -800,9 +949,10 @@
$($(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 +982,6 @@
# - TARGET
# - HOST
# - HOST_CROSS
-# - AUX-<variant-name>
# 3: Whether to use the common intermediates directory or not
# - _
# - COMMON
@@ -859,14 +1008,8 @@
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 +1027,7 @@
$(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 +1166,9 @@
$(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 +1194,7 @@
# 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 +1210,7 @@
$(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 +1221,12 @@
# 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 +1254,10 @@
# 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 +1280,19 @@
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
@@ -1173,67 +1304,7 @@
# Verify the artifact path requirements made by included products.
is_asan := $(if $(filter address,$(SANITIZE_TARGET)),true)
ifneq (true,$(or $(is_asan),$(DISABLE_ARTIFACT_PATH_REQUIREMENTS)))
- # Fakes don't get installed, and NDK stubs aren't installed to device.
- static_allowed_patterns := $(TARGET_OUT_FAKE)/% $(SOONG_OUT_DIR)/ndk/%
- # RROs become REQUIRED by the source module, but are always placed on the vendor partition.
- static_allowed_patterns += %__auto_generated_rro_product.apk
- static_allowed_patterns += %__auto_generated_rro_vendor.apk
- # Auto-included targets are not considered
- static_allowed_patterns += $(call product-installed-files,)
- # $(PRODUCT_OUT)/apex is where shared libraries in APEXes get installed.
- # The path can be considered as a fake path, as the shared libraries
- # are installed there just to have symbols files for them under
- # $(PRODUCT_OUT)/symbols/apex for debugging purpose. The /apex directory
- # is never compiled into a filesystem image.
- static_allowed_patterns += $(PRODUCT_OUT)/apex/%
- ifeq (true,$(BOARD_USES_SYSTEM_OTHER_ODEX))
- # Allow system_other odex space optimization.
- static_allowed_patterns += \
- $(TARGET_OUT_SYSTEM_OTHER)/%.odex \
- $(TARGET_OUT_SYSTEM_OTHER)/%.vdex \
- $(TARGET_OUT_SYSTEM_OTHER)/%.art
- endif
-
-CERTIFICATE_VIOLATION_MODULES_FILENAME := $(PRODUCT_OUT)/certificate_violation_modules.txt
-$(CERTIFICATE_VIOLATION_MODULES_FILENAME):
- rm -f $@
- $(foreach m,$(sort $(CERTIFICATE_VIOLATION_MODULES)), echo $(m) >> $@;)
-$(call dist-for-goals,droidcore,$(CERTIFICATE_VIOLATION_MODULES_FILENAME))
-
- all_offending_files :=
- $(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\
- $(eval requirements := $(PRODUCTS.$(makefile).ARTIFACT_PATH_REQUIREMENTS)) \
- $(eval ### Verify that the product only produces files inside its path requirements.) \
- $(eval allowed := $(PRODUCTS.$(makefile).ARTIFACT_PATH_ALLOWED_LIST)) \
- $(eval path_patterns := $(call resolve-product-relative-paths,$(requirements),%)) \
- $(eval allowed_patterns := $(call resolve-product-relative-paths,$(allowed))) \
- $(eval files := $(call product-installed-files, $(makefile))) \
- $(eval offending_files := $(filter-out $(path_patterns) $(allowed_patterns) $(static_allowed_patterns),$(files))) \
- $(call maybe-print-list-and-error,$(offending_files),\
- $(makefile) produces files outside its artifact path requirement. \
- Allowed paths are $(subst $(space),$(comma)$(space),$(addsuffix *,$(requirements)))) \
- $(eval unused_allowed := $(filter-out $(files),$(allowed_patterns))) \
- $(call maybe-print-list-and-error,$(unused_allowed),$(makefile) includes redundant allowed entries in its artifact path requirement.) \
- $(eval ### Optionally verify that nothing else produces files inside this artifact path requirement.) \
- $(eval extra_files := $(filter-out $(files) $(HOST_OUT)/%,$(product_target_FILES))) \
- $(eval files_in_requirement := $(filter $(path_patterns),$(extra_files))) \
- $(eval all_offending_files += $(files_in_requirement)) \
- $(eval allowed := $(PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST)) \
- $(eval allowed_patterns := $(call resolve-product-relative-paths,$(allowed))) \
- $(eval offending_files := $(filter-out $(allowed_patterns),$(files_in_requirement))) \
- $(eval enforcement := $(PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS)) \
- $(if $(enforcement),\
- $(call maybe-print-list-and-error,$(offending_files),\
- $(INTERNAL_PRODUCT) produces files inside $(makefile)s artifact path requirement. \
- $(PRODUCT_ARTIFACT_PATH_REQUIREMENT_HINT)) \
- $(eval unused_allowed := $(if $(filter true strict,$(enforcement)),\
- $(foreach p,$(allowed_patterns),$(if $(filter $(p),$(extra_files)),,$(p))))) \
- $(call maybe-print-list-and-error,$(unused_allowed),$(INTERNAL_PRODUCT) includes redundant artifact path requirement allowed list entries.) \
- ) \
- )
-$(PRODUCT_OUT)/offending_artifacts.txt:
- rm -f $@
- $(foreach f,$(sort $(all_offending_files)),echo $(f) >> $@;)
+ include $(BUILD_SYSTEM)/artifact_path_requirements.mk
endif
else
# We're not doing a full build, and are probably only including
@@ -1276,6 +1347,10 @@
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 +1490,12 @@
.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 +1514,11 @@
.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 +1531,8 @@
$(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 +1541,8 @@
$(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 +1552,10 @@
$(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) \
@@ -1474,6 +1566,8 @@
$(INSTALLED_FILES_JSON_RAMDISK) \
$(INSTALLED_FILES_FILE_DEBUG_RAMDISK) \
$(INSTALLED_FILES_JSON_DEBUG_RAMDISK) \
+ $(INSTALLED_FILES_FILE_VENDOR_RAMDISK) \
+ $(INSTALLED_FILES_JSON_VENDOR_RAMDISK) \
$(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK) \
$(INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK) \
$(INSTALLED_FILES_FILE_ROOT) \
@@ -1481,12 +1575,16 @@
$(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.
.PHONY: dist_files
+ifeq ($(SOONG_COLLECT_JAVA_DEPS), true)
+ $(call dist-for-goals, dist_files, $(SOONG_OUT_DIR)/module_bp_java_deps.json)
+ $(call dist-for-goals, dist_files, $(PRODUCT_OUT)/module-info.json)
+endif
+
.PHONY: apps_only
ifneq ($(TARGET_BUILD_APPS),)
# If this build is just for apps, only build apps and not the full system by default.
@@ -1532,6 +1630,9 @@
$(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))
@@ -1551,15 +1652,17 @@
$(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) \
$(INTERNAL_OTA_METADATA) \
+ $(INTERNAL_OTA_PARTIAL_PACKAGE_TARGET) \
$(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET) \
$(BUILT_OTATOOLS_PACKAGE) \
$(SYMBOLS_ZIP) \
$(PROGUARD_DICT_ZIP) \
+ $(PROGUARD_USAGE_ZIP) \
$(COVERAGE_ZIP) \
$(APPCOMPAT_ZIP) \
$(INSTALLED_FILES_FILE) \
@@ -1568,6 +1671,10 @@
$(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) \
@@ -1576,7 +1683,12 @@
$(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 \
+ $(INSTALLED_RAMDISK_BUILD_PROP_TARGET):build.prop-ramdisk \
$(BUILT_TARGET_FILES_PACKAGE) \
$(INSTALLED_ANDROID_INFO_TXT_TARGET) \
$(INSTALLED_MISC_INFO_TARGET) \
@@ -1588,13 +1700,11 @@
$(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) \
@@ -1607,6 +1717,8 @@
$(INSTALLED_FILES_JSON_RAMDISK) \
$(INSTALLED_FILES_FILE_DEBUG_RAMDISK) \
$(INSTALLED_FILES_JSON_DEBUG_RAMDISK) \
+ $(INSTALLED_FILES_FILE_VENDOR_RAMDISK) \
+ $(INSTALLED_FILES_JSON_VENDOR_RAMDISK) \
$(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK) \
$(INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK) \
$(INSTALLED_DEBUG_RAMDISK_TARGET) \
@@ -1647,10 +1759,15 @@
$(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)
@@ -1711,9 +1828,9 @@
.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:
@@ -1726,6 +1843,11 @@
ndk: $(SOONG_OUT_DIR)/ndk.timestamp
.PHONY: ndk
+# Checks that build/soong/apex/allowed_deps.txt remains up to date
+ifneq ($(UNSAFE_DISABLE_APEX_ALLOWED_DEPS_CHECK),true)
+ droidcore: ${APEX_ALLOWED_DEPS_CHECK}
+endif
+
$(call dist-write-file,$(KATI_PACKAGE_MK_DIR)/dist.mk)
$(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] writing build rules ...)
diff --git a/core/native_benchmark.mk b/core/native_benchmark.mk
deleted file mode 100644
index 073d8dd..0000000
--- 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 ef1818f..ea982cf 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 591937c..2e1bd69 100644
--- a/core/ninja_config.mk
+++ b/core/ninja_config.mk
@@ -15,7 +15,6 @@
$(dont_bother_goals) \
all \
ECLIPSE-% \
- AUX-% \
brillo_tests \
btnod \
build-art% \
@@ -25,30 +24,21 @@
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 \
userdebug \
- vts10 \
win_sdk \
winsdk-tools
diff --git a/core/notice_files.mk b/core/notice_files.mk
index 22f8e41..0430007 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -6,7 +6,7 @@
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)
@@ -79,8 +79,9 @@
endif
module_installed_filename := \
$(patsubst $(PRODUCT_OUT)/%,%,$($(my_prefix)OUT_JAVA_LIBRARIES))/$(module_leaf)
- else ifeq ($(LOCAL_MODULE_CLASS),ETC)
- # ETC modules may be uninstallable, yet still have a NOTICE file. e.g. apex components
+ else ifneq ($(filter ETC DATA,$(LOCAL_MODULE_CLASS)),)
+ # ETC and DATA modules may be uninstallable, yet still have a NOTICE file.
+ # e.g. apex components
module_installed_filename :=
else ifneq (,$(and $(filter %.sdk,$(LOCAL_MODULE)),$(filter $(patsubst %.sdk,%,$(LOCAL_MODULE)),$(SOONG_SDK_VARIANT_MODULES))))
# Soong produces uninstallable *.sdk shared libraries for embedding in APKs.
@@ -105,7 +106,7 @@
$(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 6bde485..591f7aa 100644
--- a/core/package.mk
+++ b/core/package.mk
@@ -41,15 +41,7 @@
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 @@
# 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 692ff49..a97e401 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -377,9 +377,11 @@
# 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 @@
# 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 @@
# 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 @@
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 af33f5d..dacbe21 100644
--- a/core/pathmap.mk
+++ b/core/pathmap.mk
@@ -40,7 +40,6 @@
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 922e0ef..0000000
--- 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 235acf9..0000000
--- 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 f8ba593..f5e81e7 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -120,7 +120,7 @@
# The resoure configuration options to use for this product.
_product_list_vars += PRODUCT_LOCALES
_product_list_vars += PRODUCT_AAPT_CONFIG
-_product_list_vars += PRODUCT_AAPT_PREF_CONFIG
+_product_single_value_vars += PRODUCT_AAPT_PREF_CONFIG
_product_list_vars += PRODUCT_AAPT_PREBUILT_DPI
_product_list_vars += PRODUCT_HOST_PACKAGES
_product_list_vars += PRODUCT_PACKAGES
@@ -145,25 +145,27 @@
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_list_vars += PRODUCT_PROPERTY_OVERRIDES
+# 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
-# 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
+# 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
_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
@@ -207,7 +209,7 @@
_product_list_vars += PRODUCT_SOONG_NAMESPACES
_product_list_vars += PRODUCT_DEFAULT_WIFI_CHANNELS
-_product_list_vars += PRODUCT_DEFAULT_DEV_CERTIFICATE
+_product_single_value_vars += PRODUCT_DEFAULT_DEV_CERTIFICATE
_product_list_vars += PRODUCT_MAINLINE_SEPOLICY_DEV_CERTIFICATES
_product_list_vars += PRODUCT_RESTRICT_VENDOR_FILES
@@ -226,19 +228,12 @@
_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_single_value_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,18 +251,20 @@
_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
# Per-module dex-preopt configs.
_product_list_vars += PRODUCT_DEX_PREOPT_MODULE_CONFIGS
-_product_list_vars += PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
+_product_single_value_vars += PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER
_product_list_vars += PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
-_product_list_vars += PRODUCT_DEX_PREOPT_BOOT_FLAGS
-_product_list_vars += PRODUCT_DEX_PREOPT_PROFILE_DIR
-_product_list_vars += PRODUCT_DEX_PREOPT_GENERATE_DM_FILES
-_product_list_vars += PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING
-_product_list_vars += PRODUCT_DEX_PREOPT_RESOLVE_STARTUP_STRINGS
+_product_single_value_vars += PRODUCT_DEX_PREOPT_BOOT_FLAGS
+_product_single_value_vars += PRODUCT_DEX_PREOPT_PROFILE_DIR
+_product_single_value_vars += PRODUCT_DEX_PREOPT_GENERATE_DM_FILES
+_product_single_value_vars += PRODUCT_DEX_PREOPT_NEVER_ALLOW_STRIPPING
+_product_single_value_vars += PRODUCT_DEX_PREOPT_RESOLVE_STARTUP_STRINGS
# Boot image options.
_product_single_value_vars += \
@@ -275,7 +272,7 @@
PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION \
PRODUCT_USES_DEFAULT_ART_CONFIG \
-_product_list_vars += PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
+_product_single_value_vars += PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
# Per-module sanitizer configs
_product_list_vars += PRODUCT_SANITIZER_MODULE_CONFIGS
_product_single_value_vars += PRODUCT_SYSTEM_BASE_FS_PATH
@@ -283,6 +280,8 @@
_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
@@ -316,18 +315,15 @@
# Whether the Scudo hardened allocator is disabled platform-wide
_product_single_value_vars += PRODUCT_DISABLE_SCUDO
-# A flag to override PRODUCT_COMPATIBLE_PROPERTY
-_product_single_value_vars += PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE
-
# List of extra VNDK versions to be included
_product_list_vars += PRODUCT_EXTRA_VNDK_VERSIONS
+# Whether APEX should be compressed or not
+_product_single_value_vars += PRODUCT_COMPRESSED_APEX
+
# 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
-
-# Whether the list of allowed of actionable compatible properties should be disabled or not
-_product_single_value_vars += PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE
+_product_single_value_vars += PRODUCT_PRODUCT_VNDK_VERSION
_product_single_value_vars += PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
_product_single_value_vars += PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT
@@ -374,11 +370,14 @@
_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
_product_single_value_vars += PRODUCT_BUILD_RECOVERY_IMAGE
_product_single_value_vars += PRODUCT_BUILD_BOOT_IMAGE
+_product_single_value_vars += PRODUCT_BUILD_VENDOR_BOOT_IMAGE
_product_single_value_vars += PRODUCT_BUILD_VBMETA_IMAGE
# List of boot jars delivered via apex
@@ -403,6 +402,20 @@
# If set, Java module in product partition cannot use hidden APIs.
_product_single_value_vars += PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
+# If set, only java_sdk_library can be used at inter-partition dependency.
+# Note: Build error if BOARD_VNDK_VERSION is not set while
+# PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY is true, because
+# PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY has no meaning if
+# BOARD_VNDK_VERSION is not set.
+# Note: When PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is not set, there are
+# no restrictions at dependency between system and product partition.
+_product_single_value_vars += PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY
+
+# Allowlist for PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY option.
+# Listed modules are allowed at inter-partition dependency even if it isn't
+# a java_sdk_library module.
+_product_list_vars += PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST
+
_product_single_value_vars += PRODUCT_INSTALL_EXTRA_FLATTENED_APEXES
.KATI_READONLY := _product_single_value_vars _product_list_vars
@@ -458,6 +471,13 @@
$(sort $(ARTIFACT_PATH_REQUIREMENT_PRODUCTS) $(current_mk)))
endef
+# Like require-artifacts-in-path, but does not require all allow-list entries to
+# have an effect.
+define require-artifacts-in-path-relaxed
+ $(require-artifacts-in-path) \
+ $(eval PRODUCTS.$(current_mk).ARTIFACT_PATH_REQUIREMENT_IS_RELAXED := true)
+endef
+
# Makes including non-existent modules in PRODUCT_PACKAGES an error.
# $(1): list of non-existent modules to allow.
define enforce-product-packages-exist
diff --git a/core/product_config.mk b/core/product_config.mk
index a16af05..7b72b5e 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -160,15 +160,16 @@
$(call import-products, $(current_product_makefile))
endif # Import all or just the current product makefile
+# Quick check
+$(check-all-products)
+
# Import all the products that have made artifact path requirements, so that we can verify
# the artifacts they produce.
+# These are imported after check-all-products because some of them might not be real products.
$(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\
$(if $(filter-out $(makefile),$(PRODUCTS)),$(eval $(call import-products,$(makefile))))\
)
-# Sanity check
-$(check-all-products)
-
ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
$(dump-products)
endif
@@ -184,24 +185,12 @@
all_product_makefiles :=
all_product_configs :=
-# Jacoco agent JARS to be built and installed, if any.
-ifeq ($(EMMA_INSTRUMENT),true)
- ifneq ($(EMMA_INSTRUMENT_STATIC),true)
- # For instrumented build, if Jacoco is not being included statically
- # in instrumented packages then include Jacoco classes into the
- # bootclasspath.
- $(foreach product,$(PRODUCTS),\
- $(eval PRODUCTS.$(product).PRODUCT_PACKAGES += jacocoagent)\
- $(eval PRODUCTS.$(product).PRODUCT_BOOT_JARS += jacocoagent))
- endif # EMMA_INSTRUMENT_STATIC
-endif # EMMA_INSTRUMENT
-
############################################################################
# Strip and assign the PRODUCT_ variables.
$(call strip-product-vars)
#############################################################################
-# Sanity check and assign default values
+# Quick check and assign default values
TARGET_DEVICE := $(PRODUCT_DEVICE)
@@ -231,6 +220,10 @@
# 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 +264,9 @@
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)
@@ -353,9 +344,25 @@
PRODUCT_EXTRA_VNDK_VERSIONS := $(OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS)
endif
+###########################################
+# APEXes are by default not compressed
+#
+# APEX compression can be forcibly enabled (resp. disabled) by
+# setting OVERRIDE_PRODUCT_COMPRESSED_APEX to true (resp. false), e.g. by
+# setting the OVERRIDE_PRODUCT_COMPRESSED_APEX environment variable.
+ifdef OVERRIDE_PRODUCT_COMPRESSED_APEX
+ PRODUCT_COMPRESSED_APEX := $(OVERRIDE_PRODUCT_COMPRESSED_APEX)
+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 +372,35 @@
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 +428,8 @@
PRODUCT \
SYSTEM_EXT \
ODM \
+ VENDOR_DLKM \
+ ODM_DLKM \
CACHE \
RAMDISK \
USERDATA \
diff --git a/core/rbe.mk b/core/rbe.mk
index cfad09c..91606d4 100644
--- a/core/rbe.mk
+++ b/core/rbe.mk
@@ -25,13 +25,13 @@
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"
+ cxx_compare := false
endif
ifdef RBE_JAVAC_EXEC_STRATEGY
@@ -52,12 +52,12 @@
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)" --compare="$(cxx_compare)"
+ 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.
@@ -65,15 +65,15 @@
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 0000000..e62175f
--- /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="robolectric" />
+ <option name="test-suite-tag" value="robolectric-tests" />
+
+ <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 219772a..12b7f44 100644
--- a/core/shared_library_internal.mk
+++ b/core/shared_library_internal.mk
@@ -51,8 +51,8 @@
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 1ea9fe7..0000000
--- 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 c93bb3f..ef9eace 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 @@
## 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_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_MASTER_FILE) || [[ $$? -eq 11 ]]
+ $(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 4616ad0..50ac93a 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -7,6 +7,7 @@
# 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)
@@ -52,7 +53,7 @@
# 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
@@ -85,6 +86,13 @@
$(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
@@ -173,7 +181,7 @@
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
diff --git a/core/soong_cc_prebuilt.mk b/core/soong_cc_prebuilt.mk
index 51549bd..a12ef66 100644
--- a/core/soong_cc_prebuilt.mk
+++ b/core/soong_cc_prebuilt.mk
@@ -91,6 +91,7 @@
ifdef LOCAL_INSTALLED_MODULE
ifneq ($(LOCAL_CHECK_ELF_FILES),)
my_prebuilt_src_file := $(LOCAL_PREBUILT_MODULE_FILE)
+ my_system_shared_libraries := $(LOCAL_SYSTEM_SHARED_LIBRARIES)
include $(BUILD_SYSTEM)/check_elf_file.mk
endif
endif
@@ -112,7 +113,12 @@
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,10 +143,21 @@
$(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)
+ ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+ [ -x $@ ] || ( $(call echo-error,$@,Target of symlink is not executable); false )
+ endif
+else
$(transform-prebuilt-to-target)
-ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+ ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
$(hide) chmod +x $@
+ endif
endif
ifndef LOCAL_IS_HOST_MODULE
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 51b7e38..1d252b7 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -1,7 +1,3 @@
-SOONG := $(SOONG_OUT_DIR)/soong
-SOONG_BOOTSTRAP := $(SOONG_OUT_DIR)/.soong.bootstrap
-SOONG_BUILD_NINJA := $(SOONG_OUT_DIR)/build.ninja
-SOONG_IN_MAKE := $(SOONG_OUT_DIR)/.soong.in_make
SOONG_MAKEVARS_MK := $(SOONG_OUT_DIR)/make_vars-$(TARGET_PRODUCT).mk
SOONG_VARIABLES := $(SOONG_OUT_DIR)/soong.variables
SOONG_ANDROID_MK := $(SOONG_OUT_DIR)/Android-$(TARGET_PRODUCT).mk
@@ -39,9 +35,10 @@
$(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, Skip_boot_jars_check, $(SKIP_BOOT_JARS_CHECK))
$(call add_json_bool, Debuggable, $(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
$(call add_json_bool, Eng, $(filter eng,$(TARGET_BUILD_VARIANT)))
@@ -57,6 +54,9 @@
$(call add_json_str, DeviceSecondaryCpuVariant, $(TARGET_2ND_CPU_VARIANT))
$(call add_json_list, DeviceSecondaryAbi, $(TARGET_2ND_CPU_ABI) $(TARGET_2ND_CPU_ABI2))
+$(call add_json_bool, Aml_abis, $(if $(filter mainline_sdk,$(TARGET_ARCH_SUITE)),true))
+$(call add_json_bool, Ndk_abis, $(if $(filter ndk, $(TARGET_ARCH_SUITE)),true))
+
$(call add_json_str, NativeBridgeArch, $(TARGET_NATIVE_BRIDGE_ARCH))
$(call add_json_str, NativeBridgeArchVariant, $(TARGET_NATIVE_BRIDGE_ARCH_VARIANT))
$(call add_json_str, NativeBridgeCpuVariant, $(TARGET_NATIVE_BRIDGE_CPU_VARIANT))
@@ -115,29 +115,24 @@
$(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, $(call invert_bool,$(filter false,$(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, 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,11 +172,15 @@
$(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, BoardPlatPublicSepolicyDirs, $(BOARD_PLAT_PUBLIC_SEPOLICY_DIR))
-$(call add_json_list, BoardPlatPrivateSepolicyDirs, $(BOARD_PLAT_PRIVATE_SEPOLICY_DIR))
+$(call add_json_list, BoardVendorDlkmSepolicyDirs, $(BOARD_VENDOR_DLKM_SEPOLICY_DIRS))
+$(call add_json_list, BoardOdmDlkmSepolicyDirs, $(BOARD_ODM_DLKM_SEPOLICY_DIRS))
+# TODO: BOARD_PLAT_* dirs only kept for compatibility reasons. Will be a hard error on API level 31
+$(call add_json_list, SystemExtPublicSepolicyDirs, $(SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS) $(BOARD_PLAT_PUBLIC_SEPOLICY_DIR))
+$(call add_json_list, SystemExtPrivateSepolicyDirs, $(SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS) $(BOARD_PLAT_PRIVATE_SEPOLICY_DIR))
$(call add_json_list, BoardSepolicyM4Defs, $(BOARD_SEPOLICY_M4DEFS))
$(call add_json_bool, Flatten_apex, $(filter true,$(TARGET_FLATTEN_APEX)))
+$(call add_json_bool, ForceApexSymlinkOptimization, $(filter true,$(TARGET_FORCE_APEX_SYMLINK_OPTIMIZATION)))
$(call add_json_str, DexpreoptGlobalConfig, $(DEX_PREOPT_CONFIG))
@@ -196,7 +197,6 @@
$(call add_json_list, ProductPublicSepolicyDirs, $(PRODUCT_PUBLIC_SEPOLICY_DIRS))
$(call add_json_list, ProductPrivateSepolicyDirs, $(PRODUCT_PRIVATE_SEPOLICY_DIRS))
-$(call add_json_bool, ProductCompatibleProperty, $(PRODUCT_COMPATIBLE_PROPERTY))
$(call add_json_list, TargetFSConfigGen, $(TARGET_FS_CONFIG_GEN))
@@ -211,11 +211,22 @@
$(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, EnforceInterPartitionJavaSdkLibrary, $(PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY))
+$(call add_json_list, InterPartitionJavaLibraryAllowList, $(PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST))
$(call add_json_bool, InstallExtraFlattenedApexes, $(PRODUCT_INSTALL_EXTRA_FLATTENED_APEXES))
+$(call add_json_bool, CompressedApex, $(PRODUCT_COMPRESSED_APEX))
+
$(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 add_json_bool, BoardMoveRecoveryResourcesToVendorBoot, $(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT))
+
$(call json_end)
$(file >$(SOONG_VARIABLES).tmp,$(json_contents))
diff --git a/core/soong_droiddoc_prebuilt.mk b/core/soong_droiddoc_prebuilt.mk
index c0467df..4dc5d08 100644
--- a/core/soong_droiddoc_prebuilt.mk
+++ b/core/soong_droiddoc_prebuilt.mk
@@ -29,16 +29,6 @@
$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_API_VERSIONS_XML),$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)_generated-api-versions.xml))
endif
-ifdef LOCAL_DROIDDOC_JDIFF_DOC_ZIP
-$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_JDIFF_DOC_ZIP),$(OUT_DOCS)/$(LOCAL_MODULE)-jdiff-docs.zip))
-$(call dist-for-goals,docs,$(OUT_DOCS)/$(LOCAL_MODULE)-jdiff-docs.zip)
-
-ALL_DOCS += $(OUT_DOCS)/$(LOCAL_MODULE)-jdiff-docs.zip
-
-.PHONY: $(LOCAL_MODULE) $(LOCAL_MODULE)-jdiff
-$(LOCAL_MODULE) $(LOCAL_MODULE)-jdiff : $(OUT_DOCS)/$(LOCAL_MODULE)-jdiff-docs.zip
-endif
-
ifdef LOCAL_DROIDDOC_METADATA_ZIP
$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_METADATA_ZIP),$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)-metadata.zip))
endif
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index bfde944..5444d96 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -58,6 +58,14 @@
$(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 @@
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 @@
$(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 4a9eb4a..4cfb01f 100644
--- a/core/soong_rust_prebuilt.mk
+++ b/core/soong_rust_prebuilt.mk
@@ -28,9 +28,9 @@
$(call pretty-error,Unsupported LOCAL_MODULE_$(my_prefix)ARCH=$(LOCAL_MODULE_$(my_prefix)ARCH))
endif
-# Don't install rlib/proc_macro libraries.
+# Don't install static/rlib/proc_macro libraries.
ifndef LOCAL_UNINSTALLABLE_MODULE
- ifneq ($(filter RLIB_LIBRARIES PROC_MACRO_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
+ ifneq ($(filter STATIC_LIBRARIES RLIB_LIBRARIES PROC_MACRO_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
LOCAL_UNINSTALLABLE_MODULE := true
endif
endif
@@ -57,9 +57,16 @@
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)
+ ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+ [ -x $@ ] || ( $(call echo-error,$@,Target of symlink is not executable); false )
+ endif
+else
$(transform-prebuilt-to-target)
-ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+ ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
$(hide) chmod +x $@
+ endif
endif
ifndef LOCAL_IS_HOST_MODULE
@@ -75,6 +82,34 @@
endif
endif
+create_coverage_zip :=
+
+ifeq ($(NATIVE_COVERAGE),true)
+ create_coverage_zip := true
+endif
+
+# Until Rust supports LLVM coverage, Soong assumes GCOV coverage in both cases.
+# Therefore we should create the coverage zip with the gcno files in this case as well.
+ifeq ($(CLANG_COVERAGE),true)
+ create_coverage_zip := true
+endif
+
+ifdef create_coverage_zip
+ 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 7eef167..7a87322 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -111,7 +111,7 @@
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 @@
$(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 a0e2970..0000000
--- 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 0000000..bb19dc5
--- /dev/null
+++ b/core/sysprop.mk
@@ -0,0 +1,470 @@
+#
+# 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_LAST_STABLE)" >> $(2);\
+ echo "ro.$(1).build.version.release_or_codename=$(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
+# $(6): optional list of files to append at the end. The content of each file is emitted
+# to the output
+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) $(6)
+ $(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) $(foreach file,$(strip $(6)),\
+ if [ -f "$(file)" ]; then\
+ cat $(file) >> $$@;\
+ fi;)
+ $(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) | $(BUILD_DATETIME_FILE) $(BUILD_NUMBER_FILE)
+ $(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) > $@
+
+ifdef TARGET_SYSTEM_PROP
+system_prop_file := $(TARGET_SYSTEM_PROP)
+else
+system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
+endif
+
+_prop_files_ := \
+ $(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_),\
+ $(empty)))
+
+# -----------------------------------------------------------------
+# 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),\
+ $(empty)))
+
+# -----------------------------------------------------------------
+# 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
+
+ifdef PRODUCT_OEM_PROPERTIES
+import_oem_prop := $(call intermediates-dir-for,ETC,import_oem_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)" >> $@;)
+
+_footers_ := $(import_oem_prop)
+else
+_footers_ :=
+endif
+
+$(eval $(call build-properties,\
+ product,\
+ $(INSTALLED_PRODUCT_BUILD_PROP_TARGET),\
+ $(_prop_files_),\
+ $(_prop_vars_),\
+ $(empty),\
+ $(_footers_)))
+
+# ----------------------------------------------------------------
+# 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),\
+ $(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),\
+ $(empty),\
+ $(empty),\
+ $(empty),\
+ $(empty)))
+
+# ----------------------------------------------------------------
+# 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),\
+ $(empty),\
+ $(empty),\
+ $(empty),\
+ $(empty)))
+
+# -----------------------------------------------------------------
+# 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),\
+ $(empty)))
+
+# ----------------------------------------------------------------
+# ramdisk/boot/etc/build.prop
+#
+
+RAMDISK_BUILD_PROP_REL_PATH := system/etc/ramdisk/build.prop
+INSTALLED_RAMDISK_BUILD_PROP_TARGET := $(TARGET_RAMDISK_OUT)/$(RAMDISK_BUILD_PROP_REL_PATH)
+$(eval $(call build-properties,\
+ bootimage,\
+ $(INSTALLED_RAMDISK_BUILD_PROP_TARGET),\
+ $(empty),\
+ $(empty),\
+ $(empty),\
+ $(empty)))
diff --git a/core/target_test_config.mk b/core/target_test_config.mk
deleted file mode 100644
index 61f5d2b..0000000
--- a/core/target_test_config.mk
+++ /dev/null
@@ -1,23 +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.
-#
-
-#
-# 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
diff --git a/core/tasks/art-host-tests.mk b/core/tasks/art-host-tests.mk
new file mode 100644
index 0000000..d771b06
--- /dev/null
+++ b/core/tasks/art-host-tests.mk
@@ -0,0 +1,44 @@
+# 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.
+
+.PHONY: art-host-tests
+
+intermediates_dir := $(call intermediates-dir-for,PACKAGING,art-host-tests)
+art_host_tests_zip := $(PRODUCT_OUT)/art-host-tests.zip
+# Get the hostside libraries to be packaged in the test zip. Unlike
+# device-tests.mk or general-tests.mk, the files are not copied to the
+# testcases directory.
+my_host_shared_lib_for_art_host_tests := $(foreach f,$(COMPATIBILITY.art-host-tests.HOST_SHARED_LIBRARY.FILES),$(strip \
+ $(eval _cmf_tuple := $(subst :, ,$(f))) \
+ $(eval _cmf_src := $(word 1,$(_cmf_tuple))) \
+ $(_cmf_src)))
+
+$(art_host_tests_zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_art_host_tests)
+
+$(art_host_tests_zip) : $(COMPATIBILITY.art-host-tests.FILES) $(my_host_shared_lib_for_art_host_tests) $(SOONG_ZIP)
+ echo $(sort $(COMPATIBILITY.art-host-tests.FILES)) | tr " " "\n" > $@.list
+ grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
+ $(hide) for shared_lib in $(PRIVATE_HOST_SHARED_LIBS); do \
+ echo $$shared_lib >> $@-host-libs.list; \
+ done
+ grep $(TARGET_OUT_TESTCASES) $@.list > $@-target.list || true
+ $(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $@-host.list \
+ -P target -C $(PRODUCT_OUT) -l $@-target.list \
+ -P host/testcases -C $(HOST_OUT) -l $@-host-libs.list
+ rm -f $@.list $@-host.list $@-target.list $@-host-libs.list
+
+art-host-tests: $(art_host_tests_zip)
+$(call dist-for-goals, art-host-tests, $(art_host_tests_zip))
+
+tests: art-host-tests
diff --git a/core/tasks/boot_jars_package_check.mk b/core/tasks/boot_jars_package_check.mk
deleted file mode 100644
index 825bbc3..0000000
--- a/core/tasks/boot_jars_package_check.mk
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-#
-# Rules to check if classes in the boot jars are from the list of allowed packages.
-#
-
-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), \
- $(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
-
-$(stamp): PRIVATE_BOOT_JARS := $(built_boot_jars)
-$(stamp): PRIVATE_SCRIPT := $(script)
-$(stamp): PRIVATE_ALLOWED := $(allowed_file)
-$(stamp) : $(built_boot_jars) $(script) $(allowed_file)
- @echo "Check package name for $(PRIVATE_BOOT_JARS)"
- $(hide) $(PRIVATE_SCRIPT) $(PRIVATE_ALLOWED) $(PRIVATE_BOOT_JARS)
- $(hide) mkdir -p $(dir $@) && touch $@
-
-.PHONY: check-boot-jars
-check-boot-jars : $(stamp)
-
-# Run check-boot-jars by default
-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/check_boot_jars/check_boot_jars.py b/core/tasks/check_boot_jars/check_boot_jars.py
deleted file mode 100755
index cf4ef27..0000000
--- a/core/tasks/check_boot_jars/check_boot_jars.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env python
-
-"""
-Check boot jars.
-
-Usage: check_boot_jars.py <package_allow_list_file> <jar1> <jar2> ...
-"""
-import logging
-import os.path
-import re
-import subprocess
-import sys
-
-
-# The compiled allow list RE.
-allow_list_re = None
-
-
-def LoadAllowList(filename):
- """ Load and compile allow list regular expressions from filename.
- """
- lines = []
- with open(filename, 'r') as f:
- for line in f:
- line = line.strip()
- if not line or line.startswith('#'):
- continue
- lines.append(line)
- combined_re = r'^(%s)$' % '|'.join(lines)
- global allow_list_re
- try:
- allow_list_re = re.compile(combined_re)
- except re.error:
- logging.exception(
- 'Cannot compile package allow list regular expression: %r',
- combined_re)
- allow_list_re = None
- return False
- return True
-
-
-def CheckJar(allow_list_path, jar):
- """Check a jar file.
- """
- # Get the list of files inside the jar file.
- p = subprocess.Popen(args='jar tf %s' % jar,
- stdout=subprocess.PIPE, shell=True)
- stdout, _ = p.communicate()
- if p.returncode != 0:
- return False
- items = stdout.split()
- classes = 0
- for f in items:
- if f.endswith('.class'):
- classes += 1
- package_name = os.path.dirname(f)
- package_name = package_name.replace('/', '.')
- if not package_name or not allow_list_re.match(package_name):
- print >> sys.stderr, ('Error: %s contains class file %s, whose package name %s is empty or'
- ' not in the allow list %s of packages allowed on the bootclasspath.'
- % (jar, f, package_name, allow_list_path))
- return False
- if classes == 0:
- print >> sys.stderr, ('Error: %s does not contain any class files.' % jar)
- return False
- return True
-
-
-def main(argv):
- if len(argv) < 2:
- print __doc__
- return 1
- allow_list_path = argv[0]
-
- if not LoadAllowList(allow_list_path):
- return 1
-
- passed = True
- for jar in argv[1:]:
- if not CheckJar(allow_list_path, jar):
- passed = False
- if not passed:
- return 1
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv[1:]))
diff --git a/core/tasks/check_boot_jars/package_allowed_list.txt b/core/tasks/check_boot_jars/package_allowed_list.txt
deleted file mode 100644
index 18ab427..0000000
--- a/core/tasks/check_boot_jars/package_allowed_list.txt
+++ /dev/null
@@ -1,248 +0,0 @@
-# Boot jar package name allowed list.
-# Each line is interpreted as a regular expression.
-
-###################################################
-# core-libart.jar & core-oj.jar
-java\.awt\.font
-java\.beans
-java\.io
-java\.lang
-java\.lang\.annotation
-java\.lang\.invoke
-java\.lang\.ref
-java\.lang\.reflect
-java\.math
-java\.net
-java\.nio
-java\.nio\.file
-java\.nio\.file\.spi
-java\.nio\.file\.attribute
-java\.nio\.channels
-java\.nio\.channels\.spi
-java\.nio\.charset
-java\.nio\.charset\.spi
-java\.security
-java\.security\.acl
-java\.security\.cert
-java\.security\.interfaces
-java\.security\.spec
-java\.sql
-java\.text
-java\.text\.spi
-java\.time
-java\.time\.chrono
-java\.time\.format
-java\.time\.temporal
-java\.time\.zone
-java\.util
-java\.util\.concurrent
-java\.util\.concurrent\.atomic
-java\.util\.concurrent\.locks
-java\.util\.function
-java\.util\.jar
-java\.util\.logging
-java\.util\.prefs
-java\.util\.regex
-java\.util\.spi
-java\.util\.stream
-java\.util\.zip
-# TODO: Remove javax.annotation.processing if possible, see http://b/132338110:
-javax\.annotation\.processing
-javax\.crypto
-javax\.crypto\.interfaces
-javax\.crypto\.spec
-javax\.net
-javax\.net\.ssl
-javax\.security\.auth
-javax\.security\.auth\.callback
-javax\.security\.auth\.login
-javax\.security\.auth\.x500
-javax\.security\.cert
-javax\.sql
-javax\.xml
-javax\.xml\.datatype
-javax\.xml\.namespace
-javax\.xml\.parsers
-javax\.xml\.transform
-javax\.xml\.transform\.dom
-javax\.xml\.transform\.sax
-javax\.xml\.transform\.stream
-javax\.xml\.validation
-javax\.xml\.xpath
-jdk\.internal\.util
-jdk\.internal\.vm\.annotation
-jdk\.net
-org\.w3c\.dom
-org\.w3c\.dom\.ls
-org\.w3c\.dom\.traversal
-# OpenJdk internal implementation.
-sun\.invoke\.util
-sun\.invoke\.empty
-sun\.misc
-sun\.util.*
-sun\.text.*
-sun\.security.*
-sun\.reflect.*
-sun\.nio.*
-sun\.net.*
-com\.sun\..*
-
-# TODO: Move these internal org.apache.harmony classes to libcore.*
-org\.apache\.harmony\.crypto\.internal
-org\.apache\.harmony\.dalvik
-org\.apache\.harmony\.dalvik\.ddmc
-org\.apache\.harmony\.luni\.internal\.util
-org\.apache\.harmony\.security
-org\.apache\.harmony\.security\.asn1
-org\.apache\.harmony\.security\.fortress
-org\.apache\.harmony\.security\.pkcs10
-org\.apache\.harmony\.security\.pkcs7
-org\.apache\.harmony\.security\.pkcs8
-org\.apache\.harmony\.security\.provider\.crypto
-org\.apache\.harmony\.security\.utils
-org\.apache\.harmony\.security\.x501
-org\.apache\.harmony\.security\.x509
-org\.apache\.harmony\.security\.x509\.tsp
-org\.apache\.harmony\.xml
-org\.apache\.harmony\.xml\.dom
-org\.apache\.harmony\.xml\.parsers
-
-org\.json
-org\.xmlpull\.v1
-org\.xmlpull\.v1\.sax2
-
-# TODO: jarjar org.kxml2.io to com.android org\.kxml2\.io
-org\.kxml2\.io
-org\.xml
-org\.xml\.sax
-org\.xml\.sax\.ext
-org\.xml\.sax\.helpers
-
-dalvik\..*
-libcore\..*
-android\..*
-com\.android\..*
-###################################################
-# android.test.base.jar
-junit\.extensions
-junit\.framework
-android\.test
-android\.test\.suitebuilder\.annotation
-
-
-###################################################
-# ext.jar
-# TODO: jarjar javax.sip to com.android
-javax\.sip
-javax\.sip\.address
-javax\.sip\.header
-javax\.sip\.message
-
-# TODO: jarjar org.apache.commons to com.android
-org\.apache\.commons\.codec
-org\.apache\.commons\.codec\.binary
-org\.apache\.commons\.codec\.language
-org\.apache\.commons\.codec\.net
-org\.apache\.commons\.logging
-org\.apache\.commons\.logging\.impl
-org\.apache\.http
-org\.apache\.http\.auth
-org\.apache\.http\.auth\.params
-org\.apache\.http\.client
-org\.apache\.http\.client\.entity
-org\.apache\.http\.client\.methods
-org\.apache\.http\.client\.params
-org\.apache\.http\.client\.protocol
-org\.apache\.http\.client\.utils
-org\.apache\.http\.conn
-org\.apache\.http\.conn\.params
-org\.apache\.http\.conn\.routing
-org\.apache\.http\.conn\.scheme
-org\.apache\.http\.conn\.ssl
-org\.apache\.http\.conn\.util
-org\.apache\.http\.cookie
-org\.apache\.http\.cookie\.params
-org\.apache\.http\.entity
-org\.apache\.http\.impl
-org\.apache\.http\.impl\.auth
-org\.apache\.http\.impl\.client
-org\.apache\.http\.impl\.client
-org\.apache\.http\.impl\.conn
-org\.apache\.http\.impl\.conn\.tsccm
-org\.apache\.http\.impl\.cookie
-org\.apache\.http\.impl\.entity
-org\.apache\.http\.impl\.io
-org\.apache\.http\.impl\.io
-org\.apache\.http\.io
-org\.apache\.http\.message
-org\.apache\.http\.params
-org\.apache\.http\.protocol
-org\.apache\.http\.util
-
-# TODO: jarjar gov.nist to com.android
-gov\.nist\.core
-gov\.nist\.core\.net
-gov\.nist\.javax\.sip
-gov\.nist\.javax\.sip\.address
-gov\.nist\.javax\.sip\.clientauthutils
-gov\.nist\.javax\.sip\.header
-gov\.nist\.javax\.sip\.header\.extensions
-gov\.nist\.javax\.sip\.header\.ims
-gov\.nist\.javax\.sip\.message
-gov\.nist\.javax\.sip\.parser
-gov\.nist\.javax\.sip\.parser\.extensions
-gov\.nist\.javax\.sip\.parser\.ims
-gov\.nist\.javax\.sip\.stack
-
-org\.ccil\.cowan\.tagsoup
-org\.ccil\.cowan\.tagsoup\.jaxp
-
-###################################################
-# framework.jar
-javax\.microedition\.khronos\.opengles
-javax\.microedition\.khronos\.egl
-
-android
-
-###################################################
-# apache-xml.jar
-org\.apache\.xml\.res
-org\.apache\.xml\.utils
-org\.apache\.xml\.utils\.res
-org\.apache\.xml\.dtm
-org\.apache\.xml\.dtm\.ref
-org\.apache\.xml\.dtm\.ref\.dom2dtm
-org\.apache\.xml\.dtm\.ref\.sax2dtm
-org\.apache\.xml\.serializer
-org\.apache\.xml\.serializer\.utils
-org\.apache\.xml\.serializer\.dom3
-org\.apache\.xpath
-org\.apache\.xpath\.operations
-org\.apache\.xpath\.domapi
-org\.apache\.xpath\.functions
-org\.apache\.xpath\.res
-org\.apache\.xpath\.axes
-org\.apache\.xpath\.objects
-org\.apache\.xpath\.patterns
-org\.apache\.xpath\.jaxp
-org\.apache\.xpath\.compiler
-org\.apache\.xalan
-org\.apache\.xalan\.res
-org\.apache\.xalan\.templates
-org\.apache\.xalan\.serialize
-org\.apache\.xalan\.extensions
-org\.apache\.xalan\.processor
-org\.apache\.xalan\.transformer
-org\.apache\.xalan\.xslt
-
-###################################################
-# Packages in the google namespace across all bootclasspath jars.
-com\.google\.android\..*
-com\.google\.vr\.platform.*
-com\.google\.i18n\.phonenumbers\..*
-com\.google\.i18n\.phonenumbers
-
-###################################################
-# Packages used for Android in Chrome OS
-org\.chromium\.arc
-org\.chromium\.arc\..*
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index cd5fa8e..fdd9591 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -14,9 +14,8 @@
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
+test_suite_dynamic_config := cts/tools/cts-tradefed/DynamicConfig.xml
+test_suite_readme := cts/tools/cts-tradefed/README
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 daf986f..0000000
--- 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/find-shareduid-violation.mk b/core/tasks/find-shareduid-violation.mk
index 86052f2..d6885eb 100644
--- a/core/tasks/find-shareduid-violation.mk
+++ b/core/tasks/find-shareduid-violation.mk
@@ -16,8 +16,6 @@
shareduid_violation_modules_filename := $(PRODUCT_OUT)/shareduid_violation_modules.json
-find_shareduid_script := $(BUILD_SYSTEM)/tasks/find-shareduid-violation.py
-
$(shareduid_violation_modules_filename): $(INSTALLED_SYSTEMIMAGE_TARGET) \
$(INSTALLED_RAMDISK_TARGET) \
$(INSTALLED_BOOTIMAGE_TARGET) \
@@ -26,7 +24,15 @@
$(INSTALLED_PRODUCTIMAGE_TARGET) \
$(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
-$(shareduid_violation_modules_filename): $(find_shareduid_script)
+$(shareduid_violation_modules_filename): $(HOST_OUT_EXECUTABLES)/find_shareduid_violation
$(shareduid_violation_modules_filename): $(AAPT2)
- $(find_shareduid_script) $(PRODUCT_OUT) $(AAPT2) > $@
+ $(HOST_OUT_EXECUTABLES)/find_shareduid_violation \
+ --product_out $(PRODUCT_OUT) \
+ --aapt $(AAPT2) \
+ --copy_out_system $(TARGET_COPY_OUT_SYSTEM) \
+ --copy_out_vendor $(TARGET_COPY_OUT_VENDOR) \
+ --copy_out_product $(TARGET_COPY_OUT_PRODUCT) \
+ --copy_out_system_ext $(TARGET_COPY_OUT_SYSTEM_EXT) \
+ > $@
+
$(call dist-for-goals,droidcore,$(shareduid_violation_modules_filename))
diff --git a/core/tasks/find-shareduid-violation.py b/core/tasks/find-shareduid-violation.py
deleted file mode 100755
index 1f8e4df..0000000
--- a/core/tasks/find-shareduid-violation.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env 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.
-#
-import os
-import subprocess
-from glob import glob
-from collections import defaultdict
-import sys
-import json
-
-if len(sys.argv) < 3:
- product_out = os.environ["PRODUCT_OUT"]
- aapt = "aapt2"
-else:
- product_out = sys.argv[1]
- aapt = sys.argv[2]
-
-def execute(cmd):
- p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = map(lambda b: b.decode('utf-8'), p.communicate())
- return p.returncode == 0, out, err
-
-def make_aapt_cmds(file):
- return [aapt + ' dump ' + file + ' --file AndroidManifest.xml',
- aapt + ' dump xmltree ' + file + ' --file AndroidManifest.xml']
-
-def extract_shared_uid(file):
- for cmd in make_aapt_cmds(file):
- success, manifest, error_msg = execute(cmd)
- if success:
- break
- else:
- print(error_msg, file=sys.stderr)
- sys.exit()
- return None
-
- for l in manifest.split('\n'):
- if "sharedUserId" in l:
- return l.split('"')[-2]
- return None
-
-
-partitions = ["system", "vendor", "product"]
-
-shareduid_app_dict = defaultdict(list)
-
-for p in partitions:
- for f in glob(os.path.join(product_out, p, "*", "*", "*.apk")):
- apk_file = os.path.basename(f)
- shared_uid = extract_shared_uid(f)
-
- if shared_uid is None:
- continue
- shareduid_app_dict[shared_uid].append((p, apk_file))
-
-
-output = defaultdict(lambda: defaultdict(list))
-
-for uid, app_infos in shareduid_app_dict.items():
- partitions = {p for p, _ in app_infos}
- if len(partitions) > 1:
- for part in partitions:
- output[uid][part].extend([a for p, a in app_infos if p == part])
-
-print(json.dumps(output, indent=2, sort_keys=True))
diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk
index cb84a5c..a820a28 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/host-unit-tests.mk b/core/tasks/host-unit-tests.mk
new file mode 100644
index 0000000..755b589
--- /dev/null
+++ b/core/tasks/host-unit-tests.mk
@@ -0,0 +1,50 @@
+# 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.
+
+# `host-unit-tests` shall only include hostside unittest that don't require a device to run. Tests
+# included will be run as part of presubmit check.
+# To add tests to the suite, do one of the following:
+# * For test modules configured with Android.bp, set attribute `test_options: { unit_test: true }`
+# * For test modules configured with mk, set `LOCAL_IS_UNIT_TEST := true`
+.PHONY: host-unit-tests
+
+intermediates_dir := $(call intermediates-dir-for,PACKAGING,host-unit-tests)
+host_unit_tests_zip := $(PRODUCT_OUT)/host-unit-tests.zip
+# Get the hostside libraries to be packaged in the test zip. Unlike
+# device-tests.mk or general-tests.mk, the files are not copied to the
+# testcases directory.
+my_host_shared_lib_for_host_unit_tests := $(foreach f,$(COMPATIBILITY.host-unit-tests.HOST_SHARED_LIBRARY.FILES),$(strip \
+ $(eval _cmf_tuple := $(subst :, ,$(f))) \
+ $(eval _cmf_src := $(word 1,$(_cmf_tuple))) \
+ $(_cmf_src)))
+
+$(host_unit_tests_zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_host_unit_tests)
+
+$(host_unit_tests_zip) : $(COMPATIBILITY.host-unit-tests.FILES) $(my_host_shared_lib_for_host_unit_tests) $(SOONG_ZIP)
+ echo $(sort $(COMPATIBILITY.host-unit-tests.FILES)) | tr " " "\n" > $@.list
+ grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
+ echo "" >> $@-host-libs.list
+ $(hide) for shared_lib in $(PRIVATE_HOST_SHARED_LIBS); do \
+ echo $$shared_lib >> $@-host-libs.list; \
+ done
+ grep $(TARGET_OUT_TESTCASES) $@.list > $@-target.list || true
+ $(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $@-host.list \
+ -P target -C $(PRODUCT_OUT) -l $@-target.list \
+ -P host/testcases -C $(HOST_OUT) -l $@-host-libs.list
+ rm -f $@.list $@-host.list $@-target.list $@-host-libs.list
+
+host-unit-tests: $(host_unit_tests_zip)
+$(call dist-for-goals, host-unit-tests, $(host_unit_tests_zip))
+
+tests: host-unit-tests
diff --git a/core/tasks/host_init_verifier.mk b/core/tasks/host_init_verifier.mk
new file mode 100644
index 0000000..bdf996c
--- /dev/null
+++ b/core/tasks/host_init_verifier.mk
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+
+host_init_verifier_output := $(PRODUCT_OUT)/host_init_verifier_output.txt
+
+$(host_init_verifier_output): \
+ $(INSTALLED_SYSTEMIMAGE_TARGET) \
+ $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
+ $(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_ODMIMAGE_TARGET) \
+ $(INSTALLED_PRODUCTIMAGE_TARGET) \
+ $(call intermediates-dir-for,ETC,passwd_system)/passwd_system \
+ $(call intermediates-dir-for,ETC,passwd_system_ext)/passwd_system_ext \
+ $(call intermediates-dir-for,ETC,passwd_vendor)/passwd_vendor \
+ $(call intermediates-dir-for,ETC,passwd_odm)/passwd_odm \
+ $(call intermediates-dir-for,ETC,passwd_product)/passwd_product \
+ $(call intermediates-dir-for,ETC,plat_property_contexts)/plat_property_contexts \
+ $(call intermediates-dir-for,ETC,system_ext_property_contexts)/system_ext_property_contexts \
+ $(call intermediates-dir-for,ETC,product_property_contexts)/product_property_contexts \
+ $(call intermediates-dir-for,ETC,vendor_property_contexts)/vendor_property_contexts \
+ $(call intermediates-dir-for,ETC,odm_property_contexts)/odm_property_contexts
+
+# Run host_init_verifier on the partition staging directories.
+$(host_init_verifier_output): $(HOST_INIT_VERIFIER)
+ $(HOST_INIT_VERIFIER) \
+ -p $(call intermediates-dir-for,ETC,passwd_system)/passwd_system \
+ -p $(call intermediates-dir-for,ETC,passwd_system_ext)/passwd_system_ext \
+ -p $(call intermediates-dir-for,ETC,passwd_vendor)/passwd_vendor \
+ -p $(call intermediates-dir-for,ETC,passwd_odm)/passwd_odm \
+ -p $(call intermediates-dir-for,ETC,passwd_product)/passwd_product \
+ --property-contexts=$(call intermediates-dir-for,ETC,plat_property_contexts)/plat_property_contexts \
+ --property-contexts=$(call intermediates-dir-for,ETC,system_ext_property_contexts)/system_ext_property_contexts \
+ --property-contexts=$(call intermediates-dir-for,ETC,product_property_contexts)/product_property_contexts \
+ --property-contexts=$(call intermediates-dir-for,ETC,vendor_property_contexts)/vendor_property_contexts \
+ --property-contexts=$(call intermediates-dir-for,ETC,odm_property_contexts)/odm_property_contexts \
+ --out_system $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM) \
+ --out_system_ext $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM_EXT) \
+ --out_vendor $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR) \
+ --out_odm $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ODM) \
+ --out_product $(PRODUCT_OUT)/$(TARGET_COPY_OUT_PRODUCT) \
+ > $@
+
+$(call dist-for-goals,droidcore,$(host_init_verifier_output))
diff --git a/core/tasks/ide.mk b/core/tasks/ide.mk
index e557e60..a3aa0cd 100644
--- a/core/tasks/ide.mk
+++ b/core/tasks/ide.mk
@@ -40,8 +40,7 @@
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 f6cec15..cf32d65 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -14,11 +14,12 @@
'"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/mts.mk b/core/tasks/mts.mk
index e800505..e084856 100644
--- a/core/tasks/mts.mk
+++ b/core/tasks/mts.mk
@@ -13,13 +13,20 @@
# limitations under the License.
ifneq ($(wildcard test/mts/README.md),)
-test_suite_name := mts
-test_suite_tradefed := mts-tradefed
-test_suite_readme := test/mts/README.md
-include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
+mts_test_suites :=
+mts_test_suites += mts
-.PHONY: mts
-mts: $(compatibility_zip)
-$(call dist-for-goals, mts, $(compatibility_zip))
+$(foreach module, $(mts_modules), $(eval mts_test_suites += mts-$(module)))
+
+$(foreach suite, $(mts_test_suites), \
+ $(eval test_suite_name := $(suite)) \
+ $(eval test_suite_tradefed := mts-tradefed) \
+ $(eval test_suite_readme := test/mts/README.md) \
+ $(eval include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk) \
+ $(eval .PHONY: $(suite)) \
+ $(eval $(suite): $(compatibility_zip)) \
+ $(eval $(call dist-for-goals, $(suite), $(compatibility_zip))) \
+)
+
endif
diff --git a/core/tasks/platform_availability_check.mk b/core/tasks/platform_availability_check.mk
index 043d130..1524758 100644
--- a/core/tasks/platform_availability_check.mk
+++ b/core/tasks/platform_availability_check.mk
@@ -17,6 +17,9 @@
# Check whether there is any module that isn't available for platform
# is installed to the platform.
+# Skip for unbundled builds that don't produce a platform image.
+ifeq (,$(TARGET_BUILD_UNBUNDLED))
+
# Filter FAKE and NON_INSTALLABLE modules out and then collect those are not
# available for platform
_modules_not_available_for_platform := \
@@ -26,11 +29,33 @@
$(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,$(filter-out $(HOST_OUT)/%,$(ALL_MODULES.$(m).INSTALLED)),\
+ $(eval $(call not_available_for_platform_rule,$(i),$(m)))))
+endif
+
+endif
diff --git a/core/tasks/recovery_snapshot.mk b/core/tasks/recovery_snapshot.mk
new file mode 100644
index 0000000..fea0bb9
--- /dev/null
+++ b/core/tasks/recovery_snapshot.mk
@@ -0,0 +1,34 @@
+# 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.
+
+current_makefile := $(lastword $(MAKEFILE_LIST))
+
+# BOARD_VNDK_VERSION must be set to 'current' in order to generate a recovery snapshot.
+ifeq ($(BOARD_VNDK_VERSION),current)
+
+.PHONY: recovery-snapshot
+recovery-snapshot: $(SOONG_RECOVERY_SNAPSHOT_ZIP)
+
+$(call dist-for-goals, recovery-snapshot, $(SOONG_RECOVERY_SNAPSHOT_ZIP))
+
+else # BOARD_VNDK_VERSION is NOT set to 'current'
+
+.PHONY: recovery-snapshot
+recovery-snapshot: PRIVATE_MAKEFILE := $(current_makefile)
+recovery-snapshot:
+ $(call echo-error,$(PRIVATE_MAKEFILE),\
+ "CANNOT generate Recovery snapshot. BOARD_VNDK_VERSION must be set to 'current'.")
+ exit 1
+
+endif # BOARD_VNDK_VERSION
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index c1fed90..570a39a 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -26,16 +26,15 @@
# 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 \
+test_tools := $(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 \
- $(HOST_OUT_JAVA_LIBRARIES)/compatibility-host-util-tests.jar \
- $(HOST_OUT_JAVA_LIBRARIES)/compatibility-common-util-tests.jar \
- $(HOST_OUT_JAVA_LIBRARIES)/compatibility-tradefed-tests.jar \
+ $(HOST_OUT_JAVA_LIBRARIES)/compatibility-tradefed.jar \
$(HOST_OUT_JAVA_LIBRARIES)/$(test_suite_tradefed).jar \
$(HOST_OUT_JAVA_LIBRARIES)/$(test_suite_tradefed)-tests.jar \
$(HOST_OUT_EXECUTABLES)/$(test_suite_tradefed) \
@@ -43,10 +42,28 @@
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) $(SOONG_ZIP) $(host_shared_libs)
+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
@@ -60,27 +77,28 @@
$(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_deps += $(test_suite_notice_txt)
+compatibility_zip_resources += $(test_suite_notice_txt)
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): 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_RESOURCES) | 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 :=
@@ -89,5 +107,6 @@
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 7c4266c..2b43f0f 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 @@
$(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/tools/vts_package_utils.mk b/core/tasks/tools/vts_package_utils.mk
new file mode 100644
index 0000000..47bf29c
--- /dev/null
+++ b/core/tasks/tools/vts_package_utils.mk
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+# $(1): List of target native files to copy.
+# $(2): Copy destination directory.
+# Evaluates to a list of ":"-separated pairs src:dst.
+define target-native-copy-pairs
+$(foreach m,$(1),\
+ $(eval _built_files := $(strip $(ALL_MODULES.$(m).BUILT_INSTALLED)\
+ $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).BUILT_INSTALLED)))\
+ $(foreach i, $(_built_files),\
+ $(eval bui_ins := $(subst :,$(space),$(i)))\
+ $(eval ins := $(word 2,$(bui_ins)))\
+ $(if $(filter $(TARGET_OUT_ROOT)/%,$(ins)),\
+ $(eval bui := $(word 1,$(bui_ins)))\
+ $(eval my_copy_dest := $(patsubst data/%,DATA/%,\
+ $(patsubst system/%,DATA/%,\
+ $(patsubst $(PRODUCT_OUT)/%,%,$(ins)))))\
+ $(bui):$(2)/$(my_copy_dest))))
+endef
diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk
index b4c5a3b..4d7d67e 100644
--- a/core/tasks/vendor_module_check.mk
+++ b/core/tasks/vendor_module_check.mk
@@ -108,10 +108,10 @@
$(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 a2973b4..ebe9bd4 100644
--- a/core/tasks/vndk.mk
+++ b/core/tasks/vndk.mk
@@ -20,18 +20,11 @@
# 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/tasks/vts-core-tests.mk b/core/tasks/vts-core-tests.mk
index a3247da..95c4d24 100644
--- a/core/tasks/vts-core-tests.mk
+++ b/core/tasks/vts-core-tests.mk
@@ -15,6 +15,8 @@
-include external/linux-kselftest/android/kselftest_test_list.mk
-include external/ltp/android/ltp_package_list.mk
+include $(BUILD_SYSTEM)/tasks/tools/vts_package_utils.mk
+
test_suite_name := vts
test_suite_tradefed := vts-tradefed
test_suite_readme := test/vts/tools/vts-core-tradefed/README
diff --git a/core/test_config_common.mk b/core/test_config_common.mk
deleted file mode 100644
index 487f9f2..0000000
--- 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 6ac90d8..fe90165 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -39,9 +39,9 @@
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 @@
# 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))
diff --git a/envsetup.sh b/envsetup.sh
index 793f4b6..8fa608b 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -8,7 +8,7 @@
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,8 @@
- 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.
+- syswrite: Remount partitions (e.g. system.img) as writable, rebooting if necessary.
Environment options:
- SANITIZE_HOST: Set to 'address' to use ASAN for all host modules.
@@ -119,13 +120,13 @@
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 +219,6 @@
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
@@ -308,6 +307,9 @@
unset ANDROID_HOST_OUT
export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT)
+ unset ANDROID_SOONG_HOST_OUT
+ export ANDROID_SOONG_HOST_OUT=$(get_abs_build_var SOONG_HOST_OUT)
+
unset ANDROID_HOST_OUT_TESTCASES
export ANDROID_HOST_OUT_TESTCASES=$(get_abs_build_var HOST_OUT_TESTCASES)
@@ -319,6 +321,22 @@
#export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include
}
+function bazel()
+{
+ local T="$(gettop)"
+ if [ ! "$T" ]; then
+ echo "Couldn't locate the top of the tree. Try setting TOP."
+ return
+ fi
+
+ if which bazel &>/dev/null; then
+ >&2 echo "NOTE: bazel() function sourced from envsetup.sh is being used instead of $(which bazel)"
+ >&2 echo
+ fi
+
+ "$T/tools/bazel" "$@"
+}
+
function printconfig()
{
local T=$(gettop)
@@ -357,7 +375,7 @@
function addcompletions()
{
- local T dir f
+ local f=
# Keep us from trying to run in something that's neither bash nor zsh.
if [ -z "$BASH_VERSION" -a -z "$ZSH_VERSION" ]; then
@@ -578,10 +596,25 @@
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 +632,12 @@
{
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 +670,6 @@
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 +694,6 @@
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 +703,10 @@
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 +732,10 @@
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 +758,8 @@
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
@@ -754,7 +788,7 @@
local TOPFILE=build/make/core/envsetup.mk
if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
# The following circumlocution ensures we remove symlinks from TOP.
- (cd $TOP; PWD= /bin/pwd)
+ (cd "$TOP"; PWD= /bin/pwd)
else
if [ -f $TOPFILE ] ; then
# The following circumlocution (repeated below as well) ensures
@@ -764,13 +798,13 @@
else
local HERE=$PWD
local T=
- while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
+ while [ \( ! \( -f $TOPFILE \) \) -a \( "$PWD" != "/" \) ]; do
\cd ..
T=`PWD= /bin/pwd -P`
done
- \cd $HERE
+ \cd "$HERE"
if [ -f "$T/$TOPFILE" ]; then
- echo $T
+ echo "$T"
fi
fi
fi
@@ -843,6 +877,18 @@
fi
}
+# syswrite - disable verity, reboot if needed, and remount image
+#
+# Easy way to make system.img/etc writable
+function syswrite() {
+ adb wait-for-device && adb root || return 1
+ if [[ $(adb disable-verity | grep "reboot") ]]; then
+ echo "rebooting"
+ adb reboot && adb wait-for-device && adb root || return 1
+ fi
+ adb wait-for-device && adb remount || return 1
+}
+
# coredump_setup - enable core dumps globally for any process
# that has the core-file-size limit set correctly
#
@@ -949,7 +995,7 @@
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 +1003,7 @@
*)
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 "$@" {} +
}
;;
@@ -1328,7 +1374,7 @@
mkdir -p $ANDROID_PRODUCT_OUT || return 1
# Note, can't use absolute path because of the way make works.
- m out/target/product/$(get_build_var TARGET_DEVICE)/module-info.json \
+ m $(get_build_var PRODUCT_OUT)/module-info.json \
> $ANDROID_PRODUCT_OUT/module-info.json.build.log 2>&1
}
@@ -1573,25 +1619,26 @@
# This allows loading only approved vendorsetup.sh files
function source_vendorsetup() {
unset VENDOR_PYTHONPATH
+ local T="$(gettop)"
allowed=
- for f in $(find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
+ for f in $(cd "$T" && find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
if [ -n "$allowed" ]; then
echo "More than one 'allowed_vendorsetup_sh-files' file found, not including any vendorsetup.sh files:"
echo " $allowed"
echo " $f"
return
fi
- allowed="$f"
+ allowed="$T/$f"
done
allowed_files=
[ -n "$allowed" ] && allowed_files=$(cat "$allowed")
for dir in device vendor product; do
- for f in $(test -d $dir && \
+ for f in $(cd "$T" && test -d $dir && \
find -L $dir -maxdepth 4 -name 'vendorsetup.sh' 2>/dev/null | sort); do
if [[ -z "$allowed" || "$allowed_files" =~ $f ]]; then
- echo "including $f"; . "$f"
+ echo "including $f"; . "$T/$f"
else
echo "ignoring $f, not in $allowed"
fi
@@ -1599,6 +1646,41 @@
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
diff --git a/help.sh b/help.sh
index b02b14c..4af5154 100755
--- a/help.sh
+++ b/help.sh
@@ -43,7 +43,11 @@
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 25a1703..ec39e6e 100644
--- a/rbesetup.sh
+++ b/rbesetup.sh
@@ -1,10 +1,37 @@
-source build/envsetup.sh
+function _source_env_setup_script() {
+ local -r ENV_SETUP_SCRIPT="build/make/envsetup.sh"
+ local -r TOP_DIR=$(
+ while [[ ! -f "${ENV_SETUP_SCRIPT}" ]] && [[ "${PWD}" != "/" ]]; do
+ \cd ..
+ done
+ if [[ -f "${ENV_SETUP_SCRIPT}" ]]; then
+ echo "$(PWD= /bin/pwd -P)"
+ fi
+ )
+
+ local -r FULL_PATH_ENV_SETUP_SCRIPT="${TOP_DIR}/${ENV_SETUP_SCRIPT}"
+ if [[ ! -f "${FULL_PATH_ENV_SETUP_SCRIPT}" ]]; then
+ echo "ERROR: Unable to source ${ENV_SETUP_SCRIPT}"
+ return 1
+ fi
+
+ # Need to change directory to the repo root so vendor scripts can be sourced
+ # as well.
+ local -r CUR_DIR=$PWD
+ \cd "${TOP_DIR}"
+ source "${FULL_PATH_ENV_SETUP_SCRIPT}"
+ \cd "${CUR_DIR}"
+}
+
+# This function needs to run first as the remaining defining functions may be
+# using the envsetup.sh defined functions.
+_source_env_setup_script || return
# This function prefixes the given command with appropriate variables needed
# 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.
@@ -28,7 +55,7 @@
# 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
+ if [[ -x "${uploader_path}" ]]; then
export ANDROID_ENABLE_METRICS_UPLOAD="${uploader_path}"
fi
}
@@ -36,8 +63,13 @@
# 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_CXX_EXEC_STRATEGY="racing"
+ export RBE_JAVAC_EXEC_STRATEGY="racing"
+ export RBE_R8_EXEC_STRATEGY="racing"
+ export RBE_D8_EXEC_STRATEGY="racing"
+ export RBE_use_unified_cas_ops="true"
export RBE_JAVAC=1
export RBE_R8=1
export RBE_D8=1
diff --git a/tapasHelp.sh b/tapasHelp.sh
index 38b3e34..0f46130 100755
--- a/tapasHelp.sh
+++ b/tapasHelp.sh
@@ -6,7 +6,7 @@
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/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
index e9fb096..342abd7 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -33,8 +33,8 @@
# emulator needs super.img
BOARD_BUILD_SUPER_IMAGE_BY_DEFAULT := true
- # 3G + header
- BOARD_SUPER_PARTITION_SIZE := 3229614080
+ # 4G + 8M
+ BOARD_SUPER_PARTITION_SIZE := 4303355904
BOARD_SUPER_PARTITION_GROUPS := emulator_dynamic_partitions
ifeq ($(QEMU_USE_SYSTEM_EXT_PARTITIONS),true)
@@ -56,8 +56,8 @@
vendor
endif
- # 3G
- BOARD_EMULATOR_DYNAMIC_PARTITIONS_SIZE := 3221225472
+ # 4G
+ BOARD_EMULATOR_DYNAMIC_PARTITIONS_SIZE := 4294967296
# in build environment to speed up make -j
ifeq ($(QEMU_DISABLE_AVB),true)
@@ -73,11 +73,11 @@
endif
#vendor boot
-TARGET_NO_VENDOR_BOOT := false
BOARD_INCLUDE_DTB_IN_BOOTIMG := false
BOARD_BOOT_HEADER_VERSION := 3
BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)
BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 0x06000000
+BOARD_RAMDISK_USE_LZ4 := true
# Enable chain partition for system.
BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index 49f6edc..e34dc23 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -11,7 +11,9 @@
# 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 @@
# 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 @@
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/BoardConfigPixelCommon.mk b/target/board/BoardConfigPixelCommon.mk
new file mode 100644
index 0000000..a970fec
--- /dev/null
+++ b/target/board/BoardConfigPixelCommon.mk
@@ -0,0 +1,18 @@
+# BoardConfigPixelCommon.mk
+#
+# Common compile-time definitions for Pixel devices.
+
+# Using sha256 for dm-verity partitions. b/156162446
+# system, system_other, system_ext and product.
+BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
+BOARD_AVB_SYSTEM_OTHER_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
+BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
+BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
+
+# vendor and odm.
+BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
+BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
+
+# vendor_dlkm and odm_dlkm.
+BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
+BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS += --hash_algorithm sha256
diff --git a/target/board/emulator_arm/AndroidBoard.mk b/target/board/emulator_arm/AndroidBoard.mk
new file mode 100644
index 0000000..7911f61
--- /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 0000000..287824f
--- /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/target/product/virtual_ab_ota.mk b/target/board/emulator_arm/device.mk
similarity index 72%
copy from target/product/virtual_ab_ota.mk
copy to target/board/emulator_arm/device.mk
index 1774de4..af023eb 100644
--- a/target/product/virtual_ab_ota.mk
+++ b/target/board/emulator_arm/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,5 @@
# limitations under the License.
#
-PRODUCT_VIRTUAL_AB_OTA := true
-
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.enabled=true
-
-PRODUCT_PACKAGES += e2fsck_ramdisk
+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 0000000..64829f3
--- /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/BoardConfig.mk b/target/board/emulator_arm64/BoardConfig.mk
index b34ccb4..9293625 100644
--- a/target/board/emulator_arm64/BoardConfig.mk
+++ b/target/board/emulator_arm64/BoardConfig.mk
@@ -19,11 +19,7 @@
TARGET_CPU_VARIANT := generic
TARGET_CPU_ABI := arm64-v8a
-TARGET_2ND_ARCH := arm
-TARGET_2ND_CPU_ABI := armeabi-v7a
-TARGET_2ND_CPU_ABI2 := armeabi
-
-ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk vts10,$(MAKECMDGOALS)),)
+ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk,$(MAKECMDGOALS)),)
# DO NOT USE
# DO NOT USE
#
@@ -56,7 +52,6 @@
include build/make/target/board/BoardConfigEmuCommon.mk
TARGET_NO_KERNEL := false
-TARGET_NO_VENDOR_BOOT := false
BOARD_USES_RECOVERY_AS_BOOT := true
BOARD_BOOTIMAGE_PARTITION_SIZE := 0x02000000
diff --git a/target/board/emulator_arm64/device.mk b/target/board/emulator_arm64/device.mk
index 57675d0..dc84192 100644
--- a/target/board/emulator_arm64/device.mk
+++ b/target/board/emulator_arm64/device.mk
@@ -19,14 +19,10 @@
# Cuttlefish has GKI kernel prebuilts, so use those for the GKI boot.img.
ifeq ($(TARGET_PREBUILT_KERNEL),)
- LOCAL_KERNEL := device/google/cuttlefish_kernel/5.4-arm64/kernel
+ LOCAL_KERNEL := kernel/prebuilts/5.4/arm64/kernel-5.4-lz4
else
LOCAL_KERNEL := $(TARGET_PREBUILT_KERNEL)
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 0000000..8f79166
--- /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 0000000..8a9d8da
--- /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 0000000..64829f3
--- /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 0000000..b9cbd8a
--- /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 0000000..8a9d8da
--- /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 0000000..ed9d173
--- /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 0000000..26b61a6
--- /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/product/virtual_ab_ota.mk b/target/board/emulator_x86_64_arm64/device.mk
old mode 100644
new mode 100755
similarity index 72%
copy from target/product/virtual_ab_ota.mk
copy to target/board/emulator_x86_64_arm64/device.mk
index 1774de4..af023eb
--- a/target/product/virtual_ab_ota.mk
+++ b/target/board/emulator_x86_64_arm64/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,5 @@
# limitations under the License.
#
-PRODUCT_VIRTUAL_AB_OTA := true
-
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.enabled=true
-
-PRODUCT_PACKAGES += e2fsck_ramdisk
+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 0000000..ed9d173
--- /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 0000000..21fdbc8
--- /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/product/virtual_ab_ota.mk b/target/board/emulator_x86_arm/device.mk
similarity index 72%
copy from target/product/virtual_ab_ota.mk
copy to target/board/emulator_x86_arm/device.mk
index 1774de4..af023eb 100644
--- a/target/product/virtual_ab_ota.mk
+++ b/target/board/emulator_x86_arm/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,5 @@
# limitations under the License.
#
-PRODUCT_VIRTUAL_AB_OTA := true
-
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.enabled=true
-
-PRODUCT_PACKAGES += e2fsck_ramdisk
+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 0000000..64829f3
--- /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 8624ed7..87c16da 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -30,6 +30,8 @@
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 @@
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 cfb15f0..76242c9 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 ba69623..414e032 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -23,7 +23,7 @@
TARGET_2ND_CPU_ABI := armeabi-v7a
TARGET_2ND_CPU_ABI2 := armeabi
-ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk vts10,$(MAKECMDGOALS)),)
+ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk,$(MAKECMDGOALS)),)
# DO NOT USE
# DO NOT USE
#
@@ -54,21 +54,43 @@
include build/make/target/board/BoardConfigGsiCommon.mk
-TARGET_NO_KERNEL := false
-TARGET_NO_VENDOR_BOOT := true
-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
+
+# Boot image
+BOARD_USES_RECOVERY_AS_BOOT :=
+TARGET_NO_KERNEL := false
+BOARD_USES_GENERIC_KERNEL_IMAGE := true
+BOARD_KERNEL_MODULE_INTERFACE_VERSIONS := 5.4-android12-0
+# Copy boot image in $OUT to target files. This is defined for targets where
+# the installed GKI APEXes are built from source.
+BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES := true
+
+# No vendor_boot
+BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT :=
+
+# No recovery
+BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE :=
# Some vendors still haven't cleaned up all device specific directories under
# root!
diff --git a/target/board/generic_arm64/README.txt b/target/board/generic_arm64/README.txt
index 21c71d7..8711a14 100644
--- a/target/board/generic_arm64/README.txt
+++ b/target/board/generic_arm64/README.txt
@@ -1,5 +1,7 @@
The "generic_arm64" product defines a non-hardware-specific arm64 target
-without a kernel or bootloader.
+without a bootloader.
+
+It is also the target to build the generic kernel image (GKI).
It is not a product "base class"; no other products inherit
from it or use it in any way.
diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk
index d96bfc2..e64014b 100644
--- a/target/board/generic_arm64/device.mk
+++ b/target/board/generic_arm64/device.mk
@@ -15,11 +15,22 @@
#
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
+ kernel/prebuilts/4.19/arm64/kernel-4.19-gz:kernel-4.19-gz \
+ kernel/prebuilts/5.4/arm64/kernel-5.4:kernel-5.4 \
+ kernel/prebuilts/5.4/arm64/kernel-5.4-gz:kernel-5.4-gz \
+ kernel/prebuilts/5.4/arm64/kernel-5.4-lz4:kernel-5.4-lz4 \
+ kernel/prebuilts/mainline/arm64/kernel-mainline-allsyms:kernel-mainline \
+ kernel/prebuilts/mainline/arm64/kernel-mainline-gz-allsyms:kernel-mainline-gz \
+ kernel/prebuilts/mainline/arm64/kernel-mainline-lz4-allsyms: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 += \
+ kernel/prebuilts/5.4/arm64/kernel-5.4:kernel-5.4-allsyms \
+ kernel/prebuilts/5.4/arm64/kernel-5.4-gz:kernel-5.4-gz-allsyms \
+ kernel/prebuilts/5.4/arm64/kernel-5.4-lz4:kernel-5.4-lz4-allsyms
+endif
+
+PRODUCT_BUILD_VENDOR_BOOT_IMAGE := false
+PRODUCT_BUILD_RECOVERY_IMAGE := false
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
diff --git a/target/board/generic_arm64/sepolicy/OWNERS b/target/board/generic_arm64/sepolicy/OWNERS
index ff29677..6dc2b86 100644
--- a/target/board/generic_arm64/sepolicy/OWNERS
+++ b/target/board/generic_arm64/sepolicy/OWNERS
@@ -1,8 +1 @@
-alanstokes@google.com
-bowgotsai@google.com
-jbires@google.com
-jeffv@google.com
-jgalenson@google.com
-sspatil@google.com
-tomcherry@google.com
-trong@google.com
+include platform/system/sepolicy:/OWNERS
diff --git a/target/board/generic_arm64_ab/BoardConfig.mk b/target/board/generic_arm64_ab/BoardConfig.mk
deleted file mode 100644
index 7c91607..0000000
--- a/target/board/generic_arm64_ab/BoardConfig.mk
+++ /dev/null
@@ -1,39 +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.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_ARCH := arm64
-TARGET_ARCH_VARIANT := armv8-a
-TARGET_CPU_ABI := arm64-v8a
-TARGET_CPU_ABI2 :=
-TARGET_CPU_VARIANT := generic
-
-TARGET_2ND_ARCH := arm
-TARGET_2ND_ARCH_VARIANT := armv8-a
-TARGET_2ND_CPU_ABI := armeabi-v7a
-TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_CPU_VARIANT := generic
-
-# TODO(jiyong) These might be SoC specific.
-BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/image:/firmware/image
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/verinfo:/firmware/verinfo
-
-# TODO(b/36764215): remove this setting when the generic system image
-# no longer has QCOM-specific directories under /.
-BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64/sepolicy
diff --git a/target/board/generic_arm_ab/BoardConfig.mk b/target/board/generic_arm_ab/BoardConfig.mk
deleted file mode 100644
index 21b763c..0000000
--- a/target/board/generic_arm_ab/BoardConfig.mk
+++ /dev/null
@@ -1,36 +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.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_ARCH := arm
-TARGET_ARCH_VARIANT := armv7-a-neon
-TARGET_CPU_ABI := armeabi-v7a
-TARGET_CPU_ABI2 := armeabi
-TARGET_CPU_VARIANT := generic
-
-# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
-TARGET_USES_64_BIT_BINDER := false
-
-# TODO(jiyong) These might be SoC specific.
-BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/image:/firmware/image
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/verinfo:/firmware/verinfo
-
-# TODO(b/36764215): remove this setting when the generic system image
-# no longer has QCOM-specific directories under /.
-BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64/sepolicy
diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index 83d7ecc..c40c15b 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -21,6 +21,7 @@
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 @@
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 2b10a3d..5ad008f 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-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 07bbc07..660ec6e 100755
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -24,6 +24,7 @@
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 @@
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 2b10a3d..5ad008f 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-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_ab/BoardConfig.mk b/target/board/generic_x86_ab/BoardConfig.mk
deleted file mode 100644
index 53acffd..0000000
--- a/target/board/generic_x86_ab/BoardConfig.mk
+++ /dev/null
@@ -1,24 +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.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_CPU_ABI := x86
-TARGET_ARCH := x86
-TARGET_ARCH_VARIANT := x86
-
-# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
-TARGET_USES_64_BIT_BINDER := false
diff --git a/target/board/gsi_system_ext.prop b/target/board/gsi_system_ext.prop
index f085b61..780aadc 100644
--- a/target/board/gsi_system_ext.prop
+++ b/target/board/gsi_system_ext.prop
@@ -12,6 +12,3 @@
# 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_timeout_ms=100
diff --git a/target/board/gsi_system_ext_user.prop b/target/board/gsi_system_ext_user.prop
index de8c487..217bd01 100644
--- a/target/board/gsi_system_ext_user.prop
+++ b/target/board/gsi_system_ext_user.prop
@@ -9,6 +9,3 @@
# 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_timeout_ms=100
diff --git a/target/board/mainline_arm64/sepolicy/OWNERS b/target/board/mainline_arm64/sepolicy/OWNERS
index ff29677..6dc2b86 100644
--- a/target/board/mainline_arm64/sepolicy/OWNERS
+++ b/target/board/mainline_arm64/sepolicy/OWNERS
@@ -1,8 +1 @@
-alanstokes@google.com
-bowgotsai@google.com
-jbires@google.com
-jeffv@google.com
-jgalenson@google.com
-sspatil@google.com
-tomcherry@google.com
-trong@google.com
+include platform/system/sepolicy:/OWNERS
diff --git a/core/tasks/apidiff.mk b/target/board/mainline_sdk/BoardConfig.mk
similarity index 76%
copy from core/tasks/apidiff.mk
copy to target/board/mainline_sdk/BoardConfig.mk
index 76e4749..84f8b2d 100644
--- a/core/tasks/apidiff.mk
+++ b/target/board/mainline_sdk/BoardConfig.mk
@@ -1,4 +1,4 @@
-# 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.
@@ -11,11 +11,10 @@
# 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.
-
-#
-# Rules for building API diffs.
#
-.PHONY: api-diff
+TARGET_ARCH_SUITE := mainline_sdk
-api-diff: api-stubs-docs-jdiff
+HOST_CROSS_OS := linux_bionic
+HOST_CROSS_ARCH := x86_64
+HOST_CROSS_2ND_ARCH :=
diff --git a/target/board/mainline_sdk/README.md b/target/board/mainline_sdk/README.md
new file mode 100644
index 0000000..714f797
--- /dev/null
+++ b/target/board/mainline_sdk/README.md
@@ -0,0 +1,2 @@
+This device is suitable for a soong-only build that builds for all the architectures
+needed for mainline modules sdk prebuilts.
diff --git a/target/product/virtual_ab_ota.mk b/target/board/module_arm/BoardConfig.mk
similarity index 73%
copy from target/product/virtual_ab_ota.mk
copy to target/board/module_arm/BoardConfig.mk
index 1774de4..565efc8 100644
--- a/target/product/virtual_ab_ota.mk
+++ b/target/board/module_arm/BoardConfig.mk
@@ -1,5 +1,4 @@
-#
-# Copyright (C) 2019 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,8 +13,8 @@
# limitations under the License.
#
-PRODUCT_VIRTUAL_AB_OTA := true
-
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.enabled=true
-
-PRODUCT_PACKAGES += e2fsck_ramdisk
+TARGET_ARCH := arm
+TARGET_ARCH_VARIANT := armv7-a-neon
+TARGET_CPU_VARIANT := generic
+TARGET_CPU_ABI := armeabi-v7a
+TARGET_CPU_ABI2 := armeabi
diff --git a/target/board/module_arm/README.md b/target/board/module_arm/README.md
new file mode 100644
index 0000000..b893573
--- /dev/null
+++ b/target/board/module_arm/README.md
@@ -0,0 +1,2 @@
+This device is suitable for an unbundled module targeted specifically to an arm
+device.
diff --git a/target/product/virtual_ab_ota.mk b/target/board/module_arm/device.mk
similarity index 73%
copy from target/product/virtual_ab_ota.mk
copy to target/board/module_arm/device.mk
index 1774de4..7cac5f8 100644
--- a/target/product/virtual_ab_ota.mk
+++ b/target/board/module_arm/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,5 @@
# limitations under the License.
#
-PRODUCT_VIRTUAL_AB_OTA := true
-
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.enabled=true
-
-PRODUCT_PACKAGES += e2fsck_ramdisk
+$(call inherit-product, build/make/target/product/bootclasspath.mk)
+$(call inherit-product, build/make/target/product/languages_default.mk)
diff --git a/target/board/generic_x86_64_ab/BoardConfig.mk b/target/board/module_arm64/BoardConfig.mk
similarity index 63%
copy from target/board/generic_x86_64_ab/BoardConfig.mk
copy to target/board/module_arm64/BoardConfig.mk
index 1dd5e48..66e3792 100644
--- a/target/board/generic_x86_64_ab/BoardConfig.mk
+++ b/target/board/module_arm64/BoardConfig.mk
@@ -1,5 +1,4 @@
-#
-# 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 +13,13 @@
# limitations under the License.
#
-include build/make/target/board/BoardConfigGsiCommon.mk
+TARGET_ARCH := arm64
+TARGET_ARCH_VARIANT := armv8-a
+TARGET_CPU_VARIANT := generic
+TARGET_CPU_ABI := arm64-v8a
-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_2ND_ARCH := arm
+TARGET_2ND_ARCH_VARIANT := armv8-a
+TARGET_2ND_CPU_ABI := armeabi-v7a
+TARGET_2ND_CPU_ABI2 := armeabi
+TARGET_2ND_CPU_VARIANT := generic
diff --git a/target/board/module_arm64/README.md b/target/board/module_arm64/README.md
new file mode 100644
index 0000000..cb36fbf
--- /dev/null
+++ b/target/board/module_arm64/README.md
@@ -0,0 +1,3 @@
+This device is suitable for an unbundled module targeted specifically to an
+arm64 device. 32 bit binaries built with this product will not be suitable for a
+32-bit arm device.
diff --git a/target/product/virtual_ab_ota_retrofit.mk b/target/board/module_arm64/device.mk
similarity index 67%
copy from target/product/virtual_ab_ota_retrofit.mk
copy to target/board/module_arm64/device.mk
index 3e85741..9065d4b 100644
--- a/target/product/virtual_ab_ota_retrofit.mk
+++ b/target/board/module_arm64/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,6 @@
# limitations under the License.
#
-$(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
+$(call inherit-product, build/make/target/product/bootclasspath.mk)
+$(call inherit-product, build/make/target/product/core_64_bit.mk)
+$(call inherit-product, build/make/target/product/languages_default.mk)
diff --git a/core/tasks/apidiff.mk b/target/board/module_x86/BoardConfig.mk
similarity index 79%
copy from core/tasks/apidiff.mk
copy to target/board/module_x86/BoardConfig.mk
index 76e4749..af3fffd 100644
--- a/core/tasks/apidiff.mk
+++ b/target/board/module_x86/BoardConfig.mk
@@ -1,4 +1,4 @@
-# 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.
@@ -11,11 +11,8 @@
# 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.
-
-#
-# Rules for building API diffs.
#
-.PHONY: api-diff
-
-api-diff: api-stubs-docs-jdiff
+TARGET_CPU_ABI := x86
+TARGET_ARCH := x86
+TARGET_ARCH_VARIANT := x86
diff --git a/target/board/module_x86/README.md b/target/board/module_x86/README.md
new file mode 100644
index 0000000..10866b7
--- /dev/null
+++ b/target/board/module_x86/README.md
@@ -0,0 +1,2 @@
+This device is suitable for an unbundled module targeted specifically to an
+x86 device.
diff --git a/target/product/virtual_ab_ota.mk b/target/board/module_x86/device.mk
similarity index 73%
copy from target/product/virtual_ab_ota.mk
copy to target/board/module_x86/device.mk
index 1774de4..7cac5f8 100644
--- a/target/product/virtual_ab_ota.mk
+++ b/target/board/module_x86/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,5 @@
# limitations under the License.
#
-PRODUCT_VIRTUAL_AB_OTA := true
-
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.enabled=true
-
-PRODUCT_PACKAGES += e2fsck_ramdisk
+$(call inherit-product, build/make/target/product/bootclasspath.mk)
+$(call inherit-product, build/make/target/product/languages_default.mk)
diff --git a/target/board/generic_x86_64_ab/BoardConfig.mk b/target/board/module_x86_64/BoardConfig.mk
similarity index 86%
rename from target/board/generic_x86_64_ab/BoardConfig.mk
rename to target/board/module_x86_64/BoardConfig.mk
index 1dd5e48..1ada027 100644
--- a/target/board/generic_x86_64_ab/BoardConfig.mk
+++ b/target/board/module_x86_64/BoardConfig.mk
@@ -1,5 +1,4 @@
-#
-# 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,8 +13,6 @@
# limitations under the License.
#
-include build/make/target/board/BoardConfigGsiCommon.mk
-
TARGET_CPU_ABI := x86_64
TARGET_ARCH := x86_64
TARGET_ARCH_VARIANT := x86_64
diff --git a/target/board/module_x86_64/README.md b/target/board/module_x86_64/README.md
new file mode 100644
index 0000000..3377baa
--- /dev/null
+++ b/target/board/module_x86_64/README.md
@@ -0,0 +1,3 @@
+This device is suitable for an unbundled module targeted specifically to an
+x86_64 device. 32 bit binaries built with this product will not be suitable for
+a 32-bit x86 device.
diff --git a/target/product/virtual_ab_ota_retrofit.mk b/target/board/module_x86_64/device.mk
similarity index 67%
copy from target/product/virtual_ab_ota_retrofit.mk
copy to target/board/module_x86_64/device.mk
index 3e85741..9065d4b 100644
--- a/target/product/virtual_ab_ota_retrofit.mk
+++ b/target/board/module_x86_64/device.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2019 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,8 +14,6 @@
# limitations under the License.
#
-$(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
+$(call inherit-product, build/make/target/product/bootclasspath.mk)
+$(call inherit-product, build/make/target/product/core_64_bit.mk)
+$(call inherit-product, build/make/target/product/languages_default.mk)
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index e8231af..f657fbf 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -44,25 +44,24 @@
else
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/aosp_64bitonly_x86_64.mk \
- $(LOCAL_DIR)/aosp_arm64_ab.mk \
$(LOCAL_DIR)/aosp_arm64.mk \
- $(LOCAL_DIR)/aosp_arm_ab.mk \
$(LOCAL_DIR)/aosp_arm.mk \
- $(LOCAL_DIR)/aosp_x86_64_ab.mk \
$(LOCAL_DIR)/aosp_x86_64.mk \
- $(LOCAL_DIR)/aosp_x86_ab.mk \
$(LOCAL_DIR)/aosp_x86_arm.mk \
$(LOCAL_DIR)/aosp_x86.mk \
$(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 \
@@ -74,6 +73,8 @@
endif
+PRODUCT_MAKEFILES += $(LOCAL_DIR)/mainline_sdk.mk
+
COMMON_LUNCH_CHOICES := \
aosp_arm64-eng \
aosp_arm-eng \
diff --git a/target/product/OWNERS b/target/product/OWNERS
index 1c74859..259c8f4 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 0cec14b..90acc17 100644
--- a/target/product/aosp_arm.mk
+++ b/target/product/aosp_arm.mk
@@ -26,7 +26,7 @@
#
# 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 e88a366..38f82a2 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/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
deleted file mode 100644
index 75b9cc4..0000000
--- a/target/product/aosp_arm64_ab.mk
+++ /dev/null
@@ -1,58 +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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES 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.
-
-# aosp_arm64_ab-userdebug is a Legacy GSI for the devices with:
-# - ARM 64 bits user space
-# - 64 bits binder interface
-# - system-as-root
-
-#
-# All components inherited here go to system image
-# (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)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_arm64_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# 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)
-
-#
-# Special settings for GSI releasing
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_release.mk)
-
-PRODUCT_NAME := aosp_arm64_ab
-PRODUCT_DEVICE := generic_arm64_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM64
diff --git a/target/product/aosp_arm_ab.mk b/target/product/aosp_arm_ab.mk
deleted file mode 100644
index 80ebdb1..0000000
--- a/target/product/aosp_arm_ab.mk
+++ /dev/null
@@ -1,57 +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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES 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.
-
-# aosp_arm_ab-userdebug is a Legacy GSI for the devices with:
-# - ARM 32 bits user space
-# - 32 bits binder interface
-# - system-as-root
-
-#
-# 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)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_arm_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# 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)
-
-#
-# Special settings for GSI releasing
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_release.mk)
-
-PRODUCT_NAME := aosp_arm_ab
-PRODUCT_DEVICE := generic_arm_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM32
diff --git a/target/product/aosp_product.mk b/target/product/aosp_product.mk
index e3819e6..e396ad1 100644
--- a/target/product/aosp_product.mk
+++ b/target/product/aosp_product.mk
@@ -23,9 +23,9 @@
# 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 @@
# 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 51b5daf..7db2c0f 100644
--- a/target/product/aosp_x86.mk
+++ b/target/product/aosp_x86.mk
@@ -26,7 +26,7 @@
#
# 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 9b26716..5d78264 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -32,7 +32,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_x86_64,$(TARGET_PRODUCT))
diff --git a/target/product/aosp_x86_64_ab.mk b/target/product/aosp_x86_64_ab.mk
deleted file mode 100644
index 9d23fc7..0000000
--- a/target/product/aosp_x86_64_ab.mk
+++ /dev/null
@@ -1,58 +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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES 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.
-
-# aosp_x86_64_ab-userdebug is a Legacy GSI for the devices with:
-# - x86 64 bits user space
-# - 64 bits binder interface
-# - system-as-root
-
-#
-# All components inherited here go to system image
-# (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)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_x86_64_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# 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)
-
-#
-# Special settings for GSI releasing
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_release.mk)
-
-PRODUCT_NAME := aosp_x86_64_ab
-PRODUCT_DEVICE := generic_x86_64_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on x86_64
diff --git a/target/product/aosp_x86_ab.mk b/target/product/aosp_x86_ab.mk
deleted file mode 100644
index 6b6a4c6..0000000
--- a/target/product/aosp_x86_ab.mk
+++ /dev/null
@@ -1,58 +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.
-#
-
-# PRODUCT_PROPERTY_OVERRIDES 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.
-
-# aosp_x86_ab-userdebug is a Legacy GSI for the devices with:
-# - x86 32 bits user space
-# - 32 bits binder interface
-# - system-as-root
-
-#
-# All components inherited here go to system image
-# (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)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_x86_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-#
-# 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)
-
-#
-# Special settings for GSI releasing
-#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_release.mk)
-
-PRODUCT_NAME := aosp_x86_ab
-PRODUCT_DEVICE := generic_x86_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on x86
diff --git a/target/product/aosp_x86_arm.mk b/target/product/aosp_x86_arm.mk
index deba3d9..f96e068 100644
--- a/target/product/aosp_x86_arm.mk
+++ b/target/product/aosp_x86_arm.mk
@@ -19,7 +19,7 @@
#
# 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_product.mk b/target/product/base_product.mk
index 2ed550c..5446064 100644
--- a/target/product/base_product.mk
+++ b/target/product/base_product.mk
@@ -16,8 +16,11 @@
# Base modules and settings for the product partition.
PRODUCT_PACKAGES += \
+ fs_config_dirs_product \
+ fs_config_files_product \
group_product \
ModuleMetadata \
passwd_product \
product_compatibility_matrix.xml \
product_manifest.xml \
+ selinux_policy_product \
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 4569bce..2660d69 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -27,6 +27,7 @@
android.test.base \
android.test.mock \
android.test.runner \
+ ANGLE \
apexd \
appops \
app_process \
@@ -37,7 +38,6 @@
bcc \
blank_screen \
blkid \
- service-blobstore \
bmgr \
bootanimation \
bootstat \
@@ -51,6 +51,7 @@
cmd \
com.android.adbd \
com.android.conscrypt \
+ com.android.cronet \
com.android.extservices \
com.android.i18n \
com.android.ipsec \
@@ -68,7 +69,6 @@
com.android.wifi \
ContactsProvider \
content \
- crash_dump \
CtsShimPrebuilt \
CtsShimPrivPrebuilt \
debuggerd\
@@ -116,8 +116,8 @@
iptables \
ip-up-vpn \
javax.obex \
- service-jobscheduler \
keystore \
+ keystore2 \
credstore \
ld.mc \
libaaudio \
@@ -193,6 +193,7 @@
libwilhelm \
linker \
linkerconfig \
+ llkd \
lmkd \
LocalTransport \
locksettings \
@@ -212,7 +213,7 @@
mtpd \
ndc \
netd \
- NetworkStack \
+ NetworkStackNext \
org.apache.http.legacy \
otacerts \
PackageInstaller \
@@ -248,6 +249,7 @@
shell_and_utilities_system \
sm \
snapshotctl \
+ snapuserd \
SoundPicker \
storaged \
surfaceflinger \
@@ -279,6 +281,23 @@
system_manifest.xml \
system_compatibility_matrix.xml \
+# HWASAN runtime for SANITIZE_TARGET=hwaddress builds
+ifneq (,$(filter hwaddress,$(SANITIZE_TARGET)))
+ PRODUCT_PACKAGES += \
+ libclang_rt.hwasan-aarch64-android.bootstrap
+endif
+
+# Jacoco agent JARS to be built and installed, if any.
+ifeq ($(EMMA_INSTRUMENT),true)
+ ifneq ($(EMMA_INSTRUMENT_STATIC),true)
+ # For instrumented build, if Jacoco is not being included statically
+ # in instrumented packages then include Jacoco classes into the
+ # bootclasspath.
+ PRODUCT_PACKAGES += jacocoagent
+ PRODUCT_BOOT_JARS += jacocoagent
+ endif # EMMA_INSTRUMENT_STATIC
+endif # EMMA_INSTRUMENT
+
# Host tools to install
PRODUCT_HOST_PACKAGES += \
BugReport \
@@ -315,54 +334,25 @@
tz_version_host \
tz_version_host_tzdata_apex \
-ifeq ($(ART_APEX_JARS),)
-$(error ART_APEX_JARS is empty; cannot initialize PRODUCT_BOOT_JARS variable)
-endif
-
-# The order matters for runtime class lookup performance.
-PRODUCT_BOOT_JARS := \
- $(ART_APEX_JARS) \
- framework-minus-apex \
- ext \
- telephony-common \
- voip-common \
- ims-common
-
-PRODUCT_UPDATABLE_BOOT_JARS := \
- com.android.conscrypt:conscrypt \
- com.android.media:updatable-media \
- com.android.mediaprovider:framework-mediaprovider \
- com.android.os.statsd:framework-statsd \
- com.android.permission:framework-permission \
- com.android.sdkext:framework-sdkextensions \
- com.android.wifi:framework-wifi \
- com.android.tethering:framework-tethering
PRODUCT_COPY_FILES += \
system/core/rootdir/init.usb.rc:system/etc/init/hw/init.usb.rc \
system/core/rootdir/init.usb.configfs.rc:system/etc/init/hw/init.usb.configfs.rc \
system/core/rootdir/etc/hosts:system/etc/hosts
-# Add the compatibility library that is needed when android.test.base
-# is removed from the bootclasspath.
-# Default to excluding android.test.base from the bootclasspath.
-ifneq ($(REMOVE_ATB_FROM_BCP),false)
-PRODUCT_PACKAGES += framework-atb-backward-compatibility
-PRODUCT_BOOT_JARS += framework-atb-backward-compatibility
-else
-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_VENDOR_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 := \
adb_keys \
arping \
+ dmuserd \
gdbserver \
idlcli \
init-debug.rc \
@@ -372,6 +362,8 @@
logpersist.start \
logtagd.rc \
procrank \
+ profcollectd \
+ profcollectctl \
remount \
showmap \
sqlite3 \
@@ -408,4 +400,5 @@
PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,\
frameworks/base/config/dirty-image-objects:system/etc/dirty-image-objects)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/bootclasspath.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/runtime_libart.mk)
diff --git a/target/product/base_system_ext.mk b/target/product/base_system_ext.mk
index b67549a..852d7ca 100644
--- a/target/product/base_system_ext.mk
+++ b/target/product/base_system_ext.mk
@@ -16,6 +16,9 @@
# Base modules and settings for the system_ext partition.
PRODUCT_PACKAGES += \
+ fs_config_dirs_system_ext \
+ fs_config_files_system_ext \
group_system_ext \
- system_ext_manifest.xml \
passwd_system_ext \
+ selinux_policy_system_ext \
+ system_ext_manifest.xml \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 471340b..b955841 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -66,11 +66,11 @@
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/bootclasspath.mk b/target/product/bootclasspath.mk
new file mode 100644
index 0000000..60dd071
--- /dev/null
+++ b/target/product/bootclasspath.mk
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+ifeq ($(ART_APEX_JARS),)
+ $(error ART_APEX_JARS is empty; cannot initialize PRODUCT_BOOT_JARS variable)
+endif
+
+# The order matters for runtime class lookup performance.
+PRODUCT_BOOT_JARS := \
+ $(ART_APEX_JARS) \
+ framework-minus-apex \
+ ext \
+ com.android.i18n:core-icu4j \
+ telephony-common \
+ voip-common \
+ ims-common
+
+PRODUCT_UPDATABLE_BOOT_JARS := \
+ com.android.conscrypt:conscrypt \
+ com.android.media:updatable-media \
+ com.android.mediaprovider:framework-mediaprovider \
+ com.android.os.statsd:framework-statsd \
+ com.android.permission:framework-permission \
+ com.android.sdkext:framework-sdkextensions \
+ com.android.wifi:framework-wifi \
+ com.android.tethering:framework-tethering
+
+# Add the compatibility library that is needed when android.test.base
+# is removed from the bootclasspath.
+# Default to excluding android.test.base from the bootclasspath.
+ifneq ($(REMOVE_ATB_FROM_BCP),false)
+ PRODUCT_PACKAGES += framework-atb-backward-compatibility
+ PRODUCT_BOOT_JARS += framework-atb-backward-compatibility
+else
+ PRODUCT_BOOT_JARS += android.test.base
+endif
diff --git a/target/product/cfi-common.mk b/target/product/cfi-common.mk
index fe62f74..82f53f6 100644
--- a/target/product/cfi-common.mk
+++ b/target/product/cfi-common.mk
@@ -17,6 +17,7 @@
# This is a set of common components to enable CFI for (across
# compatible product configs)
PRODUCT_CFI_INCLUDE_PATHS := \
+ device/generic/goldfish/wifi/wpa_supplicant_8_lib \
device/google/cuttlefish/guest/libs/wpa_supplicant_8_lib \
external/tinyxml2 \
external/wpa_supplicant_8 \
@@ -27,7 +28,8 @@
hardware/broadcom/wlan/bcmdhd/wpa_supplicant_8_lib \
hardware/interfaces/nfc \
hardware/qcom/wlan/qcwcn/wpa_supplicant_8_lib \
- harware/interfaces/keymaster \
+ hardware/interfaces/keymaster \
+ hardware/interfaces/keymint \
system/bt \
system/chre \
system/core/libnetutils \
diff --git a/target/product/core_64_bit.mk b/target/product/core_64_bit.mk
index f9baa27..322fa80 100644
--- a/target/product/core_64_bit.mk
+++ b/target/product/core_64_bit.mk
@@ -27,7 +27,7 @@
# 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_VENDOR_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 8901a50..53c9c74 100644
--- a/target/product/core_64_bit_only.mk
+++ b/target/product/core_64_bit_only.mk
@@ -24,7 +24,7 @@
# 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_VENDOR_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 ea5d9ad..7d380d9 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 93c861f..36da1f7 100644
--- a/target/product/emulator.mk
+++ b/target/product/emulator.mk
@@ -47,7 +47,7 @@
#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 a935d58..4d46358 100644
--- a/target/product/emulator_vendor.mk
+++ b/target/product/emulator_vendor.mk
@@ -26,7 +26,7 @@
PRODUCT_PACKAGES += \
vndk-sp
-PRODUCT_PACKAGE_OVERLAYS := device/generic/goldfish/overlay
+DEVICE_PACKAGE_OVERLAYS := device/generic/goldfish/overlay
PRODUCT_CHARACTERISTICS := emulator
@@ -39,7 +39,7 @@
#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 b356f9d..adb54ab 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 ffd3cde..a8e1e91 100644
--- a/target/product/full_base.mk
+++ b/target/product/full_base.mk
@@ -43,9 +43,9 @@
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 af4097d..d8a54cd 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 55c450a..2f40c03 100644
--- a/target/product/full_x86.mk
+++ b/target/product/full_x86.mk
@@ -28,7 +28,7 @@
$(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_ramdisk.mk b/target/product/generic_ramdisk.mk
new file mode 100644
index 0000000..ae81329
--- /dev/null
+++ b/target/product/generic_ramdisk.mk
@@ -0,0 +1,39 @@
+#
+# 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 makefile installs contents of the generic ramdisk.
+# Inherit from this makefile to declare that this product uses generic ramdisk.
+# This makefile checks that other makefiles must not install things to the
+# ramdisk.
+
+# Ramdisk
+PRODUCT_PACKAGES += \
+ init_first_stage \
+
+# Debug ramdisk
+PRODUCT_PACKAGES += \
+ userdebug_plat_sepolicy.cil \
+
+_my_paths := \
+ $(TARGET_COPY_OUT_RAMDISK)/ \
+ $(TARGET_COPY_OUT_DEBUG_RAMDISK)/ \
+ system/usr/share/zoneinfo/tz_version \
+ system/usr/share/zoneinfo/tzdata \
+
+# We use the "relaxed" version here because tzdata / tz_version is only produced
+# by this makefile on a subset of devices.
+# TODO: remove this
+$(call require-artifacts-in-path-relaxed, $(_my_paths), )
diff --git a/target/product/mainline_system.mk b/target/product/generic_system.mk
similarity index 94%
rename from target/product/mainline_system.mk
rename to target/product/generic_system.mk
index a787707..9580ade 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/generic_system.mk
@@ -34,14 +34,10 @@
PartnerBookmarksProvider \
PresencePolling \
RcsService \
- SafetyRegulatoryInfo \
Stk \
Tag \
TimeZoneUpdater \
-# Binaries
-PRODUCT_PACKAGES += llkd
-
# OTA support
PRODUCT_PACKAGES += \
recovery-refresh \
@@ -99,20 +95,25 @@
PRODUCT_PACKAGES_DEBUG += \
avbctl \
bootctl \
- tinyplay \
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.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
@@ -120,11 +121,11 @@
PRODUCT_ENFORCE_RRO_TARGETS := *
-PRODUCT_NAME := mainline_system
+PRODUCT_NAME := generic_system
PRODUCT_BRAND := generic
# Define /system partition-specific product properties to identify that /system
-# partition is mainline_system.
+# partition is generic_system.
PRODUCT_SYSTEM_NAME := mainline
PRODUCT_SYSTEM_BRAND := Android
PRODUCT_SYSTEM_MANUFACTURER := Android
diff --git a/target/product/generic_system_arm64.mk b/target/product/generic_system_arm64.mk
new file mode 100644
index 0000000..2c64479
--- /dev/null
+++ b/target/product/generic_system_arm64.mk
@@ -0,0 +1,43 @@
+#
+# 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
+
+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 0000000..cf38a98
--- /dev/null
+++ b/target/product/generic_system_x86.mk
@@ -0,0 +1,42 @@
+#
+# 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
+
+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 0000000..5f3829b
--- /dev/null
+++ b/target/product/generic_system_x86_64.mk
@@ -0,0 +1,43 @@
+#
+# 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_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 0000000..923f32d
--- /dev/null
+++ b/target/product/generic_system_x86_arm.mk
@@ -0,0 +1,42 @@
+#
+# 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
+
+PRODUCT_NAME := generic_system_x86_arm
+PRODUCT_DEVICE := mainline_x86_arm
+PRODUCT_BRAND := generic
diff --git a/target/product/generic_x86.mk b/target/product/generic_x86.mk
index 0274b5b..eeb8216 100644
--- a/target/product/generic_x86.mk
+++ b/target/product/generic_x86.mk
@@ -17,7 +17,7 @@
# This is a generic phone product that isn't specialized for a specific device.
# It includes the base Android platform.
-include $(SRC_TARGET_DIR)/product/generic.mk
+$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
# Overrides
PRODUCT_BRAND := generic_x86
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index ca171df..7f19615 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 c491d4a..b4df5fe 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -31,10 +31,6 @@
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_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 0589517..2205146 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -18,8 +18,9 @@
LLNDK: libsync.so
LLNDK: libvndksupport.so
LLNDK: libvulkan.so
-VNDK-SP: android.hardware.common-V1-ndk_platform.so
-VNDK-SP: android.hardware.graphics.common-V1-ndk_platform.so
+VNDK-SP: android.hardware.common-V2-ndk_platform.so
+VNDK-SP: android.hardware.common.fmq-V1-ndk_platform.so
+VNDK-SP: android.hardware.graphics.common-V2-ndk_platform.so
VNDK-SP: android.hardware.graphics.common@1.0.so
VNDK-SP: android.hardware.graphics.common@1.1.so
VNDK-SP: android.hardware.graphics.common@1.2.so
@@ -42,6 +43,7 @@
VNDK-SP: libc++.so
VNDK-SP: libcompiler_rt.so
VNDK-SP: libcutils.so
+VNDK-SP: libdmabufheap.so
VNDK-SP: libgralloctypes.so
VNDK-SP: libhardware.so
VNDK-SP: libhidlbase.so
@@ -54,197 +56,35 @@
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-V1-ndk_platform.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.security.keymint-V1-ndk_platform.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.keystore2-V1-ndk_platform.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 c6faba7..f482843 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 00dd576..0000000
--- 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 d464a2f..0000000
--- 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 0000000..efeef11
--- /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 adf7ca5..1043a85 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 d3521fc..241b6ba 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 @@
# 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 77c103d..c2608c4 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -43,7 +43,6 @@
CaptivePortalLogin \
CertInstaller \
clatd \
- clatd.conf \
DocumentsUI \
DownloadProviderUi \
EasterEgg \
@@ -83,7 +82,7 @@
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
deleted file mode 100644
index c1646bb..0000000
--- a/target/product/legacy_gsi_release.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# 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.
-#
-
-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 22436e6..0000000
--- 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 52b3222..0000000
--- 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/core/tasks/apidiff.mk b/target/product/mainline_sdk.mk
similarity index 79%
rename from core/tasks/apidiff.mk
rename to target/product/mainline_sdk.mk
index 76e4749..343aed6 100644
--- a/core/tasks/apidiff.mk
+++ b/target/product/mainline_sdk.mk
@@ -1,4 +1,4 @@
-# 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.
@@ -11,11 +11,8 @@
# 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.
-
-#
-# Rules for building API diffs.
#
-.PHONY: api-diff
-
-api-diff: api-stubs-docs-jdiff
+PRODUCT_NAME := mainline_sdk
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := mainline_sdk
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
new file mode 120000
index 0000000..0b6eaf0
--- /dev/null
+++ b/target/product/mainline_system.mk
@@ -0,0 +1 @@
+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 679af0a..5fa13ce 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,)
+# 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
-# 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
-
-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 e1f862c..3fb1963 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,)
+# 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
-# 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
-
-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 8806d3e..eab99c5 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,)
+# 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
-# 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
-
-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 04fb652..483fb58 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,)
+# 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
-# 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
-
-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 4d507b5..4ebec51 100644
--- a/target/product/media_system.mk
+++ b/target/product/media_system.mk
@@ -73,11 +73,11 @@
# 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/media_vendor.mk b/target/product/media_vendor.mk
index 7d4af64..ef009ad 100644
--- a/target/product/media_vendor.mk
+++ b/target/product/media_vendor.mk
@@ -23,4 +23,3 @@
# /vendor packages
PRODUCT_PACKAGES += \
libaudiopreprocessing \
- libwebrtc_audio_preprocessing \
diff --git a/target/product/profile_boot_common.mk b/target/product/profile_boot_common.mk
index a40b3e9..fa2e163 100644
--- a/target/product/profile_boot_common.mk
+++ b/target/product/profile_boot_common.mk
@@ -23,7 +23,7 @@
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 ad361dc..687e9f6 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -30,8 +30,8 @@
# ART APEX module.
# Note that this package includes the minimal boot classpath JARs (listed in
# ART_APEX_JARS), which should no longer be added directly to PRODUCT_PACKAGES.
-PRODUCT_PACKAGES += com.android.art
-PRODUCT_HOST_PACKAGES += com.android.art
+PRODUCT_PACKAGES += com.android.art-autoselect
+PRODUCT_HOST_PACKAGES += com.android.art-autoselect
# Certificates.
PRODUCT_PACKAGES += \
@@ -40,7 +40,7 @@
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,51 @@
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.install-fast?=skip \
+ pm.dexopt.install-bulk?=speed-profile \
+ pm.dexopt.install-bulk-secondary?=verify \
+ pm.dexopt.install-bulk-downgraded?=verify \
+ pm.dexopt.install-bulk-secondary-downgraded?=extract \
+ 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 += \
- 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 3ab0c57..761de05 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 @@
# 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 77b8b50..5081a87 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 @@
# 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 9df26a9..9096ff3 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,16 +47,14 @@
#
$(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
--include development/build/product_sdk.mk
+$(call inherit-product-if-exists, sdk/build/product_sdk.mk)
+$(call inherit-product-if-exists, development/build/product_sdk.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 862c66e..161043b 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,14 +48,14 @@
#
$(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
--include development/build/product_sdk.mk
+$(call inherit-product-if-exists, sdk/build/product_sdk.mk)
+$(call inherit-product-if-exists, development/build/product_sdk.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 a84a0d2..c8dc8b0 100644
--- a/target/product/updatable_apex.mk
+++ b/target/product/updatable_apex.mk
@@ -20,6 +20,6 @@
# 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 3f881af..f235d14 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
new file mode 120000
index 0000000..16f7329
--- /dev/null
+++ b/target/product/virtual_ab_ota.mk
@@ -0,0 +1 @@
+virtual_ab_ota/launch.mk
\ No newline at end of file
diff --git a/target/product/virtual_ab_ota/README.md b/target/product/virtual_ab_ota/README.md
new file mode 100644
index 0000000..2d40c03
--- /dev/null
+++ b/target/product/virtual_ab_ota/README.md
@@ -0,0 +1,16 @@
+# Virtual A/B makefiles
+
+Devices that uses Virtual A/B must inherit from one of the makefiles in this directory.
+
+## Structure
+
+```
+launch.mk
+ |- retrofit.mk
+ |- plus_non_ab.mk
+
+launch_with_vendor_ramdisk.mk
+ |- compression.mk
+
+compression_retrofit.mk
+```
diff --git a/target/product/virtual_ab_ota_plus_non_ab.mk b/target/product/virtual_ab_ota/compression.mk
similarity index 77%
copy from target/product/virtual_ab_ota_plus_non_ab.mk
copy to target/product/virtual_ab_ota/compression.mk
index 325d75e..b9f3fc8 100644
--- a/target/product/virtual_ab_ota_plus_non_ab.mk
+++ b/target/product/virtual_ab_ota/compression.mk
@@ -14,8 +14,11 @@
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk)
-PRODUCT_OTA_FORCE_NON_AB_PACKAGE := true
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.allow_non_ab=true
+PRODUCT_PACKAGES += \
+ snapuserd.vendor_ramdisk \
+ snapuserd \
+ snapuserd.recovery
diff --git a/target/product/virtual_ab_ota/compression_retrofit.mk b/target/product/virtual_ab_ota/compression_retrofit.mk
new file mode 100644
index 0000000..5da8b54
--- /dev/null
+++ b/target/product/virtual_ab_ota/compression_retrofit.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_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
+
+# For devices that are not GKI-capable (eg do not have vendor_boot),
+# snapuserd.ramdisk is included rather than snapuserd.vendor_ramdisk.
+# When using virtual_ab_ota_compression_retrofit.mk, either
+# virtual_ab_ota.mk or virtual_ab_ota_retrofit.mk must be inherited
+# as well.
+PRODUCT_PACKAGES += \
+ snapuserd.ramdisk \
+ snapuserd \
+ snapuserd.recovery
diff --git a/target/product/virtual_ab_ota.mk b/target/product/virtual_ab_ota/launch.mk
similarity index 91%
rename from target/product/virtual_ab_ota.mk
rename to target/product/virtual_ab_ota/launch.mk
index 1774de4..e4c4575 100644
--- a/target/product/virtual_ab_ota.mk
+++ b/target/product/virtual_ab_ota/launch.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/launch_with_vendor_ramdisk.mk
similarity index 66%
copy from target/product/virtual_ab_ota_plus_non_ab.mk
copy to target/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk
index 325d75e..bc81b33 100644
--- a/target/product/virtual_ab_ota_plus_non_ab.mk
+++ b/target/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk
@@ -14,8 +14,13 @@
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
+# Devices launching with Virtual A/B and has a vendor_boot partition is
+# preferred to inherit from this makefile instead of launch.mk.
-PRODUCT_OTA_FORCE_NON_AB_PACKAGE := true
+PRODUCT_VIRTUAL_AB_OTA := true
-PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.allow_non_ab=true
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.enabled=true
+
+PRODUCT_PACKAGES += \
+ linker.vendor_ramdisk \
+ e2fsck.vendor_ramdisk \
diff --git a/target/product/virtual_ab_ota_plus_non_ab.mk b/target/product/virtual_ab_ota/plus_non_ab.mk
similarity index 90%
rename from target/product/virtual_ab_ota_plus_non_ab.mk
rename to target/product/virtual_ab_ota/plus_non_ab.mk
index 325d75e..820fa1e 100644
--- a/target/product/virtual_ab_ota_plus_non_ab.mk
+++ b/target/product/virtual_ab_ota/plus_non_ab.mk
@@ -14,8 +14,8 @@
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch.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
similarity index 90%
rename from target/product/virtual_ab_ota_retrofit.mk
rename to target/product/virtual_ab_ota/retrofit.mk
index 3e85741..93b42b7 100644
--- a/target/product/virtual_ab_ota_retrofit.mk
+++ b/target/product/virtual_ab_ota/retrofit.mk
@@ -14,8 +14,8 @@
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch.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/target/product/virtual_ab_ota_plus_non_ab.mk b/target/product/virtual_ab_ota_plus_non_ab.mk
new file mode 120000
index 0000000..4979957
--- /dev/null
+++ b/target/product/virtual_ab_ota_plus_non_ab.mk
@@ -0,0 +1 @@
+virtual_ab_ota/plus_non_ab.mk
\ No newline at end of file
diff --git a/target/product/virtual_ab_ota_retrofit.mk b/target/product/virtual_ab_ota_retrofit.mk
new file mode 120000
index 0000000..1e16ca8
--- /dev/null
+++ b/target/product/virtual_ab_ota_retrofit.mk
@@ -0,0 +1 @@
+virtual_ab_ota/retrofit.mk
\ No newline at end of file
diff --git a/tools/Android.bp b/tools/Android.bp
index 8c7eb38..e0f3739 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -24,3 +24,55 @@
},
},
}
+
+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 673e06f..0000000
--- 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 de855c6..1ff8e65 100755
--- a/tools/check_elf_file.py
+++ b/tools/check_elf_file.py
@@ -174,7 +174,7 @@
@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()
@@ -207,8 +207,8 @@
def _parse_llvm_readobj(cls, elf_file_path, header, lines):
"""Parse the output of llvm-readobj."""
lines_it = iter(lines)
- imported, exported = cls._parse_dynamic_symbols(lines_it)
dt_soname, dt_needed = cls._parse_dynamic_table(elf_file_path, lines_it)
+ imported, exported = cls._parse_dynamic_symbols(lines_it)
return ELF(dt_soname, dt_needed, imported, exported, header)
@@ -397,7 +397,7 @@
sys.exit(2)
- def check_dt_needed(self):
+ def check_dt_needed(self, system_shared_lib_names):
"""Check whether all DT_NEEDED entries are specified in the build
system."""
@@ -417,6 +417,11 @@
dt_needed = sorted(set(self._file_under_test.dt_needed))
modules = [re.sub('\\.so$', '', lib) for lib in dt_needed]
+ # Remove system shared libraries from the suggestion since they are added
+ # by default.
+ modules = [name for name in modules
+ if name not in system_shared_lib_names]
+
self._note()
self._note('Fix suggestions:')
self._note(
@@ -502,6 +507,11 @@
parser.add_argument('--shared-lib', action='append', default=[],
help='Path to shared library dependencies')
+ # System Shared library names
+ parser.add_argument('--system-shared-lib', action='append', default=[],
+ help='System shared libraries to be hidden from fix '
+ 'suggestions')
+
# Check options
parser.add_argument('--skip-bad-elf-magic', action='store_true',
help='Ignore the input file without the ELF magic word')
@@ -535,7 +545,7 @@
if args.soname:
checker.check_dt_soname(args.soname)
- checker.check_dt_needed()
+ checker.check_dt_needed(args.system_shared_lib)
if not args.allow_undefined_symbols:
checker.check_symbols()
diff --git a/tools/check_identical_lib.sh b/tools/check_identical_lib.sh
index c3aa41a..c9f436f 100755
--- a/tools/check_identical_lib.sh
+++ b/tools/check_identical_lib.sh
@@ -26,7 +26,19 @@
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 66a0f18..0000000
--- 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 e84328b..0000000
--- 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 cd610f7..0000000
--- 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 036c0eb..0000000
--- 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 7912e34..0000000
--- 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 3ba8486..0000000
--- 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
deleted file mode 100644
index 6cd03a3..0000000
--- a/tools/droiddoc/templates-ndk/assets/images/icon_more.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-ndk/assets/images/icon_search.png b/tools/droiddoc/templates-ndk/assets/images/icon_search.png
deleted file mode 100644
index ee90a12..0000000
--- a/tools/droiddoc/templates-ndk/assets/images/icon_search.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-ndk/assets/images/more_bottom.png b/tools/droiddoc/templates-ndk/assets/images/more_bottom.png
deleted file mode 100644
index 632546a..0000000
--- a/tools/droiddoc/templates-ndk/assets/images/more_bottom.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-ndk/assets/images/more_mid.png b/tools/droiddoc/templates-ndk/assets/images/more_mid.png
deleted file mode 100644
index 99bc999..0000000
--- a/tools/droiddoc/templates-ndk/assets/images/more_mid.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-ndk/assets/images/more_top.png b/tools/droiddoc/templates-ndk/assets/images/more_top.png
deleted file mode 100644
index 8ead1d3..0000000
--- a/tools/droiddoc/templates-ndk/assets/images/more_top.png
+++ /dev/null
Binary files differ
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 a67b5b0..0000000
--- 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 192d219..0000000
--- 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 eef5ad7..0000000
--- 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 e55ac31..0000000
--- 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 405892d..0000000
--- 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 01d0e55..0000000
--- 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 808bc81..0000000
--- 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 9411b78..0000000
--- 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 2be179d..0000000
--- 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 fa6dde6..0000000
--- 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 b609d3b..0000000
--- 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 6f33d88..0000000
--- 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 66b7d55..0000000
--- 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 d9dca8b..0000000
--- 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 e8301be..0000000
--- 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 38c9da8..0000000
--- 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 417a5c1..0000000
--- 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 0a94598..0000000
--- 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 73aa199..0000000
--- 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 8e59693..0000000
--- 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 2225565..0000000
--- 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 5056d3a..0000000
--- 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 32a0788..0000000
--- 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 1bacb53..0000000
--- 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 24ac7b7..0000000
--- 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 ffad465..0000000
--- 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 4bf502a..0000000
--- 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 337f8d3..0000000
--- 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 8ca11d1..0046b38 100755
--- a/tools/extract_kernel.py
+++ b/tools/extract_kernel.py
@@ -40,10 +40,10 @@
# 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 @@
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 @@
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 @@
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 @@
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 64fabe6..c338462 100644
--- a/tools/fs_config/Android.mk
+++ b/tools/fs_config/Android.mk
@@ -24,16 +24,16 @@
$(error Using $(TARGET_DEVICE_DIR)/android_filesystem_config.h is deprecated, please use TARGET_FS_CONFIG_GEN instead)
endif
-system_android_filesystem_config := system/core/include/private/android_filesystem_config.h
+system_android_filesystem_config := system/core/libcutils/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_PRODUCTIMAGE_FILE_SYSTEM_TYPE),product) \
- $(if $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),system_ext) \
+ $(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) \
)
##################################
@@ -43,11 +43,12 @@
LOCAL_MODULE := fs_config_dirs
LOCAL_REQUIRED_MODULES := \
- fs_config_dirs_system \
- $(foreach t,$(fs_config_generate_extra_partition_list),$(LOCAL_MODULE)_$(t))
+ fs_config_dirs_system \
+ fs_config_dirs_system_ext \
+ fs_config_dirs_product \
+ fs_config_dirs_nonsystem
include $(BUILD_PHONY_PACKAGE)
-
##################################
# Generate the <p>/etc/fs_config_files binary files for each partition.
# Add fs_config_files to PRODUCT_PACKAGES in the device make file to enable.
@@ -56,27 +57,69 @@
LOCAL_MODULE := fs_config_files
LOCAL_REQUIRED_MODULES := \
fs_config_files_system \
- $(foreach t,$(fs_config_generate_extra_partition_list),$(LOCAL_MODULE)_$(t))
+ fs_config_files_system_ext \
+ fs_config_files_product \
+ fs_config_files_nonsystem
+include $(BUILD_PHONY_PACKAGE)
+
+##################################
+# Generate the system_ext/etc/fs_config_dirs binary file for the target if the
+# system_ext partition is generated. Add fs_config_dirs or fs_config_dirs_system_ext
+# to PRODUCT_PACKAGES in the device make file to enable.
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := fs_config_dirs_system_ext
+LOCAL_REQUIRED_MODULES := $(if $(BOARD_USES_SYSTEM_EXTIMAGE)$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),_fs_config_dirs_system_ext)
+include $(BUILD_PHONY_PACKAGE)
+
+##################################
+# Generate the system_ext/etc/fs_config_files binary file for the target if the
+# system_ext partition is generated. Add fs_config_files or fs_config_files_system_ext
+# to PRODUCT_PACKAGES in the device make file to enable.
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := fs_config_files_system_ext
+LOCAL_REQUIRED_MODULES := $(if $(BOARD_USES_SYSTEM_EXTIMAGE)$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),_fs_config_files_system_ext)
+include $(BUILD_PHONY_PACKAGE)
+
+##################################
+# Generate the product/etc/fs_config_dirs binary file for the target if the
+# product partition is generated. Add fs_config_dirs or fs_config_dirs_product
+# to PRODUCT_PACKAGES in the device make file to enable.
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := fs_config_dirs_product
+LOCAL_REQUIRED_MODULES := $(if $(BOARD_USES_PRODUCTIMAGE)$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),_fs_config_dirs_product)
+include $(BUILD_PHONY_PACKAGE)
+
+##################################
+# Generate the product/etc/fs_config_files binary file for the target if the
+# product partition is generated. Add fs_config_files or fs_config_files_product
+# to PRODUCT_PACKAGES in the device make file to enable.
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := fs_config_files_product
+LOCAL_REQUIRED_MODULES := $(if $(BOARD_USES_PRODUCTIMAGE)$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),_fs_config_files_product)
include $(BUILD_PHONY_PACKAGE)
##################################
# Generate the <p>/etc/fs_config_dirs binary files for all enabled partitions
-# excluding /system. Add fs_config_dirs_nonsystem to PRODUCT_PACKAGES in the
-# device make file to enable.
+# excluding /system, /system_ext and /product. Add fs_config_dirs_nonsystem to
+# PRODUCT_PACKAGES in the device make file to enable.
include $(CLEAR_VARS)
LOCAL_MODULE := fs_config_dirs_nonsystem
-LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),fs_config_dirs_$(t))
+LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),_fs_config_dirs_$(t))
include $(BUILD_PHONY_PACKAGE)
##################################
# Generate the <p>/etc/fs_config_files binary files for all enabled partitions
-# excluding /system. Add fs_config_files_nonsystem to PRODUCT_PACKAGES in the
-# device make file to enable.
+# excluding /system, /system_ext and /product. Add fs_config_files_nonsystem to
+# PRODUCT_PACKAGES in the device make file to enable.
include $(CLEAR_VARS)
LOCAL_MODULE := fs_config_files_nonsystem
-LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),fs_config_files_$(t))
+LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),_fs_config_files_$(t))
include $(BUILD_PHONY_PACKAGE)
##################################
@@ -132,11 +175,11 @@
ifneq ($(filter vendor,$(fs_config_generate_extra_partition_list)),)
##################################
# Generate the vendor/etc/fs_config_dirs binary file for the target
-# Add fs_config_dirs or fs_config_dirs_vendor to PRODUCT_PACKAGES in
-# the device make file to enable.
+# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES
+# in the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_dirs_vendor
+LOCAL_MODULE := _fs_config_dirs_vendor
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc
@@ -156,11 +199,11 @@
##################################
# Generate the vendor/etc/fs_config_files binary file for the target
-# Add fs_config_files or fs_config_files_vendor to PRODUCT_PACKAGES in
-# the device make file to enable
+# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES
+# in the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_files_vendor
+LOCAL_MODULE := _fs_config_files_vendor
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_files
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc
@@ -183,11 +226,11 @@
ifneq ($(filter oem,$(fs_config_generate_extra_partition_list)),)
##################################
# Generate the oem/etc/fs_config_dirs binary file for the target
-# Add fs_config_dirs or fs_config_dirs_oem to PRODUCT_PACKAGES in
-# the device make file to enable
+# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES
+# in the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_dirs_oem
+LOCAL_MODULE := _fs_config_dirs_oem
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc
@@ -207,11 +250,11 @@
##################################
# Generate the oem/etc/fs_config_files binary file for the target
-# Add fs_config_files or fs_config_files_oem to PRODUCT_PACKAGES in
-# the device make file to enable
+# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES
+# in the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_files_oem
+LOCAL_MODULE := _fs_config_files_oem
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_files
LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc
@@ -234,11 +277,11 @@
ifneq ($(filter odm,$(fs_config_generate_extra_partition_list)),)
##################################
# Generate the odm/etc/fs_config_dirs binary file for the target
-# Add fs_config_dirs or fs_config_dirs_odm to PRODUCT_PACKAGES in
-# the device make file to enable
+# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES
+# in the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_dirs_odm
+LOCAL_MODULE := _fs_config_dirs_odm
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc
@@ -258,11 +301,11 @@
##################################
# Generate the odm/etc/fs_config_files binary file for the target
-# Add fs_config_files of fs_config_files_odm to PRODUCT_PACKAGES in
-# the device make file to enable
+# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES
+# in the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_files_odm
+LOCAL_MODULE := _fs_config_files_odm
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_files
LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc
@@ -282,14 +325,116 @@
endif
-ifneq ($(filter product,$(fs_config_generate_extra_partition_list)),)
+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_nonsystem 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 or fs_config_files_nonsystem 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_nonsystem 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 or fs_config_files_nonsystem 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 ($(BOARD_USES_PRODUCTIMAGE)$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),)
##################################
# Generate the product/etc/fs_config_dirs binary file for the target
# Add fs_config_dirs or fs_config_dirs_product to PRODUCT_PACKAGES in
# the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_dirs_product
+LOCAL_MODULE := _fs_config_dirs_product
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc
@@ -309,11 +454,11 @@
##################################
# Generate the product/etc/fs_config_files binary file for the target
-# Add fs_config_files of fs_config_files_product to PRODUCT_PACKAGES in
+# Add fs_config_files or fs_config_files_product to PRODUCT_PACKAGES in
# the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_files_product
+LOCAL_MODULE := _fs_config_files_product
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_files
LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc
@@ -332,14 +477,14 @@
$(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
endif
-ifneq ($(filter system_ext,$(fs_config_generate_extra_partition_list)),)
+ifneq ($(BOARD_USES_SYSTEM_EXTIMAGE)$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),)
##################################
# Generate the system_ext/etc/fs_config_dirs binary file for the target
# Add fs_config_dirs or fs_config_dirs_system_ext to PRODUCT_PACKAGES in
# the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_dirs_system_ext
+LOCAL_MODULE := _fs_config_dirs_system_ext
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc
@@ -359,11 +504,11 @@
##################################
# Generate the system_ext/etc/fs_config_files binary file for the target
-# Add fs_config_files of fs_config_files_system_ext to PRODUCT_PACKAGES in
+# Add fs_config_files or fs_config_files_system_ext to PRODUCT_PACKAGES in
# the device make file to enable
include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_files_system_ext
+LOCAL_MODULE := _fs_config_files_system_ext
LOCAL_MODULE_CLASS := ETC
LOCAL_INSTALLED_MODULE_STEM := fs_config_files
LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc
diff --git a/tools/fs_config/OWNERS b/tools/fs_config/OWNERS
index 5599644..7529cb9 100644
--- a/tools/fs_config/OWNERS
+++ b/tools/fs_config/OWNERS
@@ -1,2 +1 @@
-tomcherry@google.com
-salyzyn@google.com
+include platform/system/core:/janitors/OWNERS
diff --git a/tools/fs_config/README b/tools/fs_config/README
deleted file mode 100644
index 21bdeb8..0000000
--- 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 0000000..bad5e10
--- /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/end_to_end_test/run_test.sh b/tools/fs_config/end_to_end_test/run_test.sh
index 7402276..b5a7e83 100755
--- a/tools/fs_config/end_to_end_test/run_test.sh
+++ b/tools/fs_config/end_to_end_test/run_test.sh
@@ -1,7 +1,7 @@
cd $ANDROID_BUILD_TOP/build/make/tools/fs_config/end_to_end_test
$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
- --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+ --aid-header $ANDROID_BUILD_TOP/system/core/libcutils/include/private/android_filesystem_config.h \
--capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
--partition system \
--all-partitions vendor,product \
@@ -13,7 +13,7 @@
echo 'Fail: Mismatch between system_fs_config_files and result_system_fs_config_files'
$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
- --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+ --aid-header $ANDROID_BUILD_TOP/system/core/libcutils/include/private/android_filesystem_config.h \
--capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
--partition system \
--all-partitions vendor,product \
@@ -25,7 +25,7 @@
echo 'Fail: Mismatch between system_fs_config_dirs and result_system_fs_config_dirs'
$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
- --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+ --aid-header $ANDROID_BUILD_TOP/system/core/libcutils/include/private/android_filesystem_config.h \
--capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
--partition vendor \
--files \
@@ -36,7 +36,7 @@
echo 'Fail: Mismatch between vendor_fs_config_files and result_vendor_fs_config_files'
$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
- --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+ --aid-header $ANDROID_BUILD_TOP/system/core/libcutils/include/private/android_filesystem_config.h \
--capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
--partition vendor \
--dirs \
@@ -47,7 +47,7 @@
echo 'Fail: Mismatch between vendor_fs_config_dirs and result_vendor_fs_config_dirs'
$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
- --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+ --aid-header $ANDROID_BUILD_TOP/system/core/libcutils/include/private/android_filesystem_config.h \
--capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
--partition product \
--files \
@@ -58,7 +58,7 @@
echo 'Fail: Mismatch between product_fs_config_files and result_product_fs_config_files'
$ANDROID_BUILD_TOP/build/make/tools/fs_config/fs_config_generator.py fsconfig \
- --aid-header $ANDROID_BUILD_TOP/system/core/include/private/android_filesystem_config.h \
+ --aid-header $ANDROID_BUILD_TOP/system/core/libcutils/include/private/android_filesystem_config.h \
--capability-header $ANDROID_BUILD_TOP/bionic/libc/kernel/uapi/linux/capability.h \
--partition product \
--dirs \
diff --git a/tools/fs_config/fs_config.c b/tools/fs_config/fs_config.c
index 2952875..2a75add 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.go b/tools/fs_config/fs_config.go
index 16bcefa..4c324fb 100644
--- a/tools/fs_config/fs_config.go
+++ b/tools/fs_config/fs_config.go
@@ -48,10 +48,10 @@
path := android.PathForModuleGen(ctx, "empty")
t.paths = android.Paths{path}
- rule := android.NewRuleBuilder()
+ rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().Text("rm -rf").Output(path)
rule.Command().Text("touch").Output(path)
- rule.Build(pctx, ctx, "fs_config_empty", "create empty file")
+ rule.Build("fs_config_empty", "create empty file")
}
}
diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py
index 1405fd3..098fde6 100755
--- a/tools/fs_config/fs_config_generator.py
+++ b/tools/fs_config/fs_config_generator.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""Generates config files for Android file system properties.
This script is used for generating configuration files for configuring
@@ -299,11 +299,10 @@
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 @@
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 @@
"""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 159e2aa..64ef0e2 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/mk2bp_catalog.py b/tools/mk2bp_catalog.py
new file mode 100755
index 0000000..c2afb9b
--- /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 9ddd5d7..d8c9cb1 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
- if "=" in line:
- key, value = line.split("=", 1)
- props[key] = value
- return props
+ # 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
- def get(self, name):
- key = name + "="
- for line in self.lines:
- if line.startswith(key):
- return line[len(key):]
- return ""
+ 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 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)
+ # 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 delete(self, name):
- key = name + "="
- self.lines = [ line for line in self.lines if not line.startswith(key) ]
-
- def write(self, f):
- f.write("\n".join(self.lines))
- f.write("\n")
+ 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()
+ 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()
- 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:
+ 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 0000000..4a6ecc2
--- /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 5785688..5cb639a 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -49,6 +49,8 @@
required: [
"blk_alloc_to_base_fs",
"e2fsck",
+ "mkerofsimage.sh",
+ "mkuserimg_mke2fs",
"simg2img",
"tune2fs",
],
@@ -73,9 +75,6 @@
"releasetools_build_super_image",
"releasetools_common",
],
- required: [
- "zip2zip",
- ],
}
python_defaults {
@@ -91,14 +90,35 @@
],
}
+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",
@@ -106,7 +126,16 @@
required: [
"brillo_update_payload",
"checkvintf",
+ "lz4",
+ "toybox",
+ "unpack_bootimg"
],
+ target: {
+ darwin: {
+ // required module "brillo_update_payload" is disabled on darwin
+ enabled: false,
+ },
+ },
}
//
@@ -239,6 +268,18 @@
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 +331,12 @@
required: [
"delta_generator",
],
+ target: {
+ darwin: {
+ // required module "delta_generator" is disabled on darwin
+ enabled: false,
+ },
+ },
}
python_binary_host {
@@ -322,6 +369,32 @@
],
}
+python_defaults {
+ name: "releasetools_find_shareduid_violation_defaults",
+ srcs: [
+ "find_shareduid_violation.py",
+ ],
+ libs: [
+ "releasetools_common",
+ ],
+}
+
+python_binary_host {
+ name: "find_shareduid_violation",
+ defaults: [
+ "releasetools_binary_defaults",
+ "releasetools_find_shareduid_violation_defaults",
+ ],
+}
+
+python_library_host {
+ name: "releasetools_find_shareduid_violation",
+ defaults: [
+ "releasetools_find_shareduid_violation_defaults",
+ "releasetools_library_defaults",
+ ],
+}
+
python_binary_host {
name: "make_recovery_patch",
defaults: ["releasetools_binary_defaults"],
@@ -356,12 +429,20 @@
"releasetools_build_super_image",
"releasetools_check_target_files_vintf",
"releasetools_common",
+ "releasetools_find_shareduid_violation",
"releasetools_img_from_target_files",
"releasetools_ota_from_target_files",
],
required: [
"checkvintf",
+ "host_init_verifier",
],
+ target: {
+ darwin: {
+ // libs dep "releasetools_ota_from_target_files" is disabled on darwin
+ enabled: false,
+ },
+ },
}
python_binary_host {
@@ -452,6 +533,7 @@
"releasetools_build_super_image",
"releasetools_check_target_files_vintf",
"releasetools_common",
+ "releasetools_find_shareduid_violation",
"releasetools_img_from_target_files",
"releasetools_ota_from_target_files",
"releasetools_verity_utils",
@@ -459,9 +541,12 @@
data: [
"testdata/**/*",
],
- required: [
- "otatools",
- ],
+ target: {
+ darwin: {
+ // libs dep "releasetools_ota_from_target_files" is disabled on darwin
+ enabled: false,
+ },
+ },
}
python_test_host {
@@ -481,7 +566,9 @@
embedded_launcher: false,
},
},
- test_suites: ["general-tests"],
+ test_options: {
+ unit_test: true,
+ },
}
python_test_host {
@@ -498,5 +585,7 @@
embedded_launcher: false,
},
},
- test_suites: ["general-tests"],
+ test_options: {
+ unit_test: true,
+ },
}
diff --git a/tools/releasetools/OWNERS b/tools/releasetools/OWNERS
index a8295d4..d7fc540 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/TEST_MAPPING b/tools/releasetools/TEST_MAPPING
deleted file mode 100644
index 0af0f04..0000000
--- a/tools/releasetools/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "releasetools_test",
- "host": true
- },
- {
- "name": "releasetools_py3_test",
- "host": true
- }
- ]
-}
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index f58b697..5f35d78 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -51,6 +51,7 @@
import os
import shlex
import shutil
+import stat
import sys
import uuid
import zipfile
@@ -281,6 +282,37 @@
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.
@@ -299,6 +331,9 @@
# AVB-sign the image as needed.
if OPTIONS.info_dict.get("avb_enable") == "true":
+ # Signing requires +w
+ os.chmod(img.name, os.stat(img.name).st_mode | stat.S_IWUSR)
+
avbtool = OPTIONS.info_dict["avb_avbtool"]
part_size = OPTIONS.info_dict["dtbo_size"]
# The AVB hash footer will be replaced if already present.
@@ -708,6 +743,18 @@
common.ZipClose(output_zip)
+def HasPartition(partition_name):
+ """Determines if the target files archive should build a given partition."""
+
+ return ((os.path.isdir(
+ os.path.join(OPTIONS.input_tmp, partition_name.upper())) and
+ OPTIONS.info_dict.get(
+ "building_{}_image".format(partition_name)) == "true") or
+ os.path.exists(
+ os.path.join(OPTIONS.input_tmp, "IMAGES",
+ "{}.img".format(partition_name))))
+
+
def AddImagesToTargetFiles(filename):
"""Creates and adds images (boot/recovery/system/...) to a target_files.zip.
@@ -736,28 +783,18 @@
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
- # 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"))
+ # {vendor,odm,product,system_ext,vendor_dlkm,odm_dlkm, system, system_other}.img
+ # can be built from source, or dropped into target_files.zip as a prebuilt blob.
+ has_vendor = HasPartition("vendor")
+ has_odm = HasPartition("odm")
+ has_vendor_dlkm = HasPartition("vendor_dlkm")
+ has_odm_dlkm = HasPartition("odm_dlkm")
+ has_product = HasPartition("product")
+ has_system_ext = HasPartition("system_ext")
+ has_system = HasPartition("system")
+ has_system_other = HasPartition("system_other")
+ 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 +902,14 @@
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)
@@ -918,8 +963,9 @@
if item not in vbmeta_vendor.split()]
vbmeta_partitions.append("vbmeta_vendor")
- banner("vbmeta")
- AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
+ if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
+ banner("vbmeta")
+ AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
if OPTIONS.info_dict.get("use_dynamic_partitions") == "true":
banner("super_empty")
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index 1c61938..dc6e3ca 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -49,8 +49,13 @@
def __init__(self, apex_path, key_passwords, codename_to_api_level_map):
self.apex_path = apex_path
- self.key_passwords = key_passwords
+ if not key_passwords:
+ self.key_passwords = dict()
+ else:
+ 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 +66,13 @@
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 +102,14 @@
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
@@ -110,7 +127,7 @@
# signed apk file.
unsigned_apk = common.MakeTempFile()
os.rename(apk_path, unsigned_apk)
- common.SignFile(unsigned_apk, apk_path, key_name, self.key_passwords,
+ common.SignFile(unsigned_apk, apk_path, key_name, self.key_passwords.get(key_name),
codename_to_api_level_map=self.codename_to_api_level_map)
has_signed_apk = True
return payload_dir, has_signed_apk
@@ -149,7 +166,8 @@
# 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')
@@ -162,7 +180,7 @@
# Add the payload image back to the apex file.
common.ZipDelete(self.apex_path, APEX_PAYLOAD_IMAGE)
- with zipfile.ZipFile(self.apex_path, 'a') as output_apex:
+ with zipfile.ZipFile(self.apex_path, 'a', allowZip64=True) as output_apex:
common.ZipWrite(output_apex, payload_img, APEX_PAYLOAD_IMAGE,
compress_type=zipfile.ZIP_STORED)
return self.apex_path
@@ -273,7 +291,7 @@
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(
@@ -336,7 +354,7 @@
common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
if APEX_PUBKEY in zip_items:
common.ZipDelete(apex_file, APEX_PUBKEY)
- apex_zip = zipfile.ZipFile(apex_file, 'a')
+ apex_zip = zipfile.ZipFile(apex_file, 'a', allowZip64=True)
common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
common.ZipWrite(apex_zip, payload_public_key, arcname=APEX_PUBKEY)
common.ZipClose(apex_zip)
@@ -356,7 +374,7 @@
aligned_apex,
signed_apex,
container_key,
- container_pw,
+ container_pw.get(container_key),
codename_to_api_level_map=codename_to_api_level_map,
extra_signapk_args=extra_signapk_args)
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 8b6a690..d33c2f7 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -521,7 +521,7 @@
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 8cf0741..820c128 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -57,7 +57,7 @@
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
@@ -250,6 +250,7 @@
run_e2fsck = False
needs_projid = prop_dict.get("needs_projid", 0)
needs_casefold = prop_dict.get("needs_casefold", 0)
+ needs_compress = prop_dict.get("needs_compress", 0)
if fs_type.startswith("ext"):
build_command = [prop_dict["ext_mkuserimg"]]
@@ -295,6 +296,18 @@
build_command.extend(["--inode_size", "256"])
if "selinux_fc" in prop_dict:
build_command.append(prop_dict["selinux_fc"])
+ elif fs_type.startswith("erofs"):
+ build_command = ["mkerofsimage.sh"]
+ build_command.extend([in_dir, out_file])
+ if "erofs_sparse_flag" in prop_dict:
+ build_command.extend([prop_dict["erofs_sparse_flag"]])
+ build_command.extend(["-m", prop_dict["mount_point"]])
+ if target_out:
+ build_command.extend(["-d", target_out])
+ if fs_config:
+ build_command.extend(["-C", fs_config])
+ if "selinux_fc" in prop_dict:
+ build_command.extend(["-c", prop_dict["selinux_fc"]])
elif fs_type.startswith("squash"):
build_command = ["mksquashfsimage.sh"]
build_command.extend([in_dir, out_file])
@@ -337,6 +350,17 @@
build_command.append("--prjquota")
if (needs_casefold):
build_command.append("--casefold")
+ if (needs_compress or prop_dict.get("system_fs_compress") == "true"):
+ build_command.append("--compression")
+ if (prop_dict.get("system_fs_compress") == "true"):
+ build_command.append("--sldc")
+ if (prop_dict.get("system_f2fs_sldc_flags") == None):
+ build_command.append(str(0))
+ else:
+ sldc_flags_str = prop_dict.get("system_f2fs_sldc_flags")
+ sldc_flags = sldc_flags_str.split()
+ build_command.append(str(len(sldc_flags)))
+ build_command.extend(sldc_flags)
else:
raise BuildImageError(
"Error: unknown filesystem type: {}".format(fs_type))
@@ -402,7 +426,7 @@
fs_type = prop_dict.get("fs_type", "")
fs_spans_partition = True
- if fs_type.startswith("squash"):
+ if fs_type.startswith("squash") or fs_type.startswith("erofs"):
fs_spans_partition = False
# Get a builder for creating an image that's to be verified by Verified Boot,
@@ -412,7 +436,16 @@
if (prop_dict.get("use_dynamic_partition_size") == "true" and
"partition_size" not in prop_dict):
# If partition_size is not defined, use output of `du' + reserved_size.
- size = GetDiskUsage(in_dir)
+ # For compressed file system, it's better to use the compressed size to avoid wasting space.
+ if fs_type.startswith("erofs"):
+ tmp_dict = prop_dict.copy()
+ if "erofs_sparse_flag" in tmp_dict:
+ tmp_dict.pop("erofs_sparse_flag")
+ BuildImageMkfs(in_dir, tmp_dict, out_file, target_out, fs_config)
+ size = GetDiskUsage(out_file)
+ os.remove(out_file)
+ else:
+ size = GetDiskUsage(in_dir)
logger.info(
"The tree size of %s is %d MB.", in_dir, size // BYTES_IN_MB)
# If not specified, give us 16MB margin for GetDiskUsage error ...
@@ -529,7 +562,10 @@
common_props = (
"extfs_sparse_flag",
+ "erofs_sparse_flag",
"squashfs_sparse_flag",
+ "system_fs_compress",
+ "system_f2fs_sldc_flags",
"f2fs_sparse_flag",
"skip_fsck",
"ext_mkuserimg",
@@ -610,6 +646,7 @@
copy_prop("userdata_selinux_fc", "selinux_fc")
copy_prop("needs_casefold", "needs_casefold")
copy_prop("needs_projid", "needs_projid")
+ copy_prop("needs_compress", "needs_compress")
elif mount_point == "cache":
copy_prop("cache_fs_type", "fs_type")
copy_prop("cache_size", "partition_size")
@@ -708,6 +745,52 @@
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 +835,10 @@
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 +878,10 @@
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_ota_package_signature.py b/tools/releasetools/check_ota_package_signature.py
index 0d990f1..58510a5 100755
--- a/tools/releasetools/check_ota_package_signature.py
+++ b/tools/releasetools/check_ota_package_signature.py
@@ -140,7 +140,7 @@
def VerifyAbOtaPayload(cert, package):
"""Verifies the payload and metadata signatures in an A/B OTA payload."""
- package_zip = zipfile.ZipFile(package, 'r')
+ package_zip = zipfile.ZipFile(package, 'r', allowZip64=True)
if 'payload.bin' not in package_zip.namelist():
common.ZipClose(package_zip)
return
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
index 95d09cc..a2ddfe7 100755
--- a/tools/releasetools/check_target_files_vintf.py
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -46,6 +46,7 @@
'/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']
@@ -99,10 +100,7 @@
'PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS is not set')
return []
- with open(version_path) as f:
- version = f.read().strip()
-
- return ['--kernel', '{}:{}'.format(version, config_path)]
+ return ['--kernel', '{}:{}'.format(version_path, config_path)]
def CheckVintfFromExtractedTargetFiles(input_tmp, info_dict=None):
@@ -219,6 +217,52 @@
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, allowZip64=True), "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 ae7da2f..0172add 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -17,6 +17,7 @@
import base64
import collections
import copy
+import datetime
import errno
import fnmatch
import getopt
@@ -53,16 +54,17 @@
# 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 @@
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 @@
self.cache_size = None
self.stash_threshold = 0.8
self.logfile = None
+ self.host_tools = {}
OPTIONS = Options()
@@ -107,13 +111,22 @@
# 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,40 @@
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 FindHostToolPath(tool_name):
+ """Finds the path to the host tool.
+
+ Args:
+ tool_name: name of the tool to find
+ Returns:
+ path to the tool if found under either one of the host_tools map or under
+ the same directory as this binary is located at. If not found, tool_name
+ is returned.
+ """
+ if tool_name in OPTIONS.host_tools:
+ return OPTIONS.host_tools[tool_name]
+
+ my_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
+ tool_path = os.path.join(my_dir, tool_name)
+ if os.path.exists(tool_path):
+ return tool_path
+
+ return tool_name
+
def Run(args, verbose=None, **kwargs):
"""Creates and returns a subprocess.Popen object.
@@ -222,8 +258,14 @@
kwargs['stderr'] = subprocess.STDOUT
if 'universal_newlines' not in kwargs:
kwargs['universal_newlines'] = True
+
+ if args:
+ # Make a copy of args in case client relies on the content of args later.
+ args = args[:]
+ args[0] = FindHostToolPath(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 +315,7 @@
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 +416,6 @@
'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:
@@ -503,6 +544,27 @@
return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_LEGACY
return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_CURRENT
+ def _GetPlatformVersion(self):
+ version_sdk = self.GetBuildProp("ro.build.version.sdk")
+ # init code switches to version_release_or_codename (see b/158483506). After
+ # API finalization, release_or_codename will be the same as release. This
+ # is the best effort to support pre-S dev stage builds.
+ if int(version_sdk) >= 30:
+ try:
+ return self.GetBuildProp("ro.build.version.release_or_codename")
+ except ExternalError:
+ logger.warning('Failed to find ro.build.version.release_or_codename')
+
+ return self.GetBuildProp("ro.build.version.release")
+
+ def _GetPartitionPlatformVersion(self, partition):
+ try:
+ return self.GetPartitionBuildProp("ro.build.version.release_or_codename",
+ partition)
+ except ExternalError:
+ return self.GetPartitionBuildProp("ro.build.version.release",
+ partition)
+
def GetOemProperty(self, key):
if self.oem_props is not None and key in self.oem_props:
return self.oem_dicts[0][key]
@@ -519,9 +581,10 @@
self.GetPartitionBuildProp("ro.product.brand", partition),
self.GetPartitionBuildProp("ro.product.name", partition),
self.GetPartitionBuildProp("ro.product.device", partition),
- self.GetPartitionBuildProp("ro.build.version.release", partition),
+ self._GetPartitionPlatformVersion(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))
@@ -534,7 +597,7 @@
self.GetBuildProp("ro.product.brand"),
self.GetBuildProp("ro.product.name"),
self.GetBuildProp("ro.product.device"),
- self.GetBuildProp("ro.build.version.release"),
+ self._GetPlatformVersion(),
self.GetBuildProp("ro.build.id"),
self.GetBuildProp("ro.build.version.incremental"),
self.GetBuildProp("ro.build.type"),
@@ -589,7 +652,7 @@
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 +715,8 @@
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 +746,7 @@
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 +766,15 @@
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 +816,7 @@
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
@@ -783,6 +852,15 @@
props._LoadBuildProp(data)
return props
+ @staticmethod
+ def FromBuildPropFile(name, build_prop_file):
+ """Constructs an instance from a build prop file."""
+
+ props = PartitionBuildProps("unknown", name)
+ with open(build_prop_file) as f:
+ props._LoadBuildProp(f.read())
+ return props
+
def _LoadBuildProp(self, data):
for line in data.split('\n'):
line = line.strip()
@@ -807,7 +885,7 @@
"""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:
@@ -972,15 +1050,35 @@
Returns:
The merged dynamic partition info dictionary.
"""
- merged_dict = {}
+
+ def uniq_concat(a, b):
+ combined = set(a.split(" "))
+ combined.update(set(b.split(" ")))
+ combined = [item.strip() for item in combined if item.strip()]
+ return " ".join(sorted(combined))
+
+ if (framework_dict.get("use_dynamic_partitions") !=
+ "true") or (vendor_dict.get("use_dynamic_partitions") != "true"):
+ raise ValueError("Both dictionaries must have use_dynamic_partitions=true")
+
+ merged_dict = {"use_dynamic_partitions": "true"}
+
+ merged_dict["dynamic_partition_list"] = uniq_concat(
+ framework_dict.get("dynamic_partition_list", ""),
+ vendor_dict.get("dynamic_partition_list", ""))
+
+ # Super block devices are defined by the vendor dict.
+ if "super_block_devices" in vendor_dict:
+ merged_dict["super_block_devices"] = vendor_dict["super_block_devices"]
+ for block_device in merged_dict["super_block_devices"].split(" "):
+ key = "super_%s_device_size" % block_device
+ if key not in vendor_dict:
+ raise ValueError("Vendor dict does not contain required key %s." % key)
+ merged_dict[key] = vendor_dict[key]
+
# Partition groups and group sizes are defined by the vendor dict because
# these values may vary for each board that uses a shared system image.
merged_dict["super_partition_groups"] = vendor_dict["super_partition_groups"]
- framework_dynamic_partition_list = framework_dict.get(
- "dynamic_partition_list", "")
- vendor_dynamic_partition_list = vendor_dict.get("dynamic_partition_list", "")
- merged_dict["dynamic_partition_list"] = ("%s %s" % (
- framework_dynamic_partition_list, vendor_dynamic_partition_list)).strip()
for partition_group in merged_dict["super_partition_groups"].split(" "):
# Set the partition group's size using the value from the vendor dict.
key = "super_%s_group_size" % partition_group
@@ -991,18 +1089,104 @@
# Set the partition group's partition list using a concatenation of the
# framework and vendor partition lists.
key = "super_%s_partition_list" % partition_group
- merged_dict[key] = (
- "%s %s" %
- (framework_dict.get(key, ""), vendor_dict.get(key, ""))).strip()
+ merged_dict[key] = uniq_concat(
+ framework_dict.get(key, ""), vendor_dict.get(key, ""))
- # 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"]
- if "virtual_ab_retrofit" in vendor_dict.keys():
- merged_dict["virtual_ab_retrofit"] = vendor_dict["virtual_ab_retrofit"]
+ # Various other flags should be copied from the vendor dict, if defined.
+ for key in ("virtual_ab", "virtual_ab_retrofit", "lpmake",
+ "super_metadata_device", "super_partition_error_limit",
+ "super_partition_size"):
+ if key in vendor_dict.keys():
+ merged_dict[key] = vendor_dict[key]
+
return merged_dict
+def PartitionMapFromTargetFiles(target_files_dir):
+ """Builds a map from partition -> path within an extracted target files directory."""
+ # Keep possible_subdirs in sync with build/make/core/board_config.mk.
+ possible_subdirs = {
+ "system": ["SYSTEM"],
+ "vendor": ["VENDOR", "SYSTEM/vendor"],
+ "product": ["PRODUCT", "SYSTEM/product"],
+ "system_ext": ["SYSTEM_EXT", "SYSTEM/system_ext"],
+ "odm": ["ODM", "VENDOR/odm", "SYSTEM/vendor/odm"],
+ "vendor_dlkm": [
+ "VENDOR_DLKM", "VENDOR/vendor_dlkm", "SYSTEM/vendor/vendor_dlkm"
+ ],
+ "odm_dlkm": ["ODM_DLKM", "VENDOR/odm_dlkm", "SYSTEM/vendor/odm_dlkm"],
+ }
+ partition_map = {}
+ for partition, subdirs in possible_subdirs.items():
+ for subdir in subdirs:
+ if os.path.exists(os.path.join(target_files_dir, subdir)):
+ partition_map[partition] = subdir
+ break
+ return partition_map
+
+
+def SharedUidPartitionViolations(uid_dict, partition_groups):
+ """Checks for APK sharedUserIds that cross partition group boundaries.
+
+ This uses a single or merged build's shareduid_violation_modules.json
+ output file, as generated by find_shareduid_violation.py or
+ core/tasks/find-shareduid-violation.mk.
+
+ An error is defined as a sharedUserId that is found in a set of partitions
+ that span more than one partition group.
+
+ Args:
+ uid_dict: A dictionary created by using the standard json module to read a
+ complete shareduid_violation_modules.json file.
+ partition_groups: A list of groups, where each group is a list of
+ partitions.
+
+ Returns:
+ A list of error messages.
+ """
+ errors = []
+ for uid, partitions in uid_dict.items():
+ found_in_groups = [
+ group for group in partition_groups
+ if set(partitions.keys()) & set(group)
+ ]
+ if len(found_in_groups) > 1:
+ errors.append(
+ "APK sharedUserId \"%s\" found across partition groups in partitions \"%s\""
+ % (uid, ",".join(sorted(partitions.keys()))))
+ return errors
+
+
+def RunHostInitVerifier(product_out, partition_map):
+ """Runs host_init_verifier on the init rc files within partitions.
+
+ host_init_verifier searches the etc/init path within each partition.
+
+ Args:
+ product_out: PRODUCT_OUT directory, containing partition directories.
+ partition_map: A map of partition name -> relative path within product_out.
+ """
+ allowed_partitions = ("system", "system_ext", "product", "vendor", "odm")
+ cmd = ["host_init_verifier"]
+ for partition, path in partition_map.items():
+ if partition not in allowed_partitions:
+ raise ExternalError("Unable to call host_init_verifier for partition %s" %
+ partition)
+ cmd.extend(["--out_%s" % partition, os.path.join(product_out, path)])
+ # Add --property-contexts if the file exists on the partition.
+ property_contexts = "%s_property_contexts" % (
+ "plat" if partition == "system" else partition)
+ property_contexts_path = os.path.join(product_out, path, "etc", "selinux",
+ property_contexts)
+ if os.path.exists(property_contexts_path):
+ cmd.append("--property-contexts=%s" % property_contexts_path)
+ # Add the passwd file if the file exists on the partition.
+ passwd_path = os.path.join(product_out, path, "etc", "passwd")
+ if os.path.exists(passwd_path):
+ cmd.extend(["-p", passwd_path])
+ return RunAndCheckOutput(cmd)
+
+
def AppendAVBSigningArgs(cmd, partition):
"""Append signing arguments for avbtool."""
# e.g., "--key path/to/signing_key --algorithm SHA256_RSA4096"
@@ -1082,6 +1266,46 @@
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 +1347,32 @@
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 +1384,7 @@
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())
@@ -1188,23 +1410,27 @@
for building the requested image.
"""
+ if info_dict is None:
+ info_dict = OPTIONS.info_dict
+
# "boot" or "recovery", without extension.
partition_name = os.path.basename(sourcedir).lower()
+ kernel = None
if partition_name == "recovery":
- kernel = "kernel"
+ if info_dict.get("exclude_kernel_from_recovery_image") == "true":
+ logger.info("Excluded kernel binary from recovery image.")
+ else:
+ kernel = "kernel"
else:
kernel = image_name.replace("boot", "kernel")
- kernel = kernel.replace(".img","")
- if not os.access(os.path.join(sourcedir, kernel), os.F_OK):
+ kernel = kernel.replace(".img", "")
+ if kernel and not os.access(os.path.join(sourcedir, kernel), os.F_OK):
return None
if has_ramdisk and not os.access(os.path.join(sourcedir, "RAMDISK"), os.F_OK):
return None
- if info_dict is None:
- info_dict = OPTIONS.info_dict
-
img = tempfile.NamedTemporaryFile()
if has_ramdisk:
@@ -1214,7 +1440,9 @@
# use MKBOOTIMG from environ, or "mkbootimg" if empty or not set
mkbootimg = os.getenv('MKBOOTIMG') or "mkbootimg"
- cmd = [mkbootimg, "--kernel", os.path.join(sourcedir, kernel)]
+ cmd = [mkbootimg]
+ if kernel:
+ cmd += ["--kernel", os.path.join(sourcedir, kernel)]
fn = os.path.join(sourcedir, "second")
if os.access(fn, os.F_OK):
@@ -1319,7 +1547,7 @@
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]
@@ -1432,6 +1660,24 @@
cmd.extend(["--vendor_ramdisk", ramdisk_img.name])
cmd.extend(["--vendor_boot", img.name])
+ ramdisk_fragment_imgs = []
+ fn = os.path.join(sourcedir, "vendor_ramdisk_fragments")
+ if os.access(fn, os.F_OK):
+ ramdisk_fragments = shlex.split(open(fn).read().rstrip("\n"))
+ for ramdisk_fragment in ramdisk_fragments:
+ fn = os.path.join(sourcedir, "RAMDISK_FRAGMENTS", ramdisk_fragment, "mkbootimg_args")
+ cmd.extend(shlex.split(open(fn).read().rstrip("\n")))
+ fn = os.path.join(sourcedir, "RAMDISK_FRAGMENTS", ramdisk_fragment, "prebuilt_ramdisk")
+ # Use prebuilt image if found, else create ramdisk from supplied files.
+ if os.access(fn, os.F_OK):
+ ramdisk_fragment_pathname = fn
+ else:
+ ramdisk_fragment_root = os.path.join(sourcedir, "RAMDISK_FRAGMENTS", ramdisk_fragment)
+ ramdisk_fragment_img = _MakeRamdisk(ramdisk_fragment_root, lz4_ramdisks=use_lz4)
+ ramdisk_fragment_imgs.append(ramdisk_fragment_img)
+ ramdisk_fragment_pathname = ramdisk_fragment_img.name
+ cmd.extend(["--vendor_ramdisk_fragment", ramdisk_fragment_pathname])
+
RunAndCheckOutput(cmd)
# AVB: if enabled, calculate and add hash.
@@ -1449,6 +1695,8 @@
img.seek(os.SEEK_SET, 0)
data = img.read()
+ for f in ramdisk_fragment_imgs:
+ f.close()
ramdisk_img.close()
img.close()
@@ -1472,7 +1720,8 @@
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 +1730,7 @@
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)
@@ -1498,7 +1747,7 @@
cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
if patterns is not None:
# Filter out non-matching patterns. unzip will complain otherwise.
- with zipfile.ZipFile(filename) as input_zip:
+ with zipfile.ZipFile(filename, allowZip64=True) as input_zip:
names = input_zip.namelist()
filtered = [
pattern for pattern in patterns if fnmatch.filter(names, pattern)]
@@ -1583,8 +1832,7 @@
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 +2031,9 @@
# 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 +2138,8 @@
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 +2249,7 @@
Put verbose logs to specified file (regardless of --verbose option.)
"""
+
def Usage(docstring):
print(docstring.rstrip("\n"))
print(COMMON_DOCSTRING)
@@ -2024,9 +2273,9 @@
"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 +2313,8 @@
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 +2412,7 @@
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 +2475,6 @@
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 +2600,7 @@
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 +2729,12 @@
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 +2773,7 @@
cmd.append(ptemp.name)
p = Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
err = []
+
def run():
_, e = p.communicate()
if e:
@@ -2550,7 +2802,6 @@
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 +3112,7 @@
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 +3121,7 @@
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 +3144,7 @@
"squashfs": "EMMC"
}
+
def GetTypeAndDevice(mount_point, info, check_no_slot=True):
"""
Use GetTypeAndDeviceExpr whenever possible. This function is kept for
@@ -2903,11 +3155,10 @@
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 +3173,7 @@
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 +3188,7 @@
return fstab[mount_point]
return None
+
def ParseCertificate(data):
"""Parses and converts a PEM-encoded certificate into DER-encoded.
@@ -3264,7 +3515,7 @@
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 +3523,7 @@
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 +3580,8 @@
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 b9c9b19..033c02e 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -301,7 +301,7 @@
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/find_shareduid_violation.py b/tools/releasetools/find_shareduid_violation.py
new file mode 100755
index 0000000..35acde3
--- /dev/null
+++ b/tools/releasetools/find_shareduid_violation.py
@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+"""Find APK sharedUserId violators.
+
+Usage: find_shareduid_violation [args]
+
+ --product_out
+ PRODUCT_OUT directory
+
+ --aapt
+ Path to aapt or aapt2
+
+ --copy_out_system
+ TARGET_COPY_OUT_SYSTEM
+
+ --copy_out_vendor_
+ TARGET_COPY_OUT_VENDOR
+
+ --copy_out_product
+ TARGET_COPY_OUT_PRODUCT
+
+ --copy_out_system_ext
+ TARGET_COPY_OUT_SYSTEM_EXT
+"""
+
+import json
+import logging
+import os
+import re
+import subprocess
+import sys
+
+from collections import defaultdict
+from glob import glob
+
+import common
+
+logger = logging.getLogger(__name__)
+
+OPTIONS = common.OPTIONS
+OPTIONS.product_out = os.environ.get("PRODUCT_OUT")
+OPTIONS.aapt = "aapt2"
+OPTIONS.copy_out_system = "system"
+OPTIONS.copy_out_vendor = "vendor"
+OPTIONS.copy_out_product = "product"
+OPTIONS.copy_out_system_ext = "system_ext"
+
+
+def execute(cmd):
+ p = subprocess.Popen(
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = map(lambda b: b.decode("utf-8"), p.communicate())
+ return p.returncode == 0, out, err
+
+
+def make_aapt_cmds(aapt, apk):
+ return [
+ aapt + " dump " + apk + " --file AndroidManifest.xml",
+ aapt + " dump xmltree " + apk + " --file AndroidManifest.xml"
+ ]
+
+
+def extract_shared_uid(aapt, apk):
+ for cmd in make_aapt_cmds(aapt, apk):
+ success, manifest, error_msg = execute(cmd)
+ if success:
+ break
+ else:
+ logger.error(error_msg)
+ sys.exit()
+
+ pattern = re.compile(r"sharedUserId.*=\"([^\"]*)")
+
+ for line in manifest.split("\n"):
+ match = pattern.search(line)
+ if match:
+ return match.group(1)
+ return None
+
+
+def FindShareduidViolation(product_out, partition_map, aapt="aapt2"):
+ """Find sharedUserId violators in the given partitions.
+
+ Args:
+ product_out: The base directory containing the partition directories.
+ partition_map: A map of partition name -> directory name.
+ aapt: The name of the aapt binary. Defaults to aapt2.
+
+ Returns:
+ A string containing a JSON object describing the shared UIDs.
+ """
+ shareduid_app_dict = defaultdict(lambda: defaultdict(list))
+
+ for part, location in partition_map.items():
+ for f in glob(os.path.join(product_out, location, "*", "*", "*.apk")):
+ apk_file = os.path.basename(f)
+ shared_uid = extract_shared_uid(aapt, f)
+
+ if shared_uid is None:
+ continue
+ shareduid_app_dict[shared_uid][part].append(apk_file)
+
+ # Only output sharedUserId values that appear in >1 partition.
+ output = {}
+ for uid, partitions in shareduid_app_dict.items():
+ if len(partitions) > 1:
+ output[uid] = shareduid_app_dict[uid]
+
+ return json.dumps(output, indent=2, sort_keys=True)
+
+
+def main():
+ common.InitLogging()
+
+ def option_handler(o, a):
+ if o == "--product_out":
+ OPTIONS.product_out = a
+ elif o == "--aapt":
+ OPTIONS.aapt = a
+ elif o == "--copy_out_system":
+ OPTIONS.copy_out_system = a
+ elif o == "--copy_out_vendor":
+ OPTIONS.copy_out_vendor = a
+ elif o == "--copy_out_product":
+ OPTIONS.copy_out_product = a
+ elif o == "--copy_out_system_ext":
+ OPTIONS.copy_out_system_ext = a
+ else:
+ return False
+ return True
+
+ args = common.ParseOptions(
+ sys.argv[1:],
+ __doc__,
+ extra_long_opts=[
+ "product_out=",
+ "aapt=",
+ "copy_out_system=",
+ "copy_out_vendor=",
+ "copy_out_product=",
+ "copy_out_system_ext=",
+ ],
+ extra_option_handler=option_handler)
+
+ if args:
+ common.Usage(__doc__)
+ sys.exit(1)
+
+ partition_map = {
+ "system": OPTIONS.copy_out_system,
+ "vendor": OPTIONS.copy_out_vendor,
+ "product": OPTIONS.copy_out_product,
+ "system_ext": OPTIONS.copy_out_system_ext,
+ }
+
+ print(
+ FindShareduidViolation(OPTIONS.product_out, partition_map, OPTIONS.aapt))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index ab38d0d..5409194 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -58,6 +58,7 @@
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 @@
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 @@
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 dd7806b..9360d7b 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -16,11 +16,15 @@
#
"""This script merges two partial target files packages.
-One package contains framework files, and the other contains vendor files.
-It produces a complete target files package that can be used to generate an
-OTA package.
+One input package contains framework files, and the other contains vendor files.
-Usage: merge_target_files.py [args]
+This script produces a complete, merged target files package:
+ - This package can be used to generate a flashable IMG package.
+ See --output-img.
+ - This package can be used to generate an OTA package. See --output-ota.
+ - The merged package is checked for compatibility between the two inputs.
+
+Usage: merge_target_files [args]
--framework-target-files framework-target-files-zip-archive
The input target files package containing framework bits. This is a zip
@@ -70,6 +74,10 @@
--rebuild_recovery
Deprecated; does nothing.
+ --allow-duplicate-apkapex-keys
+ If provided, duplicate APK/APEX keys are ignored and the value from the
+ framework is used.
+
--keep-tmp
Keep tempoary files for debugging purposes.
"""
@@ -77,6 +85,7 @@
from __future__ import print_function
import fnmatch
+import json
import logging
import os
import re
@@ -90,11 +99,14 @@
import check_target_files_vintf
import common
import img_from_target_files
+import find_shareduid_violation
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
@@ -108,6 +120,8 @@
OPTIONS.output_super_empty = None
# TODO(b/132730255): Remove this option.
OPTIONS.rebuild_recovery = False
+# TODO(b/150582573): Remove this option.
+OPTIONS.allow_duplicate_apkapex_keys = False
OPTIONS.keep_tmp = False
# In an item list (framework or vendor), we may see entries that select whole
@@ -147,16 +161,9 @@
'SYSTEM/*',
)
-# FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
-# partial framework target files package that need some special processing, such
-# as some sort of combination with items from the partial vendor target files
-# package.
-
-FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
-
# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
-# framework instance of META/misc_info.txt. The remaining keys from the
-# vendor instance.
+# framework instance of META/misc_info.txt. The remaining keys should come
+# from the vendor instance.
DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
'avb_system_hashtree_enable',
@@ -173,6 +180,9 @@
'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
@@ -194,13 +204,6 @@
'VENDOR/*',
)
-# VENDOR_EXTRACT_SPECIAL_ITEM_LIST is a list of items to extract from the
-# partial vendor target files package that need some special processing, such as
-# some sort of combination with items from the partial framework target files
-# package.
-
-VENDOR_EXTRACT_SPECIAL_ITEM_LIST = ('META/*',)
-
# The merge config lists should not attempt to extract items from both
# builds for any of the following partitions. The partitions in
# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
@@ -218,6 +221,8 @@
'SYSTEM/',
'SYSTEM_OTHER/',
'VENDOR/',
+ 'VENDOR_DLKM/',
+ 'ODM_DLKM/',
)
@@ -307,8 +312,8 @@
framework_item_list: The list of items to extract from the partial framework
target files package as is.
framework_misc_info_keys: A list of keys to obtain from the framework
- instance of META/misc_info.txt. The remaining keys from the vendor
- instance.
+ instance of META/misc_info.txt. The remaining keys should come from the
+ vendor instance.
vendor_item_list: The list of items to extract from the partial vendor
target files package as is.
@@ -333,10 +338,15 @@
'this script.')
has_error = True
+ # Check that partitions only come from one input.
for partition in SINGLE_BUILD_PARTITIONS:
- in_framework = any(
- item.startswith(partition) for item in framework_item_list)
- in_vendor = any(item.startswith(partition) for item in vendor_item_list)
+ image_path = 'IMAGES/{}.img'.format(partition.lower().replace('/', ''))
+ in_framework = (
+ any(item.startswith(partition) for item in framework_item_list) or
+ image_path in framework_item_list)
+ in_vendor = (
+ any(item.startswith(partition) for item in vendor_item_list) or
+ image_path in vendor_item_list)
if in_framework and in_vendor:
logger.error(
'Cannot extract items from %s for both the framework and vendor'
@@ -362,8 +372,8 @@
framework directory and the vendor directory, placing the merged result in the
output directory. The precondition in that the files are already extracted.
The post condition is that the output META/ab_partitions.txt contains the
- merged content. The format for each ab_partitions.txt a one partition name per
- line. The output file contains the union of the parition names.
+ merged content. The format for each ab_partitions.txt is one partition name
+ per line. The output file contains the union of the partition names.
Args:
framework_target_files_temp_dir: The name of a directory containing the
@@ -416,8 +426,8 @@
create the output target files package after all the special cases are
processed.
framework_misc_info_keys: A list of keys to obtain from the framework
- instance of META/misc_info.txt. The remaining keys from the vendor
- instance.
+ instance of META/misc_info.txt. The remaining keys should come from the
+ vendor instance.
"""
misc_info_path = ['META', 'misc_info.txt']
@@ -446,6 +456,12 @@
# false in the partial builds to prevent duplicate building of super.img.
merged_dict['build_super_partition'] = 'true'
+ # If AVB is enabled then ensure that we build vbmeta.img.
+ # Partial builds with AVB enabled may set PRODUCT_BUILD_VBMETA_IMAGE=false to
+ # skip building an incomplete vbmeta.img.
+ if merged_dict.get('avb_enable') == 'true':
+ merged_dict['avb_building_vbmeta_image'] = 'true'
+
# Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
# depending on which dictionary the key came from.
# Only the file basename is required because all selinux_fc properties are
@@ -519,6 +535,7 @@
Args:
item_list: A list of items in a target files package.
+
Returns:
A set of partitions extracted from the list of items.
"""
@@ -540,7 +557,6 @@
output_target_files_dir,
framework_partition_set,
vendor_partition_set, file_name):
-
"""Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
This function merges the contents of the META/apexkeys.txt or
@@ -590,7 +606,12 @@
if partition_tag in partition_set:
if key in merged_dict:
- raise ValueError('Duplicate key %s' % key)
+ if OPTIONS.allow_duplicate_apkapex_keys:
+ # TODO(b/150582573) Always raise on duplicates.
+ logger.warning('Duplicate key %s' % key)
+ continue
+ else:
+ raise ValueError('Duplicate key %s' % key)
merged_dict[key] = value
@@ -640,8 +661,7 @@
def process_special_cases(framework_target_files_temp_dir,
vendor_target_files_temp_dir,
output_target_files_temp_dir,
- framework_misc_info_keys,
- framework_partition_set,
+ framework_misc_info_keys, framework_partition_set,
vendor_partition_set):
"""Performs special-case processing for certain target files items.
@@ -657,8 +677,8 @@
create the output target files package after all the special cases are
processed.
framework_misc_info_keys: A list of keys to obtain from the framework
- instance of META/misc_info.txt. The remaining keys from the vendor
- instance.
+ instance of META/misc_info.txt. The remaining keys should come from the
+ vendor instance.
framework_partition_set: Partitions that are considered framework
partitions. Used to filter apexkeys.txt and apkcerts.txt.
vendor_partition_set: Partitions that are considered vendor partitions. Used
@@ -704,26 +724,6 @@
file_name='apexkeys.txt')
-def files_from_path(target_path, extra_args=None):
- """Gets files under given path.
-
- Get (sub)files from given target path and return sorted list.
-
- Args:
- target_path: Target path to get subfiles.
- extra_args: List of extra argument for find command. Optional.
-
- Returns:
- Sorted files and directories list.
- """
-
- find_command = ['find', target_path] + (extra_args or [])
- find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
- return common.RunAndCheckOutput(['sort'],
- stdin=find_process.stdout,
- verbose=False)
-
-
def create_merged_package(temp_dir, framework_target_files, framework_item_list,
vendor_target_files, vendor_item_list,
framework_misc_info_keys, rebuild_recovery):
@@ -745,64 +745,42 @@
target files package as is, meaning these items will land in the output
target files package exactly as they appear in the input partial vendor
target files package.
- framework_misc_info_keys: The list of keys to obtain from the framework
- instance of META/misc_info.txt. The remaining keys from the vendor
- instance.
+ framework_misc_info_keys: A list of keys to obtain from the framework
+ instance of META/misc_info.txt. The remaining keys should come from the
+ vendor instance.
rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
devices and write it to the system image.
Returns:
Path to merged package under temp directory.
"""
+ # Extract "as is" items from the input framework and vendor partial target
+ # files packages directly into the output temporary directory, since these items
+ # do not need special case processing.
- # Create directory names that we'll use when we extract files from framework,
- # and vendor, and for zipping the final output.
-
- framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
- vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
output_target_files_temp_dir = os.path.join(temp_dir, 'output')
-
- # Extract "as is" items from the input framework partial target files package.
- # We extract them directly into the output temporary directory since the
- # items do not need special case processing.
-
extract_items(
target_files=framework_target_files,
target_files_temp_dir=output_target_files_temp_dir,
extract_item_list=framework_item_list)
-
- # Extract "as is" items from the input vendor partial target files package. We
- # extract them directly into the output temporary directory since the items
- # do not need special case processing.
-
extract_items(
target_files=vendor_target_files,
target_files_temp_dir=output_target_files_temp_dir,
extract_item_list=vendor_item_list)
- # Extract "special" items from the input framework partial target files
- # package. We extract these items to different directory since they require
- # special processing before they will end up in the output directory.
-
+ # Perform special case processing on META/* items.
+ # After this function completes successfully, all the files we need to create
+ # the output target files package are in place.
+ framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
+ vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
extract_items(
target_files=framework_target_files,
target_files_temp_dir=framework_target_files_temp_dir,
- extract_item_list=FRAMEWORK_EXTRACT_SPECIAL_ITEM_LIST)
-
- # Extract "special" items from the input vendor partial target files package.
- # We extract these items to different directory since they require special
- # processing before they will end up in the output directory.
-
+ extract_item_list=('META/*',))
extract_items(
target_files=vendor_target_files,
target_files_temp_dir=vendor_target_files_temp_dir,
- extract_item_list=VENDOR_EXTRACT_SPECIAL_ITEM_LIST)
-
- # Now that the temporary directories contain all the extracted files, perform
- # special case processing on any items that need it. After this function
- # completes successfully, all the files we need to create the output target
- # files package are in place.
-
+ extract_item_list=('META/*',))
process_special_cases(
framework_target_files_temp_dir=framework_target_files_temp_dir,
vendor_target_files_temp_dir=vendor_target_files_temp_dir,
@@ -828,8 +806,10 @@
# Regenerate IMAGES in the target directory.
- add_img_args = ['--verbose']
- add_img_args.append('--add_missing')
+ add_img_args = [
+ '--verbose',
+ '--add_missing',
+ ]
# TODO(b/132730255): Remove this if statement.
if rebuild_recovery:
add_img_args.append('--rebuild_recovery')
@@ -882,6 +862,15 @@
output_zip = os.path.abspath(output_file)
output_target_files_meta_dir = os.path.join(source_dir, 'META')
+ def files_from_path(target_path, extra_args=None):
+ """Gets files under the given path and return a sorted list."""
+ find_command = ['find', target_path] + (extra_args or [])
+ find_process = common.Run(
+ find_command, stdout=subprocess.PIPE, verbose=False)
+ return common.RunAndCheckOutput(['sort'],
+ stdin=find_process.stdout,
+ verbose=False)
+
meta_content = files_from_path(output_target_files_meta_dir)
other_content = files_from_path(
source_dir,
@@ -930,9 +919,9 @@
target files package as is, meaning these items will land in the output
target files package exactly as they appear in the input partial framework
target files package.
- framework_misc_info_keys: The list of keys to obtain from the framework
- instance of META/misc_info.txt. The remaining keys from the vendor
- instance.
+ framework_misc_info_keys: A list of keys to obtain from the framework
+ instance of META/misc_info.txt. The remaining keys should come from the
+ vendor instance.
vendor_target_files: The name of the zip archive containing the vendor
partial target files package.
vendor_item_list: The list of items to extract from the partial vendor
@@ -960,7 +949,44 @@
rebuild_recovery)
if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
- raise RuntimeError("Incompatible VINTF metadata")
+ raise RuntimeError('Incompatible VINTF metadata')
+
+ partition_map = common.PartitionMapFromTargetFiles(
+ output_target_files_temp_dir)
+
+ # Generate and check for cross-partition violations of sharedUserId
+ # values in APKs. This requires the input target-files packages to contain
+ # *.apk files.
+ shareduid_violation_modules = os.path.join(
+ output_target_files_temp_dir, 'META', 'shareduid_violation_modules.json')
+ with open(shareduid_violation_modules, 'w') as f:
+ violation = find_shareduid_violation.FindShareduidViolation(
+ output_target_files_temp_dir, partition_map)
+
+ # Write the output to a file to enable debugging.
+ f.write(violation)
+
+ # Check for violations across the input builds' partition groups.
+ framework_partitions = item_list_to_partition_set(framework_item_list)
+ vendor_partitions = item_list_to_partition_set(vendor_item_list)
+ shareduid_errors = common.SharedUidPartitionViolations(
+ json.loads(violation), [framework_partitions, vendor_partitions])
+ if shareduid_errors:
+ for error in shareduid_errors:
+ logger.error(error)
+ raise ValueError('sharedUserId APK error. See %s' %
+ shareduid_violation_modules)
+
+ # Run host_init_verifier on the combined init rc files.
+ filtered_partitions = {
+ partition: path
+ for partition, path in partition_map.items()
+ # host_init_verifier checks only the following partitions:
+ if partition in ['system', 'system_ext', 'product', 'vendor', 'odm']
+ }
+ common.RunHostInitVerifier(
+ product_out=output_target_files_temp_dir,
+ partition_map=filtered_partitions)
generate_images(output_target_files_temp_dir, rebuild_recovery)
@@ -1068,8 +1094,10 @@
OPTIONS.output_img = a
elif o == '--output-super-empty':
OPTIONS.output_super_empty = a
- elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
+ elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
OPTIONS.rebuild_recovery = True
+ elif o == '--allow-duplicate-apkapex-keys':
+ OPTIONS.allow_duplicate_apkapex_keys = True
elif o == '--keep-tmp':
OPTIONS.keep_tmp = True
else:
@@ -1097,6 +1125,7 @@
'output-img=',
'output-super-empty=',
'rebuild_recovery',
+ 'allow-duplicate-apkapex-keys',
'keep-tmp',
],
extra_option_handler=option_handler)
@@ -1109,9 +1138,6 @@
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 0000000..471ef25
--- /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 3b68439..6b82d32 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -85,6 +85,13 @@
If not set, generates A/B package for A/B device and non-A/B package for
non-A/B device.
+ -o (--oem_settings) <main_file[,additional_files...]>
+ Comma separated list of files used to specify the expected OEM-specific
+ properties on the OEM partition of the intended device. Multiple expected
+ values can be used by providing multiple files. Only the first dict will
+ be used to compute fingerprint, while the rest will be used to assert
+ OEM-specific properties.
+
Non-A/B OTA specific options
-b (--binary) <file>
@@ -114,13 +121,6 @@
builds for an incremental package. This option is only meaningful when -i
is specified.
- -o (--oem_settings) <main_file[,additional_files...]>
- Comma seperated list of files used to specify the expected OEM-specific
- properties on the OEM partition of the intended device. Multiple expected
- values can be used by providing multiple files. Only the first dict will
- be used to compute fingerprint, while the rest will be used to assert
- OEM-specific properties.
-
--oem_no_mount
For devices with OEM-specific properties but without an OEM partition, do
not mount the OEM partition in the updater-script. This should be very
@@ -202,26 +202,38 @@
ones. Should only be used if caller knows it's safe to do so (e.g. all the
postinstall work is to dexopt apps and a data wipe will happen immediately
after). Only meaningful when generating A/B OTAs.
+
+ --partial "<PARTITION> [<PARTITION>[...]]"
+ Generate partial updates, overriding ab_partitions list with the given
+ list.
+
+ --custom_image <custom_partition=custom_image>
+ Use the specified custom_image to update custom_partition when generating
+ an A/B OTA package. e.g. "--custom_image oem=oem.img --custom_image
+ cus=cus_test.img"
"""
from __future__ import print_function
-import collections
-import copy
-import itertools
import logging
import multiprocessing
+import os
import os.path
+import re
import shlex
import shutil
import struct
+import subprocess
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 +241,16 @@
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 +266,27 @@
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
+OPTIONS.disable_verity_computation = False
+OPTIONS.partial = None
+OPTIONS.custom_images = {}
-
-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']
@@ -398,6 +403,8 @@
cmd.extend(["--source_image", source_file])
if OPTIONS.disable_fec_computation:
cmd.extend(["--disable_fec_computation", "true"])
+ if OPTIONS.disable_verity_computation:
+ cmd.extend(["--disable_verity_computation", "true"])
cmd.extend(additional_args)
self._Run(cmd)
@@ -485,13 +492,6 @@
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 +504,6 @@
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,360 +609,46 @@
return (payload_offset, metadata_total)
-class NonAbOtaPropertyFiles(PropertyFiles):
- """The property-files for non-A/B OTA.
+def UpdatesInfoForSpecialUpdates(content, partitions_filter,
+ delete_keys=None):
+ """ Updates info file for secondary payload generation, partial update, etc.
- 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.
+ Scan each line in the info file, and remove the unwanted partitions from
+ the dynamic partition list in the related properties. e.g.
+ "super_google_dynamic_partitions_partition_list=system vendor product"
+ will become "super_google_dynamic_partitions_partition_list=system".
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.
+ content: The content of the input info file. e.g. misc_info.txt.
+ partitions_filter: A function to filter the desired partitions from a given
+ list
+ delete_keys: A list of keys to delete in the info file
+
+ Returns:
+ A string of the updated info content.
"""
- 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()
+ output_list = []
+ # The suffix in partition_list variables that follows the name of the
+ # partition group.
+ list_suffix = 'partition_list'
+ for line in content.splitlines():
+ if line.startswith('#') or '=' not in line:
+ output_list.append(line)
+ continue
+ key, value = line.strip().split('=', 1)
- 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)
+ if delete_keys and key in delete_keys:
+ pass
+ elif key.endswith(list_suffix):
+ partitions = value.split()
+ # TODO for partial update, partitions in the same group must be all
+ # updated or all omitted
+ partitions = filter(partitions_filter, partitions)
+ output_list.append('{}={}'.format(key, ' '.join(partitions)))
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)
+ output_list.append(line)
+ return '\n'.join(output_list)
def GetTargetFilesZipForSecondaryImages(input_file, skip_postinstall=False):
@@ -1637,49 +672,20 @@
"""
def GetInfoForSecondaryImages(info_file):
- """Updates info file for secondary payload generation.
-
- Scan each line in the info file, and remove the unwanted partitions from
- the dynamic partition list in the related properties. e.g.
- "super_google_dynamic_partitions_partition_list=system vendor product"
- will become "super_google_dynamic_partitions_partition_list=system".
-
- Args:
- info_file: The input info file. e.g. misc_info.txt.
-
- Returns:
- A string of the updated info content.
- """
-
- output_list = []
+ """Updates info file for secondary payload generation."""
with open(info_file) as f:
- lines = f.read().splitlines()
-
- # The suffix in partition_list variables that follows the name of the
- # partition group.
- LIST_SUFFIX = 'partition_list'
- for line in lines:
- if line.startswith('#') or '=' not in line:
- output_list.append(line)
- continue
- key, value = line.strip().split('=', 1)
- if key == 'dynamic_partition_list' or key.endswith(LIST_SUFFIX):
- partitions = value.split()
- 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":
- # Remove virtual_ab flag from secondary payload so that OTA client
- # don't use snapshots for secondary update
- pass
- else:
- output_list.append(line)
- return '\n'.join(output_list)
+ content = f.read()
+ # Remove virtual_ab flag from secondary payload so that OTA client
+ # don't use snapshots for secondary update
+ delete_keys = ['virtual_ab', "virtual_ab_retrofit"]
+ return UpdatesInfoForSpecialUpdates(
+ content, lambda p: p not in SECONDARY_PAYLOAD_SKIPPED_IMAGES,
+ delete_keys)
target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
target_zip = zipfile.ZipFile(target_file, 'w', allowZip64=True)
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
infolist = input_zip.infolist()
input_tmp = common.UnzipTemp(input_file, UNZIP_PATTERN)
@@ -1712,7 +718,8 @@
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):
@@ -1741,7 +748,7 @@
The filename of target-files.zip that doesn't contain postinstall config.
"""
# We should only make a copy if postinstall_config entry exists.
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
if POSTINSTALL_CONFIG not in input_zip.namelist():
return input_file
@@ -1750,6 +757,80 @@
common.ZipDelete(target_file, POSTINSTALL_CONFIG)
return target_file
+def ParseInfoDict(target_file_path):
+ with zipfile.ZipFile(target_file_path, 'r', allowZip64=True) as zfp:
+ return common.LoadInfoDict(zfp)
+
+def GetTargetFilesZipForPartialUpdates(input_file, ab_partitions):
+ """Returns a target-files.zip for partial ota update package generation.
+
+ This function modifies ab_partitions list with the desired partitions before
+ calling the brillo_update_payload script. It also cleans up the reference to
+ the excluded partitions in the info file, e.g misc_info.txt.
+
+ Args:
+ input_file: The input target-files.zip filename.
+ ab_partitions: A list of partitions to include in the partial update
+
+ Returns:
+ The filename of target-files.zip used for partial ota update.
+ """
+
+ def AddImageForPartition(partition_name):
+ """Add the archive name for a given partition to the copy list."""
+ for prefix in ['IMAGES', 'RADIO']:
+ image_path = '{}/{}.img'.format(prefix, partition_name)
+ if image_path in namelist:
+ copy_entries.append(image_path)
+ map_path = '{}/{}.map'.format(prefix, partition_name)
+ if map_path in namelist:
+ copy_entries.append(map_path)
+ return
+
+ raise ValueError("Cannot find {} in input zipfile".format(partition_name))
+
+ with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
+ original_ab_partitions = input_zip.read(
+ AB_PARTITIONS).decode().splitlines()
+ namelist = input_zip.namelist()
+
+ unrecognized_partitions = [partition for partition in ab_partitions if
+ partition not in original_ab_partitions]
+ if unrecognized_partitions:
+ raise ValueError("Unrecognized partitions when generating partial updates",
+ unrecognized_partitions)
+
+ logger.info("Generating partial updates for %s", ab_partitions)
+
+ copy_entries = ['META/update_engine_config.txt']
+ for partition_name in ab_partitions:
+ AddImageForPartition(partition_name)
+
+ # Use zip2zip to avoid extracting the zipfile.
+ partial_target_file = common.MakeTempFile(suffix='.zip')
+ cmd = ['zip2zip', '-i', input_file, '-o', partial_target_file]
+ cmd.extend(['{}:{}'.format(name, name) for name in copy_entries])
+ common.RunAndCheckOutput(cmd)
+
+ partial_target_zip = zipfile.ZipFile(partial_target_file, 'a',
+ allowZip64=True)
+ with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
+ common.ZipWriteStr(partial_target_zip, 'META/ab_partitions.txt',
+ '\n'.join(ab_partitions))
+ for info_file in ['META/misc_info.txt', DYNAMIC_PARTITION_INFO]:
+ if info_file not in input_zip.namelist():
+ logger.warning('Cannot find %s in input zipfile', info_file)
+ continue
+ content = input_zip.read(info_file).decode()
+ modified_info = UpdatesInfoForSpecialUpdates(
+ content, lambda p: p in ab_partitions)
+ common.ZipWriteStr(partial_target_zip, info_file, modified_info)
+
+ # TODO(xunchang) handle 'META/care_map.pb', 'META/postinstall_config.txt'
+ common.ZipClose(partial_target_zip)
+
+ return partial_target_file
+
def GetTargetFilesZipForRetrofitDynamicPartitions(input_file,
super_block_devices,
@@ -1776,7 +857,7 @@
target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
shutil.copyfile(input_file, target_file)
- with zipfile.ZipFile(input_file) as input_zip:
+ with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
namelist = input_zip.namelist()
input_tmp = common.UnzipTemp(input_file, RETROFIT_DAP_UNZIP_PATTERN)
@@ -1795,7 +876,8 @@
"{} 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
@@ -1835,6 +917,107 @@
return target_file
+def GetTargetFilesZipForCustomImagesUpdates(input_file, custom_images):
+ """Returns a target-files.zip for custom partitions update.
+
+ This function modifies ab_partitions list with the desired custom partitions
+ and puts the custom images into the target target-files.zip.
+
+ Args:
+ input_file: The input target-files.zip filename.
+ custom_images: A map of custom partitions and custom images.
+
+ Returns:
+ The filename of a target-files.zip which has renamed the custom images in
+ the IMAGS/ to their partition names.
+ """
+ # Use zip2zip to avoid extracting the zipfile.
+ target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
+ cmd = ['zip2zip', '-i', input_file, '-o', target_file]
+
+ with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
+ namelist = input_zip.namelist()
+
+ # Write {custom_image}.img as {custom_partition}.img.
+ for custom_partition, custom_image in custom_images.items():
+ default_custom_image = '{}.img'.format(custom_partition)
+ if default_custom_image != custom_image:
+ logger.info("Update custom partition '%s' with '%s'",
+ custom_partition, custom_image)
+ # Default custom image need to be deleted first.
+ namelist.remove('IMAGES/{}'.format(default_custom_image))
+ # IMAGES/{custom_image}.img:IMAGES/{custom_partition}.img.
+ cmd.extend(['IMAGES/{}:IMAGES/{}'.format(custom_image,
+ default_custom_image)])
+
+ cmd.extend(['{}:{}'.format(name, name) for name in namelist])
+ common.RunAndCheckOutput(cmd)
+
+ return target_file
+
+def GeneratePartitionTimestampFlags(partition_state):
+ partition_timestamps = [
+ part.partition_name + ":" + part.version
+ for part in partition_state]
+ return ["--partition_timestamps", ",".join(partition_timestamps)]
+
+def GeneratePartitionTimestampFlagsDowngrade(pre_partition_state, post_partition_state):
+ assert pre_partition_state is not None
+ partition_timestamps = {}
+ for part in pre_partition_state:
+ partition_timestamps[part.partition_name] = part.version
+ for part in post_partition_state:
+ partition_timestamps[part.partition_name] = \
+ max(part.version, partition_timestamps[part.partition_name])
+ return [
+ "--partition_timestamps",
+ ",".join([key + ":" + val for (key, val) in partition_timestamps.items()])
+ ]
+
+def IsSparseImage(filepath):
+ with open(filepath, 'rb') as fp:
+ # Magic for android sparse image format
+ # https://source.android.com/devices/bootloader/images
+ return fp.read(4) == b'\x3A\xFF\x26\xED'
+
+def SupportsMainlineGkiUpdates(target_file):
+ """Return True if the build supports MainlineGKIUpdates.
+
+ This function scans the product.img file in IMAGES/ directory for
+ pattern |*/apex/com.android.gki.*.apex|. If there are files
+ matching this pattern, conclude that build supports mainline
+ GKI and return True
+
+ Args:
+ target_file: Path to a target_file.zip, or an extracted directory
+ Return:
+ True if thisb uild supports Mainline GKI Updates.
+ """
+ if target_file is None:
+ return False
+ if os.path.isfile(target_file):
+ target_file = common.UnzipTemp(target_file, ["IMAGES/product.img"])
+ if not os.path.isdir(target_file):
+ assert os.path.isdir(target_file), \
+ "{} must be a path to zip archive or dir containing extracted"\
+ " target_files".format(target_file)
+ image_file = os.path.join(target_file, "IMAGES", "product.img")
+
+ if not os.path.isfile(image_file):
+ return False
+
+ if IsSparseImage(image_file):
+ # Unsparse the image
+ tmp_img = common.MakeTempFile(suffix=".img")
+ subprocess.check_output(["simg2img", image_file, tmp_img])
+ image_file = tmp_img
+
+ cmd = ["debugfs_static", "-R", "ls -p /apex", image_file]
+ output = subprocess.check_output(cmd).decode()
+
+ pattern = re.compile(r"com\.android\.gki\..*\.apex")
+ return pattern.search(output) is not None
+
def GenerateAbOtaPackage(target_file, output_file, source_file=None):
"""Generates an Android OTA package that has A/B update payload."""
# Stage the output zip package for package signing.
@@ -1843,36 +1026,79 @@
else:
staging_file = output_file
output_zip = zipfile.ZipFile(staging_file, "w",
- compression=zipfile.ZIP_DEFLATED)
+ compression=zipfile.ZIP_DEFLATED, allowZip64=True)
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)
+ vendor_prop = source_info.info_dict.get("vendor.build.prop")
+ if vendor_prop and \
+ vendor_prop.GetProp("ro.virtual_ab.compression.enabled") == "true":
+ # TODO(zhangkelvin) Remove this once FEC on VABC is supported
+ logger.info("Virtual AB Compression enabled, disabling FEC")
+ OPTIONS.disable_fec_computation = True
+ OPTIONS.disable_verity_computation = True
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)
+ additional_args = []
+
+ # Prepare custom images.
+ if OPTIONS.custom_images:
+ target_file = GetTargetFilesZipForCustomImagesUpdates(
+ target_file, OPTIONS.custom_images)
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.partial:
+ target_file = GetTargetFilesZipForPartialUpdates(target_file,
+ OPTIONS.partial)
+ additional_args += ["--is_partial_update", "true"]
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).decode().strip().split("\n")
+ # Metadata to comply with Android OTA package format.
+ metadata = GetPackageMetadata(target_info, source_info)
# Generate payload.
payload = Payload()
+ partition_timestamps_flags = []
# Enforce a max timestamp this payload can be applied on top of.
if OPTIONS.downgrade:
max_timestamp = source_info.GetBuildProp("ro.build.date.utc")
+ partition_timestamps_flags = GeneratePartitionTimestampFlagsDowngrade(
+ metadata.precondition.partition_state,
+ metadata.postcondition.partition_state
+ )
else:
- max_timestamp = metadata["post-timestamp"]
- additional_args = ["--max_timestamp", max_timestamp]
+ max_timestamp = str(metadata.postcondition.timestamp)
+ partition_timestamps_flags = GeneratePartitionTimestampFlags(
+ metadata.postcondition.partition_state)
- payload.Generate(target_file, source_file, additional_args)
+ additional_args += ["--max_timestamp", max_timestamp]
+
+ if SupportsMainlineGkiUpdates(source_file):
+ logger.warn("Detected build with mainline GKI, include full boot image.")
+ additional_args.extend(["--full_boot", "true"])
+
+ payload.Generate(
+ target_file,
+ source_file,
+ additional_args + partition_timestamps_flags
+ )
# Sign the payload.
payload_signer = PayloadSigner()
@@ -1890,15 +1116,16 @@
target_file, OPTIONS.skip_postinstall)
secondary_payload = Payload(secondary=True)
secondary_payload.Generate(secondary_target_file,
- additional_args=additional_args)
+ additional_args=["--max_timestamp",
+ max_timestamp])
secondary_payload.Sign(payload_signer)
secondary_payload.WriteToZip(output_zip)
# If dm-verity is supported for the device, copy contents of care_map
# into A/B OTA package.
- target_zip = zipfile.ZipFile(target_file, "r")
+ target_zip = zipfile.ZipFile(target_file, "r", allowZip64=True)
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 +1159,6 @@
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):
@@ -2103,10 +1232,20 @@
OPTIONS.output_metadata_path = a
elif o == "--disable_fec_computation":
OPTIONS.disable_fec_computation = True
+ elif o == "--disable_verity_computation":
+ OPTIONS.disable_verity_computation = True
elif o == "--force_non_ab":
OPTIONS.force_non_ab = True
elif o == "--boot_variable_file":
OPTIONS.boot_variable_file = a
+ elif o == "--partial":
+ partitions = a.split()
+ if not partitions:
+ raise ValueError("Cannot parse partitions in {}".format(a))
+ OPTIONS.partial = partitions
+ elif o == "--custom_image":
+ custom_partition, custom_image = a.split("=")
+ OPTIONS.custom_images[custom_partition] = custom_image
else:
return False
return True
@@ -2143,8 +1282,11 @@
"skip_compatibility_check",
"output_metadata_path=",
"disable_fec_computation",
+ "disable_verity_computation",
"force_non_ab",
"boot_variable_file=",
+ "partial=",
+ "custom_image=",
], extra_option_handler=option_handler)
if len(args) != 2:
@@ -2153,13 +1295,6 @@
common.InitLogging()
- if OPTIONS.downgrade:
- # We should only allow downgrading incrementals (as opposed to full).
- # Otherwise the device may go back from arbitrary build with this full
- # OTA package.
- if OPTIONS.incremental_source is None:
- raise ValueError("Cannot generate downgradable full OTAs")
-
# Load the build info dicts from the zip directly or the extracted input
# directory. We don't need to unzip the entire target-files zips, because they
# won't be needed for A/B OTAs (brillo_update_payload does that on its own).
@@ -2170,21 +1305,43 @@
if OPTIONS.extracted_input is not None:
OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.extracted_input)
else:
- with zipfile.ZipFile(args[0], 'r') as input_zip:
- OPTIONS.info_dict = common.LoadInfoDict(input_zip)
+ OPTIONS.info_dict = ParseInfoDict(args[0])
+
+ if OPTIONS.downgrade:
+ # We should only allow downgrading incrementals (as opposed to full).
+ # Otherwise the device may go back from arbitrary build with this full
+ # OTA package.
+ if OPTIONS.incremental_source is None:
+ raise ValueError("Cannot generate downgradable full OTAs")
+
+
+ # TODO(xunchang) for retrofit and partial updates, maybe we should rebuild the
+ # target-file and reload the info_dict. So the info will be consistent with
+ # the modified target-file.
logger.info("--- target info ---")
common.DumpInfoDict(OPTIONS.info_dict)
+
# Load the source build dict if applicable.
if OPTIONS.incremental_source is not None:
OPTIONS.target_info_dict = OPTIONS.info_dict
- with zipfile.ZipFile(OPTIONS.incremental_source, 'r') as source_zip:
- OPTIONS.source_info_dict = common.LoadInfoDict(source_zip)
+ OPTIONS.source_info_dict = ParseInfoDict(OPTIONS.incremental_source)
logger.info("--- source info ---")
common.DumpInfoDict(OPTIONS.source_info_dict)
+ if OPTIONS.partial:
+ OPTIONS.info_dict['ab_partitions'] = \
+ list(
+ set(OPTIONS.info_dict['ab_partitions']) & set(OPTIONS.partial)
+ )
+ if OPTIONS.source_info_dict:
+ OPTIONS.source_info_dict['ab_partitions'] = \
+ list(
+ set(OPTIONS.source_info_dict['ab_partitions']) & set(OPTIONS.partial)
+ )
+
# Load OEM dicts if provided.
OPTIONS.oem_dicts = _LoadOemDicts(OPTIONS.oem_source)
@@ -2192,7 +1349,7 @@
# 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 +1402,6 @@
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 0000000..20d3091
--- /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 0000000..ff2b2c5
--- /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_package_parser.py b/tools/releasetools/ota_package_parser.py
index 331122b..1e733b9 100755
--- a/tools/releasetools/ota_package_parser.py
+++ b/tools/releasetools/ota_package_parser.py
@@ -215,7 +215,7 @@
logging.basicConfig(level=logging.INFO, format=logging_format)
try:
- with zipfile.ZipFile(args.ota_package, 'r') as package:
+ with zipfile.ZipFile(args.ota_package, 'r', allowZip64=True) as package:
package_parser = OtaPackageParser(package)
package_parser.Analyze()
except:
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
new file mode 100644
index 0000000..cb0f6e6
--- /dev/null
+++ b/tools/releasetools/ota_utils.py
@@ -0,0 +1,621 @@
+# 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 logging
+import os
+import zipfile
+
+import ota_metadata_pb2
+from common import (ZipDelete, ZipClose, OPTIONS, MakeTempFile,
+ ZipWriteStr, BuildInfo, LoadDictionaryFromFile,
+ SignFile, PARTITIONS_WITH_CARE_MAP, PartitionBuildProps,
+ MakeTempDir, RunAndCheckOutput, ExternalError)
+
+logger = logging.getLogger(__name__)
+
+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/*']
+
+# See sysprop.mk. If file is moved, add new search paths here; don't remove
+# existing search paths.
+RAMDISK_BUILD_PROP_REL_PATHS = ['system/etc/ramdisk/build.prop']
+
+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, allowZip64=True) 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', allowZip64=True)
+ 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, allowZip64=True) 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', allowZip64=True)
+ 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, allowZip64=True) 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, allowZip64=True) 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)
+
+
+def GetBootImageTimestamp(boot_img):
+ """
+ Get timestamp from ramdisk within the boot image
+
+ Args:
+ boot_img: the boot image file. Ramdisk must be compressed with lz4 format.
+
+ Return:
+ An integer that corresponds to the timestamp of the boot image, or None
+ if file has unknown format. Raise exception if an unexpected error has
+ occurred.
+ """
+
+ tmp_dir = MakeTempDir('boot_', suffix='.img')
+ try:
+ RunAndCheckOutput(['unpack_bootimg', '--boot_img', boot_img, '--out', tmp_dir])
+ ramdisk = os.path.join(tmp_dir, 'ramdisk')
+ if not os.path.isfile(ramdisk):
+ logger.warning('Unable to get boot image timestamp: no ramdisk in boot')
+ return None
+ uncompressed_ramdisk = os.path.join(tmp_dir, 'uncompressed_ramdisk')
+ RunAndCheckOutput(['lz4', '-d', ramdisk, uncompressed_ramdisk])
+
+ abs_uncompressed_ramdisk = os.path.abspath(uncompressed_ramdisk)
+ extracted_ramdisk = MakeTempDir('extracted_ramdisk')
+ # Use "toybox cpio" instead of "cpio" because the latter invokes cpio from
+ # the host environment.
+ RunAndCheckOutput(['toybox', 'cpio', '-F', abs_uncompressed_ramdisk, '-i'],
+ cwd=extracted_ramdisk)
+
+ prop_file = None
+ for search_path in RAMDISK_BUILD_PROP_REL_PATHS:
+ prop_file = os.path.join(extracted_ramdisk, search_path)
+ if os.path.isfile(prop_file):
+ break
+ logger.warning('Unable to get boot image timestamp: no %s in ramdisk', search_path)
+
+ if not prop_file:
+ return None
+
+ props = PartitionBuildProps.FromBuildPropFile('boot', prop_file)
+ timestamp = props.GetProp('ro.bootimage.build.date.utc')
+ if timestamp:
+ return int(timestamp)
+ logger.warning('Unable to get boot image timestamp: ro.bootimage.build.date.utc is undefined')
+ return None
+
+ except ExternalError as e:
+ logger.warning('Unable to get boot image timestamp: %s', e)
+ return None
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 47360c9..e8674b6 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -383,8 +383,8 @@
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 @@
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 @@
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.
@@ -515,7 +515,7 @@
data,
payload_key,
container_key,
- key_passwords[container_key],
+ key_passwords,
apk_keys,
codename_to_api_level_map,
no_hashtree=True,
@@ -608,22 +608,22 @@
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/.
@@ -813,7 +813,7 @@
keys: A list of public keys to use during OTA package verification.
"""
temp_file = io.BytesIO()
- certs_zip = zipfile.ZipFile(temp_file, "w")
+ certs_zip = zipfile.ZipFile(temp_file, "w", allowZip64=True)
for k in keys:
common.ZipWrite(certs_zip, k)
common.ZipClose(certs_zip)
@@ -967,11 +967,10 @@
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 @@
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 @@
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,))
@@ -1295,7 +1294,7 @@
common.InitLogging()
- input_zip = zipfile.ZipFile(args[0], "r")
+ input_zip = zipfile.ZipFile(args[0], "r", allowZip64=True)
output_zip = zipfile.ZipFile(args[1], "w",
compression=zipfile.ZIP_DEFLATED,
allowZip64=True)
diff --git a/tools/releasetools/test_add_img_to_target_files.py b/tools/releasetools/test_add_img_to_target_files.py
index c82a40b..6b7a7db 100644
--- a/tools/releasetools/test_add_img_to_target_files.py
+++ b/tools/releasetools/test_add_img_to_target_files.py
@@ -93,10 +93,10 @@
# Set up the output zip.
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
AddPackRadioImages(output_zip, images)
- with zipfile.ZipFile(output_file, 'r') as verify_zip:
+ with zipfile.ZipFile(output_file, 'r', allowZip64=True) as verify_zip:
for image in images:
self.assertIn('IMAGES/' + image + '.img', verify_zip.namelist())
@@ -344,12 +344,12 @@
image_paths = self._test_AddCareMapForAbOta()
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
AddCareMapForAbOta(output_zip, ['system', 'vendor'], image_paths)
care_map_name = "META/care_map.pb"
temp_dir = common.MakeTempDir()
- with zipfile.ZipFile(output_file, 'r') as verify_zip:
+ with zipfile.ZipFile(output_file, 'r', allowZip64=True) as verify_zip:
self.assertTrue(care_map_name in verify_zip.namelist())
verify_zip.extract(care_map_name, path=temp_dir)
@@ -367,10 +367,10 @@
image_paths = self._test_AddCareMapForAbOta()
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) 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 7b4a4b0..71f6433 100644
--- a/tools/releasetools/test_apex_utils.py
+++ b/tools/releasetools/test_apex_utils.py
@@ -160,7 +160,7 @@
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'
@@ -174,8 +174,8 @@
@test_utils.SkipIfExternalToolsUnavailable()
def test_ApexApkSigner_noAssetDir(self):
no_asset = common.MakeTempFile(suffix='.apex')
- with zipfile.ZipFile(no_asset, 'w') as output_zip:
- with zipfile.ZipFile(self.apex_with_apk, 'r') as input_zip:
+ with zipfile.ZipFile(no_asset, 'w', allowZip64=True) as output_zip:
+ with zipfile.ZipFile(self.apex_with_apk, 'r', allowZip64=True) as input_zip:
name_list = input_zip.namelist()
for name in name_list:
if not name.startswith('assets'):
diff --git a/tools/releasetools/test_check_target_files_vintf.py b/tools/releasetools/test_check_target_files_vintf.py
index 79f9018..8725dd6 100644
--- a/tools/releasetools/test_check_target_files_vintf.py
+++ b/tools/releasetools/test_check_target_files_vintf.py
@@ -35,20 +35,20 @@
'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 @@
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 @@
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 e4f0812..ecd759c 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -15,10 +15,12 @@
#
import copy
+import json
import os
import subprocess
import tempfile
import time
+import unittest
import zipfile
from hashlib import sha1
@@ -362,7 +364,7 @@
self.assertEqual(int(expected_stat.st_mtime), int(new_stat.st_mtime))
# Reopen the zip file to verify.
- zip_file = zipfile.ZipFile(zip_file_name, "r")
+ zip_file = zipfile.ZipFile(zip_file_name, "r", allowZip64=True)
# Verify the timestamp.
info = zip_file.getinfo(arcname)
@@ -398,7 +400,7 @@
arcname = arcname[1:]
zip_file.close()
- zip_file = zipfile.ZipFile(zip_file_name, "w")
+ zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
try:
sha1_hash = sha1()
@@ -430,7 +432,7 @@
zip_file_name = zip_file.name
zip_file.close()
- zip_file = zipfile.ZipFile(zip_file_name, "w")
+ zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
try:
expected_compress_type = extra_args.get("compress_type",
@@ -474,7 +476,7 @@
arcname_large = arcname_large[1:]
zip_file.close()
- zip_file = zipfile.ZipFile(zip_file_name, "w")
+ zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
try:
sha1_hash = sha1()
@@ -598,7 +600,7 @@
try:
random_string = os.urandom(1024)
- zip_file = zipfile.ZipFile(zip_file_name, "w")
+ zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
# Default perms should be 0o644 when passing the filename.
common.ZipWriteStr(zip_file, "foo", random_string)
# Honor the specified perms.
@@ -643,7 +645,7 @@
try:
common.ZipDelete(zip_file.name, 'Test2')
- with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
+ with zipfile.ZipFile(zip_file.name, 'r', allowZip64=True) as check_zip:
entries = check_zip.namelist()
self.assertTrue('Test1' in entries)
self.assertFalse('Test2' in entries)
@@ -651,21 +653,21 @@
self.assertRaises(
common.ExternalError, common.ZipDelete, zip_file.name, 'Test2')
- with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
+ with zipfile.ZipFile(zip_file.name, 'r', allowZip64=True) as check_zip:
entries = check_zip.namelist()
self.assertTrue('Test1' in entries)
self.assertFalse('Test2' in entries)
self.assertTrue('Test3' in entries)
common.ZipDelete(zip_file.name, ['Test3'])
- with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
+ with zipfile.ZipFile(zip_file.name, 'r', allowZip64=True) as check_zip:
entries = check_zip.namelist()
self.assertTrue('Test1' in entries)
self.assertFalse('Test2' in entries)
self.assertFalse('Test3' in entries)
common.ZipDelete(zip_file.name, ['Test1', 'Test2'])
- with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
+ with zipfile.ZipFile(zip_file.name, 'r', allowZip64=True) as check_zip:
entries = check_zip.namelist()
self.assertFalse('Test1' in entries)
self.assertFalse('Test2' in entries)
@@ -833,7 +835,7 @@
if additional is None:
additional = []
target_files = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.writestr('META/apkcerts.txt', apkcerts_txt)
for entry in additional:
target_files_zip.writestr(entry, '')
@@ -841,7 +843,7 @@
def test_ReadApkCerts_NoncompressedApks(self):
target_files = self._write_apkcerts_txt(self.APKCERTS_TXT1)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
certmap, ext = common.ReadApkCerts(input_zip)
self.assertDictEqual(self.APKCERTS_CERTMAP1, certmap)
@@ -854,7 +856,7 @@
self.APKCERTS_TXT2,
['Compressed1.apk.gz', 'Compressed3.apk'])
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
certmap, ext = common.ReadApkCerts(input_zip)
self.assertDictEqual(self.APKCERTS_CERTMAP2, certmap)
@@ -864,7 +866,7 @@
target_files = self._write_apkcerts_txt(
self.APKCERTS_TXT3, ['Compressed4.apk.xz'])
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
certmap, ext = common.ReadApkCerts(input_zip)
self.assertDictEqual(self.APKCERTS_CERTMAP3, certmap)
@@ -875,7 +877,7 @@
self.APKCERTS_TXT1 + self.APKCERTS_TXT2,
['Compressed1.apk.gz', 'Compressed3.apk'])
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
certmap, ext = common.ReadApkCerts(input_zip)
certmap_merged = self.APKCERTS_CERTMAP1.copy()
@@ -888,7 +890,7 @@
self.APKCERTS_TXT2 + self.APKCERTS_TXT3,
['Compressed1.apk.gz', 'Compressed4.apk.xz'])
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
self.assertRaises(ValueError, common.ReadApkCerts, input_zip)
def test_ReadApkCerts_MismatchingKeys(self):
@@ -898,12 +900,12 @@
)
target_files = self._write_apkcerts_txt(malformed_apkcerts_txt)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
self.assertRaises(ValueError, common.ReadApkCerts, input_zip)
def test_ReadApkCerts_WithWithoutOptionalFields(self):
target_files = self._write_apkcerts_txt(self.APKCERTS_TXT4)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
certmap, ext = common.ReadApkCerts(input_zip)
self.assertDictEqual(self.APKCERTS_CERTMAP4, certmap)
@@ -972,7 +974,7 @@
@test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_emptyBlockMapFile(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.write(
test_utils.construct_sparse_image([
(0xCAC1, 6),
@@ -984,7 +986,7 @@
target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
tempdir = common.UnzipTemp(target_files)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
self.assertDictEqual(
@@ -994,6 +996,55 @@
},
sparse_image.file_map)
+ def test_PartitionMapFromTargetFiles(self):
+ target_files_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(target_files_dir, 'SYSTEM'))
+ os.makedirs(os.path.join(target_files_dir, 'SYSTEM', 'vendor'))
+ os.makedirs(os.path.join(target_files_dir, 'PRODUCT'))
+ os.makedirs(os.path.join(target_files_dir, 'SYSTEM', 'product'))
+ os.makedirs(os.path.join(target_files_dir, 'SYSTEM', 'vendor', 'odm'))
+ os.makedirs(os.path.join(target_files_dir, 'VENDOR_DLKM'))
+ partition_map = common.PartitionMapFromTargetFiles(target_files_dir)
+ self.assertDictEqual(
+ partition_map,
+ {
+ 'system': 'SYSTEM',
+ 'vendor': 'SYSTEM/vendor',
+ # Prefer PRODUCT over SYSTEM/product
+ 'product': 'PRODUCT',
+ 'odm': 'SYSTEM/vendor/odm',
+ 'vendor_dlkm': 'VENDOR_DLKM',
+ # No system_ext or odm_dlkm
+ })
+
+ def test_SharedUidPartitionViolations(self):
+ uid_dict = {
+ 'android.uid.phone': {
+ 'system': ['system_phone.apk'],
+ 'system_ext': ['system_ext_phone.apk'],
+ },
+ 'android.uid.wifi': {
+ 'vendor': ['vendor_wifi.apk'],
+ 'odm': ['odm_wifi.apk'],
+ },
+ }
+ errors = common.SharedUidPartitionViolations(
+ uid_dict, [('system', 'system_ext'), ('vendor', 'odm')])
+ self.assertEqual(errors, [])
+
+ def test_SharedUidPartitionViolations_Violation(self):
+ uid_dict = {
+ 'android.uid.phone': {
+ 'system': ['system_phone.apk'],
+ 'vendor': ['vendor_phone.apk'],
+ },
+ }
+ errors = common.SharedUidPartitionViolations(
+ uid_dict, [('system', 'system_ext'), ('vendor', 'odm')])
+ self.assertIn(
+ ('APK sharedUserId "android.uid.phone" found across partition groups '
+ 'in partitions "system,vendor"'), errors)
+
def test_GetSparseImage_missingImageFile(self):
self.assertRaises(
AssertionError, common.GetSparseImage, 'system2', self.testdata_dir,
@@ -1005,7 +1056,7 @@
@test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_missingBlockMapFile(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.write(
test_utils.construct_sparse_image([
(0xCAC1, 6),
@@ -1016,7 +1067,7 @@
target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
tempdir = common.UnzipTemp(target_files)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
self.assertRaises(
AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
False)
@@ -1025,7 +1076,7 @@
def test_GetSparseImage_sharedBlocks_notAllowed(self):
"""Tests the case of having overlapping blocks but disallowed."""
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.write(
test_utils.construct_sparse_image([(0xCAC2, 16)]),
arcname='IMAGES/system.img')
@@ -1039,7 +1090,7 @@
target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
tempdir = common.UnzipTemp(target_files)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
self.assertRaises(
AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
False)
@@ -1048,7 +1099,7 @@
def test_GetSparseImage_sharedBlocks_allowed(self):
"""Tests the case for target using BOARD_EXT4_SHARE_DUP_BLOCKS := true."""
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
# Construct an image with a care_map of "0-5 9-12".
target_files_zip.write(
test_utils.construct_sparse_image([(0xCAC2, 16)]),
@@ -1063,7 +1114,7 @@
target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
tempdir = common.UnzipTemp(target_files)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
sparse_image = common.GetSparseImage('system', tempdir, input_zip, True)
self.assertDictEqual(
@@ -1093,7 +1144,7 @@
def test_GetSparseImage_incompleteRanges(self):
"""Tests the case of ext4 images with holes."""
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.write(
test_utils.construct_sparse_image([(0xCAC2, 16)]),
arcname='IMAGES/system.img')
@@ -1107,7 +1158,7 @@
target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
tempdir = common.UnzipTemp(target_files)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
self.assertEqual(
@@ -1118,7 +1169,7 @@
@test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_systemRootImage_filenameWithExtraLeadingSlash(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.write(
test_utils.construct_sparse_image([(0xCAC2, 16)]),
arcname='IMAGES/system.img')
@@ -1135,7 +1186,7 @@
target_files_zip.writestr('SYSTEM/app/file3', os.urandom(4096 * 4))
tempdir = common.UnzipTemp(target_files)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
self.assertEqual(
@@ -1148,7 +1199,7 @@
@test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_systemRootImage_nonSystemFiles(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.write(
test_utils.construct_sparse_image([(0xCAC2, 16)]),
arcname='IMAGES/system.img')
@@ -1162,7 +1213,7 @@
target_files_zip.writestr('ROOT/init.rc', os.urandom(4096 * 4))
tempdir = common.UnzipTemp(target_files)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
self.assertEqual(
@@ -1173,7 +1224,7 @@
@test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_fileNotFound(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.write(
test_utils.construct_sparse_image([(0xCAC2, 16)]),
arcname='IMAGES/system.img')
@@ -1185,7 +1236,7 @@
target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 7))
tempdir = common.UnzipTemp(target_files)
- with zipfile.ZipFile(target_files, 'r') as input_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as input_zip:
self.assertRaises(
AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
False)
@@ -1273,7 +1324,7 @@
@staticmethod
def _test_LoadInfoDict_createTargetFiles(info_dict, fstab_path):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
info_values = ''.join(
['{}={}\n'.format(k, v) for k, v in sorted(info_dict.items())])
common.ZipWriteStr(target_files_zip, 'META/misc_info.txt', info_values)
@@ -1293,7 +1344,7 @@
target_files = self._test_LoadInfoDict_createTargetFiles(
self.INFO_DICT_DEFAULT,
'BOOT/RAMDISK/system/etc/recovery.fstab')
- with zipfile.ZipFile(target_files, 'r') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as target_files_zip:
loaded_dict = common.LoadInfoDict(target_files_zip)
self.assertEqual(3, loaded_dict['recovery_api_version'])
self.assertEqual(2, loaded_dict['fstab_version'])
@@ -1304,7 +1355,7 @@
target_files = self._test_LoadInfoDict_createTargetFiles(
self.INFO_DICT_DEFAULT,
'BOOT/RAMDISK/etc/recovery.fstab')
- with zipfile.ZipFile(target_files, 'r') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as target_files_zip:
loaded_dict = common.LoadInfoDict(target_files_zip)
self.assertEqual(3, loaded_dict['recovery_api_version'])
self.assertEqual(2, loaded_dict['fstab_version'])
@@ -1345,7 +1396,7 @@
target_files = self._test_LoadInfoDict_createTargetFiles(
info_dict,
'RECOVERY/RAMDISK/system/etc/recovery.fstab')
- with zipfile.ZipFile(target_files, 'r') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as target_files_zip:
loaded_dict = common.LoadInfoDict(target_files_zip)
self.assertEqual(3, loaded_dict['recovery_api_version'])
self.assertEqual(2, loaded_dict['fstab_version'])
@@ -1361,7 +1412,7 @@
target_files = self._test_LoadInfoDict_createTargetFiles(
info_dict,
'RECOVERY/RAMDISK/system/etc/recovery.fstab')
- with zipfile.ZipFile(target_files, 'r') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as target_files_zip:
loaded_dict = common.LoadInfoDict(target_files_zip)
self.assertEqual(3, loaded_dict['recovery_api_version'])
self.assertEqual(2, loaded_dict['fstab_version'])
@@ -1375,7 +1426,7 @@
target_files = self._test_LoadInfoDict_createTargetFiles(
info_dict,
'RECOVERY/RAMDISK/system/etc/recovery.fstab')
- with zipfile.ZipFile(target_files, 'r') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as target_files_zip:
loaded_dict = common.LoadInfoDict(target_files_zip)
self.assertEqual(3, loaded_dict['recovery_api_version'])
self.assertEqual(2, loaded_dict['fstab_version'])
@@ -1387,7 +1438,7 @@
self.INFO_DICT_DEFAULT,
'BOOT/RAMDISK/system/etc/recovery.fstab')
common.ZipDelete(target_files, 'META/misc_info.txt')
- with zipfile.ZipFile(target_files, 'r') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as target_files_zip:
self.assertRaises(ValueError, common.LoadInfoDict, target_files_zip)
@test_utils.SkipIfExternalToolsUnavailable()
@@ -1411,19 +1462,23 @@
target_files = self._test_LoadInfoDict_createTargetFiles(
self.INFO_DICT_DEFAULT,
'BOOT/RAMDISK/system/etc/recovery.fstab')
- with zipfile.ZipFile(target_files, 'r') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'r', allowZip64=True) as target_files_zip:
self.assertRaises(
AssertionError, common.LoadInfoDict, target_files_zip, True)
def test_MergeDynamicPartitionInfoDicts_ReturnsMergedDict(self):
framework_dict = {
+ 'use_dynamic_partitions': 'true',
'super_partition_groups': 'group_a',
'dynamic_partition_list': 'system',
'super_group_a_partition_list': 'system',
}
vendor_dict = {
+ 'use_dynamic_partitions': 'true',
'super_partition_groups': 'group_a group_b',
'dynamic_partition_list': 'vendor product',
+ 'super_block_devices': 'super',
+ 'super_super_device_size': '3000',
'super_group_a_partition_list': 'vendor',
'super_group_a_group_size': '1000',
'super_group_b_partition_list': 'product',
@@ -1433,8 +1488,11 @@
framework_dict=framework_dict,
vendor_dict=vendor_dict)
expected_merged_dict = {
+ 'use_dynamic_partitions': 'true',
'super_partition_groups': 'group_a group_b',
- 'dynamic_partition_list': 'system vendor product',
+ 'dynamic_partition_list': 'product system vendor',
+ 'super_block_devices': 'super',
+ 'super_super_device_size': '3000',
'super_group_a_partition_list': 'system vendor',
'super_group_a_group_size': '1000',
'super_group_b_partition_list': 'product',
@@ -1444,12 +1502,14 @@
def test_MergeDynamicPartitionInfoDicts_IgnoringFrameworkGroupSize(self):
framework_dict = {
+ 'use_dynamic_partitions': 'true',
'super_partition_groups': 'group_a',
'dynamic_partition_list': 'system',
'super_group_a_partition_list': 'system',
'super_group_a_group_size': '5000',
}
vendor_dict = {
+ 'use_dynamic_partitions': 'true',
'super_partition_groups': 'group_a group_b',
'dynamic_partition_list': 'vendor product',
'super_group_a_partition_list': 'vendor',
@@ -1461,8 +1521,9 @@
framework_dict=framework_dict,
vendor_dict=vendor_dict)
expected_merged_dict = {
+ 'use_dynamic_partitions': 'true',
'super_partition_groups': 'group_a group_b',
- 'dynamic_partition_list': 'system vendor product',
+ 'dynamic_partition_list': 'product system vendor',
'super_group_a_partition_list': 'system vendor',
'super_group_a_group_size': '1000',
'super_group_b_partition_list': 'product',
@@ -1527,6 +1588,88 @@
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 +1679,12 @@
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,
@@ -1621,7 +1764,7 @@
@staticmethod
def get_op_list(output_path):
- with zipfile.ZipFile(output_path) as output_zip:
+ with zipfile.ZipFile(output_path, allowZip64=True) as output_zip:
with output_zip.open('dynamic_partitions_op_list') as op_list:
return [line.decode().strip() for line in op_list.readlines()
if not line.startswith(b'#')]
@@ -1641,7 +1784,7 @@
MockBlockDifference("vendor", FakeSparseImage(1 * GiB))]
dp_diff = common.DynamicPartitionsDifference(target_info, block_diffs)
- with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+ with zipfile.ZipFile(self.output_path, 'w', allowZip64=True) as output_zip:
dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
self.assertEqual(str(self.script).strip(), """
@@ -1689,7 +1832,7 @@
dp_diff = common.DynamicPartitionsDifference(target_info,
block_diffs=[],
source_info_dict=source_info)
- with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+ with zipfile.ZipFile(self.output_path, 'w', allowZip64=True) as output_zip:
dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
lines = self.get_op_list(self.output_path)
@@ -1733,7 +1876,7 @@
dp_diff = common.DynamicPartitionsDifference(target_info, block_diffs,
source_info_dict=source_info)
- with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+ with zipfile.ZipFile(self.output_path, 'w', allowZip64=True) as output_zip:
dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
metadata_idx = self.script.lines.index(
@@ -1804,7 +1947,7 @@
dp_diff = common.DynamicPartitionsDifference(target_info, block_diffs,
source_info_dict=source_info)
- with zipfile.ZipFile(self.output_path, 'w') as output_zip:
+ with zipfile.ZipFile(self.output_path, 'w', allowZip64=True) as output_zip:
dp_diff.WriteScript(self.script, output_zip, write_verify_script=True)
self.assertNotIn("block_image_update", str(self.script),
@@ -1827,7 +1970,7 @@
@staticmethod
def _BuildZipFile(entries):
input_file = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(input_file, 'w') as input_zip:
+ with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
for name, content in entries.items():
input_zip.writestr(name, content)
@@ -1844,7 +1987,7 @@
'ODM/etc/build.prop': '\n'.join(build_prop),
})
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
placeholder_values = {
'ro.boot.product.device_name': ['std', 'pro']
}
@@ -1876,7 +2019,7 @@
'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
})
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
placeholder_values = {
'ro.boot.product.device_name': 'std'
}
@@ -1891,7 +2034,7 @@
'ro.product.odm.name': 'product1',
}, partition_props.build_props)
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
placeholder_values = {
'ro.boot.product.device_name': 'pro'
}
@@ -1912,7 +2055,7 @@
'ODM/etc/build.prop': '\n'.join(build_prop),
})
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
partition_props = common.PartitionBuildProps.FromInputFile(
input_zip, 'odm')
@@ -1955,7 +2098,7 @@
'ODM/etc/build_product2.prop': '\n'.join(product2_prop),
})
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
placeholder_values = {
'ro.boot.product.device_name': 'std',
'ro.boot.product.product_name': 'product1',
@@ -1972,7 +2115,7 @@
'ro.product.odm.name': 'product1'
}, partition_props.build_props)
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
placeholder_values = {
'ro.boot.product.device_name': 'pro',
'ro.boot.product.product_name': 'product2',
@@ -2006,7 +2149,7 @@
'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
})
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
placeholder_values = {
'ro.boot.product.device_name': 'std',
}
@@ -2043,7 +2186,7 @@
'ODM/etc/build_product2.prop': '\n'.join(product2_prop),
})
- with zipfile.ZipFile(input_file, 'r') as input_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
placeholder_values = {
'ro.boot.product.device_name': 'std',
'ro.boot.product.product_name': 'product1',
diff --git a/tools/releasetools/test_merge_target_files.py b/tools/releasetools/test_merge_target_files.py
index ff8593b..7ea7f96 100644
--- a/tools/releasetools/test_merge_target_files.py
+++ b/tools/releasetools/test_merge_target_files.py
@@ -117,6 +117,15 @@
DEFAULT_FRAMEWORK_MISC_INFO_KEYS,
vendor_item_list))
+ def test_validate_config_lists_ReturnsFalseIfSharedExtractedPartitionImage(
+ self):
+ vendor_item_list = list(DEFAULT_VENDOR_ITEM_LIST)
+ vendor_item_list.append('IMAGES/system.img')
+ self.assertFalse(
+ validate_config_lists(DEFAULT_FRAMEWORK_ITEM_LIST,
+ DEFAULT_FRAMEWORK_MISC_INFO_KEYS,
+ vendor_item_list))
+
def test_validate_config_lists_ReturnsFalseIfBadSystemMiscInfoKeys(self):
for bad_key in ['dynamic_partition_list', 'super_partition_groups']:
framework_misc_info_keys = list(DEFAULT_FRAMEWORK_MISC_INFO_KEYS)
@@ -144,8 +153,7 @@
process_apex_keys_apk_certs_common(framework_dir, vendor_dir, output_dir,
set(['product', 'system', 'system_ext']),
- set(['odm', 'vendor']),
- 'apexkeys.txt')
+ set(['odm', 'vendor']), 'apexkeys.txt')
merged_entries = []
merged_path = os.path.join(self.testdata_dir, 'apexkeys_merge.txt')
@@ -180,8 +188,7 @@
self.assertRaises(ValueError, process_apex_keys_apk_certs_common,
framework_dir, conflict_dir, output_dir,
set(['product', 'system', 'system_ext']),
- set(['odm', 'vendor']),
- 'apexkeys.txt')
+ set(['odm', 'vendor']), 'apexkeys.txt')
def test_process_apex_keys_apk_certs_HandlesApkCertsSyntax(self):
output_dir = common.MakeTempDir()
@@ -201,8 +208,7 @@
process_apex_keys_apk_certs_common(framework_dir, vendor_dir, output_dir,
set(['product', 'system', 'system_ext']),
- set(['odm', 'vendor']),
- 'apkcerts.txt')
+ set(['odm', 'vendor']), 'apkcerts.txt')
merged_entries = []
merged_path = os.path.join(self.testdata_dir, 'apkcerts_merge.txt')
diff --git a/tools/releasetools/test_non_ab_ota.py b/tools/releasetools/test_non_ab_ota.py
new file mode 100644
index 0000000..5207e2f
--- /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 7783f96..8bf7778 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -20,20 +20,26 @@
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,
+ GetTargetFilesZipForCustomImagesUpdates,
+ GetTargetFilesZipForPartialUpdates,
+ GetTargetFilesZipForSecondaryImages,
+ GetTargetFilesZipWithoutPostinstallConfig,
+ Payload, PayloadSigner, POSTINSTALL_CONFIG,
+ StreamingPropertyFiles, AB_PARTITIONS)
+from test_utils import PropertyFilesTestCase
def construct_target_files(secondary=False):
"""Returns a target-files.zip file for generating OTA packages."""
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
# META/update_engine_config.txt
target_files_zip.writestr(
'META/update_engine_config.txt',
@@ -61,7 +67,7 @@
'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 +148,13 @@
),
'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 +168,71 @@
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 +240,55 @@
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 +308,7 @@
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 +322,22 @@
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)
@@ -415,7 +419,7 @@
'super_google_dynamic_partitions_partition_list=system vendor product',
])
- with zipfile.ZipFile(input_file, 'a') as append_zip:
+ with zipfile.ZipFile(input_file, 'a', allowZip64=True) as append_zip:
common.ZipWriteStr(append_zip, 'META/misc_info.txt', misc_info)
common.ZipWriteStr(append_zip, 'META/dynamic_partitions_info.txt',
dynamic_partitions_info)
@@ -448,6 +452,86 @@
updated_dynamic_partitions_info)
@test_utils.SkipIfExternalToolsUnavailable()
+ def test_GetTargetFilesZipForPartialUpdates_singlePartition(self):
+ input_file = construct_target_files()
+ with zipfile.ZipFile(input_file, 'a', allowZip64=True) as append_zip:
+ common.ZipWriteStr(append_zip, 'IMAGES/system.map', 'fake map')
+
+ target_file = GetTargetFilesZipForPartialUpdates(input_file, ['system'])
+ with zipfile.ZipFile(target_file) as verify_zip:
+ namelist = verify_zip.namelist()
+ ab_partitions = verify_zip.read('META/ab_partitions.txt').decode()
+
+ self.assertIn('META/ab_partitions.txt', namelist)
+ self.assertIn('META/update_engine_config.txt', namelist)
+ self.assertIn('IMAGES/system.img', namelist)
+ self.assertIn('IMAGES/system.map', namelist)
+
+ self.assertNotIn('IMAGES/boot.img', namelist)
+ self.assertNotIn('IMAGES/system_other.img', namelist)
+ self.assertNotIn('RADIO/bootloader.img', namelist)
+ self.assertNotIn('RADIO/modem.img', namelist)
+
+ self.assertEqual('system', ab_partitions)
+
+ @test_utils.SkipIfExternalToolsUnavailable()
+ def test_GetTargetFilesZipForPartialUpdates_unrecognizedPartition(self):
+ input_file = construct_target_files()
+ self.assertRaises(ValueError, GetTargetFilesZipForPartialUpdates,
+ input_file, ['product'])
+
+ @test_utils.SkipIfExternalToolsUnavailable()
+ def test_GetTargetFilesZipForPartialUpdates_dynamicPartitions(self):
+ input_file = construct_target_files(secondary=True)
+ misc_info = '\n'.join([
+ 'use_dynamic_partition_size=true',
+ 'use_dynamic_partitions=true',
+ 'dynamic_partition_list=system vendor product',
+ 'super_partition_groups=google_dynamic_partitions',
+ 'super_google_dynamic_partitions_group_size=4873781248',
+ 'super_google_dynamic_partitions_partition_list=system vendor product',
+ ])
+ dynamic_partitions_info = '\n'.join([
+ 'super_partition_groups=google_dynamic_partitions',
+ 'super_google_dynamic_partitions_group_size=4873781248',
+ 'super_google_dynamic_partitions_partition_list=system vendor product',
+ ])
+
+ with zipfile.ZipFile(input_file, 'a', allowZip64=True) as append_zip:
+ common.ZipWriteStr(append_zip, 'META/misc_info.txt', misc_info)
+ common.ZipWriteStr(append_zip, 'META/dynamic_partitions_info.txt',
+ dynamic_partitions_info)
+
+ target_file = GetTargetFilesZipForPartialUpdates(input_file,
+ ['boot', 'system'])
+ with zipfile.ZipFile(target_file) as verify_zip:
+ namelist = verify_zip.namelist()
+ ab_partitions = verify_zip.read('META/ab_partitions.txt').decode()
+ updated_misc_info = verify_zip.read('META/misc_info.txt').decode()
+ updated_dynamic_partitions_info = verify_zip.read(
+ 'META/dynamic_partitions_info.txt').decode()
+
+ self.assertIn('META/ab_partitions.txt', namelist)
+ self.assertIn('IMAGES/boot.img', namelist)
+ self.assertIn('IMAGES/system.img', namelist)
+ self.assertIn('META/misc_info.txt', namelist)
+ self.assertIn('META/dynamic_partitions_info.txt', namelist)
+
+ self.assertNotIn('IMAGES/system_other.img', namelist)
+ self.assertNotIn('RADIO/bootloader.img', namelist)
+ self.assertNotIn('RADIO/modem.img', namelist)
+
+ # Check the vendor & product are removed from the partitions list.
+ expected_misc_info = misc_info.replace('system vendor product',
+ 'system')
+ expected_dynamic_partitions_info = dynamic_partitions_info.replace(
+ 'system vendor product', 'system')
+ self.assertEqual(expected_misc_info, updated_misc_info)
+ self.assertEqual(expected_dynamic_partitions_info,
+ updated_dynamic_partitions_info)
+ self.assertEqual('boot\nsystem', ab_partitions)
+
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetTargetFilesZipWithoutPostinstallConfig(self):
input_file = construct_target_files()
target_file = GetTargetFilesZipWithoutPostinstallConfig(input_file)
@@ -462,6 +546,46 @@
with zipfile.ZipFile(target_file) as verify_zip:
self.assertNotIn(POSTINSTALL_CONFIG, verify_zip.namelist())
+ @test_utils.SkipIfExternalToolsUnavailable()
+ def test_GetTargetFilesZipForCustomImagesUpdates_oemDefaultImage(self):
+ input_file = construct_target_files()
+ with zipfile.ZipFile(input_file, 'a', allowZip64=True) as append_zip:
+ common.ZipWriteStr(append_zip, 'IMAGES/oem.img', 'oem')
+ common.ZipWriteStr(append_zip, 'IMAGES/oem_test.img', 'oem_test')
+
+ target_file = GetTargetFilesZipForCustomImagesUpdates(
+ input_file, {'oem': 'oem.img'})
+
+ with zipfile.ZipFile(target_file) as verify_zip:
+ namelist = verify_zip.namelist()
+ ab_partitions = verify_zip.read('META/ab_partitions.txt').decode()
+ oem_image = verify_zip.read('IMAGES/oem.img').decode()
+
+ self.assertIn('META/ab_partitions.txt', namelist)
+ self.assertEqual('boot\nsystem\nvendor\nbootloader\nmodem', ab_partitions)
+ self.assertIn('IMAGES/oem.img', namelist)
+ self.assertEqual('oem', oem_image)
+
+ @test_utils.SkipIfExternalToolsUnavailable()
+ def test_GetTargetFilesZipForCustomImagesUpdates_oemTestImage(self):
+ input_file = construct_target_files()
+ with zipfile.ZipFile(input_file, 'a', allowZip64=True) as append_zip:
+ common.ZipWriteStr(append_zip, 'IMAGES/oem.img', 'oem')
+ common.ZipWriteStr(append_zip, 'IMAGES/oem_test.img', 'oem_test')
+
+ target_file = GetTargetFilesZipForCustomImagesUpdates(
+ input_file, {'oem': 'oem_test.img'})
+
+ with zipfile.ZipFile(target_file) as verify_zip:
+ namelist = verify_zip.namelist()
+ ab_partitions = verify_zip.read('META/ab_partitions.txt').decode()
+ oem_image = verify_zip.read('IMAGES/oem.img').decode()
+
+ self.assertIn('META/ab_partitions.txt', namelist)
+ self.assertEqual('boot\nsystem\nvendor\nbootloader\nmodem', ab_partitions)
+ self.assertIn('IMAGES/oem.img', namelist)
+ self.assertEqual('oem_test', oem_image)
+
def _test_FinalizeMetadata(self, large_entry=False):
entries = [
'required-entry1',
@@ -470,20 +594,20 @@
zip_file = PropertyFilesTest.construct_zip_package(entries)
# Add a large entry of 1 GiB if requested.
if large_entry:
- with zipfile.ZipFile(zip_file, 'a') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'a', allowZip64=True) as zip_fp:
zip_fp.writestr(
# Using 'zoo' so that the entry stays behind others after signing.
'zoo',
'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):
@@ -512,7 +636,7 @@
'optional-entry2',
]
zip_file = PropertyFilesTest.construct_zip_package(entries)
- with zipfile.ZipFile(zip_file, 'a') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'a', allowZip64=True) as zip_fp:
zip_fp.writestr(
# 'foo-entry1' will appear ahead of all other entries (in alphabetical
# order) after the signing, which will in turn trigger the
@@ -521,66 +645,13 @@
'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 +670,7 @@
)
-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):
@@ -642,11 +680,11 @@
)
zip_file = self.construct_zip_package(entries)
property_files = TestPropertyFiles()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
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):
@@ -658,11 +696,11 @@
)
zip_file = self.construct_zip_package(entries)
property_files = TestPropertyFiles()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
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):
@@ -671,7 +709,7 @@
)
zip_file = self.construct_zip_package(entries)
property_files = TestPropertyFiles()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
self.assertRaises(KeyError, property_files.Compute, zip_fp)
@test_utils.SkipIfExternalToolsUnavailable()
@@ -680,19 +718,21 @@
'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()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
raw_metadata = property_files.GetPropertyFilesString(
zip_fp, reserve_space=False)
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,10 +743,11 @@
'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()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
# First get the raw metadata string (i.e. without padding space).
raw_metadata = property_files.GetPropertyFilesString(
zip_fp, reserve_space=False)
@@ -737,10 +778,11 @@
'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()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
# First get the raw metadata string (i.e. without padding space).
raw_metadata = property_files.GetPropertyFilesString(
zip_fp, reserve_space=False)
@@ -753,8 +795,8 @@
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()
@@ -782,11 +824,11 @@
)
zip_file = self.construct_zip_package(entries)
property_files = StreamingPropertyFiles()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
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,19 +838,21 @@
'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()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
raw_metadata = property_files.GetPropertyFilesString(
zip_fp, reserve_space=False)
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,10 +862,11 @@
'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()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
# First get the raw metadata string (i.e. without padding space).
raw_metadata = property_files.GetPropertyFilesString(
zip_fp, reserve_space=False)
@@ -834,8 +879,8 @@
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 +894,7 @@
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):
@@ -879,7 +924,7 @@
payload.Sign(payload_signer)
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
payload.WriteToZip(output_zip)
# Find out the payload metadata offset and size.
@@ -944,7 +989,7 @@
payload.Sign(payload_signer)
zip_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(zip_file, 'w') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'w', allowZip64=True) as zip_fp:
# 'payload.bin',
payload.WriteToZip(zip_fp)
@@ -954,6 +999,7 @@
# 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(
@@ -965,13 +1011,13 @@
def test_Compute(self):
zip_file = self.construct_zip_package_withValidPayload()
property_files = AbOtaPropertyFiles()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
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'))
@@ -979,15 +1025,16 @@
def test_Finalize(self):
zip_file = self.construct_zip_package_withValidPayload(with_metadata=True)
property_files = AbOtaPropertyFiles()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) 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'))
@@ -995,57 +1042,7 @@
def test_Verify(self):
zip_file = self.construct_zip_package_withValidPayload(with_metadata=True)
property_files = AbOtaPropertyFiles()
- with zipfile.ZipFile(zip_file, 'r') as zip_fp:
- raw_metadata = property_files.GetPropertyFilesString(
- zip_fp, reserve_space=False)
-
- 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:
+ with zipfile.ZipFile(zip_file, 'r', allowZip64=True) as zip_fp:
raw_metadata = property_files.GetPropertyFilesString(
zip_fp, reserve_space=False)
@@ -1065,7 +1062,7 @@
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 +1080,7 @@
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 +1157,7 @@
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
@@ -1212,7 +1209,7 @@
payload.Sign(PayloadSigner())
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
payload.WriteToZip(output_zip)
import check_ota_package_signature
@@ -1226,7 +1223,7 @@
payload.Sign(PayloadSigner())
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
payload.WriteToZip(output_zip)
import check_ota_package_signature
@@ -1265,7 +1262,7 @@
payload.Sign(PayloadSigner())
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
payload.WriteToZip(output_zip)
with zipfile.ZipFile(output_file) as verify_zip:
@@ -1287,14 +1284,14 @@
payload = self._create_payload_full()
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
self.assertRaises(AssertionError, payload.WriteToZip, output_zip)
# Also test with incremental payload.
payload = self._create_payload_incremental()
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
self.assertRaises(AssertionError, payload.WriteToZip, output_zip)
@test_utils.SkipIfExternalToolsUnavailable()
@@ -1303,7 +1300,7 @@
payload.Sign(PayloadSigner())
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
payload.WriteToZip(output_zip)
with zipfile.ZipFile(output_file) as verify_zip:
@@ -1315,8 +1312,8 @@
# 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,20 +1323,41 @@
'recovery_api_version=3',
'fstab_version=2',
'recovery_as_boot=true',
+ 'ab_update=true',
]
BUILD_PROP = [
- 'ro.build.version.release=version-release',
'ro.build.id=build-id',
'ro.build.version.incremental=version-incremental',
'ro.build.type=build-type',
'ro.build.tags=build-tags',
+ 'ro.build.version.release=version-release',
+ 'ro.build.version.release_or_codename=version-release',
'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 +1486,7 @@
'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 +1494,8 @@
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 +1504,33 @@
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 +1538,8 @@
'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 +1561,22 @@
'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 +1589,22 @@
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 +1614,31 @@
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_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 308172f..18e4858 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -164,15 +164,15 @@
"veritykeyid=id:d24f2590e9abab5cff5f59da4c4f0366e3f43e94\n")
input_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(input_file, 'w') as input_zip:
+ with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
input_zip.writestr('BOOT/cmdline', BOOT_CMDLINE1)
# Test with the first certificate.
cert_file = os.path.join(self.testdata_dir, 'verity.x509.pem')
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(input_file, 'r') as input_zip, \
- zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip, \
+ zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
ReplaceVerityKeyId(input_zip, output_zip, cert_file)
with zipfile.ZipFile(output_file) as output_zip:
@@ -181,8 +181,8 @@
# Test with the second certificate.
cert_file = os.path.join(self.testdata_dir, 'testkey.x509.pem')
- with zipfile.ZipFile(input_file, 'r') as input_zip, \
- zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip, \
+ zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
ReplaceVerityKeyId(input_zip, output_zip, cert_file)
with zipfile.ZipFile(output_file) as output_zip:
@@ -195,12 +195,12 @@
"loop.max_part=7\n")
input_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(input_file, 'w') as input_zip:
+ with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
input_zip.writestr('BOOT/cmdline', BOOT_CMDLINE)
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(input_file, 'r') as input_zip, \
- zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip, \
+ zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
ReplaceVerityKeyId(input_zip, output_zip, None)
with zipfile.ZipFile(output_file) as output_zip:
@@ -284,7 +284,7 @@
]
entry_name = 'SYSTEM/etc/security/otacerts.zip'
output_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(output_file, 'w') as output_zip:
+ with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
WriteOtacerts(output_zip, entry_name, certs)
with zipfile.ZipFile(output_file) as input_zip:
self.assertIn(entry_name, input_zip.namelist())
@@ -294,7 +294,7 @@
def test_CheckApkAndApexKeysAvailable(self):
input_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(input_file, 'w') as input_zip:
+ with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
input_zip.writestr('SYSTEM/app/App1.apk', "App1-content")
input_zip.writestr('SYSTEM/app/App2.apk.gz', "App2-content")
@@ -318,7 +318,7 @@
def test_CheckApkAndApexKeysAvailable_invalidApexKeys(self):
input_file = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(input_file, 'w') as input_zip:
+ with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
input_zip.writestr('SYSTEM/apex/Apex1.apex', "Apex1-content")
input_zip.writestr('SYSTEM/apex/Apex2.apex', "Apex2-content")
@@ -466,10 +466,10 @@
def test_ReadApexKeysInfo(self):
target_files = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.writestr('META/apexkeys.txt', self.APEX_KEYS_TXT)
- with zipfile.ZipFile(target_files) as target_files_zip:
+ with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
@@ -491,10 +491,10 @@
'container_private_key="build/make/target/product/security/testkey2.pk8" '
'partition="system"')
target_files = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
- with zipfile.ZipFile(target_files) as target_files_zip:
+ with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
self.assertRaises(ValueError, ReadApexKeysInfo, target_files_zip)
def test_ReadApexKeysInfo_missingPayloadPrivateKey(self):
@@ -505,10 +505,10 @@
'container_certificate="build/make/target/product/security/testkey.x509.pem" '
'container_private_key="build/make/target/product/security/testkey.pk8"')
target_files = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
- with zipfile.ZipFile(target_files) as target_files_zip:
+ with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
@@ -528,10 +528,10 @@
'container_certificate="build/make/target/product/security/testkey.x509.pem" '
'container_private_key="build/make/target/product/security/testkey.pk8"')
target_files = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
- with zipfile.ZipFile(target_files) as target_files_zip:
+ with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
@@ -551,10 +551,10 @@
'container_certificate="PRESIGNED" '
'container_private_key="PRESIGNED"')
target_files = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
- with zipfile.ZipFile(target_files) as target_files_zip:
+ with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
@@ -574,10 +574,10 @@
'container_certificate="PRESIGNED" '
'container_private_key="PRESIGNED"')
target_files = common.MakeTempFile(suffix='.zip')
- with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
- with zipfile.ZipFile(target_files) as target_files_zip:
+ with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
diff --git a/tools/releasetools/test_utils.py b/tools/releasetools/test_utils.py
index e999757..ccd97a9 100755
--- a/tools/releasetools/test_utils.py
+++ b/tools/releasetools/test_utils.py
@@ -22,9 +22,11 @@
import logging
import os
import os.path
+import re
import struct
import sys
import unittest
+import zipfile
import common
@@ -192,9 +194,57 @@
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', allowZip64=True) 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 6504515..e9896ae 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -25,10 +25,9 @@
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):
@@ -273,7 +272,7 @@
input_file = common.MakeTempFile()
all_entries = ['SYSTEM/', 'SYSTEM/b', 'SYSTEM/a', 'IMAGES/',
'IMAGES/system.map', 'IMAGES/system.img']
- with zipfile.ZipFile(input_file, 'w') as input_zip:
+ with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
for name in all_entries:
input_zip.write(os.path.join(input_tmp, name), arcname=name)
@@ -322,10 +321,45 @@
input_file = common.MakeTempFile()
all_entries = ['SYSTEM/', 'SYSTEM/abc', 'IMAGES/',
'IMAGES/system.map', 'IMAGES/system.img']
- with zipfile.ZipFile(input_file, 'w') as input_zip:
+ with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
for name in all_entries:
input_zip.write(os.path.join(input_tmp, name), arcname=name)
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 d02bc7f..a850390 100644
--- a/tools/releasetools/test_verity_utils.py
+++ b/tools/releasetools/test_verity_utils.py
@@ -233,8 +233,8 @@
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 b9caf9e..a827f22 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 a9355d7..5b1b544 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 7dd3964..c6a9771 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 0000000..89f1ef3
--- /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 0000000..8bfd816
--- /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
similarity index 74%
rename from tools/releasetools/testdata/vintf/kernel/SYSTEM/compatibility_matrix.xml
rename to tools/releasetools/testdata/vintf/kernel/SYSTEM/etc/vintf/compatibility_matrix.1.xml
index ed46b6b..a92dd6e 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
similarity index 71%
rename from tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/compatibility_matrix.xml
rename to tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/etc/vintf/compatibility_matrix.1.xml
index 5d891fa..1700e21 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
similarity index 85%
rename from tools/releasetools/testdata/vintf/sku_compat/SYSTEM/compatibility_matrix.xml
rename to tools/releasetools/testdata/vintf/sku_compat/SYSTEM/etc/vintf/compatibility_matrix.1.xml
index 19a9b6a..22272fd 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
similarity index 85%
rename from tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/compatibility_matrix.xml
rename to tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/etc/vintf/compatibility_matrix.1.xml
index e0e0d6c..1a3fc43 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 ac469eb..d2178b2 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -236,6 +236,15 @@
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 @@
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 @@
'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(
@@ -444,9 +487,11 @@
input_tmp = common.UnzipTemp(args.target_files)
info_dict = common.LoadInfoDict(input_tmp)
- with zipfile.ZipFile(args.target_files, 'r') as input_zip:
+ with zipfile.ZipFile(args.target_files, 'r', allowZip64=True) 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/signapk/Android.bp b/tools/signapk/Android.bp
index c799dbf..b90f010 100644
--- a/tools/signapk/Android.bp
+++ b/tools/signapk/Android.bp
@@ -16,7 +16,7 @@
// the signapk tool (a .jar application used to sign packages)
// ============================================================
-java_library_host {
+java_binary_host {
name: "signapk",
srcs: ["src/**/*.java"],
manifest: "SignApk.mf",
@@ -27,11 +27,12 @@
"conscrypt-unbundled",
],
- required: ["libconscrypt_openjdk_jni"],
+ jni_libs: ["libconscrypt_openjdk_jni"],
// The post-build signing tools need signapk.jar (and its shared libraries,
// handled in their own Android.bp files)
dist: {
+ tag: ".jar",
targets: ["droidcore"],
},
}
diff --git a/tools/soong_to_convert.py b/tools/soong_to_convert.py
index 083f6f7..949131b 100755
--- a/tools/soong_to_convert.py
+++ b/tools/soong_to_convert.py
@@ -78,7 +78,7 @@
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 0000000..12d52e5
--- /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/android_project_list.py b/tools/warn/android_project_list.py
index 1010b24..82c0fbd 100644
--- a/tools/warn/android_project_list.py
+++ b/tools/warn/android_project_list.py
@@ -109,7 +109,7 @@
create_pattern('system/bt'),
create_pattern('system/connectivity'),
create_pattern('system/core/adb'),
- create_pattern('system/core/base'),
+ create_pattern('system/libbase'),
create_pattern('system/core/debuggerd'),
create_pattern('system/core/fastboot'),
create_pattern('system/core/fingerprintd'),
@@ -118,8 +118,8 @@
create_pattern('system/core/healthd'),
create_pattern('system/core/include'),
create_pattern('system/core/init'),
- create_pattern('system/core/libbacktrace'),
- create_pattern('system/core/liblog'),
+ create_pattern('system/unwinding/libbacktrace'),
+ create_pattern('system/logging/liblog'),
create_pattern('system/core/libpixelflinger'),
create_pattern('system/core/libprocessgroup'),
create_pattern('system/core/libsysutils'),
diff --git a/tools/warn/chrome_project_list.py b/tools/warn/chrome_project_list.py
new file mode 100644
index 0000000..6096522
--- /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/cpp_warn_patterns.py b/tools/warn/cpp_warn_patterns.py
index 65ce73a..e8783bc 100644
--- a/tools/warn/cpp_warn_patterns.py
+++ b/tools/warn/cpp_warn_patterns.py
@@ -155,6 +155,7 @@
[r".*: warning: unknown attribute '.+'"]),
medium('Attribute ignored',
[r".*: warning: '_*packed_*' attribute ignored",
+ r".*: warning: .* not supported .*Wignored-attributes",
r".*: warning: attribute declaration must precede definition .+ignored-attributes"]),
medium('Visibility problem',
[r".*: warning: declaration of '.+' will not be visible outside of this function"]),
@@ -251,6 +252,8 @@
[r".*: warning: taking address of temporary"]),
medium('Taking address of packed member',
[r".*: warning: taking address of packed member"]),
+ medium('Pack alignment value is modified',
+ [r".*: warning: .*#pragma pack alignment value is modified.*Wpragma-pack.*"]),
medium('Possible broken line continuation',
[r".*: warning: backslash and newline separated by space"]),
medium('Undefined variable template',
@@ -332,7 +335,7 @@
[r".*: warning: extra tokens at end of #endif directive"]),
medium('Comparison between different enums',
[r".*: warning: comparison between '.+' and '.+'.+Wenum-compare",
- r".*: warning: comparison of .* enumeration types .*-Wenum-compare-switch"]),
+ r".*: warning: comparison of .* enumeration types .*-Wenum-compare.*"]),
medium('Conversion may change value',
[r".*: warning: converting negative value '.+' to '.+'",
r".*: warning: conversion to '.+' .+ may (alter|change)"]),
@@ -396,6 +399,8 @@
r".*: warning: absolute value function '.+' given .+ which may cause truncation .+Wabsolute-value"]),
low('Using C++11 extensions',
[r".*: warning: 'auto' type specifier is a C\+\+11 extension"]),
+ low('Using C++17 extensions',
+ [r".*: warning: .* a C\+\+17 extension .+Wc\+\+17-extensions"]),
low('Refers to implicitly defined namespace',
[r".*: warning: using directive refers to implicitly-defined namespace .+"]),
low('Invalid pp token',
@@ -437,8 +442,10 @@
[r".*: warning: unannotated fall-through between switch labels.+Wimplicit-fallthrough"]),
medium('Invalid partial specialization',
[r".*: warning: class template partial specialization.+Winvalid-partial-specialization"]),
- medium('Overlapping compatisons',
+ medium('Overlapping comparisons',
[r".*: warning: overlapping comparisons.+Wtautological-overlap-compare"]),
+ medium('bitwise comparison',
+ [r".*: warning: bitwise comparison.+Wtautological-bitwise-compare"]),
medium('int in bool context',
[r".*: warning: converting.+to a boolean.+Wint-in-bool-context"]),
medium('bitwise conditional parentheses',
diff --git a/tools/warn/html_writer.py b/tools/warn/html_writer.py
new file mode 100644
index 0000000..026a6d0
--- /dev/null
+++ b/tools/warn/html_writer.py
@@ -0,0 +1,698 @@
+# 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'])
+
+
+def dump_csv_with_description(csvwriter, warning_records, warning_messages,
+ warn_patterns, project_names):
+ """Outputs all the warning messages by project."""
+ csv_output = []
+ for record in warning_records:
+ project_name = project_names[record[1]]
+ pattern = warn_patterns[record[0]]
+ severity = pattern['severity'].header
+ category = pattern['category']
+ description = pattern['description']
+ warning = warning_messages[record[2]]
+ csv_output.append([project_name, severity,
+ category, description,
+ warning])
+ csv_output = sorted(csv_output)
+ for output in csv_output:
+ csvwriter.writerow(output)
+
+
+# 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.csvwithdescription:
+ with open(flags.csvwithdescription, 'w') as f:
+ dump_csv_with_description(csv.writer(f, lineterminator='\n'),
+ warning_records, warning_messages,
+ warn_patterns, project_names)
+
+ 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 80e2e1d..ac1ed5d 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,27 @@
java_medium('Static method should be qualified',
[r'.*\.java:.*: warning: \[static\] static method should be qualified']),
medium('AbstractInner'),
+ medium('BothPackageInfoAndHtml'),
+ medium('BuilderSetStyle'),
medium('CallbackName'),
medium('ExecutorRegistration'),
+ medium('HiddenTypeParameter'),
medium('JavaApiUsedByMainlineModule'),
medium('ListenerLast'),
+ medium('MinMaxConstant'),
medium('MissingBuildMethod'),
+ medium('MissingGetterMatchingBuilder'),
medium('NoByteOrShort'),
medium('OverlappingConstants'),
medium('SetterReturnsThis'),
+ medium('StaticFinalBuilder'),
+ 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 +794,8 @@
# 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 dd6a1b0..4b20493 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 1350936..8df5b87 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 @@
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,44 +115,56 @@
'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: "]),
+ yacc('reduce/reduce conflicts',
+ [r".*\.yy?: warning: .+ reduce/reduce conflicts "]),
yacc('shift/reduce conflicts',
[r".*\.yy?: warning: .+ shift/reduce conflicts "]),
{'category': 'yacc', 'severity': Severity.SKIP,
'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 b1c38e4..b4c03c9 100644
--- a/tools/warn/severity.py
+++ b/tools/warn/severity.py
@@ -20,24 +20,26 @@
# pylint:disable=old-style-class
+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."""
- class SeverityInfo:
-
- def __init__(self, value, color, column_header, header):
- self.value = value
- self.color = color
- self.column_header = column_header
- self.header = header
-
# 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 2c5ab79..5416cb2 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 @@
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 @@
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 @@
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 bdfd489..56e8787 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 0c9d9ef..b2dd8ab 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,206 @@
# 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 = []
+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 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'] = {}
+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('--csvwithdescription', default='',
+ help="""Save CSV warning file to the passed path this csv
+ will contain all the warning descriptions""")
+ 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
-initialize_arrays()
+def get_project_names(project_list):
+ """Get project_names from project_list."""
+ return [p[0] for p in project_list]
-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
+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 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
-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)]
+# 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/'
- 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 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 +245,110 @@
# 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):]
+ return path
+
+
+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.
+ 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_path(path):
- """Normalize file path relative to android_root."""
- # If path is not an absolute path, just normalize it.
- path = os.path.normpath(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
-
-
-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 +363,25 @@
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 +389,8 @@
# 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 +405,182 @@
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
+
+ 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
-# Return s with escaped backslash and quotation characters.
-def escape_string(s):
- # pytype: disable=attribute-error
- return s.replace('\\', '\\\\').replace('"', '\\"')
- # pytype: enable=attribute-error
+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)
-# 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 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 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);
- }
-"""
-
-
-# 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 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 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:
- writer('<script>groupBySeverity();</script>')
- dump_fixed(writer)
- dump_html_epilogue(writer)
+ 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
-##### Functions to count warnings and dump csv file. #########################
+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 description_for_csv(category):
- if not category['description']:
- return '?'
- return category['description']
+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
+ }]
-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 = create_launch_subprocs_fn(num_cpu,
+ classify_warnings_fn,
+ arg_groups,
+ group_results)
else:
- dump_html(sys.stdout)
+ 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:
+ 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/Android.bp b/tools/zipalign/Android.bp
index 8e6196d..1ebf4eb 100644
--- a/tools/zipalign/Android.bp
+++ b/tools/zipalign/Android.bp
@@ -4,20 +4,31 @@
// Zip alignment tool
//
-cc_binary_host {
- name: "zipalign",
+cc_defaults {
+ name: "zipalign_defaults",
+ target: {
+ windows: {
+ host_ldlibs: ["-lpthread"],
+ enabled: true,
+ },
+ },
+}
+cc_library_host_static {
+ name: "libzipalign",
srcs: [
"ZipAlign.cpp",
"ZipEntry.cpp",
"ZipFile.cpp",
],
-
+ export_include_dirs: [
+ "include",
+ ],
cflags: ["-Wall", "-Werror"],
// NOTE: Do not add any shared_libs dependencies because they will break the
// static_sdk_tools target.
- static_libs: [
+ whole_static_libs: [
"libutils",
"libcutils",
"liblog",
@@ -26,11 +37,39 @@
"libbase",
"libzopfli",
],
+ defaults: ["zipalign_defaults"],
+}
- target: {
- windows: {
- host_ldlibs: ["-lpthread"],
- enabled: true,
- },
+cc_binary_host {
+ name: "zipalign",
+ srcs: [
+ "ZipAlignMain.cpp",
+ ],
+ cflags: ["-Wall", "-Werror"],
+ static_libs: [
+ "libzipalign",
+ ],
+ defaults: ["zipalign_defaults"],
+}
+
+cc_test_host {
+ name: "zipalign_tests",
+ srcs: [
+ "tests/src/*_test.cpp",
+ ],
+ test_options: {
+ unit_test: true,
},
+ static_libs: [
+ "libbase",
+ "libzipalign",
+ "libgmock",
+ ],
+ data: [
+ "tests/data/diffOrders.zip",
+ "tests/data/holes.zip",
+ "tests/data/unaligned.zip",
+ ],
+ defaults: ["zipalign_defaults"],
+ test_suites: ["general-tests"],
}
diff --git a/tools/zipalign/OWNERS b/tools/zipalign/OWNERS
new file mode 100644
index 0000000..d701e4a
--- /dev/null
+++ b/tools/zipalign/OWNERS
@@ -0,0 +1,2 @@
+include platform/system/core:/janitors/OWNERS
+sanglardf@google.com
diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp
index eea1749..08f67ff 100644
--- a/tools/zipalign/ZipAlign.cpp
+++ b/tools/zipalign/ZipAlign.cpp
@@ -14,35 +14,13 @@
* limitations under the License.
*/
-/*
- * Zip alignment tool
- */
#include "ZipFile.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-using namespace android;
-
-/*
- * Show program usage.
- */
-void usage(void)
-{
- fprintf(stderr, "Zip alignment utility\n");
- fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
- fprintf(stderr,
- "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
- " zipalign -c [-p] [-v] <align> infile.zip\n\n" );
- fprintf(stderr,
- " <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
- fprintf(stderr, " -c: check alignment only (does not modify file)\n");
- fprintf(stderr, " -f: overwrite existing outfile.zip\n");
- fprintf(stderr, " -p: memory page alignment for stored shared object files\n");
- fprintf(stderr, " -v: verbose output\n");
- fprintf(stderr, " -z: recompress using Zopfli\n");
-}
+namespace android {
static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
ZipEntry* pEntry) {
@@ -69,7 +47,6 @@
{
int numEntries = pZin->getNumEntries();
ZipEntry* pEntry;
- int bias = 0;
status_t status;
for (int i = 0; i < numEntries; i++) {
@@ -90,30 +67,20 @@
if (zopfli) {
status = pZout->addRecompress(pZin, pEntry, &pNewEntry);
- bias += pNewEntry->getCompressedLen() - pEntry->getCompressedLen();
} else {
status = pZout->add(pZin, pEntry, padding, &pNewEntry);
}
} else {
const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
- /*
- * Copy the entry, adjusting as required. We assume that the
- * file position in the new file will be equal to the file
- * position in the original.
- */
- off_t newOffset = pEntry->getFileOffset() + bias;
- padding = (alignTo - (newOffset % alignTo)) % alignTo;
-
//printf("--- %s: orig at %ld(+%d) len=%ld, adding pad=%d\n",
// pEntry->getFileName(), (long) pEntry->getFileOffset(),
// bias, (long) pEntry->getUncompressedLen(), padding);
- status = pZout->add(pZin, pEntry, padding, &pNewEntry);
+ status = pZout->add(pZin, pEntry, alignTo, &pNewEntry);
}
if (status != OK)
return 1;
- bias += padding;
//printf(" added '%s' at %ld (pad=%d)\n",
// pNewEntry->getFileName(), (long) pNewEntry->getFileOffset(),
// padding);
@@ -126,7 +93,7 @@
* Process a file. We open the input and output files, failing if the
* output file exists and "force" wasn't specified.
*/
-static int process(const char* inFileName, const char* outFileName,
+int process(const char* inFileName, const char* outFileName,
int alignment, bool force, bool zopfli, bool pageAlignSharedLibs)
{
ZipFile zin, zout;
@@ -169,7 +136,7 @@
/*
* Verify the alignment of a zip archive.
*/
-static int verify(const char* fileName, int alignment, bool verbose,
+int verify(const char* fileName, int alignment, bool verbose,
bool pageAlignSharedLibs)
{
ZipFile zipFile;
@@ -218,92 +185,4 @@
return foundBad ? 1 : 0;
}
-/*
- * Parse args.
- */
-int main(int argc, char* const argv[])
-{
- bool wantUsage = false;
- bool check = false;
- bool force = false;
- bool verbose = false;
- bool zopfli = false;
- bool pageAlignSharedLibs = false;
- int result = 1;
- int alignment;
- char* endp;
-
- if (argc < 4) {
- wantUsage = true;
- goto bail;
- }
-
- argc--;
- argv++;
-
- while (argc && argv[0][0] == '-') {
- const char* cp = argv[0] +1;
-
- while (*cp != '\0') {
- switch (*cp) {
- case 'c':
- check = true;
- break;
- case 'f':
- force = true;
- break;
- case 'v':
- verbose = true;
- break;
- case 'z':
- zopfli = true;
- break;
- case 'p':
- pageAlignSharedLibs = true;
- break;
- default:
- fprintf(stderr, "ERROR: unknown flag -%c\n", *cp);
- wantUsage = true;
- goto bail;
- }
-
- cp++;
- }
-
- argc--;
- argv++;
- }
-
- if (!((check && argc == 2) || (!check && argc == 3))) {
- wantUsage = true;
- goto bail;
- }
-
- alignment = strtol(argv[0], &endp, 10);
- if (*endp != '\0' || alignment <= 0) {
- fprintf(stderr, "Invalid value for alignment: %s\n", argv[0]);
- wantUsage = true;
- goto bail;
- }
-
- if (check) {
- /* check existing archive for correct alignment */
- result = verify(argv[1], alignment, verbose, pageAlignSharedLibs);
- } else {
- /* create the new archive */
- result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs);
-
- /* trust, but verify */
- if (result == 0) {
- result = verify(argv[2], alignment, verbose, pageAlignSharedLibs);
- }
- }
-
-bail:
- if (wantUsage) {
- usage();
- result = 2;
- }
-
- return result;
-}
+} // namespace android
diff --git a/tools/zipalign/ZipAlignMain.cpp b/tools/zipalign/ZipAlignMain.cpp
new file mode 100644
index 0000000..49be916
--- /dev/null
+++ b/tools/zipalign/ZipAlignMain.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Zip alignment tool
+ */
+
+#include "ZipAlign.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace android;
+
+/*
+ * Show program usage.
+ */
+void usage(void)
+{
+ fprintf(stderr, "Zip alignment utility\n");
+ fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
+ fprintf(stderr,
+ "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
+ " zipalign -c [-p] [-v] <align> infile.zip\n\n" );
+ fprintf(stderr,
+ " <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
+ fprintf(stderr, " -c: check alignment only (does not modify file)\n");
+ fprintf(stderr, " -f: overwrite existing outfile.zip\n");
+ fprintf(stderr, " -p: memory page alignment for stored shared object files\n");
+ fprintf(stderr, " -v: verbose output\n");
+ fprintf(stderr, " -z: recompress using Zopfli\n");
+}
+
+
+/*
+ * Parse args.
+ */
+int main(int argc, char* const argv[])
+{
+ bool wantUsage = false;
+ bool check = false;
+ bool force = false;
+ bool verbose = false;
+ bool zopfli = false;
+ bool pageAlignSharedLibs = false;
+ int result = 1;
+ int alignment;
+ char* endp;
+
+ if (argc < 4) {
+ wantUsage = true;
+ goto bail;
+ }
+
+ argc--;
+ argv++;
+
+ while (argc && argv[0][0] == '-') {
+ const char* cp = argv[0] +1;
+
+ while (*cp != '\0') {
+ switch (*cp) {
+ case 'c':
+ check = true;
+ break;
+ case 'f':
+ force = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'z':
+ zopfli = true;
+ break;
+ case 'p':
+ pageAlignSharedLibs = true;
+ break;
+ default:
+ fprintf(stderr, "ERROR: unknown flag -%c\n", *cp);
+ wantUsage = true;
+ goto bail;
+ }
+
+ cp++;
+ }
+
+ argc--;
+ argv++;
+ }
+
+ if (!((check && argc == 2) || (!check && argc == 3))) {
+ wantUsage = true;
+ goto bail;
+ }
+
+ alignment = strtol(argv[0], &endp, 10);
+ if (*endp != '\0' || alignment <= 0) {
+ fprintf(stderr, "Invalid value for alignment: %s\n", argv[0]);
+ wantUsage = true;
+ goto bail;
+ }
+
+ if (check) {
+ /* check existing archive for correct alignment */
+ result = verify(argv[1], alignment, verbose, pageAlignSharedLibs);
+ } else {
+ /* create the new archive */
+ result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs);
+
+ /* trust, but verify */
+ if (result == 0) {
+ result = verify(argv[2], alignment, verbose, pageAlignSharedLibs);
+ }
+ }
+
+bail:
+ if (wantUsage) {
+ usage();
+ result = 2;
+ }
+
+ return result;
+}
diff --git a/tools/zipalign/ZipEntry.cpp b/tools/zipalign/ZipEntry.cpp
index 810d74a..5233f0a 100644
--- a/tools/zipalign/ZipEntry.cpp
+++ b/tools/zipalign/ZipEntry.cpp
@@ -29,7 +29,7 @@
#include <string.h>
#include <time.h>
-using namespace android;
+namespace android {
/*
* Initialize a new ZipEntry structure from a FILE* positioned at a
@@ -696,3 +696,5 @@
ALOGD(" comment: '%s'\n", mFileComment);
}
+} // namespace android
+
diff --git a/tools/zipalign/ZipFile.cpp b/tools/zipalign/ZipFile.cpp
index 63fb962..9938a06 100644
--- a/tools/zipalign/ZipFile.cpp
+++ b/tools/zipalign/ZipFile.cpp
@@ -35,7 +35,7 @@
#include <assert.h>
#include <inttypes.h>
-using namespace android;
+namespace android {
/*
* Some environments require the "b", some choke on it.
@@ -134,7 +134,7 @@
/*
* Return the Nth entry in the archive.
*/
-android::ZipEntry* ZipFile::getEntryByIndex(int idx) const
+ZipEntry* ZipFile::getEntryByIndex(int idx) const
{
if (idx < 0 || idx >= (int) mEntries.size())
return NULL;
@@ -145,7 +145,7 @@
/*
* Find an entry by name.
*/
-android::ZipEntry* ZipFile::getEntryByName(const char* fileName) const
+ZipEntry* ZipFile::getEntryByName(const char* fileName) const
{
/*
* Do a stupid linear string-compare search.
@@ -503,6 +503,32 @@
}
/*
+ * Based on the current position in the output zip, assess where the entry
+ * payload will end up if written as-is. If alignment is not satisfactory,
+ * add some padding in the extra field.
+ *
+ */
+status_t ZipFile::alignEntry(android::ZipEntry* pEntry, uint32_t alignTo){
+ if (alignTo == 0 || alignTo == 1)
+ return OK;
+
+ // Calculate where the entry payload offset will end up if we were to write
+ // it as-is.
+ uint64_t expectedPayloadOffset = ftell(mZipFp) +
+ android::ZipEntry::LocalFileHeader::kLFHLen +
+ pEntry->mLFH.mFileNameLength +
+ pEntry->mLFH.mExtraFieldLength;
+
+ // If the alignment is not what was requested, add some padding in the extra
+ // so the payload ends up where is requested.
+ uint64_t alignDiff = alignTo - (expectedPayloadOffset % alignTo);
+ if (alignDiff == 0)
+ return OK;
+
+ return pEntry->addPadding(alignDiff);
+}
+
+/*
* Add an entry by copying it from another zip file. If "padding" is
* nonzero, the specified number of bytes will be added to the "extra"
* field in the header.
@@ -510,7 +536,7 @@
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
status_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
- int padding, ZipEntry** ppEntry)
+ int alignTo, ZipEntry** ppEntry)
{
ZipEntry* pEntry = NULL;
status_t result;
@@ -537,11 +563,10 @@
result = pEntry->initFromExternal(pSourceEntry);
if (result != OK)
goto bail;
- if (padding != 0) {
- result = pEntry->addPadding(padding);
- if (result != OK)
- goto bail;
- }
+
+ result = alignEntry(pEntry, alignTo);
+ if (result != OK)
+ goto bail;
/*
* From here on out, failures are more interesting.
@@ -1221,7 +1246,7 @@
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 +1269,7 @@
private:
FILE* fp_;
- mutable uint32_t current_offset_;
+ mutable off64_t current_offset_;
};
// free the memory when you're done
@@ -1397,3 +1422,4 @@
mCentralDirSize, mCentralDirOffset, mCommentLen);
}
+} // namespace android
diff --git a/tools/zipalign/ZipFile.h b/tools/zipalign/ZipFile.h
index 11d20c5..854f981 100644
--- a/tools/zipalign/ZipFile.h
+++ b/tools/zipalign/ZipFile.h
@@ -102,14 +102,14 @@
}
/*
- * Add an entry by copying it from another zip file. If "padding" is
- * nonzero, the specified number of bytes will be added to the "extra"
- * field in the header.
+ * Add an entry by copying it from another zip file. If "alignment" is
+ * nonzero, an appropriate number of bytes will be added to the "extra"
+ * field in the header so the entry payload is aligned.
*
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
status_t add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
- int padding, ZipEntry** ppEntry);
+ int alignment, ZipEntry** ppEntry);
/*
* Add an entry by copying it from another zip file, recompressing with
@@ -163,6 +163,8 @@
ZipFile(const ZipFile& src);
ZipFile& operator=(const ZipFile& src);
+ status_t alignEntry(android::ZipEntry* pEntry, uint32_t alignTo);
+
class EndOfCentralDir {
public:
EndOfCentralDir(void) :
diff --git a/tools/zipalign/include/ZipAlign.h b/tools/zipalign/include/ZipAlign.h
new file mode 100644
index 0000000..ab36086
--- /dev/null
+++ b/tools/zipalign/include/ZipAlign.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef ZIPALIGN_H
+#define ZIPALIGN_H
+
+namespace android {
+
+/*
+ * Generate a new, aligned, zip "output" from an "input" zip.
+ * - alignTo: Alignment (in bytes) for uncompressed entries.
+ * - force : Overwrite output if it exists, fail otherwise.
+ * - zopfli : Recompress compressed entries with more efficient algorithm.
+ * Copy compressed entries as-is, and unaligned, otherwise.
+ * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ * alignTo, or all files to alignTo if false..
+ *
+ * Returns 0 on success.
+ */
+int process(const char* input, const char* output, int alignTo, bool force,
+ bool zopfli, bool pageAlignSharedLibs);
+
+/*
+ * Verify the alignment of a zip archive.
+ * - alignTo: Alignment (in bytes) for uncompressed entries.
+ * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ * alignTo, or all files to alignTo if false..
+ *
+ * Returns 0 on success.
+ */
+int verify(const char* fileName, int alignTo, bool verbose,
+ bool pageAlignSharedLibs);
+
+} // namespace android
+
+#endif // ZIPALIGN_H
diff --git a/tools/zipalign/tests/data/diffOrders.zip b/tools/zipalign/tests/data/diffOrders.zip
new file mode 100644
index 0000000..8f512ed
--- /dev/null
+++ b/tools/zipalign/tests/data/diffOrders.zip
Binary files differ
diff --git a/tools/zipalign/tests/data/holes.zip b/tools/zipalign/tests/data/holes.zip
new file mode 100644
index 0000000..c88f891
--- /dev/null
+++ b/tools/zipalign/tests/data/holes.zip
Binary files differ
diff --git a/tools/zipalign/tests/data/unaligned.zip b/tools/zipalign/tests/data/unaligned.zip
new file mode 100644
index 0000000..d572b1a
--- /dev/null
+++ b/tools/zipalign/tests/data/unaligned.zip
Binary files differ
diff --git a/tools/zipalign/tests/src/align_test.cpp b/tools/zipalign/tests/src/align_test.cpp
new file mode 100644
index 0000000..c79e791
--- /dev/null
+++ b/tools/zipalign/tests/src/align_test.cpp
@@ -0,0 +1,53 @@
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "ZipAlign.h"
+
+#include <stdio.h>
+#include <string>
+
+#include <android-base/file.h>
+
+using namespace android;
+
+static std::string GetTestPath(const std::string& filename) {
+ static std::string test_data_dir = android::base::GetExecutableDirectory() + "/tests/data/";
+ return test_data_dir + filename;
+}
+
+TEST(Align, Unaligned) {
+ const std::string src = GetTestPath("unaligned.zip");
+ const std::string dst = GetTestPath("unaligned_out.zip");
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, false);
+ ASSERT_EQ(0, verified);
+}
+
+// Align a zip featuring a hole at the beginning. The
+// hole in the archive is a delete entry in the Central
+// Directory.
+TEST(Align, Holes) {
+ const std::string src = GetTestPath("holes.zip");
+ const std::string dst = GetTestPath("holes_out.zip");
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, false, true);
+ ASSERT_EQ(0, verified);
+}
+
+// Align a zip where LFH order and CD entries differ.
+TEST(Align, DifferenteOrders) {
+ const std::string src = GetTestPath("diffOrders.zip");
+ const std::string dst = GetTestPath("diffOrders_out.zip");
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, false, true);
+ ASSERT_EQ(0, verified);
+}